From a9db5a2eaa51b71f6906dec726c4efa05b8bebe4 Mon Sep 17 00:00:00 2001
From: github-actions <github-actions@github.com>
Date: Fri, 24 Jan 2025 17:14:25 +0000
Subject: [PATCH] CI run 3609 pushed to gh-pages

---
 demo/trunk/dist/dwv.min.js     | 2 +-
 demo/trunk/dist/dwv.min.js.map | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/demo/trunk/dist/dwv.min.js b/demo/trunk/dist/dwv.min.js
index aedcbf3a3d..c7ea0c6ce4 100644
--- a/demo/trunk/dist/dwv.min.js
+++ b/demo/trunk/dist/dwv.min.js
@@ -1,2 +1,2 @@
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("konva"),require("magic-wand-tool"),require("jszip")):"function"==typeof define&&define.amd?define(["konva","konmagic-wand-tool","jszip"],t):"object"==typeof exports?exports.dwv=t(require("konva"),require("magic-wand-tool"),require("jszip")):e.dwv=t(e.Konva,e.MagicWand,e.JSZip)}(this,(function(e,t,n){return function(){"use strict";var i={654:function(e){e.exports=n},944:function(t){t.exports=e},324:function(e){e.exports=t}},r={};function o(e){var t=r[e];if(void 0!==t)return t.exports;var n=r[e]={exports:{}};return i[e](n,n.exports,o),n.exports}o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,{a:t}),t},o.d=function(e,t){for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var a={};o.r(a),o.d(a,{Annotation:function(){return Yi},AnnotationGroup:function(){return Xi},AnnotationGroupFactory:function(){return io},App:function(){return Po},AppOptions:function(){return Lo},ChangeSegmentColourCommand:function(){return Ao},Circle:function(){return Fi},ColourMap:function(){return m},DataElement:function(){return ve},DeleteSegmentCommand:function(){return Oo},DicomCode:function(){return kt},DicomData:function(){return ro},DicomParser:function(){return ke},DicomSRContent:function(){return $r},DicomWriter:function(){return Qt},DrawController:function(){return ji},DrawLayer:function(){return Zi},DrawShapeHandler:function(){return Ii},Ellipse:function(){return Ei},Geometry:function(){return it},Image:function(){return Un},Index:function(){return s},LayerGroup:function(){return $i},MaskFactory:function(){return Fn},MaskSegment:function(){return pn},MaskSegmentHelper:function(){return wo},MaskSegmentViewHelper:function(){return bo},Matrix33:function(){return A},NumberRange:function(){return tt},Orientation:function(){return gt},OverlayData:function(){return vo},PlaneHelper:function(){return Gn},Point:function(){return E},Point2D:function(){return R},Point3D:function(){return F},PositionHelper:function(){return Hn},Protractor:function(){return Ui},RGB:function(){return D},ROI:function(){return Ti},Rectangle:function(){return Mi},RescaleSlopeAndIntercept:function(){return je},Scalar2D:function(){return xo},Scalar3D:function(){return Ro},ScrollWheel:function(){return Jn},Size:function(){return Ze},Spacing:function(){return nt},Tag:function(){return de},ToolConfig:function(){return To},ToolboxController:function(){return ur},Vector3D:function(){return P},View:function(){return Bn},ViewConfig:function(){return Io},ViewController:function(){return zn},ViewLayer:function(){return _n},WindowLevel:function(){return u},WriterRule:function(){return At},addTagsToDictionary:function(){return Z},buildMultipart:function(){return X},createImage:function(){return En},createMaskImage:function(){return qn},createView:function(){return Nn},custom:function(){return L},decoderScripts:function(){return yr},getDefaultDicomSegJson:function(){return Rn},getDicomSRContentItem:function(){return to},getDwvVersion:function(){return Pe},getElementsFromJSONTags:function(){return Bt},getEllipseIndices:function(){return qi},getLayerDetailsFromEvent:function(){return Ki},getMousePoint:function(){return jn},getOrientationName:function(){return Dt},getPixelDataTag:function(){return De},getRectangleIndices:function(){return Qi},getReverseOrientation:function(){return be},getSRContent:function(){return eo},getTagFromKey:function(){return Se},getTouchPoints:function(){return Xn},getTypedArray:function(){return Me},getUID:function(){return xt},hasDicomPrefix:function(){return we},i18n:function(){return q},isEqualRgb:function(){return y},labToUintLab:function(){return C},logger:function(){return c},luts:function(){return f},precisionRound:function(){return B},srgbToCielab:function(){return I},toolList:function(){return ki},toolOptions:function(){return Hi}});class s{#e;constructor(e){if(!e||void 0===e)throw new Error("Cannot create index with no values.");if(0===e.length)throw new Error("Cannot create index with empty values.");if(!e.every((function(e){return!isNaN(e)})))throw new Error("Cannot create index with non number values.");this.#e=e}get(e){return this.#e[e]}length(){return this.#e.length}toString(){return"("+this.#e.toString()+")"}getValues(){return this.#e.slice()}canCompare(e){return!!e&&this.length()===e.length()}equals(e){if(!this.canCompare(e))return!1;for(let t=0,n=this.length();t<n;++t)if(this.get(t)!==e.get(t))return!1;return!0}compare(e){if(!this.canCompare(e))return null;const t=[];for(let n=0,i=this.length();n<i;++n)this.get(n)!==e.get(n)&&t.push(n);return t}add(e){if(!this.canCompare(e))return null;const t=[];for(let n=0,i=this.length();n<i;++n)t.push(this.get(n)+e.get(n));return new s(t)}#t(e,t){const n=this.#e.slice();return e<n.length?n[e]+=t:console.warn("Cannot add to given dimension: ",e,n.length),new s(n)}next(e){return this.#t(e,1)}previous(e){return this.#t(e,-1)}getWithNew2D(e,t){const n=[e,t];for(let e=2,t=this.length();e<t;++e)n.push(this.get(e));return new s(n)}}class l{#n;#i;#r;#o;constructor(e,t){if(this.#n=e,this.#i=e.isID(),this.#r=Math.pow(2,t),!this.#i){this.#o=new Float32Array(this.#r);for(let e=0;e<this.#r;++e)this.#o[e]=this.#n.apply(e)}}getRSI(){return this.#n}getLength(){return this.#r}getValue(e){return this.#i?e:this.#o[e]}}const c={levels:{TRACE:0,DEBUG:1,INFO:2,WARN:3,ERROR:4},level:3,trace:function(e){this.level<=this.levels.TRACE&&console.trace(e)},debug:function(e){this.level<=this.levels.DEBUG&&console.debug(e)},info:function(e){this.level<=this.levels.INFO&&console.info(e)},warn:function(e){this.level<=this.levels.WARN&&console.warn(e)},error:function(e){this.level<=this.levels.ERROR&&console.error(e)}};class u{center;width;constructor(e,t){t<1&&(c.warn("Using minimum window width since input is not valid: "+t),t=1),this.center=e,this.width=t}equals(e){return null!=e&&this.center===e.center&&this.width===e.width}}class d{#a;#s=0;#l=0;#c=255;#u=null;#d=null;#h=null;#S=null;constructor(e){this.#a=e,this.#g()}getWindowLevel(){return this.#a}#g(){const e=this.#a.center,t=this.#a.width,n=e+this.#s;this.#u=n-.5-(t-1)/2,this.#d=n-.5+(t-1)/2,this.#h=(this.#c-this.#l)/(t-1),this.#S=(-(n-.5)/(t-1)+.5)*(this.#c-this.#l)+this.#l}setSignedOffset(e){this.#s=e,this.#g()}apply(e){return e<=this.#u?this.#l:e>this.#d?this.#c:e*this.#h+this.#S}}class h{#p;#m;#o;#f=0;#D=!0;constructor(e,t,n){if(this.#p=e,t){const e=this.#p.getLength();this.#f=e/2}else this.#f=0;this.#D=n}getVoiLut(){return this.#m}getModalityLut(){return this.#p}setVoiLut(e){if(this.#m=e,this.#m.setSignedOffset(this.#p.getRSI().getSlope()*this.#f),this.#D){const e=this.#p.getLength();this.#o=new Uint8ClampedArray(e);for(let t=0;t<e;++t)this.#o[t]=this.#m.apply(this.#p.getValue(t))}}getValue(e){return this.#D?this.#o[e+this.#f]:Math.floor(this.#m.apply(e+this.#f))}}function S(e){const t=[];for(let n=0;n<256;++n)t.push(e(n));return t}function g(e){return e}function p(e){return 255-e}class m{red;green;blue;constructor(e,t,n){this.red=e,this.green=t,this.blue=n}}const f={plain:{red:S(g),green:S(g),blue:S(g)},invPlain:{red:S(p),green:S(p),blue:S(p)},rainbow:{blue:[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,252,255,247,239,231,223,215,207,199,191,183,175,167,159,151,143,135,127,119,111,103,95,87,79,71,63,55,47,39,31,23,15,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],green:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,251,249,247,245,243,241,239,237,235,233,231,229,227,225,223,221,219,217,215,213,211,209,207,205,203,201,199,197,195,193,192,189,186,183,180,177,174,171,168,165,162,159,156,153,150,147,144,141,138,135,132,129,126,123,120,117,114,111,108,105,102,99,96,93,90,87,84,81,78,75,72,69,66,63,60,57,54,51,48,45,42,39,36,33,30,27,24,21,18,15,12,9,6,3],red:[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,62,60,58,56,54,52,50,48,46,44,42,40,38,36,34,32,30,28,26,24,22,20,18,16,14,12,10,8,6,4,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255]},hot:{red:S((function(e){const t=3*e;return t>255?255:t})),green:S((function(e){const t=256/3;let n=0;return e>=t&&(n=3*(e-t),n>255)?255:n})),blue:S((function(e){const t=256/3;let n=0;return e>=2*t&&(n=3*(e-2*t),n>255)?255:n}))},hot_iron:{red:[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],green:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,255],blue:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,252,255]},pet:{red:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,65,67,69,71,73,75,77,79,81,83,85,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,171,173,175,177,179,181,183,185,187,189,191,193,195,197,199,201,203,205,207,209,211,213,215,217,219,221,223,225,227,229,231,233,235,237,239,241,243,245,247,249,251,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],green:[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,65,67,69,71,73,75,77,79,81,83,85,87,89,91,93,95,97,99,101,103,105,107,109,111,113,115,117,119,121,123,125,128,126,124,122,120,118,116,114,112,110,108,106,104,102,100,98,96,94,92,90,88,86,84,82,80,78,76,74,72,70,68,66,64,63,61,59,57,55,53,51,49,47,45,43,41,39,37,35,33,31,29,27,25,23,21,19,17,15,13,11,9,7,5,3,1,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,255],blue:[0,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,65,67,69,71,73,75,77,79,81,83,85,87,89,91,93,95,97,99,101,103,105,107,109,111,113,115,117,119,121,123,125,127,129,131,133,135,137,139,141,143,145,147,149,151,153,155,157,159,161,163,165,167,169,171,173,175,177,179,181,183,185,187,189,191,193,195,197,199,201,203,205,207,209,211,213,215,217,219,221,223,225,227,229,231,233,235,237,239,241,243,245,247,249,251,253,255,252,248,244,240,236,232,228,224,220,216,212,208,204,200,196,192,188,184,180,176,172,168,164,160,156,152,148,144,140,136,132,128,124,120,116,112,108,104,100,96,92,88,84,80,76,72,68,64,60,56,52,48,44,40,36,32,28,24,20,16,12,8,4,0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,85,89,93,97,101,105,109,113,117,121,125,129,133,137,141,145,149,153,157,161,165,170,174,178,182,186,190,194,198,202,206,210,214,218,222,226,230,234,238,242,246,250,255]},hot_metal_blue:{red:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,6,9,12,15,18,21,24,26,29,32,35,38,41,44,47,50,52,55,57,59,62,64,66,69,71,74,76,78,81,83,85,88,90,93,96,99,102,105,108,111,114,116,119,122,125,128,131,134,137,140,143,146,149,152,155,158,161,164,166,169,172,175,178,181,184,187,190,194,198,201,205,209,213,217,221,224,228,232,236,240,244,247,251,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],green:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,4,6,8,9,11,13,15,17,19,21,23,24,26,28,30,32,34,36,38,40,41,43,45,47,49,51,53,55,56,58,60,62,64,66,68,70,72,73,75,77,79,81,83,85,87,88,90,92,94,96,98,100,102,104,105,107,109,111,113,115,117,119,120,122,124,126,128,130,132,134,136,137,139,141,143,145,147,149,151,152,154,156,158,160,162,164,166,168,169,171,173,175,177,179,181,183,184,186,188,190,192,194,196,198,200,201,203,205,207,209,211,213,215,216,218,220,222,224,226,228,229,231,233,235,237,239,240,242,244,246,248,250,251,253,255],blue:[0,2,4,6,8,10,12,14,16,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,65,67,69,71,73,75,77,79,81,83,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,117,119,121,123,125,127,129,131,133,135,137,139,141,143,145,147,149,151,153,155,157,159,161,163,165,167,169,171,173,175,177,179,181,183,184,186,188,190,192,194,196,198,200,197,194,191,188,185,182,179,176,174,171,168,165,162,159,156,153,150,144,138,132,126,121,115,109,103,97,91,85,79,74,68,62,56,50,47,44,41,38,35,32,29,26,24,21,18,15,12,9,6,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,6,9,12,15,18,21,24,26,29,32,35,38,41,44,47,50,53,56,59,62,65,68,71,74,76,79,82,85,88,91,94,97,100,103,106,109,112,115,118,121,124,126,129,132,135,138,141,144,147,150,153,156,159,162,165,168,171,174,176,179,182,185,188,191,194,197,200,203,206,210,213,216,219,223,226,229,232,236,239,242,245,249,252,255]},pet_20step:{red:[0,0,0,0,0,0,0,0,0,0,0,0,0,96,96,96,96,96,96,96,96,96,96,96,96,96,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,80,80,80,80,80,80,80,80,80,80,80,80,80,96,96,96,96,96,96,96,96,96,96,96,96,96,112,112,112,112,112,112,112,112,112,112,112,112,112,128,128,128,128,128,128,128,128,128,128,128,128,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,80,80,80,80,80,80,80,80,80,80,80,80,80,64,64,64,64,64,64,64,64,64,64,64,64,224,224,224,224,224,224,224,224,224,224,224,224,224,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,192,192,192,192,192,192,192,192,192,192,192,192,192,176,176,176,176,176,176,176,176,176,176,176,176,176,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],green:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,80,80,80,80,80,80,80,80,80,80,80,80,80,96,96,96,96,96,96,96,96,96,96,96,96,96,112,112,112,112,112,112,112,112,112,112,112,112,112,128,128,128,128,128,128,128,128,128,128,128,128,96,96,96,96,96,96,96,96,96,96,96,96,96,144,144,144,144,144,144,144,144,144,144,144,144,144,192,192,192,192,192,192,192,192,192,192,192,192,192,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,208,208,208,208,208,208,208,208,208,208,208,208,208,176,176,176,176,176,176,176,176,176,176,176,176,176,144,144,144,144,144,144,144,144,144,144,144,144,96,96,96,96,96,96,96,96,96,96,96,96,96,48,48,48,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255],blue:[0,0,0,0,0,0,0,0,0,0,0,0,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,112,112,112,112,112,112,112,112,112,112,112,112,128,128,128,128,128,128,128,128,128,128,128,128,128,176,176,176,176,176,176,176,176,176,176,176,176,176,192,192,192,192,192,192,192,192,192,192,192,192,192,224,224,224,224,224,224,224,224,224,224,224,224,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,80,80,80,80,80,80,80,80,80,80,80,80,80,64,64,64,64,64,64,64,64,64,64,64,64,80,80,80,80,80,80,80,80,80,80,80,80,80,96,96,96,96,96,96,96,96,96,96,96,96,96,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255]}};class D{r;g;b;constructor(e,t,n){this.r=e,this.g=t,this.b=n}}function y(e,t){return null!==e&&null!==t&&void 0!==e&&void 0!==t&&e.r===t.r&&e.g===t.g&&e.b===t.b}function C(e){return{l:655.35*e.l,a:257*e.a+32896,b:257*e.b+32896}}const v={x:95.0489,y:100,z:108.884};function I(e){return function(e){function t(e){let t=null;return t=e>.008856452?Math.pow(e,.333333333):7.787037037*e+.137931034,t}const n=v,i=t(e.y/n.y);return{l:116*i-16,a:500*(t(e.x/n.x)-i),b:200*(i-t(e.z/n.z))}}(function(e){function t(e){let t=null;return t=e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4),t}const n=t(e.r/255),i=t(e.g/255),r=t(e.b/255);return{x:100*(.4124*n+.3576*i+.1805*r),y:100*(.2126*n+.7152*i+.0722*r),z:100*(.0193*n+.1192*i+.9505*r)}}(e))}function T(e){const t={Yellow:"#ffff00",Red:"#ff0000",White:"#ffffff",Green:"#008000",Blue:"#0000ff",Lime:"#00ff00",Fuchsia:"#ff00ff",Black:"#000000"};let n="#ffff00";return void 0!==t[e]&&(n=t[e]),n}const L={wlPresets:void 0,labelTexts:void 0,openRoiDialog:void 0,getTagTime:void 0,getTagPixelUnit:void 0};class P{#y;#C;#v;constructor(e,t,n){this.#y=e,this.#C=t,this.#v=n}getX(){return this.#y}getY(){return this.#C}getZ(){return this.#v}equals(e){return null!==e&&this.#y===e.getX()&&this.#C===e.getY()&&this.#v===e.getZ()}toString(){return"("+this.#y+", "+this.#C+", "+this.#v+")"}norm(){return Math.sqrt(this.#y*this.#y+this.#C*this.#C+this.#v*this.#v)}crossProduct(e){return new P(this.#C*e.getZ()-e.getY()*this.#v,this.#v*e.getX()-e.getZ()*this.#y,this.#y*e.getY()-e.getX()*this.#C)}dotProduct(e){return this.#y*e.getX()+this.#C*e.getY()+this.#v*e.getZ()}isCodirectional(e){return this.dotProduct(e)>0}}Number.EPSILON;const w=1e-4;function O(e,t,n){return void 0===n&&(n=Number.EPSILON),Math.abs(e-t)<n}class A{#e;#I;constructor(e){this.#e=e}get(e,t){return this.#e[3*e+t]}getInverse(){return void 0===this.#I&&(this.#I=function(e){const t=e.get(0,0),n=e.get(0,1),i=e.get(0,2),r=e.get(1,0),o=e.get(1,1),a=e.get(1,2),s=e.get(2,0),l=e.get(2,1),u=e.get(2,2),d=o*u-a*l,h=a*s-r*u,S=r*l-o*s;let g=t*d+n*h+i*S;if(0!==g)return g=1/g,new A([g*d,g*(i*l-n*u),g*(n*a-i*o),g*h,g*(t*u-i*s),g*(i*r-t*a),g*S,g*(n*s-t*l),g*(t*o-n*r)]);c.warn("Cannot invert 3*3 matrix with zero determinant.")}(this)),this.#I}equals(e,t){for(let n=0;n<3;++n)for(let i=0;i<3;++i)if(!O(this.get(n,i),e.get(n,i),t))return!1;return!0}toString(){let e="[";for(let t=0;t<3;++t){0!==t&&(e+=", \n ");for(let n=0;n<3;++n)0!==n&&(e+=", "),e+=this.get(t,n)}return e+="]",e}multiply(e){const t=[];for(let n=0;n<3;++n)for(let i=0;i<3;++i){let r=0;for(let t=0;t<3;++t)r+=this.get(n,t)*e.get(t,i);t.push(r)}return new A(t)}getAbs(){const e=[];for(let t=0;t<3;++t)for(let n=0;n<3;++n)e.push(Math.abs(this.get(t,n)));return new A(e)}multiplyArray3D(e){if(3!==e.length)throw new Error("Cannot multiply 3x3 matrix with non 3D array: "+e.length);const t=[];for(let n=0;n<3;++n){let i=0;for(let t=0;t<3;++t)i+=this.get(n,t)*e[t];t.push(i)}return t}multiplyVector3D(e){const t=this.multiplyArray3D([e.getX(),e.getY(),e.getZ()]);return new P(t[0],t[1],t[2])}multiplyPoint3D(e){const t=this.multiplyArray3D([e.getX(),e.getY(),e.getZ()]);return new F(t[0],t[1],t[2])}multiplyIndex3D(e){const t=this.multiplyArray3D(e.getValues());return new s(t)}getRowAbsMax(e){const t=[Math.abs(this.get(e,0)),Math.abs(this.get(e,1)),Math.abs(this.get(e,2))],n=Math.max.apply(null,t),i=t.indexOf(n);return{value:this.get(e,i),index:i}}getColAbsMax(e){const t=[Math.abs(this.get(0,e)),Math.abs(this.get(1,e)),Math.abs(this.get(2,e))],n=Math.max.apply(null,t),i=t.indexOf(n);return{value:this.get(i,e),index:i}}asOneAndZeros(){const e=[];for(let t=0;t<3;++t){const n=this.getRowAbsMax(t),i=n.value>0?1:-1;for(let t=0;t<3;++t)t===n.index?e.push(1*i):e.push(0)}return new A(e)}getThirdColMajorDirection(){return this.getColAbsMax(2).index}}function b(){return new A([1,0,0,0,1,0,0,0,1])}function x(e){return e.equals(b())}class R{#y;#C;constructor(e,t){this.#y=e,this.#C=t}getX(){return this.#y}getY(){return this.#C}getValues(){return[this.#y,this.#C]}getCentroid(){return this}equals(e){return null!=e&&this.#y===e.getX()&&this.#C===e.getY()}toString(){return"("+this.#y+", "+this.#C+")"}getDistance(e){const t=this.#y-e.getX(),n=this.#C-e.getY();return Math.sqrt(t*t+n*n)}}class F{#y;#C;#v;constructor(e,t,n){this.#y=e,this.#C=t,this.#v=n}getX(){return this.#y}getY(){return this.#C}getZ(){return this.#v}getValues(){return[this.#y,this.#C,this.#v]}equals(e){return null!==e&&this.#y===e.getX()&&this.#C===e.getY()&&this.#v===e.getZ()}isSimilar(e,t){return null!==e&&O(this.#y,e.getX(),t)&&O(this.#C,e.getY(),t)&&O(this.#v,e.getZ(),t)}toString(){return"("+this.#y+", "+this.#C+", "+this.#v+")"}getDistance(e){return Math.sqrt(this.#T(e))}#T(e){const t=this.#y-e.getX(),n=this.#C-e.getY(),i=this.#v-e.getZ();return t*t+n*n+i*i}getClosest(e){let t=0,n=this.#T(e[t]);for(let i=0;i<e.length;++i){const r=this.#T(e[i]);r<n&&(t=i,n=r)}return t}minus(e){return new P(this.#y-e.getX(),this.#C-e.getY(),this.#v-e.getZ())}}class E{#e;constructor(e){if(!e||void 0===e)throw new Error("Cannot create point with no values.");if(0===e.length)throw new Error("Cannot create point with empty values.");if(!e.every((function(e){return!isNaN(e)})))throw new Error("Cannot create point with non number values.");this.#e=e}get(e){return this.#e[e]}length(){return this.#e.length}toString(){return"("+this.#e.toString()+")"}getValues(){return this.#e.slice()}canCompare(e){return!!e&&this.length()===e.length()}equals(e){if(!this.canCompare(e))return!1;for(let t=0,n=this.length();t<n;++t)if(this.get(t)!==e.get(t))return!1;return!0}compare(e){if(!this.canCompare(e))return null;const t=[];for(let n=0,i=this.length();n<i;++n)this.get(n)!==e.get(n)&&t.push(n);return t}get3D(){return new F(this.get(0),this.get(1),this.get(2))}add(e){if(!this.canCompare(e))return null;const t=[],n=this.getValues(),i=e.getValues();for(let e=0;e<n.length;++e)t.push(n[e]+i[e]);return new E(t)}mergeWith3D(e){const t=this.getValues();return t[0]=e.getX(),t[1]=e.getY(),t[2]=e.getZ(),new E(t)}}const q={t(e){let t=e;const n=e.split(".");return 2===n.length&&"unit"===n[0]&&(t={mm:"mm",cm2:"cm²",degree:"°"}[n[1]]),t}};function U(e,t,n){if(null==e||null==t)return!1;const i=n>0?0|n:0;return e.substring(i,i+t.length)===t}function M(e,t){return null!=e&&null!=t&&e.substring(e.length-t.length)===t}function Q(e){const t=[];if(null==e)return t;const n=/{(\w+)}/g;let i=n.exec(e);for(;i;)t.push(i[1]),i=n.exec(e);return t}function V(e){let t=null;if(null!=e&&"."!==e[0]){const n=e.toLowerCase().split(".");1!==n.length&&(t=n.pop(),/[a-z]/.test(t)&&!t.includes("/")||(t=null))}return t}function N(e){const t=new Uint8Array(e.length);for(let n=0,i=e.length;n<i;n++)t[n]=e.charCodeAt(n);return t}function B(e,t){const n=Math.pow(10,t),i=.01/n;return Math.round(e*n+i)/n}function G(e,t){if(void 0===t){t=[];for(let n=0;n<e.length;++n)t.push(n)}for(let n=0;n<t.length;++n)if(t[n]>=e.length)throw new Error("Non valid dimension for toStringId");let n="";for(let i=0;i<t.length;++i)0!==i&&(n+="_"),n+="#"+t[i]+"-"+e[t[i]];return n}function k(e,t){return null!==e&&null!==t&&void 0!==e&&void 0!==t&&H(e.slice().sort(),t.slice().sort())}function H(e,t){return null!==e&&null!==t&&void 0!==e&&void 0!==t&&e.length===t.length&&e.every((function(e,n){return e===t[n]}))}function z(e){return String.fromCharCode.apply(String,e)}function W(e,t,n,i){(void 0===n||n<0||n>=e.length)&&(n=0),(void 0===i||i<=n||i>e.length)&&(i=e.length);for(let r=n;r<i;++r)if(t(e[r],r,e))return r}function Y(e){return function(t,n,i){for(let t=0;t<e.length;++t)if(i[n+t]!==e[t])return!1;return!0}}function X(e,t){const n="\r\n";let i=0;const r=[];for(let o=0;o<e.length;++o){let a="";0!==o&&(a+=n),a+="--"+t+n;const s=Object.keys(e[o]);for(let t=0;t<s.length;++t){const i=s[t];"data"!==i&&(a+=i+": "+e[o][i]+n)}a+=n;const l=N(a);r.push(l),i+=l.byteLength+e[o].data.byteLength}const o=N("\r\n--"+t+"--"+n),a=new Uint8Array(i+o.byteLength);let s=0;for(let t=0;t<e.length;++t)a.set(r[t],s),s+=r[t].byteLength,a.set(new Uint8Array(e[t].data),s),s+=e[t].data.byteLength;return a.set(o,s),a}const j={"0000":{"0000":["UL","1","CommandGroupLength"],"0001":["UL","1","CommandLengthToEnd"],"0002":["UI","1","AffectedSOPClassUID"],"0003":["UI","1","RequestedSOPClassUID"],"0010":["SH","1","CommandRecognitionCode"],"0100":["US","1","CommandField"],"0110":["US","1","MessageID"],"0120":["US","1","MessageIDBeingRespondedTo"],"0200":["AE","1","Initiator"],"0300":["AE","1","Receiver"],"0400":["AE","1","FindLocation"],"0600":["AE","1","MoveDestination"],"0700":["US","1","Priority"],"0800":["US","1","CommandDataSetType"],"0850":["US","1","NumberOfMatches"],"0860":["US","1","ResponseSequenceNumber"],"0900":["US","1","Status"],"0901":["AT","1-n","OffendingElement"],"0902":["LO","1","ErrorComment"],"0903":["US","1","ErrorID"],1e3:["UI","1","AffectedSOPInstanceUID"],1001:["UI","1","RequestedSOPInstanceUID"],1002:["US","1","EventTypeID"],1005:["AT","1-n","AttributeIdentifierList"],1008:["US","1","ActionTypeID"],1020:["US","1","NumberOfRemainingSuboperations"],1021:["US","1","NumberOfCompletedSuboperations"],1022:["US","1","NumberOfFailedSuboperations"],1023:["US","1","NumberOfWarningSuboperations"],1030:["AE","1","MoveOriginatorApplicationEntityTitle"],1031:["US","1","MoveOriginatorMessageID"],4e3:["LT","1","DialogReceiver"],4010:["LT","1","TerminalType"],5010:["SH","1","MessageSetID"],5020:["SH","1","EndMessageID"],5110:["LT","1","DisplayFormat"],5120:["LT","1","PagePositionID"],5130:["CS","1","TextFormatID"],5140:["CS","1","NormalReverse"],5150:["CS","1","AddGrayScale"],5160:["CS","1","Borders"],5170:["IS","1","Copies"],5180:["CS","1","CommandMagnificationType"],5190:["CS","1","Erase"],"51A0":["CS","1","Print"],"51B0":["US","1-n","Overlays"]},"0002":{"0000":["UL","1","FileMetaInformationGroupLength"],"0001":["OB","1","FileMetaInformationVersion"],"0002":["UI","1","MediaStorageSOPClassUID"],"0003":["UI","1","MediaStorageSOPInstanceUID"],"0010":["UI","1","TransferSyntaxUID"],"0012":["UI","1","ImplementationClassUID"],"0013":["SH","1","ImplementationVersionName"],"0016":["AE","1","SourceApplicationEntityTitle"],"0017":["AE","1","SendingApplicationEntityTitle"],"0018":["AE","1","ReceivingApplicationEntityTitle"],"0026":["UR","1","SourcePresentationAddress"],"0027":["UR","1","SendingPresentationAddress"],"0028":["UR","1","ReceivingPresentationAddress"],"0031":["OB","1","RTVMetaInformationVersion"],"0032":["UI","1","RTVCommunicationSOPClassUID"],"0033":["UI","1","RTVCommunicationSOPInstanceUID"],"0035":["OB","1","RTVSourceIdentifier"],"0036":["OB","1","RTVFlowIdentifier"],"0037":["UL","1","RTVFlowRTPSamplingRate"],"0038":["FD","1","RTVFlowActualFrameDuration"],"0100":["UI","1","PrivateInformationCreatorUID"],"0102":["OB","1","PrivateInformation"]},"0004":{"0000":["UL","1","GenericGroupLength"],1130:["CS","1","FileSetID"],1141:["CS","1-8","FileSetDescriptorFileID"],1142:["CS","1","SpecificCharacterSetOfFileSetDescriptorFile"],1200:["UL","1","OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity"],1202:["UL","1","OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity"],1212:["US","1","FileSetConsistencyFlag"],1220:["SQ","1","DirectoryRecordSequence"],1400:["UL","1","OffsetOfTheNextDirectoryRecord"],1410:["US","1","RecordInUseFlag"],1420:["UL","1","OffsetOfReferencedLowerLevelDirectoryEntity"],1430:["CS","1","DirectoryRecordType"],1432:["UI","1","PrivateRecordUID"],1500:["CS","1-8","ReferencedFileID"],1504:["UL","1","MRDRDirectoryRecordOffset"],1510:["UI","1","ReferencedSOPClassUIDInFile"],1511:["UI","1","ReferencedSOPInstanceUIDInFile"],1512:["UI","1","ReferencedTransferSyntaxUIDInFile"],"151A":["UI","1-n","ReferencedRelatedGeneralSOPClassUIDInFile"],1600:["UL","1","NumberOfReferences"]},"0008":{"0000":["UL","1","GenericGroupLength"],"0001":["UL","1","LengthToEnd"],"0005":["CS","1-n","SpecificCharacterSet"],"0006":["SQ","1","LanguageCodeSequence"],"0008":["CS","2-n","ImageType"],"0010":["SH","1","RecognitionCode"],"0012":["DA","1","InstanceCreationDate"],"0013":["TM","1","InstanceCreationTime"],"0014":["UI","1","InstanceCreatorUID"],"0015":["DT","1","InstanceCoercionDateTime"],"0016":["UI","1","SOPClassUID"],"0018":["UI","1","SOPInstanceUID"],"001A":["UI","1-n","RelatedGeneralSOPClassUID"],"001B":["UI","1","OriginalSpecializedSOPClassUID"],"0020":["DA","1","StudyDate"],"0021":["DA","1","SeriesDate"],"0022":["DA","1","AcquisitionDate"],"0023":["DA","1","ContentDate"],"0024":["DA","1","OverlayDate"],"0025":["DA","1","CurveDate"],"002A":["DT","1","AcquisitionDateTime"],"0030":["TM","1","StudyTime"],"0031":["TM","1","SeriesTime"],"0032":["TM","1","AcquisitionTime"],"0033":["TM","1","ContentTime"],"0034":["TM","1","OverlayTime"],"0035":["TM","1","CurveTime"],"0040":["US","1","DataSetType"],"0041":["LO","1","DataSetSubtype"],"0042":["CS","1","NuclearMedicineSeriesType"],"0050":["SH","1","AccessionNumber"],"0051":["SQ","1","IssuerOfAccessionNumberSequence"],"0052":["CS","1","QueryRetrieveLevel"],"0053":["CS","1","QueryRetrieveView"],"0054":["AE","1-n","RetrieveAETitle"],"0055":["AE","1","StationAETitle"],"0056":["CS","1","InstanceAvailability"],"0058":["UI","1-n","FailedSOPInstanceUIDList"],"0060":["CS","1","Modality"],"0061":["CS","1-n","ModalitiesInStudy"],"0062":["UI","1-n","SOPClassesInStudy"],"0063":["SQ","1","AnatomicRegionsInStudyCodeSequence"],"0064":["CS","1","ConversionType"],"0068":["CS","1","PresentationIntentType"],"0070":["LO","1","Manufacturer"],"0080":["LO","1","InstitutionName"],"0081":["ST","1","InstitutionAddress"],"0082":["SQ","1","InstitutionCodeSequence"],"0090":["PN","1","ReferringPhysicianName"],"0092":["ST","1","ReferringPhysicianAddress"],"0094":["SH","1-n","ReferringPhysicianTelephoneNumbers"],"0096":["SQ","1","ReferringPhysicianIdentificationSequence"],"009C":["PN","1-n","ConsultingPhysicianName"],"009D":["SQ","1","ConsultingPhysicianIdentificationSequence"],"0100":["SH","1","CodeValue"],"0101":["LO","1","ExtendedCodeValue"],"0102":["SH","1","CodingSchemeDesignator"],"0103":["SH","1","CodingSchemeVersion"],"0104":["LO","1","CodeMeaning"],"0105":["CS","1","MappingResource"],"0106":["DT","1","ContextGroupVersion"],"0107":["DT","1","ContextGroupLocalVersion"],"0108":["LT","1","ExtendedCodeMeaning"],"0109":["SQ","1","CodingSchemeResourcesSequence"],"010A":["CS","1","CodingSchemeURLType"],"010B":["CS","1","ContextGroupExtensionFlag"],"010C":["UI","1","CodingSchemeUID"],"010D":["UI","1","ContextGroupExtensionCreatorUID"],"010E":["UR","1","CodingSchemeURL"],"010F":["CS","1","ContextIdentifier"],"0110":["SQ","1","CodingSchemeIdentificationSequence"],"0112":["LO","1","CodingSchemeRegistry"],"0114":["ST","1","CodingSchemeExternalID"],"0115":["ST","1","CodingSchemeName"],"0116":["ST","1","CodingSchemeResponsibleOrganization"],"0117":["UI","1","ContextUID"],"0118":["UI","1","MappingResourceUID"],"0119":["UC","1","LongCodeValue"],"0120":["UR","1","URNCodeValue"],"0121":["SQ","1","EquivalentCodeSequence"],"0122":["LO","1","MappingResourceName"],"0123":["SQ","1","ContextGroupIdentificationSequence"],"0124":["SQ","1","MappingResourceIdentificationSequence"],"0201":["SH","1","TimezoneOffsetFromUTC"],"0202":["","",""],"0220":["SQ","1","ResponsibleGroupCodeSequence"],"0221":["CS","1","EquipmentModality"],"0222":["LO","1","ManufacturerRelatedModelGroup"],"0300":["SQ","1","PrivateDataElementCharacteristicsSequence"],"0301":["US","1","PrivateGroupReference"],"0302":["LO","1","PrivateCreatorReference"],"0303":["CS","1","BlockIdentifyingInformationStatus"],"0304":["US","1-n","NonidentifyingPrivateElements"],"0305":["SQ","1","DeidentificationActionSequence"],"0306":["US","1-n","IdentifyingPrivateElements"],"0307":["CS","1","DeidentificationAction"],"0308":["US","1","PrivateDataElement"],"0309":["UL","1-3","PrivateDataElementValueMultiplicity"],"030A":["CS","1","PrivateDataElementValueRepresentation"],"030B":["UL","1-2","PrivateDataElementNumberOfItems"],"030C":["UC","1","PrivateDataElementName"],"030D":["UC","1","PrivateDataElementKeyword"],"030E":["UT","1","PrivateDataElementDescription"],"030F":["UT","1","PrivateDataElementEncoding"],"0310":["SQ","1","PrivateDataElementDefinitionSequence"],1e3:["AE","1","NetworkID"],1010:["SH","1","StationName"],1030:["LO","1","StudyDescription"],1032:["SQ","1","ProcedureCodeSequence"],"103E":["LO","1","SeriesDescription"],"103F":["SQ","1","SeriesDescriptionCodeSequence"],1040:["LO","1","InstitutionalDepartmentName"],1041:["SQ","1","InstitutionalDepartmentTypeCodeSequence"],1048:["PN","1-n","PhysiciansOfRecord"],1049:["SQ","1","PhysiciansOfRecordIdentificationSequence"],1050:["PN","1-n","PerformingPhysicianName"],1052:["SQ","1","PerformingPhysicianIdentificationSequence"],1060:["PN","1-n","NameOfPhysiciansReadingStudy"],1062:["SQ","1","PhysiciansReadingStudyIdentificationSequence"],1070:["PN","1-n","OperatorsName"],1072:["SQ","1","OperatorIdentificationSequence"],1080:["LO","1-n","AdmittingDiagnosesDescription"],1084:["SQ","1","AdmittingDiagnosesCodeSequence"],1090:["LO","1","ManufacturerModelName"],1100:["SQ","1","ReferencedResultsSequence"],1110:["SQ","1","ReferencedStudySequence"],1111:["SQ","1","ReferencedPerformedProcedureStepSequence"],1115:["SQ","1","ReferencedSeriesSequence"],1120:["SQ","1","ReferencedPatientSequence"],1125:["SQ","1","ReferencedVisitSequence"],1130:["SQ","1","ReferencedOverlaySequence"],1134:["SQ","1","ReferencedStereometricInstanceSequence"],"113A":["SQ","1","ReferencedWaveformSequence"],1140:["SQ","1","ReferencedImageSequence"],1145:["SQ","1","ReferencedCurveSequence"],"114A":["SQ","1","ReferencedInstanceSequence"],"114B":["SQ","1","ReferencedRealWorldValueMappingInstanceSequence"],1150:["UI","1","ReferencedSOPClassUID"],1155:["UI","1","ReferencedSOPInstanceUID"],1156:["SQ","1","DefinitionSourceSequence"],"115A":["UI","1-n","SOPClassesSupported"],1160:["IS","1-n","ReferencedFrameNumber"],1161:["UL","1-n","SimpleFrameList"],1162:["UL","3-3n","CalculatedFrameList"],1163:["FD","2","TimeRange"],1164:["SQ","1","FrameExtractionSequence"],1167:["UI","1","MultiFrameSourceSOPInstanceUID"],1190:["UR","1","RetrieveURL"],1195:["UI","1","TransactionUID"],1196:["US","1","WarningReason"],1197:["US","1","FailureReason"],1198:["SQ","1","FailedSOPSequence"],1199:["SQ","1","ReferencedSOPSequence"],"119A":["SQ","1","OtherFailuresSequence"],1200:["SQ","1","StudiesContainingOtherReferencedInstancesSequence"],1250:["SQ","1","RelatedSeriesSequence"],2110:["CS","1","LossyImageCompressionRetired"],2111:["ST","1","DerivationDescription"],2112:["SQ","1","SourceImageSequence"],2120:["SH","1","StageName"],2122:["IS","1","StageNumber"],2124:["IS","1","NumberOfStages"],2127:["SH","1","ViewName"],2128:["IS","1","ViewNumber"],2129:["IS","1","NumberOfEventTimers"],"212A":["IS","1","NumberOfViewsInStage"],2130:["DS","1-n","EventElapsedTimes"],2132:["LO","1-n","EventTimerNames"],2133:["SQ","1","EventTimerSequence"],2134:["FD","1","EventTimeOffset"],2135:["SQ","1","EventCodeSequence"],2142:["IS","1","StartTrim"],2143:["IS","1","StopTrim"],2144:["IS","1","RecommendedDisplayFrameRate"],2200:["CS","1","TransducerPosition"],2204:["CS","1","TransducerOrientation"],2208:["CS","1","AnatomicStructure"],2218:["SQ","1","AnatomicRegionSequence"],2220:["SQ","1","AnatomicRegionModifierSequence"],2228:["SQ","1","PrimaryAnatomicStructureSequence"],2229:["SQ","1","AnatomicStructureSpaceOrRegionSequence"],2230:["SQ","1","PrimaryAnatomicStructureModifierSequence"],2240:["SQ","1","TransducerPositionSequence"],2242:["SQ","1","TransducerPositionModifierSequence"],2244:["SQ","1","TransducerOrientationSequence"],2246:["SQ","1","TransducerOrientationModifierSequence"],2251:["SQ","1","AnatomicStructureSpaceOrRegionCodeSequenceTrial"],2253:["SQ","1","AnatomicPortalOfEntranceCodeSequenceTrial"],2255:["SQ","1","AnatomicApproachDirectionCodeSequenceTrial"],2256:["ST","1","AnatomicPerspectiveDescriptionTrial"],2257:["SQ","1","AnatomicPerspectiveCodeSequenceTrial"],2258:["ST","1","AnatomicLocationOfExaminingInstrumentDescriptionTrial"],2259:["SQ","1","AnatomicLocationOfExaminingInstrumentCodeSequenceTrial"],"225A":["SQ","1","AnatomicStructureSpaceOrRegionModifierCodeSequenceTrial"],"225C":["SQ","1","OnAxisBackgroundAnatomicStructureCodeSequenceTrial"],3001:["SQ","1","AlternateRepresentationSequence"],3002:["UI","1-n","AvailableTransferSyntaxUID"],3010:["UI","1-n","IrradiationEventUID"],3011:["SQ","1","SourceIrradiationEventSequence"],3012:["UI","1","RadiopharmaceuticalAdministrationEventUID"],4e3:["LT","1","IdentifyingComments"],9007:["CS","4","FrameType"],9092:["SQ","1","ReferencedImageEvidenceSequence"],9121:["SQ","1","ReferencedRawDataSequence"],9123:["UI","1","CreatorVersionUID"],9124:["SQ","1","DerivationImageSequence"],9154:["SQ","1","SourceImageEvidenceSequence"],9205:["CS","1","PixelPresentation"],9206:["CS","1","VolumetricProperties"],9207:["CS","1","VolumeBasedCalculationTechnique"],9208:["CS","1","ComplexImageComponent"],9209:["CS","1","AcquisitionContrast"],9215:["SQ","1","DerivationCodeSequence"],9237:["SQ","1","ReferencedPresentationStateSequence"],9410:["SQ","1","ReferencedOtherPlaneSequence"],9458:["SQ","1","FrameDisplaySequence"],9459:["FL","1","RecommendedDisplayFrameRateInFloat"],9460:["CS","1","SkipFrameRangeFlag"]},"0010":{"0000":["UL","1","GenericGroupLength"],"0010":["PN","1","PatientName"],"0020":["LO","1","PatientID"],"0021":["LO","1","IssuerOfPatientID"],"0022":["CS","1","TypeOfPatientID"],"0024":["SQ","1","IssuerOfPatientIDQualifiersSequence"],"0026":["SQ","1","SourcePatientGroupIdentificationSequence"],"0027":["SQ","1","GroupOfPatientsIdentificationSequence"],"0028":["US","3","SubjectRelativePositionInImage"],"0030":["DA","1","PatientBirthDate"],"0032":["TM","1","PatientBirthTime"],"0033":["LO","1","PatientBirthDateInAlternativeCalendar"],"0034":["LO","1","PatientDeathDateInAlternativeCalendar"],"0035":["CS","1","PatientAlternativeCalendar"],"0040":["CS","1","PatientSex"],"0050":["SQ","1","PatientInsurancePlanCodeSequence"],"0101":["SQ","1","PatientPrimaryLanguageCodeSequence"],"0102":["SQ","1","PatientPrimaryLanguageModifierCodeSequence"],"0200":["CS","1","QualityControlSubject"],"0201":["SQ","1","QualityControlSubjectTypeCodeSequence"],"0212":["UC","1","StrainDescription"],"0213":["LO","1","StrainNomenclature"],"0214":["LO","1","StrainStockNumber"],"0215":["SQ","1","StrainSourceRegistryCodeSequence"],"0216":["SQ","1","StrainStockSequence"],"0217":["LO","1","StrainSource"],"0218":["UT","1","StrainAdditionalInformation"],"0219":["SQ","1","StrainCodeSequence"],"0221":["SQ","1","GeneticModificationsSequence"],"0222":["UC","1","GeneticModificationsDescription"],"0223":["LO","1","GeneticModificationsNomenclature"],"0229":["SQ","1","GeneticModificationsCodeSequence"],1e3:["LO","1-n","OtherPatientIDs"],1001:["PN","1-n","OtherPatientNames"],1002:["SQ","1","OtherPatientIDsSequence"],1005:["PN","1","PatientBirthName"],1010:["AS","1","PatientAge"],1020:["DS","1","PatientSize"],1021:["SQ","1","PatientSizeCodeSequence"],1022:["DS","1","PatientBodyMassIndex"],1023:["DS","1","MeasuredAPDimension"],1024:["DS","1","MeasuredLateralDimension"],1030:["DS","1","PatientWeight"],1040:["LO","1","PatientAddress"],1050:["LO","1-n","InsurancePlanIdentification"],1060:["PN","1","PatientMotherBirthName"],1080:["LO","1","MilitaryRank"],1081:["LO","1","BranchOfService"],1090:["LO","1","MedicalRecordLocator"],1100:["SQ","1","ReferencedPatientPhotoSequence"],2e3:["LO","1-n","MedicalAlerts"],2110:["LO","1-n","Allergies"],2150:["LO","1","CountryOfResidence"],2152:["LO","1","RegionOfResidence"],2154:["SH","1-n","PatientTelephoneNumbers"],2155:["LT","1","PatientTelecomInformation"],2160:["SH","1","EthnicGroup"],2180:["SH","1","Occupation"],"21A0":["CS","1","SmokingStatus"],"21B0":["LT","1","AdditionalPatientHistory"],"21C0":["US","1","PregnancyStatus"],"21D0":["DA","1","LastMenstrualDate"],"21F0":["LO","1","PatientReligiousPreference"],2201:["LO","1","PatientSpeciesDescription"],2202:["SQ","1","PatientSpeciesCodeSequence"],2203:["CS","1","PatientSexNeutered"],2210:["CS","1","AnatomicalOrientationType"],2292:["LO","1","PatientBreedDescription"],2293:["SQ","1","PatientBreedCodeSequence"],2294:["SQ","1","BreedRegistrationSequence"],2295:["LO","1","BreedRegistrationNumber"],2296:["SQ","1","BreedRegistryCodeSequence"],2297:["PN","1","ResponsiblePerson"],2298:["CS","1","ResponsiblePersonRole"],2299:["LO","1","ResponsibleOrganization"],4e3:["LT","1","PatientComments"],9431:["FL","1","ExaminedBodyThickness"]},"0012":{"0000":["UL","1","GenericGroupLength"],"0010":["LO","1","ClinicalTrialSponsorName"],"0020":["LO","1","ClinicalTrialProtocolID"],"0021":["LO","1","ClinicalTrialProtocolName"],"0030":["LO","1","ClinicalTrialSiteID"],"0031":["LO","1","ClinicalTrialSiteName"],"0040":["LO","1","ClinicalTrialSubjectID"],"0042":["LO","1","ClinicalTrialSubjectReadingID"],"0050":["LO","1","ClinicalTrialTimePointID"],"0051":["ST","1","ClinicalTrialTimePointDescription"],"0052":["FD","1","LongitudinalTemporalOffsetFromEvent"],"0053":["CS","1","LongitudinalTemporalEventType"],"0060":["LO","1","ClinicalTrialCoordinatingCenterName"],"0062":["CS","1","PatientIdentityRemoved"],"0063":["LO","1-n","DeidentificationMethod"],"0064":["SQ","1","DeidentificationMethodCodeSequence"],"0071":["LO","1","ClinicalTrialSeriesID"],"0072":["LO","1","ClinicalTrialSeriesDescription"],"0081":["LO","1","ClinicalTrialProtocolEthicsCommitteeName"],"0082":["LO","1","ClinicalTrialProtocolEthicsCommitteeApprovalNumber"],"0083":["SQ","1","ConsentForClinicalTrialUseSequence"],"0084":["CS","1","DistributionType"],"0085":["CS","1","ConsentForDistributionFlag"],"0086":["DA","1","EthicsCommitteeApprovalEffectivenessStartDate"],"0087":["DA","1","EthicsCommitteeApprovalEffectivenessEndDate"]},"0014":{"0000":["UL","1","GenericGroupLength"],"0023":["ST","1","CADFileFormat"],"0024":["ST","1","ComponentReferenceSystem"],"0025":["ST","1","ComponentManufacturingProcedure"],"0028":["ST","1","ComponentManufacturer"],"0030":["DS","1-n","MaterialThickness"],"0032":["DS","1-n","MaterialPipeDiameter"],"0034":["DS","1-n","MaterialIsolationDiameter"],"0042":["ST","1","MaterialGrade"],"0044":["ST","1","MaterialPropertiesDescription"],"0045":["ST","1","MaterialPropertiesFileFormatRetired"],"0046":["LT","1","MaterialNotes"],"0050":["CS","1","ComponentShape"],"0052":["CS","1","CurvatureType"],"0054":["DS","1","OuterDiameter"],"0056":["DS","1","InnerDiameter"],"0100":["LO","1-n","ComponentWelderIDs"],"0101":["CS","1","SecondaryApprovalStatus"],"0102":["DA","1","SecondaryReviewDate"],"0103":["TM","1","SecondaryReviewTime"],"0104":["PN","1","SecondaryReviewerName"],"0105":["ST","1","RepairID"],"0106":["SQ","1","MultipleComponentApprovalSequence"],"0107":["CS","1-n","OtherApprovalStatus"],"0108":["CS","1-n","OtherSecondaryApprovalStatus"],1010:["ST","1","ActualEnvironmentalConditions"],1020:["DA","1","ExpiryDate"],1040:["ST","1","EnvironmentalConditions"],2002:["SQ","1","EvaluatorSequence"],2004:["IS","1","EvaluatorNumber"],2006:["PN","1","EvaluatorName"],2008:["IS","1","EvaluationAttempt"],2012:["SQ","1","IndicationSequence"],2014:["IS","1","IndicationNumber"],2016:["SH","1","IndicationLabel"],2018:["ST","1","IndicationDescription"],"201A":["CS","1-n","IndicationType"],"201C":["CS","1","IndicationDisposition"],"201E":["SQ","1","IndicationROISequence"],2030:["SQ","1","IndicationPhysicalPropertySequence"],2032:["SH","1","PropertyLabel"],2202:["IS","1","CoordinateSystemNumberOfAxes"],2204:["SQ","1","CoordinateSystemAxesSequence"],2206:["ST","1","CoordinateSystemAxisDescription"],2208:["CS","1","CoordinateSystemDataSetMapping"],"220A":["IS","1","CoordinateSystemAxisNumber"],"220C":["CS","1","CoordinateSystemAxisType"],"220E":["CS","1","CoordinateSystemAxisUnits"],2210:["OB","1","CoordinateSystemAxisValues"],2220:["SQ","1","CoordinateSystemTransformSequence"],2222:["ST","1","TransformDescription"],2224:["IS","1","TransformNumberOfAxes"],2226:["IS","1-n","TransformOrderOfAxes"],2228:["CS","1","TransformedAxisUnits"],"222A":["DS","1-n","CoordinateSystemTransformRotationAndScaleMatrix"],"222C":["DS","1-n","CoordinateSystemTransformTranslationMatrix"],3011:["DS","1","InternalDetectorFrameTime"],3012:["DS","1","NumberOfFramesIntegrated"],3020:["SQ","1","DetectorTemperatureSequence"],3022:["ST","1","SensorName"],3024:["DS","1","HorizontalOffsetOfSensor"],3026:["DS","1","VerticalOffsetOfSensor"],3028:["DS","1","SensorTemperature"],3040:["SQ","1","DarkCurrentSequence"],3050:["ox","1","DarkCurrentCounts"],3060:["SQ","1","GainCorrectionReferenceSequence"],3070:["ox","1","AirCounts"],3071:["DS","1","KVUsedInGainCalibration"],3072:["DS","1","MAUsedInGainCalibration"],3073:["DS","1","NumberOfFramesUsedForIntegration"],3074:["LO","1","FilterMaterialUsedInGainCalibration"],3075:["DS","1","FilterThicknessUsedInGainCalibration"],3076:["DA","1","DateOfGainCalibration"],3077:["TM","1","TimeOfGainCalibration"],3080:["OB","1","BadPixelImage"],3099:["LT","1","CalibrationNotes"],3100:["LT","1","LinearityCorrectionTechnique"],3101:["LT","1","BeamHardeningCorrectionTechnique"],4002:["SQ","1","PulserEquipmentSequence"],4004:["CS","1","PulserType"],4006:["LT","1","PulserNotes"],4008:["SQ","1","ReceiverEquipmentSequence"],"400A":["CS","1","AmplifierType"],"400C":["LT","1","ReceiverNotes"],"400E":["SQ","1","PreAmplifierEquipmentSequence"],"400F":["LT","1","PreAmplifierNotes"],4010:["SQ","1","TransmitTransducerSequence"],4011:["SQ","1","ReceiveTransducerSequence"],4012:["US","1","NumberOfElements"],4013:["CS","1","ElementShape"],4014:["DS","1","ElementDimensionA"],4015:["DS","1","ElementDimensionB"],4016:["DS","1","ElementPitchA"],4017:["DS","1","MeasuredBeamDimensionA"],4018:["DS","1","MeasuredBeamDimensionB"],4019:["DS","1","LocationOfMeasuredBeamDiameter"],"401A":["DS","1","NominalFrequency"],"401B":["DS","1","MeasuredCenterFrequency"],"401C":["DS","1","MeasuredBandwidth"],"401D":["DS","1","ElementPitchB"],4020:["SQ","1","PulserSettingsSequence"],4022:["DS","1","PulseWidth"],4024:["DS","1","ExcitationFrequency"],4026:["CS","1","ModulationType"],4028:["DS","1","Damping"],4030:["SQ","1","ReceiverSettingsSequence"],4031:["DS","1","AcquiredSoundpathLength"],4032:["CS","1","AcquisitionCompressionType"],4033:["IS","1","AcquisitionSampleSize"],4034:["DS","1","RectifierSmoothing"],4035:["SQ","1","DACSequence"],4036:["CS","1","DACType"],4038:["DS","1-n","DACGainPoints"],"403A":["DS","1-n","DACTimePoints"],"403C":["DS","1-n","DACAmplitude"],4040:["SQ","1","PreAmplifierSettingsSequence"],4050:["SQ","1","TransmitTransducerSettingsSequence"],4051:["SQ","1","ReceiveTransducerSettingsSequence"],4052:["DS","1","IncidentAngle"],4054:["ST","1","CouplingTechnique"],4056:["ST","1","CouplingMedium"],4057:["DS","1","CouplingVelocity"],4058:["DS","1","ProbeCenterLocationX"],4059:["DS","1","ProbeCenterLocationZ"],"405A":["DS","1","SoundPathLength"],"405C":["ST","1","DelayLawIdentifier"],4060:["SQ","1","GateSettingsSequence"],4062:["DS","1","GateThreshold"],4064:["DS","1","VelocityOfSound"],4070:["SQ","1","CalibrationSettingsSequence"],4072:["ST","1","CalibrationProcedure"],4074:["SH","1","ProcedureVersion"],4076:["DA","1","ProcedureCreationDate"],4078:["DA","1","ProcedureExpirationDate"],"407A":["DA","1","ProcedureLastModifiedDate"],"407C":["TM","1-n","CalibrationTime"],"407E":["DA","1-n","CalibrationDate"],4080:["SQ","1","ProbeDriveEquipmentSequence"],4081:["CS","1","DriveType"],4082:["LT","1","ProbeDriveNotes"],4083:["SQ","1","DriveProbeSequence"],4084:["DS","1","ProbeInductance"],4085:["DS","1","ProbeResistance"],4086:["SQ","1","ReceiveProbeSequence"],4087:["SQ","1","ProbeDriveSettingsSequence"],4088:["DS","1","BridgeResistors"],4089:["DS","1","ProbeOrientationAngle"],"408B":["DS","1","UserSelectedGainY"],"408C":["DS","1","UserSelectedPhase"],"408D":["DS","1","UserSelectedOffsetX"],"408E":["DS","1","UserSelectedOffsetY"],4091:["SQ","1","ChannelSettingsSequence"],4092:["DS","1","ChannelThreshold"],"409A":["SQ","1","ScannerSettingsSequence"],"409B":["ST","1","ScanProcedure"],"409C":["DS","1","TranslationRateX"],"409D":["DS","1","TranslationRateY"],"409F":["DS","1","ChannelOverlap"],"40A0":["LO","1-n","ImageQualityIndicatorType"],"40A1":["LO","1-n","ImageQualityIndicatorMaterial"],"40A2":["LO","1-n","ImageQualityIndicatorSize"],5002:["IS","1","LINACEnergy"],5004:["IS","1","LINACOutput"],5100:["US","1","ActiveAperture"],5101:["DS","1","TotalAperture"],5102:["DS","1","ApertureElevation"],5103:["DS","1","MainLobeAngle"],5104:["DS","1","MainRoofAngle"],5105:["CS","1","ConnectorType"],5106:["SH","1","WedgeModelNumber"],5107:["DS","1","WedgeAngleFloat"],5108:["DS","1","WedgeRoofAngle"],5109:["CS","1","WedgeElement1Position"],"510A":["DS","1","WedgeMaterialVelocity"],"510B":["SH","1","WedgeMaterial"],"510C":["DS","1","WedgeOffsetZ"],"510D":["DS","1","WedgeOriginOffsetX"],"510E":["DS","1","WedgeTimeDelay"],"510F":["SH","1","WedgeName"],5110:["SH","1","WedgeManufacturerName"],5111:["LO","1","WedgeDescription"],5112:["DS","1","NominalBeamAngle"],5113:["DS","1","WedgeOffsetX"],5114:["DS","1","WedgeOffsetY"],5115:["DS","1","WedgeTotalLength"],5116:["DS","1","WedgeInContactLength"],5117:["DS","1","WedgeFrontGap"],5118:["DS","1","WedgeTotalHeight"],5119:["DS","1","WedgeFrontHeight"],"511A":["DS","1","WedgeRearHeight"],"511B":["DS","1","WedgeTotalWidth"],"511C":["DS","1","WedgeInContactWidth"],"511D":["DS","1","WedgeChamferHeight"],"511E":["CS","1","WedgeCurve"],"511F":["DS","1","RadiusAlongWedge"]},"0016":{"0000":["UL","1","GenericGroupLength"],"0001":["DS","1","WhitePoint"],"0002":["DS","3","PrimaryChromaticities"],"0003":["UT","1","BatteryLevel"],"0004":["DS","1","ExposureTimeInSeconds"],"0005":["DS","1","FNumber"],"0006":["IS","1","OECFRows"],"0007":["IS","1","OECFColumns"],"0008":["UC","1-n","OECFColumnNames"],"0009":["DS","1-n","OECFValues"],"000A":["IS","1","SpatialFrequencyResponseRows"],"000B":["IS","1","SpatialFrequencyResponseColumns"],"000C":["UC","1-n","SpatialFrequencyResponseColumnNames"],"000D":["DS","1-n","SpatialFrequencyResponseValues"],"000E":["IS","1","ColorFilterArrayPatternRows"],"000F":["IS","1","ColorFilterArrayPatternColumns"],"0010":["DS","1-n","ColorFilterArrayPatternValues"],"0011":["US","1","FlashFiringStatus"],"0012":["US","1","FlashReturnStatus"],"0013":["US","1","FlashMode"],"0014":["US","1","FlashFunctionPresent"],"0015":["US","1","FlashRedEyeMode"],"0016":["US","1","ExposureProgram"],"0017":["UT","1","SpectralSensitivity"],"0018":["IS","1","PhotographicSensitivity"],"0019":["IS","1","SelfTimerMode"],"001A":["US","1","SensitivityType"],"001B":["IS","1","StandardOutputSensitivity"],"001C":["IS","1","RecommendedExposureIndex"],"001D":["IS","1","ISOSpeed"],"001E":["IS","1","ISOSpeedLatitudeyyy"],"001F":["IS","1","ISOSpeedLatitudezzz"],"0020":["UT","1","EXIFVersion"],"0021":["DS","1","ShutterSpeedValue"],"0022":["DS","1","ApertureValue"],"0023":["DS","1","BrightnessValue"],"0024":["DS","1","ExposureBiasValue"],"0025":["DS","1","MaxApertureValue"],"0026":["DS","1","SubjectDistance"],"0027":["US","1","MeteringMode"],"0028":["US","1","LightSource"],"0029":["DS","1","FocalLength"],"002A":["IS","2-4","SubjectArea"],"002B":["OB","1","MakerNote"],"0030":["DS","1","Temperature"],"0031":["DS","1","Humidity"],"0032":["DS","1","Pressure"],"0033":["DS","1","WaterDepth"],"0034":["DS","1","Acceleration"],"0035":["DS","1","CameraElevationAngle"],"0036":["DS","1-2","FlashEnergy"],"0037":["IS","2","SubjectLocation"],"0038":["DS","1","PhotographicExposureIndex"],"0039":["US","1","SensingMethod"],"003A":["US","1","FileSource"],"003B":["US","1","SceneType"],"0041":["US","1","CustomRendered"],"0042":["US","1","ExposureMode"],"0043":["US","1","WhiteBalance"],"0044":["DS","1","DigitalZoomRatio"],"0045":["IS","1","FocalLengthIn35mmFilm"],"0046":["US","1","SceneCaptureType"],"0047":["US","1","GainControl"],"0048":["US","1","Contrast"],"0049":["US","1","Saturation"],"004A":["US","1","Sharpness"],"004B":["OB","1","DeviceSettingDescription"],"004C":["US","1","SubjectDistanceRange"],"004D":["UT","1","CameraOwnerName"],"004E":["DS","4","LensSpecification"],"004F":["UT","1","LensMake"],"0050":["UT","1","LensModel"],"0051":["UT","1","LensSerialNumber"],"0061":["CS","1","InteroperabilityIndex"],"0062":["OB","1","InteroperabilityVersion"],"0070":["OB","1","GPSVersionID"],"0071":["CS","1","GPSLatitudeRef"],"0072":["DS","3","GPSLatitude"],"0073":["CS","1","GPSLongitudeRef"],"0074":["DS","3","GPSLongitude"],"0075":["US","1","GPSAltitudeRef"],"0076":["DS","1","GPSAltitude"],"0077":["DT","1","GPSTimeStamp"],"0078":["UT","1","GPSSatellites"],"0079":["CS","1","GPSStatus"],"007A":["CS","1","GPSMeasureMode"],"007B":["DS","1","GPSDOP"],"007C":["CS","1","GPSSpeedRef"],"007D":["DS","1","GPSSpeed"],"007E":["CS","1","GPSTrackRef"],"007F":["DS","1","GPSTrack"],"0080":["CS","1","GPSImgDirectionRef"],"0081":["DS","1","GPSImgDirection"],"0082":["UT","1","GPSMapDatum"],"0083":["CS","1","GPSDestLatitudeRef"],"0084":["DS","3","GPSDestLatitude"],"0085":["CS","1","GPSDestLongitudeRef"],"0086":["DS","3","GPSDestLongitude"],"0087":["CS","1","GPSDestBearingRef"],"0088":["DS","1","GPSDestBearing"],"0089":["CS","1","GPSDestDistanceRef"],"008A":["DS","1","GPSDestDistance"],"008B":["OB","1","GPSProcessingMethod"],"008C":["OB","1","GPSAreaInformation"],"008D":["DT","1","GPSDateStamp"],"008E":["IS","1","GPSDifferential"],1001:["CS","1","LightSourcePolarization"],1002:["DS","1","EmitterColorTemperature"],1003:["CS","1","ContactMethod"],1004:["CS","1-n","ImmersionMedia"],1005:["DS","1","OpticalMagnificationFactor"]},"0018":{"0000":["UL","1","GenericGroupLength"],"0010":["LO","1","ContrastBolusAgent"],"0012":["SQ","1","ContrastBolusAgentSequence"],"0013":["FL","1","ContrastBolusT1Relaxivity"],"0014":["SQ","1","ContrastBolusAdministrationRouteSequence"],"0015":["CS","1","BodyPartExamined"],"0020":["CS","1-n","ScanningSequence"],"0021":["CS","1-n","SequenceVariant"],"0022":["CS","1-n","ScanOptions"],"0023":["CS","1","MRAcquisitionType"],"0024":["SH","1","SequenceName"],"0025":["CS","1","AngioFlag"],"0026":["SQ","1","InterventionDrugInformationSequence"],"0027":["TM","1","InterventionDrugStopTime"],"0028":["DS","1","InterventionDrugDose"],"0029":["SQ","1","InterventionDrugCodeSequence"],"002A":["SQ","1","AdditionalDrugSequence"],"0030":["LO","1-n","Radionuclide"],"0031":["LO","1","Radiopharmaceutical"],"0032":["DS","1","EnergyWindowCenterline"],"0033":["DS","1-n","EnergyWindowTotalWidth"],"0034":["LO","1","InterventionDrugName"],"0035":["TM","1","InterventionDrugStartTime"],"0036":["SQ","1","InterventionSequence"],"0037":["CS","1","TherapyType"],"0038":["CS","1","InterventionStatus"],"0039":["CS","1","TherapyDescription"],"003A":["ST","1","InterventionDescription"],"0040":["IS","1","CineRate"],"0042":["CS","1","InitialCineRunState"],"0050":["DS","1","SliceThickness"],"0060":["DS","1","KVP"],"0061":["DS","1",""],"0070":["IS","1","CountsAccumulated"],"0071":["CS","1","AcquisitionTerminationCondition"],"0072":["DS","1","EffectiveDuration"],"0073":["CS","1","AcquisitionStartCondition"],"0074":["IS","1","AcquisitionStartConditionData"],"0075":["IS","1","AcquisitionTerminationConditionData"],"0080":["DS","1","RepetitionTime"],"0081":["DS","1","EchoTime"],"0082":["DS","1","InversionTime"],"0083":["DS","1","NumberOfAverages"],"0084":["DS","1","ImagingFrequency"],"0085":["SH","1","ImagedNucleus"],"0086":["IS","1-n","EchoNumbers"],"0087":["DS","1","MagneticFieldStrength"],"0088":["DS","1","SpacingBetweenSlices"],"0089":["IS","1","NumberOfPhaseEncodingSteps"],"0090":["DS","1","DataCollectionDiameter"],"0091":["IS","1","EchoTrainLength"],"0093":["DS","1","PercentSampling"],"0094":["DS","1","PercentPhaseFieldOfView"],"0095":["DS","1","PixelBandwidth"],1e3:["LO","1","DeviceSerialNumber"],1002:["UI","1","DeviceUID"],1003:["LO","1","DeviceID"],1004:["LO","1","PlateID"],1005:["LO","1","GeneratorID"],1006:["LO","1","GridID"],1007:["LO","1","CassetteID"],1008:["LO","1","GantryID"],1009:["UT","1","UniqueDeviceIdentifier"],"100A":["SQ","1","UDISequence"],"100B":["UI","1-n","ManufacturerDeviceClassUID"],1010:["LO","1","SecondaryCaptureDeviceID"],1011:["LO","1","HardcopyCreationDeviceID"],1012:["DA","1","DateOfSecondaryCapture"],1014:["TM","1","TimeOfSecondaryCapture"],1016:["LO","1","SecondaryCaptureDeviceManufacturer"],1017:["LO","1","HardcopyDeviceManufacturer"],1018:["LO","1","SecondaryCaptureDeviceManufacturerModelName"],1019:["LO","1-n","SecondaryCaptureDeviceSoftwareVersions"],"101A":["LO","1-n","HardcopyDeviceSoftwareVersion"],"101B":["LO","1","HardcopyDeviceManufacturerModelName"],1020:["LO","1-n","SoftwareVersions"],1022:["SH","1","VideoImageFormatAcquired"],1023:["LO","1","DigitalImageFormatAcquired"],1030:["LO","1","ProtocolName"],1040:["LO","1","ContrastBolusRoute"],1041:["DS","1","ContrastBolusVolume"],1042:["TM","1","ContrastBolusStartTime"],1043:["TM","1","ContrastBolusStopTime"],1044:["DS","1","ContrastBolusTotalDose"],1045:["IS","1","SyringeCounts"],1046:["DS","1-n","ContrastFlowRate"],1047:["DS","1-n","ContrastFlowDuration"],1048:["CS","1","ContrastBolusIngredient"],1049:["DS","1","ContrastBolusIngredientConcentration"],1050:["DS","1","SpatialResolution"],1060:["DS","1","TriggerTime"],1061:["LO","1","TriggerSourceOrType"],1062:["IS","1","NominalInterval"],1063:["DS","1","FrameTime"],1064:["LO","1","CardiacFramingType"],1065:["DS","1-n","FrameTimeVector"],1066:["DS","1","FrameDelay"],1067:["DS","1","ImageTriggerDelay"],1068:["DS","1","MultiplexGroupTimeOffset"],1069:["DS","1","TriggerTimeOffset"],"106A":["CS","1","SynchronizationTrigger"],"106C":["US","2","SynchronizationChannel"],"106E":["UL","1","TriggerSamplePosition"],1070:["LO","1","RadiopharmaceuticalRoute"],1071:["DS","1","RadiopharmaceuticalVolume"],1072:["TM","1","RadiopharmaceuticalStartTime"],1073:["TM","1","RadiopharmaceuticalStopTime"],1074:["DS","1","RadionuclideTotalDose"],1075:["DS","1","RadionuclideHalfLife"],1076:["DS","1","RadionuclidePositronFraction"],1077:["DS","1","RadiopharmaceuticalSpecificActivity"],1078:["DT","1","RadiopharmaceuticalStartDateTime"],1079:["DT","1","RadiopharmaceuticalStopDateTime"],1080:["CS","1","BeatRejectionFlag"],1081:["IS","1","LowRRValue"],1082:["IS","1","HighRRValue"],1083:["IS","1","IntervalsAcquired"],1084:["IS","1","IntervalsRejected"],1085:["LO","1","PVCRejection"],1086:["IS","1","SkipBeats"],1088:["IS","1","HeartRate"],1090:["IS","1","CardiacNumberOfImages"],1094:["IS","1","TriggerWindow"],1100:["DS","1","ReconstructionDiameter"],1110:["DS","1","DistanceSourceToDetector"],1111:["DS","1","DistanceSourceToPatient"],1114:["DS","1","EstimatedRadiographicMagnificationFactor"],1120:["DS","1","GantryDetectorTilt"],1121:["DS","1","GantryDetectorSlew"],1130:["DS","1","TableHeight"],1131:["DS","1","TableTraverse"],1134:["CS","1","TableMotion"],1135:["DS","1-n","TableVerticalIncrement"],1136:["DS","1-n","TableLateralIncrement"],1137:["DS","1-n","TableLongitudinalIncrement"],1138:["DS","1","TableAngle"],"113A":["CS","1","TableType"],1140:["CS","1","RotationDirection"],1141:["DS","1","AngularPosition"],1142:["DS","1-n","RadialPosition"],1143:["DS","1","ScanArc"],1144:["DS","1","AngularStep"],1145:["DS","1","CenterOfRotationOffset"],1146:["DS","1-n","RotationOffset"],1147:["CS","1","FieldOfViewShape"],1149:["IS","1-2","FieldOfViewDimensions"],1150:["IS","1","ExposureTime"],1151:["IS","1","XRayTubeCurrent"],1152:["IS","1","Exposure"],1153:["IS","1","ExposureInuAs"],1154:["DS","1","AveragePulseWidth"],1155:["CS","1","RadiationSetting"],1156:["CS","1","RectificationType"],"115A":["CS","1","RadiationMode"],"115E":["DS","1","ImageAndFluoroscopyAreaDoseProduct"],1160:["SH","1","FilterType"],1161:["LO","1-n","TypeOfFilters"],1162:["DS","1","IntensifierSize"],1164:["DS","2","ImagerPixelSpacing"],1166:["CS","1-n","Grid"],1170:["IS","1","GeneratorPower"],1180:["SH","1","CollimatorGridName"],1181:["CS","1","CollimatorType"],1182:["IS","1-2","FocalDistance"],1183:["DS","1-2","XFocusCenter"],1184:["DS","1-2","YFocusCenter"],1190:["DS","1-n","FocalSpots"],1191:["CS","1","AnodeTargetMaterial"],"11A0":["DS","1","BodyPartThickness"],"11A2":["DS","1","CompressionForce"],"11A3":["DS","1","CompressionPressure"],"11A4":["LO","1","PaddleDescription"],"11A5":["DS","1","CompressionContactArea"],"11B0":["LO","1","AcquisitionMode"],"11B1":["LO","1","DoseModeName"],"11B2":["CS","1","AcquiredSubtractionMaskFlag"],"11B3":["CS","1","FluoroscopyPersistenceFlag"],"11B4":["CS","1","FluoroscopyLastImageHoldPersistenceFlag"],"11B5":["IS","1","UpperLimitNumberOfPersistentFluoroscopyFrames"],"11B6":["CS","1","ContrastBolusAutoInjectionTriggerFlag"],"11B7":["FD","1","ContrastBolusInjectionDelay"],"11B8":["SQ","1","XAAcquisitionPhaseDetailsSequence"],"11B9":["FD","1","XAAcquisitionFrameRate"],"11BA":["SQ","1","XAPlaneDetailsSequence"],"11BB":["LO","1","AcquisitionFieldOfViewLabel"],"11BC":["SQ","1","XRayFilterDetailsSequence"],"11BD":["FD","1","XAAcquisitionDuration"],"11BE":["CS","1","ReconstructionPipelineType"],"11BF":["SQ","1","ImageFilterDetailsSequence"],"11C0":["CS","1","AppliedMaskSubtractionFlag"],"11C1":["SQ","1","RequestedSeriesDescriptionCodeSequence"],1200:["DA","1-n","DateOfLastCalibration"],1201:["TM","1-n","TimeOfLastCalibration"],1202:["DT","1","DateTimeOfLastCalibration"],1203:["DT","1","CalibrationDateTime"],1210:["SH","1-n","ConvolutionKernel"],1240:["IS","1-n","UpperLowerPixelValues"],1242:["IS","1","ActualFrameDuration"],1243:["IS","1","CountRate"],1244:["US","1","PreferredPlaybackSequencing"],1250:["SH","1","ReceiveCoilName"],1251:["SH","1","TransmitCoilName"],1260:["SH","1","PlateType"],1261:["LO","1","PhosphorType"],1271:["FD","1","WaterEquivalentDiameter"],1272:["SQ","1","WaterEquivalentDiameterCalculationMethodCodeSequence"],1300:["DS","1","ScanVelocity"],1301:["CS","1-n","WholeBodyTechnique"],1302:["IS","1","ScanLength"],1310:["US","4","AcquisitionMatrix"],1312:["CS","1","InPlanePhaseEncodingDirection"],1314:["DS","1","FlipAngle"],1315:["CS","1","VariableFlipAngleFlag"],1316:["DS","1","SAR"],1318:["DS","1","dBdt"],1320:["FL","1","B1rms"],1400:["LO","1","AcquisitionDeviceProcessingDescription"],1401:["LO","1","AcquisitionDeviceProcessingCode"],1402:["CS","1","CassetteOrientation"],1403:["CS","1","CassetteSize"],1404:["US","1","ExposuresOnPlate"],1405:["IS","1","RelativeXRayExposure"],1411:["DS","1","ExposureIndex"],1412:["DS","1","TargetExposureIndex"],1413:["DS","1","DeviationIndex"],1450:["DS","1","ColumnAngulation"],1460:["DS","1","TomoLayerHeight"],1470:["DS","1","TomoAngle"],1480:["DS","1","TomoTime"],1490:["CS","1","TomoType"],1491:["CS","1","TomoClass"],1495:["IS","1","NumberOfTomosynthesisSourceImages"],1500:["CS","1","PositionerMotion"],1508:["CS","1","PositionerType"],1510:["DS","1","PositionerPrimaryAngle"],1511:["DS","1","PositionerSecondaryAngle"],1520:["DS","1-n","PositionerPrimaryAngleIncrement"],1521:["DS","1-n","PositionerSecondaryAngleIncrement"],1530:["DS","1","DetectorPrimaryAngle"],1531:["DS","1","DetectorSecondaryAngle"],1600:["CS","1-3","ShutterShape"],1602:["IS","1","ShutterLeftVerticalEdge"],1604:["IS","1","ShutterRightVerticalEdge"],1606:["IS","1","ShutterUpperHorizontalEdge"],1608:["IS","1","ShutterLowerHorizontalEdge"],1610:["IS","2","CenterOfCircularShutter"],1612:["IS","1","RadiusOfCircularShutter"],1620:["IS","2-2n","VerticesOfThePolygonalShutter"],1622:["US","1","ShutterPresentationValue"],1623:["US","1","ShutterOverlayGroup"],1624:["US","3","ShutterPresentationColorCIELabValue"],1630:["CS","1","OutlineShapeType"],1631:["FD","1","OutlineLeftVerticalEdge"],1632:["FD","1","OutlineRightVerticalEdge"],1633:["FD","1","OutlineUpperHorizontalEdge"],1634:["FD","1","OutlineLowerHorizontalEdge"],1635:["FD","2","CenterOfCircularOutline"],1636:["FD","1","DiameterOfCircularOutline"],1637:["UL","1","NumberOfPolygonalVertices"],1638:["OF","1","VerticesOfThePolygonalOutline"],1700:["CS","1-3","CollimatorShape"],1702:["IS","1","CollimatorLeftVerticalEdge"],1704:["IS","1","CollimatorRightVerticalEdge"],1706:["IS","1","CollimatorUpperHorizontalEdge"],1708:["IS","1","CollimatorLowerHorizontalEdge"],1710:["IS","2","CenterOfCircularCollimator"],1712:["IS","1","RadiusOfCircularCollimator"],1720:["IS","2-2n","VerticesOfThePolygonalCollimator"],1800:["CS","1","AcquisitionTimeSynchronized"],1801:["SH","1","TimeSource"],1802:["CS","1","TimeDistributionProtocol"],1803:["LO","1","NTPSourceAddress"],2001:["IS","1-n","PageNumberVector"],2002:["SH","1-n","FrameLabelVector"],2003:["DS","1-n","FramePrimaryAngleVector"],2004:["DS","1-n","FrameSecondaryAngleVector"],2005:["DS","1-n","SliceLocationVector"],2006:["SH","1-n","DisplayWindowLabelVector"],2010:["DS","2","NominalScannedPixelSpacing"],2020:["CS","1","DigitizingDeviceTransportDirection"],2030:["DS","1","RotationOfScannedFilm"],2041:["SQ","1","BiopsyTargetSequence"],2042:["UI","1","TargetUID"],2043:["FL","2","LocalizingCursorPosition"],2044:["FL","3","CalculatedTargetPosition"],2045:["SH","1","TargetLabel"],2046:["FL","1","DisplayedZValue"],3100:["CS","1","IVUSAcquisition"],3101:["DS","1","IVUSPullbackRate"],3102:["DS","1","IVUSGatedRate"],3103:["IS","1","IVUSPullbackStartFrameNumber"],3104:["IS","1","IVUSPullbackStopFrameNumber"],3105:["IS","1-n","LesionNumber"],4e3:["LT","1","AcquisitionComments"],5e3:["SH","1-n","OutputPower"],5010:["LO","1-n","TransducerData"],5011:["SQ","1","TransducerIdentificationSequence"],5012:["DS","1","FocusDepth"],5020:["LO","1","ProcessingFunction"],5021:["LO","1","PostprocessingFunction"],5022:["DS","1","MechanicalIndex"],5024:["DS","1","BoneThermalIndex"],5026:["DS","1","CranialThermalIndex"],5027:["DS","1","SoftTissueThermalIndex"],5028:["DS","1","SoftTissueFocusThermalIndex"],5029:["DS","1","SoftTissueSurfaceThermalIndex"],5030:["DS","1","DynamicRange"],5040:["DS","1","TotalGain"],5050:["IS","1","DepthOfScanField"],5100:["CS","1","PatientPosition"],5101:["CS","1","ViewPosition"],5104:["SQ","1","ProjectionEponymousNameCodeSequence"],5210:["DS","6","ImageTransformationMatrix"],5212:["DS","3","ImageTranslationVector"],6e3:["DS","1","Sensitivity"],6011:["SQ","1","SequenceOfUltrasoundRegions"],6012:["US","1","RegionSpatialFormat"],6014:["US","1","RegionDataType"],6016:["UL","1","RegionFlags"],6018:["UL","1","RegionLocationMinX0"],"601A":["UL","1","RegionLocationMinY0"],"601C":["UL","1","RegionLocationMaxX1"],"601E":["UL","1","RegionLocationMaxY1"],6020:["SL","1","ReferencePixelX0"],6022:["SL","1","ReferencePixelY0"],6024:["US","1","PhysicalUnitsXDirection"],6026:["US","1","PhysicalUnitsYDirection"],6028:["FD","1","ReferencePixelPhysicalValueX"],"602A":["FD","1","ReferencePixelPhysicalValueY"],"602C":["FD","1","PhysicalDeltaX"],"602E":["FD","1","PhysicalDeltaY"],6030:["UL","1","TransducerFrequency"],6031:["CS","1","TransducerType"],6032:["UL","1","PulseRepetitionFrequency"],6034:["FD","1","DopplerCorrectionAngle"],6036:["FD","1","SteeringAngle"],6038:["UL","1","DopplerSampleVolumeXPositionRetired"],6039:["SL","1","DopplerSampleVolumeXPosition"],"603A":["UL","1","DopplerSampleVolumeYPositionRetired"],"603B":["SL","1","DopplerSampleVolumeYPosition"],"603C":["UL","1","TMLinePositionX0Retired"],"603D":["SL","1","TMLinePositionX0"],"603E":["UL","1","TMLinePositionY0Retired"],"603F":["SL","1","TMLinePositionY0"],6040:["UL","1","TMLinePositionX1Retired"],6041:["SL","1","TMLinePositionX1"],6042:["UL","1","TMLinePositionY1Retired"],6043:["SL","1","TMLinePositionY1"],6044:["US","1","PixelComponentOrganization"],6046:["UL","1","PixelComponentMask"],6048:["UL","1","PixelComponentRangeStart"],"604A":["UL","1","PixelComponentRangeStop"],"604C":["US","1","PixelComponentPhysicalUnits"],"604E":["US","1","PixelComponentDataType"],6050:["UL","1","NumberOfTableBreakPoints"],6052:["UL","1-n","TableOfXBreakPoints"],6054:["FD","1-n","TableOfYBreakPoints"],6056:["UL","1","NumberOfTableEntries"],6058:["UL","1-n","TableOfPixelValues"],"605A":["FL","1-n","TableOfParameterValues"],6060:["FL","1-n","RWaveTimeVector"],6070:["US","1","ActiveImageAreaOverlayGroup"],7e3:["CS","1","DetectorConditionsNominalFlag"],7001:["DS","1","DetectorTemperature"],7004:["CS","1","DetectorType"],7005:["CS","1","DetectorConfiguration"],7006:["LT","1","DetectorDescription"],7008:["LT","1","DetectorMode"],"700A":["SH","1","DetectorID"],"700C":["DA","1","DateOfLastDetectorCalibration"],"700E":["TM","1","TimeOfLastDetectorCalibration"],7010:["IS","1","ExposuresOnDetectorSinceLastCalibration"],7011:["IS","1","ExposuresOnDetectorSinceManufactured"],7012:["DS","1","DetectorTimeSinceLastExposure"],7014:["DS","1","DetectorActiveTime"],7016:["DS","1","DetectorActivationOffsetFromExposure"],"701A":["DS","2","DetectorBinning"],7020:["DS","2","DetectorElementPhysicalSize"],7022:["DS","2","DetectorElementSpacing"],7024:["CS","1","DetectorActiveShape"],7026:["DS","1-2","DetectorActiveDimensions"],7028:["DS","2","DetectorActiveOrigin"],"702A":["LO","1","DetectorManufacturerName"],"702B":["LO","1","DetectorManufacturerModelName"],7030:["DS","2","FieldOfViewOrigin"],7032:["DS","1","FieldOfViewRotation"],7034:["CS","1","FieldOfViewHorizontalFlip"],7036:["FL","2","PixelDataAreaOriginRelativeToFOV"],7038:["FL","1","PixelDataAreaRotationAngleRelativeToFOV"],7040:["LT","1","GridAbsorbingMaterial"],7041:["LT","1","GridSpacingMaterial"],7042:["DS","1","GridThickness"],7044:["DS","1","GridPitch"],7046:["IS","2","GridAspectRatio"],7048:["DS","1","GridPeriod"],"704C":["DS","1","GridFocalDistance"],7050:["CS","1-n","FilterMaterial"],7052:["DS","1-n","FilterThicknessMinimum"],7054:["DS","1-n","FilterThicknessMaximum"],7056:["FL","1-n","FilterBeamPathLengthMinimum"],7058:["FL","1-n","FilterBeamPathLengthMaximum"],7060:["CS","1","ExposureControlMode"],7062:["LT","1","ExposureControlModeDescription"],7064:["CS","1","ExposureStatus"],7065:["DS","1","PhototimerSetting"],8150:["DS","1","ExposureTimeInuS"],8151:["DS","1","XRayTubeCurrentInuA"],9004:["CS","1","ContentQualification"],9005:["SH","1","PulseSequenceName"],9006:["SQ","1","MRImagingModifierSequence"],9008:["CS","1","EchoPulseSequence"],9009:["CS","1","InversionRecovery"],9010:["CS","1","FlowCompensation"],9011:["CS","1","MultipleSpinEcho"],9012:["CS","1","MultiPlanarExcitation"],9014:["CS","1","PhaseContrast"],9015:["CS","1","TimeOfFlightContrast"],9016:["CS","1","Spoiling"],9017:["CS","1","SteadyStatePulseSequence"],9018:["CS","1","EchoPlanarPulseSequence"],9019:["FD","1","TagAngleFirstAxis"],9020:["CS","1","MagnetizationTransfer"],9021:["CS","1","T2Preparation"],9022:["CS","1","BloodSignalNulling"],9024:["CS","1","SaturationRecovery"],9025:["CS","1","SpectrallySelectedSuppression"],9026:["CS","1","SpectrallySelectedExcitation"],9027:["CS","1","SpatialPresaturation"],9028:["CS","1","Tagging"],9029:["CS","1","OversamplingPhase"],9030:["FD","1","TagSpacingFirstDimension"],9032:["CS","1","GeometryOfKSpaceTraversal"],9033:["CS","1","SegmentedKSpaceTraversal"],9034:["CS","1","RectilinearPhaseEncodeReordering"],9035:["FD","1","TagThickness"],9036:["CS","1","PartialFourierDirection"],9037:["CS","1","CardiacSynchronizationTechnique"],9041:["LO","1","ReceiveCoilManufacturerName"],9042:["SQ","1","MRReceiveCoilSequence"],9043:["CS","1","ReceiveCoilType"],9044:["CS","1","QuadratureReceiveCoil"],9045:["SQ","1","MultiCoilDefinitionSequence"],9046:["LO","1","MultiCoilConfiguration"],9047:["SH","1","MultiCoilElementName"],9048:["CS","1","MultiCoilElementUsed"],9049:["SQ","1","MRTransmitCoilSequence"],9050:["LO","1","TransmitCoilManufacturerName"],9051:["CS","1","TransmitCoilType"],9052:["FD","1-2","SpectralWidth"],9053:["FD","1-2","ChemicalShiftReference"],9054:["CS","1","VolumeLocalizationTechnique"],9058:["US","1","MRAcquisitionFrequencyEncodingSteps"],9059:["CS","1","Decoupling"],9060:["CS","1-2","DecoupledNucleus"],9061:["FD","1-2","DecouplingFrequency"],9062:["CS","1","DecouplingMethod"],9063:["FD","1-2","DecouplingChemicalShiftReference"],9064:["CS","1","KSpaceFiltering"],9065:["CS","1-2","TimeDomainFiltering"],9066:["US","1-2","NumberOfZeroFills"],9067:["CS","1","BaselineCorrection"],9069:["FD","1","ParallelReductionFactorInPlane"],9070:["FD","1","CardiacRRIntervalSpecified"],9073:["FD","1","AcquisitionDuration"],9074:["DT","1","FrameAcquisitionDateTime"],9075:["CS","1","DiffusionDirectionality"],9076:["SQ","1","DiffusionGradientDirectionSequence"],9077:["CS","1","ParallelAcquisition"],9078:["CS","1","ParallelAcquisitionTechnique"],9079:["FD","1-n","InversionTimes"],9080:["ST","1","MetaboliteMapDescription"],9081:["CS","1","PartialFourier"],9082:["FD","1","EffectiveEchoTime"],9083:["SQ","1","MetaboliteMapCodeSequence"],9084:["SQ","1","ChemicalShiftSequence"],9085:["CS","1","CardiacSignalSource"],9087:["FD","1","DiffusionBValue"],9089:["FD","3","DiffusionGradientOrientation"],9090:["FD","3","VelocityEncodingDirection"],9091:["FD","1","VelocityEncodingMinimumValue"],9092:["SQ","1","VelocityEncodingAcquisitionSequence"],9093:["US","1","NumberOfKSpaceTrajectories"],9094:["CS","1","CoverageOfKSpace"],9095:["UL","1","SpectroscopyAcquisitionPhaseRows"],9096:["FD","1","ParallelReductionFactorInPlaneRetired"],9098:["FD","1-2","TransmitterFrequency"],9100:["CS","1-2","ResonantNucleus"],9101:["CS","1","FrequencyCorrection"],9103:["SQ","1","MRSpectroscopyFOVGeometrySequence"],9104:["FD","1","SlabThickness"],9105:["FD","3","SlabOrientation"],9106:["FD","3","MidSlabPosition"],9107:["SQ","1","MRSpatialSaturationSequence"],9112:["SQ","1","MRTimingAndRelatedParametersSequence"],9114:["SQ","1","MREchoSequence"],9115:["SQ","1","MRModifierSequence"],9117:["SQ","1","MRDiffusionSequence"],9118:["SQ","1","CardiacSynchronizationSequence"],9119:["SQ","1","MRAveragesSequence"],9125:["SQ","1","MRFOVGeometrySequence"],9126:["SQ","1","VolumeLocalizationSequence"],9127:["UL","1","SpectroscopyAcquisitionDataColumns"],9147:["CS","1","DiffusionAnisotropyType"],9151:["DT","1","FrameReferenceDateTime"],9152:["SQ","1","MRMetaboliteMapSequence"],9155:["FD","1","ParallelReductionFactorOutOfPlane"],9159:["UL","1","SpectroscopyAcquisitionOutOfPlanePhaseSteps"],9166:["CS","1","BulkMotionStatus"],9168:["FD","1","ParallelReductionFactorSecondInPlane"],9169:["CS","1","CardiacBeatRejectionTechnique"],9170:["CS","1","RespiratoryMotionCompensationTechnique"],9171:["CS","1","RespiratorySignalSource"],9172:["CS","1","BulkMotionCompensationTechnique"],9173:["CS","1","BulkMotionSignalSource"],9174:["CS","1","ApplicableSafetyStandardAgency"],9175:["LO","1","ApplicableSafetyStandardDescription"],9176:["SQ","1","OperatingModeSequence"],9177:["CS","1","OperatingModeType"],9178:["CS","1","OperatingMode"],9179:["CS","1","SpecificAbsorptionRateDefinition"],9180:["CS","1","GradientOutputType"],9181:["FD","1","SpecificAbsorptionRateValue"],9182:["FD","1","GradientOutput"],9183:["CS","1","FlowCompensationDirection"],9184:["FD","1","TaggingDelay"],9185:["ST","1","RespiratoryMotionCompensationTechniqueDescription"],9186:["SH","1","RespiratorySignalSourceID"],9195:["FD","1","ChemicalShiftMinimumIntegrationLimitInHz"],9196:["FD","1","ChemicalShiftMaximumIntegrationLimitInHz"],9197:["SQ","1","MRVelocityEncodingSequence"],9198:["CS","1","FirstOrderPhaseCorrection"],9199:["CS","1","WaterReferencedPhaseCorrection"],9200:["CS","1","MRSpectroscopyAcquisitionType"],9214:["CS","1","RespiratoryCyclePosition"],9217:["FD","1","VelocityEncodingMaximumValue"],9218:["FD","1","TagSpacingSecondDimension"],9219:["SS","1","TagAngleSecondAxis"],9220:["FD","1","FrameAcquisitionDuration"],9226:["SQ","1","MRImageFrameTypeSequence"],9227:["SQ","1","MRSpectroscopyFrameTypeSequence"],9231:["US","1","MRAcquisitionPhaseEncodingStepsInPlane"],9232:["US","1","MRAcquisitionPhaseEncodingStepsOutOfPlane"],9234:["UL","1","SpectroscopyAcquisitionPhaseColumns"],9236:["CS","1","CardiacCyclePosition"],9239:["SQ","1","SpecificAbsorptionRateSequence"],9240:["US","1","RFEchoTrainLength"],9241:["US","1","GradientEchoTrainLength"],9250:["CS","1","ArterialSpinLabelingContrast"],9251:["SQ","1","MRArterialSpinLabelingSequence"],9252:["LO","1","ASLTechniqueDescription"],9253:["US","1","ASLSlabNumber"],9254:["FD","1","ASLSlabThickness"],9255:["FD","3","ASLSlabOrientation"],9256:["FD","3","ASLMidSlabPosition"],9257:["CS","1","ASLContext"],9258:["UL","1","ASLPulseTrainDuration"],9259:["CS","1","ASLCrusherFlag"],"925A":["FD","1","ASLCrusherFlowLimit"],"925B":["LO","1","ASLCrusherDescription"],"925C":["CS","1","ASLBolusCutoffFlag"],"925D":["SQ","1","ASLBolusCutoffTimingSequence"],"925E":["LO","1","ASLBolusCutoffTechnique"],"925F":["UL","1","ASLBolusCutoffDelayTime"],9260:["SQ","1","ASLSlabSequence"],9295:["FD","1","ChemicalShiftMinimumIntegrationLimitInppm"],9296:["FD","1","ChemicalShiftMaximumIntegrationLimitInppm"],9297:["CS","1","WaterReferenceAcquisition"],9298:["IS","1","EchoPeakPosition"],9301:["SQ","1","CTAcquisitionTypeSequence"],9302:["CS","1","AcquisitionType"],9303:["FD","1","TubeAngle"],9304:["SQ","1","CTAcquisitionDetailsSequence"],9305:["FD","1","RevolutionTime"],9306:["FD","1","SingleCollimationWidth"],9307:["FD","1","TotalCollimationWidth"],9308:["SQ","1","CTTableDynamicsSequence"],9309:["FD","1","TableSpeed"],9310:["FD","1","TableFeedPerRotation"],9311:["FD","1","SpiralPitchFactor"],9312:["SQ","1","CTGeometrySequence"],9313:["FD","3","DataCollectionCenterPatient"],9314:["SQ","1","CTReconstructionSequence"],9315:["CS","1","ReconstructionAlgorithm"],9316:["CS","1","ConvolutionKernelGroup"],9317:["FD","2","ReconstructionFieldOfView"],9318:["FD","3","ReconstructionTargetCenterPatient"],9319:["FD","1","ReconstructionAngle"],9320:["SH","1","ImageFilter"],9321:["SQ","1","CTExposureSequence"],9322:["FD","2","ReconstructionPixelSpacing"],9323:["CS","1-n","ExposureModulationType"],9324:["FD","1","EstimatedDoseSaving"],9325:["SQ","1","CTXRayDetailsSequence"],9326:["SQ","1","CTPositionSequence"],9327:["FD","1","TablePosition"],9328:["FD","1","ExposureTimeInms"],9329:["SQ","1","CTImageFrameTypeSequence"],9330:["FD","1","XRayTubeCurrentInmA"],9332:["FD","1","ExposureInmAs"],9333:["CS","1","ConstantVolumeFlag"],9334:["CS","1","FluoroscopyFlag"],9335:["FD","1","DistanceSourceToDataCollectionCenter"],9337:["US","1","ContrastBolusAgentNumber"],9338:["SQ","1","ContrastBolusIngredientCodeSequence"],9340:["SQ","1","ContrastAdministrationProfileSequence"],9341:["SQ","1","ContrastBolusUsageSequence"],9342:["CS","1","ContrastBolusAgentAdministered"],9343:["CS","1","ContrastBolusAgentDetected"],9344:["CS","1","ContrastBolusAgentPhase"],9345:["FD","1","CTDIvol"],9346:["SQ","1","CTDIPhantomTypeCodeSequence"],9351:["FL","1","CalciumScoringMassFactorPatient"],9352:["FL","3","CalciumScoringMassFactorDevice"],9353:["FL","1","EnergyWeightingFactor"],9360:["SQ","1","CTAdditionalXRaySourceSequence"],9361:["CS","1","MultienergyCTAcquisition"],9362:["SQ","1","MultienergyCTAcquisitionSequence"],9363:["SQ","1","MultienergyCTProcessingSequence"],9364:["SQ","1","MultienergyCTCharacteristicsSequence"],9365:["SQ","1","MultienergyCTXRaySourceSequence"],9366:["US","1","XRaySourceIndex"],9367:["UC","1","XRaySourceID"],9368:["CS","1","MultienergySourceTechnique"],9369:["DT","1","SourceStartDateTime"],"936A":["DT","1","SourceEndDateTime"],"936B":["US","1","SwitchingPhaseNumber"],"936C":["DS","1","SwitchingPhaseNominalDuration"],"936D":["DS","1","SwitchingPhaseTransitionDuration"],"936E":["DS","1","EffectiveBinEnergy"],"936F":["SQ","1","MultienergyCTXRayDetectorSequence"],9370:["US","1","XRayDetectorIndex"],9371:["UC","1","XRayDetectorID"],9372:["CS","1","MultienergyDetectorType"],9373:["ST","1","XRayDetectorLabel"],9374:["DS","1","NominalMaxEnergy"],9375:["DS","1","NominalMinEnergy"],9376:["US","1-n","ReferencedXRayDetectorIndex"],9377:["US","1-n","ReferencedXRaySourceIndex"],9378:["US","1-n","ReferencedPathIndex"],9379:["SQ","1","MultienergyCTPathSequence"],"937A":["US","1","MultienergyCTPathIndex"],"937B":["UT","1","MultienergyAcquisitionDescription"],"937C":["FD","1","MonoenergeticEnergyEquivalent"],"937D":["SQ","1","MaterialCodeSequence"],"937E":["CS","1","DecompositionMethod"],"937F":["UT","1","DecompositionDescription"],9380:["SQ","1","DecompositionAlgorithmIdentificationSequence"],9381:["SQ","1","DecompositionMaterialSequence"],9382:["SQ","1","MaterialAttenuationSequence"],9383:["DS","1","PhotonEnergy"],9384:["DS","1","XRayMassAttenuationCoefficient"],9401:["SQ","1","ProjectionPixelCalibrationSequence"],9402:["FL","1","DistanceSourceToIsocenter"],9403:["FL","1","DistanceObjectToTableTop"],9404:["FL","2","ObjectPixelSpacingInCenterOfBeam"],9405:["SQ","1","PositionerPositionSequence"],9406:["SQ","1","TablePositionSequence"],9407:["SQ","1","CollimatorShapeSequence"],9410:["CS","1","PlanesInAcquisition"],9412:["SQ","1","XAXRFFrameCharacteristicsSequence"],9417:["SQ","1","FrameAcquisitionSequence"],9420:["CS","1","XRayReceptorType"],9423:["LO","1","AcquisitionProtocolName"],9424:["LT","1","AcquisitionProtocolDescription"],9425:["CS","1","ContrastBolusIngredientOpaque"],9426:["FL","1","DistanceReceptorPlaneToDetectorHousing"],9427:["CS","1","IntensifierActiveShape"],9428:["FL","1-2","IntensifierActiveDimensions"],9429:["FL","2","PhysicalDetectorSize"],9430:["FL","2","PositionOfIsocenterProjection"],9432:["SQ","1","FieldOfViewSequence"],9433:["LO","1","FieldOfViewDescription"],9434:["SQ","1","ExposureControlSensingRegionsSequence"],9435:["CS","1","ExposureControlSensingRegionShape"],9436:["SS","1","ExposureControlSensingRegionLeftVerticalEdge"],9437:["SS","1","ExposureControlSensingRegionRightVerticalEdge"],9438:["SS","1","ExposureControlSensingRegionUpperHorizontalEdge"],9439:["SS","1","ExposureControlSensingRegionLowerHorizontalEdge"],9440:["SS","2","CenterOfCircularExposureControlSensingRegion"],9441:["US","1","RadiusOfCircularExposureControlSensingRegion"],9442:["SS","2-n","VerticesOfThePolygonalExposureControlSensingRegion"],9445:["","",""],9447:["FL","1","ColumnAngulationPatient"],9449:["FL","1","BeamAngle"],9451:["SQ","1","FrameDetectorParametersSequence"],9452:["FL","1","CalculatedAnatomyThickness"],9455:["SQ","1","CalibrationSequence"],9456:["SQ","1","ObjectThicknessSequence"],9457:["CS","1","PlaneIdentification"],9461:["FL","1-2","FieldOfViewDimensionsInFloat"],9462:["SQ","1","IsocenterReferenceSystemSequence"],9463:["FL","1","PositionerIsocenterPrimaryAngle"],9464:["FL","1","PositionerIsocenterSecondaryAngle"],9465:["FL","1","PositionerIsocenterDetectorRotationAngle"],9466:["FL","1","TableXPositionToIsocenter"],9467:["FL","1","TableYPositionToIsocenter"],9468:["FL","1","TableZPositionToIsocenter"],9469:["FL","1","TableHorizontalRotationAngle"],9470:["FL","1","TableHeadTiltAngle"],9471:["FL","1","TableCradleTiltAngle"],9472:["SQ","1","FrameDisplayShutterSequence"],9473:["FL","1","AcquiredImageAreaDoseProduct"],9474:["CS","1","CArmPositionerTabletopRelationship"],9476:["SQ","1","XRayGeometrySequence"],9477:["SQ","1","IrradiationEventIdentificationSequence"],9504:["SQ","1","XRay3DFrameTypeSequence"],9506:["SQ","1","ContributingSourcesSequence"],9507:["SQ","1","XRay3DAcquisitionSequence"],9508:["FL","1","PrimaryPositionerScanArc"],9509:["FL","1","SecondaryPositionerScanArc"],9510:["FL","1","PrimaryPositionerScanStartAngle"],9511:["FL","1","SecondaryPositionerScanStartAngle"],9514:["FL","1","PrimaryPositionerIncrement"],9515:["FL","1","SecondaryPositionerIncrement"],9516:["DT","1","StartAcquisitionDateTime"],9517:["DT","1","EndAcquisitionDateTime"],9518:["SS","1","PrimaryPositionerIncrementSign"],9519:["SS","1","SecondaryPositionerIncrementSign"],9524:["LO","1","ApplicationName"],9525:["LO","1","ApplicationVersion"],9526:["LO","1","ApplicationManufacturer"],9527:["CS","1","AlgorithmType"],9528:["LO","1","AlgorithmDescription"],9530:["SQ","1","XRay3DReconstructionSequence"],9531:["LO","1","ReconstructionDescription"],9538:["SQ","1","PerProjectionAcquisitionSequence"],9541:["SQ","1","DetectorPositionSequence"],9542:["SQ","1","XRayAcquisitionDoseSequence"],9543:["FD","1","XRaySourceIsocenterPrimaryAngle"],9544:["FD","1","XRaySourceIsocenterSecondaryAngle"],9545:["FD","1","BreastSupportIsocenterPrimaryAngle"],9546:["FD","1","BreastSupportIsocenterSecondaryAngle"],9547:["FD","1","BreastSupportXPositionToIsocenter"],9548:["FD","1","BreastSupportYPositionToIsocenter"],9549:["FD","1","BreastSupportZPositionToIsocenter"],9550:["FD","1","DetectorIsocenterPrimaryAngle"],9551:["FD","1","DetectorIsocenterSecondaryAngle"],9552:["FD","1","DetectorXPositionToIsocenter"],9553:["FD","1","DetectorYPositionToIsocenter"],9554:["FD","1","DetectorZPositionToIsocenter"],9555:["SQ","1","XRayGridSequence"],9556:["SQ","1","XRayFilterSequence"],9557:["FD","3","DetectorActiveAreaTLHCPosition"],9558:["FD","6","DetectorActiveAreaOrientation"],9559:["CS","1","PositionerPrimaryAngleDirection"],9601:["SQ","1","DiffusionBMatrixSequence"],9602:["FD","1","DiffusionBValueXX"],9603:["FD","1","DiffusionBValueXY"],9604:["FD","1","DiffusionBValueXZ"],9605:["FD","1","DiffusionBValueYY"],9606:["FD","1","DiffusionBValueYZ"],9607:["FD","1","DiffusionBValueZZ"],9621:["SQ","1","FunctionalMRSequence"],9622:["CS","1","FunctionalSettlingPhaseFramesPresent"],9623:["DT","1","FunctionalSyncPulse"],9624:["CS","1","SettlingPhaseFrame"],9701:["DT","1","DecayCorrectionDateTime"],9715:["FD","1","StartDensityThreshold"],9716:["FD","1","StartRelativeDensityDifferenceThreshold"],9717:["FD","1","StartCardiacTriggerCountThreshold"],9718:["FD","1","StartRespiratoryTriggerCountThreshold"],9719:["FD","1","TerminationCountsThreshold"],9720:["FD","1","TerminationDensityThreshold"],9721:["FD","1","TerminationRelativeDensityThreshold"],9722:["FD","1","TerminationTimeThreshold"],9723:["FD","1","TerminationCardiacTriggerCountThreshold"],9724:["FD","1","TerminationRespiratoryTriggerCountThreshold"],9725:["CS","1","DetectorGeometry"],9726:["FD","1","TransverseDetectorSeparation"],9727:["FD","1","AxialDetectorDimension"],9729:["US","1","RadiopharmaceuticalAgentNumber"],9732:["SQ","1","PETFrameAcquisitionSequence"],9733:["SQ","1","PETDetectorMotionDetailsSequence"],9734:["SQ","1","PETTableDynamicsSequence"],9735:["SQ","1","PETPositionSequence"],9736:["SQ","1","PETFrameCorrectionFactorsSequence"],9737:["SQ","1","RadiopharmaceuticalUsageSequence"],9738:["CS","1","AttenuationCorrectionSource"],9739:["US","1","NumberOfIterations"],9740:["US","1","NumberOfSubsets"],9749:["SQ","1","PETReconstructionSequence"],9751:["SQ","1","PETFrameTypeSequence"],9755:["CS","1","TimeOfFlightInformationUsed"],9756:["CS","1","ReconstructionType"],9758:["CS","1","DecayCorrected"],9759:["CS","1","AttenuationCorrected"],9760:["CS","1","ScatterCorrected"],9761:["CS","1","DeadTimeCorrected"],9762:["CS","1","GantryMotionCorrected"],9763:["CS","1","PatientMotionCorrected"],9764:["CS","1","CountLossNormalizationCorrected"],9765:["CS","1","RandomsCorrected"],9766:["CS","1","NonUniformRadialSamplingCorrected"],9767:["CS","1","SensitivityCalibrated"],9768:["CS","1","DetectorNormalizationCorrection"],9769:["CS","1","IterativeReconstructionMethod"],9770:["CS","1","AttenuationCorrectionTemporalRelationship"],9771:["SQ","1","PatientPhysiologicalStateSequence"],9772:["SQ","1","PatientPhysiologicalStateCodeSequence"],9801:["FD","1-n","DepthsOfFocus"],9803:["SQ","1","ExcludedIntervalsSequence"],9804:["DT","1","ExclusionStartDateTime"],9805:["FD","1","ExclusionDuration"],9806:["SQ","1","USImageDescriptionSequence"],9807:["SQ","1","ImageDataTypeSequence"],9808:["CS","1","DataType"],9809:["SQ","1","TransducerScanPatternCodeSequence"],"980B":["CS","1","AliasedDataType"],"980C":["CS","1","PositionMeasuringDeviceUsed"],"980D":["SQ","1","TransducerGeometryCodeSequence"],"980E":["SQ","1","TransducerBeamSteeringCodeSequence"],"980F":["SQ","1","TransducerApplicationCodeSequence"],9810:["xs","1","ZeroVelocityPixelValue"],9900:["LO","1","ReferenceLocationLabel"],9901:["UT","1","ReferenceLocationDescription"],9902:["SQ","1","ReferenceBasisCodeSequence"],9903:["SQ","1","ReferenceGeometryCodeSequence"],9904:["DS","1","OffsetDistance"],9905:["CS","1","OffsetDirection"],9906:["SQ","1","PotentialScheduledProtocolCodeSequence"],9907:["SQ","1","PotentialRequestedProcedureCodeSequence"],9908:["UC","1-n","PotentialReasonsForProcedure"],9909:["SQ","1","PotentialReasonsForProcedureCodeSequence"],"990A":["UC","1-n","PotentialDiagnosticTasks"],"990B":["SQ","1","ContraindicationsCodeSequence"],"990C":["SQ","1","ReferencedDefinedProtocolSequence"],"990D":["SQ","1","ReferencedPerformedProtocolSequence"],"990E":["SQ","1","PredecessorProtocolSequence"],"990F":["UT","1","ProtocolPlanningInformation"],9910:["UT","1","ProtocolDesignRationale"],9911:["SQ","1","PatientSpecificationSequence"],9912:["SQ","1","ModelSpecificationSequence"],9913:["SQ","1","ParametersSpecificationSequence"],9914:["SQ","1","InstructionSequence"],9915:["US","1","InstructionIndex"],9916:["LO","1","InstructionText"],9917:["UT","1","InstructionDescription"],9918:["CS","1","InstructionPerformedFlag"],9919:["DT","1","InstructionPerformedDateTime"],"991A":["UT","1","InstructionPerformanceComment"],"991B":["SQ","1","PatientPositioningInstructionSequence"],"991C":["SQ","1","PositioningMethodCodeSequence"],"991D":["SQ","1","PositioningLandmarkSequence"],"991E":["UI","1","TargetFrameOfReferenceUID"],"991F":["SQ","1","AcquisitionProtocolElementSpecificationSequence"],9920:["SQ","1","AcquisitionProtocolElementSequence"],9921:["US","1","ProtocolElementNumber"],9922:["LO","1","ProtocolElementName"],9923:["UT","1","ProtocolElementCharacteristicsSummary"],9924:["UT","1","ProtocolElementPurpose"],9930:["CS","1","AcquisitionMotion"],9931:["SQ","1","AcquisitionStartLocationSequence"],9932:["SQ","1","AcquisitionEndLocationSequence"],9933:["SQ","1","ReconstructionProtocolElementSpecificationSequence"],9934:["SQ","1","ReconstructionProtocolElementSequence"],9935:["SQ","1","StorageProtocolElementSpecificationSequence"],9936:["SQ","1","StorageProtocolElementSequence"],9937:["LO","1","RequestedSeriesDescription"],9938:["US","1-n","SourceAcquisitionProtocolElementNumber"],9939:["US","1-n","SourceAcquisitionBeamNumber"],"993A":["US","1-n","SourceReconstructionProtocolElementNumber"],"993B":["SQ","1","ReconstructionStartLocationSequence"],"993C":["SQ","1","ReconstructionEndLocationSequence"],"993D":["SQ","1","ReconstructionAlgorithmSequence"],"993E":["SQ","1","ReconstructionTargetCenterLocationSequence"],9941:["UT","1","ImageFilterDescription"],9942:["FD","1","CTDIvolNotificationTrigger"],9943:["FD","1","DLPNotificationTrigger"],9944:["CS","1","AutoKVPSelectionType"],9945:["FD","1","AutoKVPUpperBound"],9946:["FD","1","AutoKVPLowerBound"],9947:["CS","1","ProtocolDefinedPatientPosition"],A001:["SQ","1","ContributingEquipmentSequence"],A002:["DT","1","ContributionDateTime"],A003:["ST","1","ContributionDescription"]},"0020":{"0000":["UL","1","GenericGroupLength"],"000D":["UI","1","StudyInstanceUID"],"000E":["UI","1","SeriesInstanceUID"],"0010":["SH","1","StudyID"],"0011":["IS","1","SeriesNumber"],"0012":["IS","1","AcquisitionNumber"],"0013":["IS","1","InstanceNumber"],"0014":["IS","1","IsotopeNumber"],"0015":["IS","1","PhaseNumber"],"0016":["IS","1","IntervalNumber"],"0017":["IS","1","TimeSlotNumber"],"0018":["IS","1","AngleNumber"],"0019":["IS","1","ItemNumber"],"0020":["CS","2","PatientOrientation"],"0022":["IS","1","OverlayNumber"],"0024":["IS","1","CurveNumber"],"0026":["IS","1","LUTNumber"],"0030":["DS","3","ImagePosition"],"0032":["DS","3","ImagePositionPatient"],"0035":["DS","6","ImageOrientation"],"0037":["DS","6","ImageOrientationPatient"],"0050":["DS","1","Location"],"0052":["UI","1","FrameOfReferenceUID"],"0060":["CS","1","Laterality"],"0062":["CS","1","ImageLaterality"],"0070":["LO","1","ImageGeometryType"],"0080":["CS","1-n","MaskingImage"],"00AA":["IS","1","ReportNumber"],"0100":["IS","1","TemporalPositionIdentifier"],"0105":["IS","1","NumberOfTemporalPositions"],"0110":["DS","1","TemporalResolution"],"0200":["UI","1","SynchronizationFrameOfReferenceUID"],"0242":["UI","1","SOPInstanceUIDOfConcatenationSource"],1e3:["IS","1","SeriesInStudy"],1001:["IS","1","AcquisitionsInSeries"],1002:["IS","1","ImagesInAcquisition"],1003:["IS","1","ImagesInSeries"],1004:["IS","1","AcquisitionsInStudy"],1005:["IS","1","ImagesInStudy"],1020:["LO","1-n","Reference"],"103F":["LO","1","TargetPositionReferenceIndicator"],1040:["LO","1","PositionReferenceIndicator"],1041:["DS","1","SliceLocation"],1070:["IS","1-n","OtherStudyNumbers"],1200:["IS","1","NumberOfPatientRelatedStudies"],1202:["IS","1","NumberOfPatientRelatedSeries"],1204:["IS","1","NumberOfPatientRelatedInstances"],1206:["IS","1","NumberOfStudyRelatedSeries"],1208:["IS","1","NumberOfStudyRelatedInstances"],1209:["IS","1","NumberOfSeriesRelatedInstances"],3100:["CS","1-n","SourceImageIDs"],3401:["CS","1","ModifyingDeviceID"],3402:["CS","1","ModifiedImageID"],3403:["DA","1","ModifiedImageDate"],3404:["LO","1","ModifyingDeviceManufacturer"],3405:["TM","1","ModifiedImageTime"],3406:["LO","1","ModifiedImageDescription"],4e3:["LT","1","ImageComments"],5e3:["AT","1-n","OriginalImageIdentification"],5002:["LO","1-n","OriginalImageIdentificationNomenclature"],9056:["SH","1","StackID"],9057:["UL","1","InStackPositionNumber"],9071:["SQ","1","FrameAnatomySequence"],9072:["CS","1","FrameLaterality"],9111:["SQ","1","FrameContentSequence"],9113:["SQ","1","PlanePositionSequence"],9116:["SQ","1","PlaneOrientationSequence"],9128:["UL","1","TemporalPositionIndex"],9153:["FD","1","NominalCardiacTriggerDelayTime"],9154:["FL","1","NominalCardiacTriggerTimePriorToRPeak"],9155:["FL","1","ActualCardiacTriggerTimePriorToRPeak"],9156:["US","1","FrameAcquisitionNumber"],9157:["UL","1-n","DimensionIndexValues"],9158:["LT","1","FrameComments"],9161:["UI","1","ConcatenationUID"],9162:["US","1","InConcatenationNumber"],9163:["US","1","InConcatenationTotalNumber"],9164:["UI","1","DimensionOrganizationUID"],9165:["AT","1","DimensionIndexPointer"],9167:["AT","1","FunctionalGroupPointer"],9170:["SQ","1","UnassignedSharedConvertedAttributesSequence"],9171:["SQ","1","UnassignedPerFrameConvertedAttributesSequence"],9172:["SQ","1","ConversionSourceAttributesSequence"],9213:["LO","1","DimensionIndexPrivateCreator"],9221:["SQ","1","DimensionOrganizationSequence"],9222:["SQ","1","DimensionIndexSequence"],9228:["UL","1","ConcatenationFrameOffsetNumber"],9238:["LO","1","FunctionalGroupPrivateCreator"],9241:["FL","1","NominalPercentageOfCardiacPhase"],9245:["FL","1","NominalPercentageOfRespiratoryPhase"],9246:["FL","1","StartingRespiratoryAmplitude"],9247:["CS","1","StartingRespiratoryPhase"],9248:["FL","1","EndingRespiratoryAmplitude"],9249:["CS","1","EndingRespiratoryPhase"],9250:["CS","1","RespiratoryTriggerType"],9251:["FD","1","RRIntervalTimeNominal"],9252:["FD","1","ActualCardiacTriggerDelayTime"],9253:["SQ","1","RespiratorySynchronizationSequence"],9254:["FD","1","RespiratoryIntervalTime"],9255:["FD","1","NominalRespiratoryTriggerDelayTime"],9256:["FD","1","RespiratoryTriggerDelayThreshold"],9257:["FD","1","ActualRespiratoryTriggerDelayTime"],9301:["FD","3","ImagePositionVolume"],9302:["FD","6","ImageOrientationVolume"],9307:["CS","1","UltrasoundAcquisitionGeometry"],9308:["FD","3","ApexPosition"],9309:["FD","16","VolumeToTransducerMappingMatrix"],"930A":["FD","16","VolumeToTableMappingMatrix"],"930B":["CS","1","VolumeToTransducerRelationship"],"930C":["CS","1","PatientFrameOfReferenceSource"],"930D":["FD","1","TemporalPositionTimeOffset"],"930E":["SQ","1","PlanePositionVolumeSequence"],"930F":["SQ","1","PlaneOrientationVolumeSequence"],9310:["SQ","1","TemporalPositionSequence"],9311:["CS","1","DimensionOrganizationType"],9312:["UI","1","VolumeFrameOfReferenceUID"],9313:["UI","1","TableFrameOfReferenceUID"],9421:["LO","1","DimensionDescriptionLabel"],9450:["SQ","1","PatientOrientationInFrameSequence"],9453:["LO","1","FrameLabel"],9518:["US","1-n","AcquisitionIndex"],9529:["SQ","1","ContributingSOPInstancesReferenceSequence"],9536:["US","1","ReconstructionIndex"]},"0022":{"0000":["UL","1","GenericGroupLength"],"0001":["US","1","LightPathFilterPassThroughWavelength"],"0002":["US","2","LightPathFilterPassBand"],"0003":["US","1","ImagePathFilterPassThroughWavelength"],"0004":["US","2","ImagePathFilterPassBand"],"0005":["CS","1","PatientEyeMovementCommanded"],"0006":["SQ","1","PatientEyeMovementCommandCodeSequence"],"0007":["FL","1","SphericalLensPower"],"0008":["FL","1","CylinderLensPower"],"0009":["FL","1","CylinderAxis"],"000A":["FL","1","EmmetropicMagnification"],"000B":["FL","1","IntraOcularPressure"],"000C":["FL","1","HorizontalFieldOfView"],"000D":["CS","1","PupilDilated"],"000E":["FL","1","DegreeOfDilation"],"0010":["FL","1","StereoBaselineAngle"],"0011":["FL","1","StereoBaselineDisplacement"],"0012":["FL","1","StereoHorizontalPixelOffset"],"0013":["FL","1","StereoVerticalPixelOffset"],"0014":["FL","1","StereoRotation"],"0015":["SQ","1","AcquisitionDeviceTypeCodeSequence"],"0016":["SQ","1","IlluminationTypeCodeSequence"],"0017":["SQ","1","LightPathFilterTypeStackCodeSequence"],"0018":["SQ","1","ImagePathFilterTypeStackCodeSequence"],"0019":["SQ","1","LensesCodeSequence"],"001A":["SQ","1","ChannelDescriptionCodeSequence"],"001B":["SQ","1","RefractiveStateSequence"],"001C":["SQ","1","MydriaticAgentCodeSequence"],"001D":["SQ","1","RelativeImagePositionCodeSequence"],"001E":["FL","1","CameraAngleOfView"],"0020":["SQ","1","StereoPairsSequence"],"0021":["SQ","1","LeftImageSequence"],"0022":["SQ","1","RightImageSequence"],"0028":["CS","1","StereoPairsPresent"],"0030":["FL","1","AxialLengthOfTheEye"],"0031":["SQ","1","OphthalmicFrameLocationSequence"],"0032":["FL","2-2n","ReferenceCoordinates"],"0035":["FL","1","DepthSpatialResolution"],"0036":["FL","1","MaximumDepthDistortion"],"0037":["FL","1","AlongScanSpatialResolution"],"0038":["FL","1","MaximumAlongScanDistortion"],"0039":["CS","1","OphthalmicImageOrientation"],"0041":["FL","1","DepthOfTransverseImage"],"0042":["SQ","1","MydriaticAgentConcentrationUnitsSequence"],"0048":["FL","1","AcrossScanSpatialResolution"],"0049":["FL","1","MaximumAcrossScanDistortion"],"004E":["DS","1","MydriaticAgentConcentration"],"0055":["FL","1","IlluminationWaveLength"],"0056":["FL","1","IlluminationPower"],"0057":["FL","1","IlluminationBandwidth"],"0058":["SQ","1","MydriaticAgentSequence"],1007:["SQ","1","OphthalmicAxialMeasurementsRightEyeSequence"],1008:["SQ","1","OphthalmicAxialMeasurementsLeftEyeSequence"],1009:["CS","1","OphthalmicAxialMeasurementsDeviceType"],1010:["CS","1","OphthalmicAxialLengthMeasurementsType"],1012:["SQ","1","OphthalmicAxialLengthSequence"],1019:["FL","1","OphthalmicAxialLength"],1024:["SQ","1","LensStatusCodeSequence"],1025:["SQ","1","VitreousStatusCodeSequence"],1028:["SQ","1","IOLFormulaCodeSequence"],1029:["LO","1","IOLFormulaDetail"],1033:["FL","1","KeratometerIndex"],1035:["SQ","1","SourceOfOphthalmicAxialLengthCodeSequence"],1036:["SQ","1","SourceOfCornealSizeDataCodeSequence"],1037:["FL","1","TargetRefraction"],1039:["CS","1","RefractiveProcedureOccurred"],1040:["SQ","1","RefractiveSurgeryTypeCodeSequence"],1044:["SQ","1","OphthalmicUltrasoundMethodCodeSequence"],1045:["SQ","1","SurgicallyInducedAstigmatismSequence"],1046:["CS","1","TypeOfOpticalCorrection"],1047:["SQ","1","ToricIOLPowerSequence"],1048:["SQ","1","PredictedToricErrorSequence"],1049:["CS","1","PreSelectedForImplantation"],"104A":["SQ","1","ToricIOLPowerForExactEmmetropiaSequence"],"104B":["SQ","1","ToricIOLPowerForExactTargetRefractionSequence"],1050:["SQ","1","OphthalmicAxialLengthMeasurementsSequence"],1053:["FL","1","IOLPower"],1054:["FL","1","PredictedRefractiveError"],1059:["FL","1","OphthalmicAxialLengthVelocity"],1065:["LO","1","LensStatusDescription"],1066:["LO","1","VitreousStatusDescription"],1090:["SQ","1","IOLPowerSequence"],1092:["SQ","1","LensConstantSequence"],1093:["LO","1","IOLManufacturer"],1094:["LO","1","LensConstantDescription"],1095:["LO","1","ImplantName"],1096:["SQ","1","KeratometryMeasurementTypeCodeSequence"],1097:["LO","1","ImplantPartNumber"],1100:["SQ","1","ReferencedOphthalmicAxialMeasurementsSequence"],1101:["SQ","1","OphthalmicAxialLengthMeasurementsSegmentNameCodeSequence"],1103:["SQ","1","RefractiveErrorBeforeRefractiveSurgeryCodeSequence"],1121:["FL","1","IOLPowerForExactEmmetropia"],1122:["FL","1","IOLPowerForExactTargetRefraction"],1125:["SQ","1","AnteriorChamberDepthDefinitionCodeSequence"],1127:["SQ","1","LensThicknessSequence"],1128:["SQ","1","AnteriorChamberDepthSequence"],"112A":["SQ","1","CalculationCommentSequence"],"112B":["CS","1","CalculationCommentType"],"112C":["LT","1","CalculationComment"],1130:["FL","1","LensThickness"],1131:["FL","1","AnteriorChamberDepth"],1132:["SQ","1","SourceOfLensThicknessDataCodeSequence"],1133:["SQ","1","SourceOfAnteriorChamberDepthDataCodeSequence"],1134:["SQ","1","SourceOfRefractiveMeasurementsSequence"],1135:["SQ","1","SourceOfRefractiveMeasurementsCodeSequence"],1140:["CS","1","OphthalmicAxialLengthMeasurementModified"],1150:["SQ","1","OphthalmicAxialLengthDataSourceCodeSequence"],1153:["SQ","1","OphthalmicAxialLengthAcquisitionMethodCodeSequence"],1155:["FL","1","SignalToNoiseRatio"],1159:["LO","1","OphthalmicAxialLengthDataSourceDescription"],1210:["SQ","1","OphthalmicAxialLengthMeasurementsTotalLengthSequence"],1211:["SQ","1","OphthalmicAxialLengthMeasurementsSegmentalLengthSequence"],1212:["SQ","1","OphthalmicAxialLengthMeasurementsLengthSummationSequence"],1220:["SQ","1","UltrasoundOphthalmicAxialLengthMeasurementsSequence"],1225:["SQ","1","OpticalOphthalmicAxialLengthMeasurementsSequence"],1230:["SQ","1","UltrasoundSelectedOphthalmicAxialLengthSequence"],1250:["SQ","1","OphthalmicAxialLengthSelectionMethodCodeSequence"],1255:["SQ","1","OpticalSelectedOphthalmicAxialLengthSequence"],1257:["SQ","1","SelectedSegmentalOphthalmicAxialLengthSequence"],1260:["SQ","1","SelectedTotalOphthalmicAxialLengthSequence"],1262:["SQ","1","OphthalmicAxialLengthQualityMetricSequence"],1265:["SQ","1","OphthalmicAxialLengthQualityMetricTypeCodeSequence"],1273:["LO","1","OphthalmicAxialLengthQualityMetricTypeDescription"],1300:["SQ","1","IntraocularLensCalculationsRightEyeSequence"],1310:["SQ","1","IntraocularLensCalculationsLeftEyeSequence"],1330:["SQ","1","ReferencedOphthalmicAxialLengthMeasurementQCImageSequence"],1415:["CS","1","OphthalmicMappingDeviceType"],1420:["SQ","1","AcquisitionMethodCodeSequence"],1423:["SQ","1","AcquisitionMethodAlgorithmSequence"],1436:["SQ","1","OphthalmicThicknessMapTypeCodeSequence"],1443:["SQ","1","OphthalmicThicknessMappingNormalsSequence"],1445:["SQ","1","RetinalThicknessDefinitionCodeSequence"],1450:["SQ","1","PixelValueMappingToCodedConceptSequence"],1452:["xs","1","MappedPixelValue"],1454:["LO","1","PixelValueMappingExplanation"],1458:["SQ","1","OphthalmicThicknessMapQualityThresholdSequence"],1460:["FL","1","OphthalmicThicknessMapThresholdQualityRating"],1463:["FL","2","AnatomicStructureReferencePoint"],1465:["SQ","1","RegistrationToLocalizerSequence"],1466:["CS","1","RegisteredLocalizerUnits"],1467:["FL","2","RegisteredLocalizerTopLeftHandCorner"],1468:["FL","2","RegisteredLocalizerBottomRightHandCorner"],1470:["SQ","1","OphthalmicThicknessMapQualityRatingSequence"],1472:["SQ","1","RelevantOPTAttributesSequence"],1512:["SQ","1","TransformationMethodCodeSequence"],1513:["SQ","1","TransformationAlgorithmSequence"],1515:["CS","1","OphthalmicAxialLengthMethod"],1517:["FL","1","OphthalmicFOV"],1518:["SQ","1","TwoDimensionalToThreeDimensionalMapSequence"],1525:["SQ","1","WideFieldOphthalmicPhotographyQualityRatingSequence"],1526:["SQ","1","WideFieldOphthalmicPhotographyQualityThresholdSequence"],1527:["FL","1","WideFieldOphthalmicPhotographyThresholdQualityRating"],1528:["FL","1","XCoordinatesCenterPixelViewAngle"],1529:["FL","1","YCoordinatesCenterPixelViewAngle"],1530:["UL","1","NumberOfMapPoints"],1531:["OF","1","TwoDimensionalToThreeDimensionalMapData"],1612:["SQ","1","DerivationAlgorithmSequence"],1615:["SQ","1","OphthalmicImageTypeCodeSequence"],1616:["LO","1","OphthalmicImageTypeDescription"],1618:["SQ","1","ScanPatternTypeCodeSequence"],1620:["SQ","1","ReferencedSurfaceMeshIdentificationSequence"],1622:["CS","1","OphthalmicVolumetricPropertiesFlag"],1624:["FL","1","OphthalmicAnatomicReferencePointXCoordinate"],1626:["FL","1","OphthalmicAnatomicReferencePointYCoordinate"],1628:["SQ","1","OphthalmicEnFaceImageQualityRatingSequence"],1630:["DS","1","QualityThreshold"],1640:["SQ","1","OCTBscanAnalysisAcquisitionParametersSequence"],1642:["UL","1","NumberOfBscansPerFrame"],1643:["FL","1","BscanSlabThickness"],1644:["FL","1","DistanceBetweenBscanSlabs"],1645:["FL","1","BscanCycleTime"],1646:["FL","1-n","BscanCycleTimeVector"],1649:["FL","1","AscanRate"],1650:["FL","1","BscanRate"],1658:["UL","1","SurfaceMeshZPixelOffset"]},"0024":{"0000":["UL","1","GenericGroupLength"],"0010":["FL","1","VisualFieldHorizontalExtent"],"0011":["FL","1","VisualFieldVerticalExtent"],"0012":["CS","1","VisualFieldShape"],"0016":["SQ","1","ScreeningTestModeCodeSequence"],"0018":["FL","1","MaximumStimulusLuminance"],"0020":["FL","1","BackgroundLuminance"],"0021":["SQ","1","StimulusColorCodeSequence"],"0024":["SQ","1","BackgroundIlluminationColorCodeSequence"],"0025":["FL","1","StimulusArea"],"0028":["FL","1","StimulusPresentationTime"],"0032":["SQ","1","FixationSequence"],"0033":["SQ","1","FixationMonitoringCodeSequence"],"0034":["SQ","1","VisualFieldCatchTrialSequence"],"0035":["US","1","FixationCheckedQuantity"],"0036":["US","1","PatientNotProperlyFixatedQuantity"],"0037":["CS","1","PresentedVisualStimuliDataFlag"],"0038":["US","1","NumberOfVisualStimuli"],"0039":["CS","1","ExcessiveFixationLossesDataFlag"],"0040":["CS","1","ExcessiveFixationLosses"],"0042":["US","1","StimuliRetestingQuantity"],"0044":["LT","1","CommentsOnPatientPerformanceOfVisualField"],"0045":["CS","1","FalseNegativesEstimateFlag"],"0046":["FL","1","FalseNegativesEstimate"],"0048":["US","1","NegativeCatchTrialsQuantity"],"0050":["US","1","FalseNegativesQuantity"],"0051":["CS","1","ExcessiveFalseNegativesDataFlag"],"0052":["CS","1","ExcessiveFalseNegatives"],"0053":["CS","1","FalsePositivesEstimateFlag"],"0054":["FL","1","FalsePositivesEstimate"],"0055":["CS","1","CatchTrialsDataFlag"],"0056":["US","1","PositiveCatchTrialsQuantity"],"0057":["CS","1","TestPointNormalsDataFlag"],"0058":["SQ","1","TestPointNormalsSequence"],"0059":["CS","1","GlobalDeviationProbabilityNormalsFlag"],"0060":["US","1","FalsePositivesQuantity"],"0061":["CS","1","ExcessiveFalsePositivesDataFlag"],"0062":["CS","1","ExcessiveFalsePositives"],"0063":["CS","1","VisualFieldTestNormalsFlag"],"0064":["SQ","1","ResultsNormalsSequence"],"0065":["SQ","1","AgeCorrectedSensitivityDeviationAlgorithmSequence"],"0066":["FL","1","GlobalDeviationFromNormal"],"0067":["SQ","1","GeneralizedDefectSensitivityDeviationAlgorithmSequence"],"0068":["FL","1","LocalizedDeviationFromNormal"],"0069":["LO","1","PatientReliabilityIndicator"],"0070":["FL","1","VisualFieldMeanSensitivity"],"0071":["FL","1","GlobalDeviationProbability"],"0072":["CS","1","LocalDeviationProbabilityNormalsFlag"],"0073":["FL","1","LocalizedDeviationProbability"],"0074":["CS","1","ShortTermFluctuationCalculated"],"0075":["FL","1","ShortTermFluctuation"],"0076":["CS","1","ShortTermFluctuationProbabilityCalculated"],"0077":["FL","1","ShortTermFluctuationProbability"],"0078":["CS","1","CorrectedLocalizedDeviationFromNormalCalculated"],"0079":["FL","1","CorrectedLocalizedDeviationFromNormal"],"0080":["CS","1","CorrectedLocalizedDeviationFromNormalProbabilityCalculated"],"0081":["FL","1","CorrectedLocalizedDeviationFromNormalProbability"],"0083":["SQ","1","GlobalDeviationProbabilitySequence"],"0085":["SQ","1","LocalizedDeviationProbabilitySequence"],"0086":["CS","1","FovealSensitivityMeasured"],"0087":["FL","1","FovealSensitivity"],"0088":["FL","1","VisualFieldTestDuration"],"0089":["SQ","1","VisualFieldTestPointSequence"],"0090":["FL","1","VisualFieldTestPointXCoordinate"],"0091":["FL","1","VisualFieldTestPointYCoordinate"],"0092":["FL","1","AgeCorrectedSensitivityDeviationValue"],"0093":["CS","1","StimulusResults"],"0094":["FL","1","SensitivityValue"],"0095":["CS","1","RetestStimulusSeen"],"0096":["FL","1","RetestSensitivityValue"],"0097":["SQ","1","VisualFieldTestPointNormalsSequence"],"0098":["FL","1","QuantifiedDefect"],"0100":["FL","1","AgeCorrectedSensitivityDeviationProbabilityValue"],"0102":["CS","1","GeneralizedDefectCorrectedSensitivityDeviationFlag"],"0103":["FL","1","GeneralizedDefectCorrectedSensitivityDeviationValue"],"0104":["FL","1","GeneralizedDefectCorrectedSensitivityDeviationProbabilityValue"],"0105":["FL","1","MinimumSensitivityValue"],"0106":["CS","1","BlindSpotLocalized"],"0107":["FL","1","BlindSpotXCoordinate"],"0108":["FL","1","BlindSpotYCoordinate"],"0110":["SQ","1","VisualAcuityMeasurementSequence"],"0112":["SQ","1","RefractiveParametersUsedOnPatientSequence"],"0113":["CS","1","MeasurementLaterality"],"0114":["SQ","1","OphthalmicPatientClinicalInformationLeftEyeSequence"],"0115":["SQ","1","OphthalmicPatientClinicalInformationRightEyeSequence"],"0117":["CS","1","FovealPointNormativeDataFlag"],"0118":["FL","1","FovealPointProbabilityValue"],"0120":["CS","1","ScreeningBaselineMeasured"],"0122":["SQ","1","ScreeningBaselineMeasuredSequence"],"0124":["CS","1","ScreeningBaselineType"],"0126":["FL","1","ScreeningBaselineValue"],"0202":["LO","1","AlgorithmSource"],"0306":["LO","1","DataSetName"],"0307":["LO","1","DataSetVersion"],"0308":["LO","1","DataSetSource"],"0309":["LO","1","DataSetDescription"],"0317":["SQ","1","VisualFieldTestReliabilityGlobalIndexSequence"],"0320":["SQ","1","VisualFieldGlobalResultsIndexSequence"],"0325":["SQ","1","DataObservationSequence"],"0338":["CS","1","IndexNormalsFlag"],"0341":["FL","1","IndexProbability"],"0344":["SQ","1","IndexProbabilitySequence"]},"0028":{"0000":["UL","1","GenericGroupLength"],"0002":["US","1","SamplesPerPixel"],"0003":["US","1","SamplesPerPixelUsed"],"0004":["CS","1","PhotometricInterpretation"],"0005":["US","1","ImageDimensions"],"0006":["US","1","PlanarConfiguration"],"0008":["IS","1","NumberOfFrames"],"0009":["AT","1-n","FrameIncrementPointer"],"000A":["AT","1-n","FrameDimensionPointer"],"0010":["US","1","Rows"],"0011":["US","1","Columns"],"0012":["US","1","Planes"],"0014":["US","1","UltrasoundColorDataPresent"],"0020":["","",""],"0030":["DS","2","PixelSpacing"],"0031":["DS","2","ZoomFactor"],"0032":["DS","2","ZoomCenter"],"0034":["IS","2","PixelAspectRatio"],"0040":["CS","1","ImageFormat"],"0050":["LO","1-n","ManipulatedImage"],"0051":["CS","1-n","CorrectedImage"],"005F":["LO","1","CompressionRecognitionCode"],"0060":["CS","1","CompressionCode"],"0061":["SH","1","CompressionOriginator"],"0062":["LO","1","CompressionLabel"],"0063":["SH","1","CompressionDescription"],"0065":["CS","1-n","CompressionSequence"],"0066":["AT","1-n","CompressionStepPointers"],"0068":["US","1","RepeatInterval"],"0069":["US","1","BitsGrouped"],"0070":["US","1-n","PerimeterTable"],"0071":["xs","1","PerimeterValue"],"0080":["US","1","PredictorRows"],"0081":["US","1","PredictorColumns"],"0082":["US","1-n","PredictorConstants"],"0090":["CS","1","BlockedPixels"],"0091":["US","1","BlockRows"],"0092":["US","1","BlockColumns"],"0093":["US","1","RowOverlap"],"0094":["US","1","ColumnOverlap"],"0100":["US","1","BitsAllocated"],"0101":["US","1","BitsStored"],"0102":["US","1","HighBit"],"0103":["US","1","PixelRepresentation"],"0104":["xs","1","SmallestValidPixelValue"],"0105":["xs","1","LargestValidPixelValue"],"0106":["xs","1","SmallestImagePixelValue"],"0107":["xs","1","LargestImagePixelValue"],"0108":["xs","1","SmallestPixelValueInSeries"],"0109":["xs","1","LargestPixelValueInSeries"],"0110":["xs","1","SmallestImagePixelValueInPlane"],"0111":["xs","1","LargestImagePixelValueInPlane"],"0120":["xs","1","PixelPaddingValue"],"0121":["xs","1","PixelPaddingRangeLimit"],"0122":["FL","1","FloatPixelPaddingValue"],"0123":["FD","1","DoubleFloatPixelPaddingValue"],"0124":["FL","1","FloatPixelPaddingRangeLimit"],"0125":["FD","1","DoubleFloatPixelPaddingRangeLimit"],"0200":["US","1","ImageLocation"],"0300":["CS","1","QualityControlImage"],"0301":["CS","1","BurnedInAnnotation"],"0302":["CS","1","RecognizableVisualFeatures"],"0303":["CS","1","LongitudinalTemporalInformationModified"],"0304":["UI","1","ReferencedColorPaletteInstanceUID"],"0400":["LO","1","TransformLabel"],"0401":["LO","1","TransformVersionNumber"],"0402":["US","1","NumberOfTransformSteps"],"0403":["LO","1-n","SequenceOfCompressedData"],"0404":["AT","1-n","DetailsOfCoefficients"],"04x0":["US","1","RowsForNthOrderCoefficients"],"04x1":["US","1","ColumnsForNthOrderCoefficients"],"04x2":["LO","1-n","CoefficientCoding"],"04x3":["AT","1-n","CoefficientCodingPointers"],"0700":["LO","1","DCTLabel"],"0701":["CS","1-n","DataBlockDescription"],"0702":["AT","1-n","DataBlock"],"0710":["US","1","NormalizationFactorFormat"],"0720":["US","1","ZonalMapNumberFormat"],"0721":["AT","1-n","ZonalMapLocation"],"0722":["US","1","ZonalMapFormat"],"0730":["US","1","AdaptiveMapFormat"],"0740":["US","1","CodeNumberFormat"],"08x0":["CS","1-n","CodeLabel"],"08x2":["US","1","NumberOfTables"],"08x3":["AT","1-n","CodeTableLocation"],"08x4":["US","1","BitsForCodeWord"],"08x8":["AT","1-n","ImageDataLocation"],"0A02":["CS","1","PixelSpacingCalibrationType"],"0A04":["LO","1","PixelSpacingCalibrationDescription"],1040:["CS","1","PixelIntensityRelationship"],1041:["SS","1","PixelIntensityRelationshipSign"],1050:["DS","1-n","WindowCenter"],1051:["DS","1-n","WindowWidth"],1052:["DS","1","RescaleIntercept"],1053:["DS","1","RescaleSlope"],1054:["LO","1","RescaleType"],1055:["LO","1-n","WindowCenterWidthExplanation"],1056:["CS","1","VOILUTFunction"],1080:["CS","1","GrayScale"],1090:["CS","1","RecommendedViewingMode"],1100:["xs","3","GrayLookupTableDescriptor"],1101:["xs","3","RedPaletteColorLookupTableDescriptor"],1102:["xs","3","GreenPaletteColorLookupTableDescriptor"],1103:["xs","3","BluePaletteColorLookupTableDescriptor"],1104:["US","3","AlphaPaletteColorLookupTableDescriptor"],1111:["xs","4","LargeRedPaletteColorLookupTableDescriptor"],1112:["xs","4","LargeGreenPaletteColorLookupTableDescriptor"],1113:["xs","4","LargeBluePaletteColorLookupTableDescriptor"],1199:["UI","1","PaletteColorLookupTableUID"],1200:["xs","1-n or 1","GrayLookupTableData"],1201:["OW","1","RedPaletteColorLookupTableData"],1202:["OW","1","GreenPaletteColorLookupTableData"],1203:["OW","1","BluePaletteColorLookupTableData"],1204:["OW","1","AlphaPaletteColorLookupTableData"],1211:["OW","1","LargeRedPaletteColorLookupTableData"],1212:["OW","1","LargeGreenPaletteColorLookupTableData"],1213:["OW","1","LargeBluePaletteColorLookupTableData"],1214:["UI","1","LargePaletteColorLookupTableUID"],1221:["OW","1","SegmentedRedPaletteColorLookupTableData"],1222:["OW","1","SegmentedGreenPaletteColorLookupTableData"],1223:["OW","1","SegmentedBluePaletteColorLookupTableData"],1224:["OW","1","SegmentedAlphaPaletteColorLookupTableData"],1230:["SQ","1","StoredValueColorRangeSequence"],1231:["FD","1","MinimumStoredValueMapped"],1232:["FD","1","MaximumStoredValueMapped"],1300:["CS","1","BreastImplantPresent"],1350:["CS","1","PartialView"],1351:["ST","1","PartialViewDescription"],1352:["SQ","1","PartialViewCodeSequence"],"135A":["CS","1","SpatialLocationsPreserved"],1401:["SQ","1","DataFrameAssignmentSequence"],1402:["CS","1","DataPathAssignment"],1403:["US","1","BitsMappedToColorLookupTable"],1404:["SQ","1","BlendingLUT1Sequence"],1405:["CS","1","BlendingLUT1TransferFunction"],1406:["FD","1","BlendingWeightConstant"],1407:["US","3","BlendingLookupTableDescriptor"],1408:["OW","1","BlendingLookupTableData"],"140B":["SQ","1","EnhancedPaletteColorLookupTableSequence"],"140C":["SQ","1","BlendingLUT2Sequence"],"140D":["CS","1","BlendingLUT2TransferFunction"],"140E":["CS","1","DataPathID"],"140F":["CS","1","RGBLUTTransferFunction"],1410:["CS","1","AlphaLUTTransferFunction"],2e3:["OB","1","ICCProfile"],2002:["CS","1","ColorSpace"],2110:["CS","1","LossyImageCompression"],2112:["DS","1-n","LossyImageCompressionRatio"],2114:["CS","1-n","LossyImageCompressionMethod"],3e3:["SQ","1","ModalityLUTSequence"],3002:["xs","3","LUTDescriptor"],3003:["LO","1","LUTExplanation"],3004:["LO","1","ModalityLUTType"],3006:["xx","1-n or 1","LUTData"],3010:["SQ","1","VOILUTSequence"],3110:["SQ","1","SoftcopyVOILUTSequence"],4e3:["LT","1","ImagePresentationComments"],5e3:["SQ","1","BiPlaneAcquisitionSequence"],6010:["US","1","RepresentativeFrameNumber"],6020:["US","1-n","FrameNumbersOfInterest"],6022:["LO","1-n","FrameOfInterestDescription"],6023:["CS","1-n","FrameOfInterestType"],6030:["US","1-n","MaskPointers"],6040:["US","1-n","RWavePointer"],6100:["SQ","1","MaskSubtractionSequence"],6101:["CS","1","MaskOperation"],6102:["US","2-2n","ApplicableFrameRange"],6110:["US","1-n","MaskFrameNumbers"],6112:["US","1","ContrastFrameAveraging"],6114:["FL","2","MaskSubPixelShift"],6120:["SS","1","TIDOffset"],6190:["ST","1","MaskOperationExplanation"],7e3:["SQ","1","EquipmentAdministratorSequence"],7001:["US","1","NumberOfDisplaySubsystems"],7002:["US","1","CurrentConfigurationID"],7003:["US","1","DisplaySubsystemID"],7004:["SH","1","DisplaySubsystemName"],7005:["LO","1","DisplaySubsystemDescription"],7006:["CS","1","SystemStatus"],7007:["LO","1","SystemStatusComment"],7008:["SQ","1","TargetLuminanceCharacteristicsSequence"],7009:["US","1","LuminanceCharacteristicsID"],"700A":["SQ","1","DisplaySubsystemConfigurationSequence"],"700B":["US","1","ConfigurationID"],"700C":["SH","1","ConfigurationName"],"700D":["LO","1","ConfigurationDescription"],"700E":["US","1","ReferencedTargetLuminanceCharacteristicsID"],"700F":["SQ","1","QAResultsSequence"],7010:["SQ","1","DisplaySubsystemQAResultsSequence"],7011:["SQ","1","ConfigurationQAResultsSequence"],7012:["SQ","1","MeasurementEquipmentSequence"],7013:["CS","1-n","MeasurementFunctions"],7014:["CS","1","MeasurementEquipmentType"],7015:["SQ","1","VisualEvaluationResultSequence"],7016:["SQ","1","DisplayCalibrationResultSequence"],7017:["US","1","DDLValue"],7018:["FL","2","CIExyWhitePoint"],7019:["CS","1","DisplayFunctionType"],"701A":["FL","1","GammaValue"],"701B":["US","1","NumberOfLuminancePoints"],"701C":["SQ","1","LuminanceResponseSequence"],"701D":["FL","1","TargetMinimumLuminance"],"701E":["FL","1","TargetMaximumLuminance"],"701F":["FL","1","LuminanceValue"],7020:["LO","1","LuminanceResponseDescription"],7021:["CS","1","WhitePointFlag"],7022:["SQ","1","DisplayDeviceTypeCodeSequence"],7023:["SQ","1","DisplaySubsystemSequence"],7024:["SQ","1","LuminanceResultSequence"],7025:["CS","1","AmbientLightValueSource"],7026:["CS","1-n","MeasuredCharacteristics"],7027:["SQ","1","LuminanceUniformityResultSequence"],7028:["SQ","1","VisualEvaluationTestSequence"],7029:["CS","1","TestResult"],"702A":["LO","1","TestResultComment"],"702B":["CS","1","TestImageValidation"],"702C":["SQ","1","TestPatternCodeSequence"],"702D":["SQ","1","MeasurementPatternCodeSequence"],"702E":["SQ","1","VisualEvaluationMethodCodeSequence"],"7FE0":["UR","1","PixelDataProviderURL"],9001:["UL","1","DataPointRows"],9002:["UL","1","DataPointColumns"],9003:["CS","1","SignalDomainColumns"],9099:["US","1","LargestMonochromePixelValue"],9108:["CS","1","DataRepresentation"],9110:["SQ","1","PixelMeasuresSequence"],9132:["SQ","1","FrameVOILUTSequence"],9145:["SQ","1","PixelValueTransformationSequence"],9235:["CS","1","SignalDomainRows"],9411:["FL","1","DisplayFilterPercentage"],9415:["SQ","1","FramePixelShiftSequence"],9416:["US","1","SubtractionItemID"],9422:["SQ","1","PixelIntensityRelationshipLUTSequence"],9443:["SQ","1","FramePixelDataPropertiesSequence"],9444:["CS","1","GeometricalProperties"],9445:["FL","1","GeometricMaximumDistortion"],9446:["CS","1-n","ImageProcessingApplied"],9454:["CS","1","MaskSelectionMode"],9474:["CS","1","LUTFunction"],9478:["FL","1","MaskVisibilityPercentage"],9501:["SQ","1","PixelShiftSequence"],9502:["SQ","1","RegionPixelShiftSequence"],9503:["SS","2-2n","VerticesOfTheRegion"],9505:["SQ","1","MultiFramePresentationSequence"],9506:["US","2-2n","PixelShiftFrameRange"],9507:["US","2-2n","LUTFrameRange"],9520:["DS","16","ImageToEquipmentMappingMatrix"],9537:["CS","1","EquipmentCoordinateSystemIdentification"]},"0032":{"0000":["UL","1","GenericGroupLength"],"000A":["CS","1","StudyStatusID"],"000C":["CS","1","StudyPriorityID"],"0012":["LO","1","StudyIDIssuer"],"0032":["DA","1","StudyVerifiedDate"],"0033":["TM","1","StudyVerifiedTime"],"0034":["DA","1","StudyReadDate"],"0035":["TM","1","StudyReadTime"],1e3:["DA","1","ScheduledStudyStartDate"],1001:["TM","1","ScheduledStudyStartTime"],1010:["DA","1","ScheduledStudyStopDate"],1011:["TM","1","ScheduledStudyStopTime"],1020:["LO","1","ScheduledStudyLocation"],1021:["AE","1-n","ScheduledStudyLocationAETitle"],1030:["LO","1","ReasonForStudy"],1031:["SQ","1","RequestingPhysicianIdentificationSequence"],1032:["PN","1","RequestingPhysician"],1033:["LO","1","RequestingService"],1034:["SQ","1","RequestingServiceCodeSequence"],1040:["DA","1","StudyArrivalDate"],1041:["TM","1","StudyArrivalTime"],1050:["DA","1","StudyCompletionDate"],1051:["TM","1","StudyCompletionTime"],1055:["CS","1","StudyComponentStatusID"],1060:["LO","1","RequestedProcedureDescription"],1064:["SQ","1","RequestedProcedureCodeSequence"],1065:["SQ","1","RequestedLateralityCodeSequence"],1066:["UT","1","ReasonForVisit"],1067:["SQ","1","ReasonForVisitCodeSequence"],1070:["LO","1","RequestedContrastAgent"],4e3:["LT","1","StudyComments"]},"0034":{"0000":["UL","1","GenericGroupLength"],"0001":["SQ","1","FlowIdentifierSequence"],"0002":["OB","1","FlowIdentifier"],"0003":["UI","1","FlowTransferSyntaxUID"],"0004":["UL","1","FlowRTPSamplingRate"],"0005":["OB","1","SourceIdentifier"],"0007":["OB","1","FrameOriginTimestamp"],"0008":["CS","1","IncludesImagingSubject"],"0009":["SQ","1","FrameUsefulnessGroupSequence"],"000A":["SQ","1","RealTimeBulkDataFlowSequence"],"000B":["SQ","1","CameraPositionGroupSequence"],"000C":["CS","1","IncludesInformation"],"000D":["SQ","1","TimeOfFrameGroupSequence"]},"0038":{"0000":["UL","1","GenericGroupLength"],"0004":["SQ","1","ReferencedPatientAliasSequence"],"0008":["CS","1","VisitStatusID"],"0010":["LO","1","AdmissionID"],"0011":["LO","1","IssuerOfAdmissionID"],"0014":["SQ","1","IssuerOfAdmissionIDSequence"],"0016":["LO","1","RouteOfAdmissions"],"001A":["DA","1","ScheduledAdmissionDate"],"001B":["TM","1","ScheduledAdmissionTime"],"001C":["DA","1","ScheduledDischargeDate"],"001D":["TM","1","ScheduledDischargeTime"],"001E":["LO","1","ScheduledPatientInstitutionResidence"],"0020":["DA","1","AdmittingDate"],"0021":["TM","1","AdmittingTime"],"0030":["DA","1","DischargeDate"],"0032":["TM","1","DischargeTime"],"0040":["LO","1","DischargeDiagnosisDescription"],"0044":["SQ","1","DischargeDiagnosisCodeSequence"],"0050":["LO","1","SpecialNeeds"],"0060":["LO","1","ServiceEpisodeID"],"0061":["LO","1","IssuerOfServiceEpisodeID"],"0062":["LO","1","ServiceEpisodeDescription"],"0064":["SQ","1","IssuerOfServiceEpisodeIDSequence"],"0100":["SQ","1","PertinentDocumentsSequence"],"0101":["SQ","1","PertinentResourcesSequence"],"0102":["LO","1","ResourceDescription"],"0300":["LO","1","CurrentPatientLocation"],"0400":["LO","1","PatientInstitutionResidence"],"0500":["LO","1","PatientState"],"0502":["SQ","1","PatientClinicalTrialParticipationSequence"],4e3:["LT","1","VisitComments"]},"003A":{"0000":["UL","1","GenericGroupLength"],"0004":["CS","1","WaveformOriginality"],"0005":["US","1","NumberOfWaveformChannels"],"0010":["UL","1","NumberOfWaveformSamples"],"001A":["DS","1","SamplingFrequency"],"0020":["SH","1","MultiplexGroupLabel"],"0200":["SQ","1","ChannelDefinitionSequence"],"0202":["IS","1","WaveformChannelNumber"],"0203":["SH","1","ChannelLabel"],"0205":["CS","1-n","ChannelStatus"],"0208":["SQ","1","ChannelSourceSequence"],"0209":["SQ","1","ChannelSourceModifiersSequence"],"020A":["SQ","1","SourceWaveformSequence"],"020C":["LO","1","ChannelDerivationDescription"],"0210":["DS","1","ChannelSensitivity"],"0211":["SQ","1","ChannelSensitivityUnitsSequence"],"0212":["DS","1","ChannelSensitivityCorrectionFactor"],"0213":["DS","1","ChannelBaseline"],"0214":["DS","1","ChannelTimeSkew"],"0215":["DS","1","ChannelSampleSkew"],"0218":["DS","1","ChannelOffset"],"021A":["US","1","WaveformBitsStored"],"0220":["DS","1","FilterLowFrequency"],"0221":["DS","1","FilterHighFrequency"],"0222":["DS","1","NotchFilterFrequency"],"0223":["DS","1","NotchFilterBandwidth"],"0230":["FL","1","WaveformDataDisplayScale"],"0231":["US","3","WaveformDisplayBackgroundCIELabValue"],"0240":["SQ","1","WaveformPresentationGroupSequence"],"0241":["US","1","PresentationGroupNumber"],"0242":["SQ","1","ChannelDisplaySequence"],"0244":["US","3","ChannelRecommendedDisplayCIELabValue"],"0245":["FL","1","ChannelPosition"],"0246":["CS","1","DisplayShadingFlag"],"0247":["FL","1","FractionalChannelDisplayScale"],"0248":["FL","1","AbsoluteChannelDisplayScale"],"0300":["SQ","1","MultiplexedAudioChannelsDescriptionCodeSequence"],"0301":["IS","1","ChannelIdentificationCode"],"0302":["CS","1","ChannelMode"],"0310":["UI","1","MultiplexGroupUID"],"0311":["DS","1","PowerlineFrequency"],"0312":["SQ","1","ChannelImpedanceSequence"],"0313":["DS","1","ImpedanceValue"],"0314":["DT","1","ImpedanceMeasurementDateTime"],"0315":["DS","1","ImpedanceMeasurementFrequency"],"0316":["CS","1","ImpedanceMeasurementCurrentType"]},"0040":{"0000":["UL","1","GenericGroupLength"],"0001":["AE","1-n","ScheduledStationAETitle"],"0002":["DA","1","ScheduledProcedureStepStartDate"],"0003":["TM","1","ScheduledProcedureStepStartTime"],"0004":["DA","1","ScheduledProcedureStepEndDate"],"0005":["TM","1","ScheduledProcedureStepEndTime"],"0006":["PN","1","ScheduledPerformingPhysicianName"],"0007":["LO","1","ScheduledProcedureStepDescription"],"0008":["SQ","1","ScheduledProtocolCodeSequence"],"0009":["SH","1","ScheduledProcedureStepID"],"000A":["SQ","1","StageCodeSequence"],"000B":["SQ","1","ScheduledPerformingPhysicianIdentificationSequence"],"0010":["SH","1-n","ScheduledStationName"],"0011":["SH","1","ScheduledProcedureStepLocation"],"0012":["LO","1","PreMedication"],"0020":["CS","1","ScheduledProcedureStepStatus"],"0026":["SQ","1","OrderPlacerIdentifierSequence"],"0027":["SQ","1","OrderFillerIdentifierSequence"],"0031":["UT","1","LocalNamespaceEntityID"],"0032":["UT","1","UniversalEntityID"],"0033":["CS","1","UniversalEntityIDType"],"0035":["CS","1","IdentifierTypeCode"],"0036":["SQ","1","AssigningFacilitySequence"],"0039":["SQ","1","AssigningJurisdictionCodeSequence"],"003A":["SQ","1","AssigningAgencyOrDepartmentCodeSequence"],"0100":["SQ","1","ScheduledProcedureStepSequence"],"0220":["SQ","1","ReferencedNonImageCompositeSOPInstanceSequence"],"0241":["AE","1","PerformedStationAETitle"],"0242":["SH","1","PerformedStationName"],"0243":["SH","1","PerformedLocation"],"0244":["DA","1","PerformedProcedureStepStartDate"],"0245":["TM","1","PerformedProcedureStepStartTime"],"0250":["DA","1","PerformedProcedureStepEndDate"],"0251":["TM","1","PerformedProcedureStepEndTime"],"0252":["CS","1","PerformedProcedureStepStatus"],"0253":["SH","1","PerformedProcedureStepID"],"0254":["LO","1","PerformedProcedureStepDescription"],"0255":["LO","1","PerformedProcedureTypeDescription"],"0260":["SQ","1","PerformedProtocolCodeSequence"],"0261":["CS","1","PerformedProtocolType"],"0270":["SQ","1","ScheduledStepAttributesSequence"],"0275":["SQ","1","RequestAttributesSequence"],"0280":["ST","1","CommentsOnThePerformedProcedureStep"],"0281":["SQ","1","PerformedProcedureStepDiscontinuationReasonCodeSequence"],"0293":["SQ","1","QuantitySequence"],"0294":["DS","1","Quantity"],"0295":["SQ","1","MeasuringUnitsSequence"],"0296":["SQ","1","BillingItemSequence"],"0300":["US","1","TotalTimeOfFluoroscopy"],"0301":["US","1","TotalNumberOfExposures"],"0302":["US","1","EntranceDose"],"0303":["US","1-2","ExposedArea"],"0306":["DS","1","DistanceSourceToEntrance"],"0307":["DS","1","DistanceSourceToSupport"],"030E":["SQ","1","ExposureDoseSequence"],"0310":["ST","1","CommentsOnRadiationDose"],"0312":["DS","1","XRayOutput"],"0314":["DS","1","HalfValueLayer"],"0316":["DS","1","OrganDose"],"0318":["CS","1","OrganExposed"],"0320":["SQ","1","BillingProcedureStepSequence"],"0321":["SQ","1","FilmConsumptionSequence"],"0324":["SQ","1","BillingSuppliesAndDevicesSequence"],"0330":["SQ","1","ReferencedProcedureStepSequence"],"0340":["SQ","1","PerformedSeriesSequence"],"0400":["LT","1","CommentsOnTheScheduledProcedureStep"],"0440":["SQ","1","ProtocolContextSequence"],"0441":["SQ","1","ContentItemModifierSequence"],"0500":["SQ","1","ScheduledSpecimenSequence"],"050A":["LO","1","SpecimenAccessionNumber"],"0512":["LO","1","ContainerIdentifier"],"0513":["SQ","1","IssuerOfTheContainerIdentifierSequence"],"0515":["SQ","1","AlternateContainerIdentifierSequence"],"0518":["SQ","1","ContainerTypeCodeSequence"],"051A":["LO","1","ContainerDescription"],"0520":["SQ","1","ContainerComponentSequence"],"0550":["SQ","1","SpecimenSequence"],"0551":["LO","1","SpecimenIdentifier"],"0552":["SQ","1","SpecimenDescriptionSequenceTrial"],"0553":["ST","1","SpecimenDescriptionTrial"],"0554":["UI","1","SpecimenUID"],"0555":["SQ","1","AcquisitionContextSequence"],"0556":["ST","1","AcquisitionContextDescription"],"0560":["SQ","1","SpecimenDescriptionSequence"],"0562":["SQ","1","IssuerOfTheSpecimenIdentifierSequence"],"059A":["SQ","1","SpecimenTypeCodeSequence"],"0600":["LO","1","SpecimenShortDescription"],"0602":["UT","1","SpecimenDetailedDescription"],"0610":["SQ","1","SpecimenPreparationSequence"],"0612":["SQ","1","SpecimenPreparationStepContentItemSequence"],"0620":["SQ","1","SpecimenLocalizationContentItemSequence"],"06FA":["LO","1","SlideIdentifier"],"0710":["SQ","1","WholeSlideMicroscopyImageFrameTypeSequence"],"071A":["SQ","1","ImageCenterPointCoordinatesSequence"],"072A":["DS","1","XOffsetInSlideCoordinateSystem"],"073A":["DS","1","YOffsetInSlideCoordinateSystem"],"074A":["DS","1","ZOffsetInSlideCoordinateSystem"],"08D8":["SQ","1","PixelSpacingSequence"],"08DA":["SQ","1","CoordinateSystemAxisCodeSequence"],"08EA":["SQ","1","MeasurementUnitsCodeSequence"],"09F8":["SQ","1","VitalStainCodeSequenceTrial"],1001:["SH","1","RequestedProcedureID"],1002:["LO","1","ReasonForTheRequestedProcedure"],1003:["SH","1","RequestedProcedurePriority"],1004:["LO","1","PatientTransportArrangements"],1005:["LO","1","RequestedProcedureLocation"],1006:["SH","1","PlacerOrderNumberProcedure"],1007:["SH","1","FillerOrderNumberProcedure"],1008:["LO","1","ConfidentialityCode"],1009:["SH","1","ReportingPriority"],"100A":["SQ","1","ReasonForRequestedProcedureCodeSequence"],1010:["PN","1-n","NamesOfIntendedRecipientsOfResults"],1011:["SQ","1","IntendedRecipientsOfResultsIdentificationSequence"],1012:["SQ","1","ReasonForPerformedProcedureCodeSequence"],1060:["LO","1","RequestedProcedureDescriptionTrial"],1101:["SQ","1","PersonIdentificationCodeSequence"],1102:["ST","1","PersonAddress"],1103:["LO","1-n","PersonTelephoneNumbers"],1104:["LT","1","PersonTelecomInformation"],1400:["LT","1","RequestedProcedureComments"],2001:["LO","1","ReasonForTheImagingServiceRequest"],2004:["DA","1","IssueDateOfImagingServiceRequest"],2005:["TM","1","IssueTimeOfImagingServiceRequest"],2006:["SH","1","PlacerOrderNumberImagingServiceRequestRetired"],2007:["SH","1","FillerOrderNumberImagingServiceRequestRetired"],2008:["PN","1","OrderEnteredBy"],2009:["SH","1","OrderEntererLocation"],2010:["SH","1","OrderCallbackPhoneNumber"],2011:["LT","1","OrderCallbackTelecomInformation"],2016:["LO","1","PlacerOrderNumberImagingServiceRequest"],2017:["LO","1","FillerOrderNumberImagingServiceRequest"],2400:["LT","1","ImagingServiceRequestComments"],3001:["LO","1","ConfidentialityConstraintOnPatientDataDescription"],4001:["CS","1","GeneralPurposeScheduledProcedureStepStatus"],4002:["CS","1","GeneralPurposePerformedProcedureStepStatus"],4003:["CS","1","GeneralPurposeScheduledProcedureStepPriority"],4004:["SQ","1","ScheduledProcessingApplicationsCodeSequence"],4005:["DT","1","ScheduledProcedureStepStartDateTime"],4006:["CS","1","MultipleCopiesFlag"],4007:["SQ","1","PerformedProcessingApplicationsCodeSequence"],4008:["DT","1","ScheduledProcedureStepExpirationDateTime"],4009:["SQ","1","HumanPerformerCodeSequence"],4010:["DT","1","ScheduledProcedureStepModificationDateTime"],4011:["DT","1","ExpectedCompletionDateTime"],4015:["SQ","1","ResultingGeneralPurposePerformedProcedureStepsSequence"],4016:["SQ","1","ReferencedGeneralPurposeScheduledProcedureStepSequence"],4018:["SQ","1","ScheduledWorkitemCodeSequence"],4019:["SQ","1","PerformedWorkitemCodeSequence"],4020:["CS","1","InputAvailabilityFlag"],4021:["SQ","1","InputInformationSequence"],4022:["SQ","1","RelevantInformationSequence"],4023:["UI","1","ReferencedGeneralPurposeScheduledProcedureStepTransactionUID"],4025:["SQ","1","ScheduledStationNameCodeSequence"],4026:["SQ","1","ScheduledStationClassCodeSequence"],4027:["SQ","1","ScheduledStationGeographicLocationCodeSequence"],4028:["SQ","1","PerformedStationNameCodeSequence"],4029:["SQ","1","PerformedStationClassCodeSequence"],4030:["SQ","1","PerformedStationGeographicLocationCodeSequence"],4031:["SQ","1","RequestedSubsequentWorkitemCodeSequence"],4032:["SQ","1","NonDICOMOutputCodeSequence"],4033:["SQ","1","OutputInformationSequence"],4034:["SQ","1","ScheduledHumanPerformersSequence"],4035:["SQ","1","ActualHumanPerformersSequence"],4036:["LO","1","HumanPerformerOrganization"],4037:["PN","1","HumanPerformerName"],4040:["CS","1","RawDataHandling"],4041:["CS","1","InputReadinessState"],4050:["DT","1","PerformedProcedureStepStartDateTime"],4051:["DT","1","PerformedProcedureStepEndDateTime"],4052:["DT","1","ProcedureStepCancellationDateTime"],4070:["SQ","1","OutputDestinationSequence"],4071:["SQ","1","DICOMStorageSequence"],4072:["SQ","1","STOWRSStorageSequence"],4073:["UR","1","StorageURL"],4074:["SQ","1","XDSStorageSequence"],8302:["DS","1","EntranceDoseInmGy"],8303:["CS","1","EntranceDoseDerivation"],9092:["SQ","1","ParametricMapFrameTypeSequence"],9094:["SQ","1","ReferencedImageRealWorldValueMappingSequence"],9096:["SQ","1","RealWorldValueMappingSequence"],9098:["SQ","1","PixelValueMappingCodeSequence"],9210:["SH","1","LUTLabel"],9211:["xs","1","RealWorldValueLastValueMapped"],9212:["FD","1-n","RealWorldValueLUTData"],9213:["FD","1","DoubleFloatRealWorldValueLastValueMapped"],9214:["FD","1","DoubleFloatRealWorldValueFirstValueMapped"],9216:["xs","1","RealWorldValueFirstValueMapped"],9220:["SQ","1","QuantityDefinitionSequence"],9224:["FD","1","RealWorldValueIntercept"],9225:["FD","1","RealWorldValueSlope"],A007:["CS","1","FindingsFlagTrial"],A010:["CS","1","RelationshipType"],A020:["SQ","1","FindingsSequenceTrial"],A021:["UI","1","FindingsGroupUIDTrial"],A022:["UI","1","ReferencedFindingsGroupUIDTrial"],A023:["DA","1","FindingsGroupRecordingDateTrial"],A024:["TM","1","FindingsGroupRecordingTimeTrial"],A026:["SQ","1","FindingsSourceCategoryCodeSequenceTrial"],A027:["LO","1","VerifyingOrganization"],A028:["SQ","1","DocumentingOrganizationIdentifierCodeSequenceTrial"],A030:["DT","1","VerificationDateTime"],A032:["DT","1","ObservationDateTime"],A033:["DT","1","ObservationStartDateTime"],A040:["CS","1","ValueType"],A043:["SQ","1","ConceptNameCodeSequence"],A047:["LO","1","MeasurementPrecisionDescriptionTrial"],A050:["CS","1","ContinuityOfContent"],A057:["CS","1-n","UrgencyOrPriorityAlertsTrial"],A060:["LO","1","SequencingIndicatorTrial"],A066:["SQ","1","DocumentIdentifierCodeSequenceTrial"],A067:["PN","1","DocumentAuthorTrial"],A068:["SQ","1","DocumentAuthorIdentifierCodeSequenceTrial"],A070:["SQ","1","IdentifierCodeSequenceTrial"],A073:["SQ","1","VerifyingObserverSequence"],A074:["OB","1","ObjectBinaryIdentifierTrial"],A075:["PN","1","VerifyingObserverName"],A076:["SQ","1","DocumentingObserverIdentifierCodeSequenceTrial"],A078:["SQ","1","AuthorObserverSequence"],A07A:["SQ","1","ParticipantSequence"],A07C:["SQ","1","CustodialOrganizationSequence"],A080:["CS","1","ParticipationType"],A082:["DT","1","ParticipationDateTime"],A084:["CS","1","ObserverType"],A085:["SQ","1","ProcedureIdentifierCodeSequenceTrial"],A088:["SQ","1","VerifyingObserverIdentificationCodeSequence"],A089:["OB","1","ObjectDirectoryBinaryIdentifierTrial"],A090:["SQ","1","EquivalentCDADocumentSequence"],A0B0:["US","2-2n","ReferencedWaveformChannels"],A110:["DA","1","DateOfDocumentOrVerbalTransactionTrial"],A112:["TM","1","TimeOfDocumentCreationOrVerbalTransactionTrial"],A120:["DT","1","DateTime"],A121:["DA","1","Date"],A122:["TM","1","Time"],A123:["PN","1","PersonName"],A124:["UI","1","UID"],A125:["CS","2","ReportStatusIDTrial"],A130:["CS","1","TemporalRangeType"],A132:["UL","1-n","ReferencedSamplePositions"],A136:["US","1-n","ReferencedFrameNumbers"],A138:["DS","1-n","ReferencedTimeOffsets"],A13A:["DT","1-n","ReferencedDateTime"],A160:["UT","1","TextValue"],A161:["FD","1-n","FloatingPointValue"],A162:["SL","1-n","RationalNumeratorValue"],A163:["UL","1-n","RationalDenominatorValue"],A167:["SQ","1","ObservationCategoryCodeSequenceTrial"],A168:["SQ","1","ConceptCodeSequence"],A16A:["ST","1","BibliographicCitationTrial"],A170:["SQ","1","PurposeOfReferenceCodeSequence"],A171:["UI","1","ObservationUID"],A172:["UI","1","ReferencedObservationUIDTrial"],A173:["CS","1","ReferencedObservationClassTrial"],A174:["CS","1","ReferencedObjectObservationClassTrial"],A180:["US","1","AnnotationGroupNumber"],A192:["DA","1","ObservationDateTrial"],A193:["TM","1","ObservationTimeTrial"],A194:["CS","1","MeasurementAutomationTrial"],A195:["SQ","1","ModifierCodeSequence"],A224:["ST","1","IdentificationDescriptionTrial"],A290:["CS","1","CoordinatesSetGeometricTypeTrial"],A296:["SQ","1","AlgorithmCodeSequenceTrial"],A297:["ST","1","AlgorithmDescriptionTrial"],A29A:["SL","2-2n","PixelCoordinatesSetTrial"],A300:["SQ","1","MeasuredValueSequence"],A301:["SQ","1","NumericValueQualifierCodeSequence"],A307:["PN","1","CurrentObserverTrial"],A30A:["DS","1-n","NumericValue"],A313:["SQ","1","ReferencedAccessionSequenceTrial"],A33A:["ST","1","ReportStatusCommentTrial"],A340:["SQ","1","ProcedureContextSequenceTrial"],A352:["PN","1","VerbalSourceTrial"],A353:["ST","1","AddressTrial"],A354:["LO","1","TelephoneNumberTrial"],A358:["SQ","1","VerbalSourceIdentifierCodeSequenceTrial"],A360:["SQ","1","PredecessorDocumentsSequence"],A370:["SQ","1","ReferencedRequestSequence"],A372:["SQ","1","PerformedProcedureCodeSequence"],A375:["SQ","1","CurrentRequestedProcedureEvidenceSequence"],A380:["SQ","1","ReportDetailSequenceTrial"],A385:["SQ","1","PertinentOtherEvidenceSequence"],A390:["SQ","1","HL7StructuredDocumentReferenceSequence"],A402:["UI","1","ObservationSubjectUIDTrial"],A403:["CS","1","ObservationSubjectClassTrial"],A404:["SQ","1","ObservationSubjectTypeCodeSequenceTrial"],A491:["CS","1","CompletionFlag"],A492:["LO","1","CompletionFlagDescription"],A493:["CS","1","VerificationFlag"],A494:["CS","1","ArchiveRequested"],A496:["CS","1","PreliminaryFlag"],A504:["SQ","1","ContentTemplateSequence"],A525:["SQ","1","IdenticalDocumentsSequence"],A600:["CS","1","ObservationSubjectContextFlagTrial"],A601:["CS","1","ObserverContextFlagTrial"],A603:["CS","1","ProcedureContextFlagTrial"],A730:["SQ","1","ContentSequence"],A731:["SQ","1","RelationshipSequenceTrial"],A732:["SQ","1","RelationshipTypeCodeSequenceTrial"],A744:["SQ","1","LanguageCodeSequenceTrial"],A801:["SQ","1","TabulatedValuesSequence"],A802:["UL","1","NumberOfTableRows"],A803:["UL","1","NumberOfTableColumns"],A804:["UL","1","TableRowNumber"],A805:["UL","1","TableColumnNumber"],A806:["SQ","1","TableRowDefinitionSequence"],A807:["SQ","1","TableColumnDefinitionSequence"],A808:["SQ","1","CellValuesSequence"],A992:["ST","1","UniformResourceLocatorTrial"],B020:["SQ","1","WaveformAnnotationSequence"],DB00:["CS","1","TemplateIdentifier"],DB06:["DT","1","TemplateVersion"],DB07:["DT","1","TemplateLocalVersion"],DB0B:["CS","1","TemplateExtensionFlag"],DB0C:["UI","1","TemplateExtensionOrganizationUID"],DB0D:["UI","1","TemplateExtensionCreatorUID"],DB73:["UL","1-n","ReferencedContentItemIdentifier"],E001:["ST","1","HL7InstanceIdentifier"],E004:["DT","1","HL7DocumentEffectiveTime"],E006:["SQ","1","HL7DocumentTypeCodeSequence"],E008:["SQ","1","DocumentClassCodeSequence"],E010:["UR","1","RetrieveURI"],E011:["UI","1","RetrieveLocationUID"],E020:["CS","1","TypeOfInstances"],E021:["SQ","1","DICOMRetrievalSequence"],E022:["SQ","1","DICOMMediaRetrievalSequence"],E023:["SQ","1","WADORetrievalSequence"],E024:["SQ","1","XDSRetrievalSequence"],E025:["SQ","1","WADORSRetrievalSequence"],E030:["UI","1","RepositoryUniqueID"],E031:["UI","1","HomeCommunityID"]},"0042":{"0000":["UL","1","GenericGroupLength"],"0010":["ST","1","DocumentTitle"],"0011":["OB","1","EncapsulatedDocument"],"0012":["LO","1","MIMETypeOfEncapsulatedDocument"],"0013":["SQ","1","SourceInstanceSequence"],"0014":["LO","1-n","ListOfMIMETypes"],"0015":["UL","1","EncapsulatedDocumentLength"]},"0044":{"0000":["UL","1","GenericGroupLength"],"0001":["ST","1","ProductPackageIdentifier"],"0002":["CS","1","SubstanceAdministrationApproval"],"0003":["LT","1","ApprovalStatusFurtherDescription"],"0004":["DT","1","ApprovalStatusDateTime"],"0007":["SQ","1","ProductTypeCodeSequence"],"0008":["LO","1-n","ProductName"],"0009":["LT","1","ProductDescription"],"000A":["LO","1","ProductLotIdentifier"],"000B":["DT","1","ProductExpirationDateTime"],"0010":["DT","1","SubstanceAdministrationDateTime"],"0011":["LO","1","SubstanceAdministrationNotes"],"0012":["LO","1","SubstanceAdministrationDeviceID"],"0013":["SQ","1","ProductParameterSequence"],"0019":["SQ","1","SubstanceAdministrationParameterSequence"],"0100":["SQ","1","ApprovalSequence"],"0101":["SQ","1","AssertionCodeSequence"],"0102":["UI","1","AssertionUID"],"0103":["SQ","1","AsserterIdentificationSequence"],"0104":["DT","1","AssertionDateTime"],"0105":["DT","1","AssertionExpirationDateTime"],"0106":["UT","1","AssertionComments"],"0107":["SQ","1","RelatedAssertionSequence"],"0108":["UI","1","ReferencedAssertionUID"],"0109":["SQ","1","ApprovalSubjectSequence"],"010A":["SQ","1","OrganizationalRoleCodeSequence"]},"0046":{"0000":["UL","1","GenericGroupLength"],"0012":["LO","1","LensDescription"],"0014":["SQ","1","RightLensSequence"],"0015":["SQ","1","LeftLensSequence"],"0016":["SQ","1","UnspecifiedLateralityLensSequence"],"0018":["SQ","1","CylinderSequence"],"0028":["SQ","1","PrismSequence"],"0030":["FD","1","HorizontalPrismPower"],"0032":["CS","1","HorizontalPrismBase"],"0034":["FD","1","VerticalPrismPower"],"0036":["CS","1","VerticalPrismBase"],"0038":["CS","1","LensSegmentType"],"0040":["FD","1","OpticalTransmittance"],"0042":["FD","1","ChannelWidth"],"0044":["FD","1","PupilSize"],"0046":["FD","1","CornealSize"],"0047":["SQ","1","CornealSizeSequence"],"0050":["SQ","1","AutorefractionRightEyeSequence"],"0052":["SQ","1","AutorefractionLeftEyeSequence"],"0060":["FD","1","DistancePupillaryDistance"],"0062":["FD","1","NearPupillaryDistance"],"0063":["FD","1","IntermediatePupillaryDistance"],"0064":["FD","1","OtherPupillaryDistance"],"0070":["SQ","1","KeratometryRightEyeSequence"],"0071":["SQ","1","KeratometryLeftEyeSequence"],"0074":["SQ","1","SteepKeratometricAxisSequence"],"0075":["FD","1","RadiusOfCurvature"],"0076":["FD","1","KeratometricPower"],"0077":["FD","1","KeratometricAxis"],"0080":["SQ","1","FlatKeratometricAxisSequence"],"0092":["CS","1","BackgroundColor"],"0094":["CS","1","Optotype"],"0095":["CS","1","OptotypePresentation"],"0097":["SQ","1","SubjectiveRefractionRightEyeSequence"],"0098":["SQ","1","SubjectiveRefractionLeftEyeSequence"],"0100":["SQ","1","AddNearSequence"],"0101":["SQ","1","AddIntermediateSequence"],"0102":["SQ","1","AddOtherSequence"],"0104":["FD","1","AddPower"],"0106":["FD","1","ViewingDistance"],"0110":["SQ","1","CorneaMeasurementsSequence"],"0111":["SQ","1","SourceOfCorneaMeasurementDataCodeSequence"],"0112":["SQ","1","SteepCornealAxisSequence"],"0113":["SQ","1","FlatCornealAxisSequence"],"0114":["FD","1","CornealPower"],"0115":["FD","1","CornealAxis"],"0116":["SQ","1","CorneaMeasurementMethodCodeSequence"],"0117":["FL","1","RefractiveIndexOfCornea"],"0118":["FL","1","RefractiveIndexOfAqueousHumor"],"0121":["SQ","1","VisualAcuityTypeCodeSequence"],"0122":["SQ","1","VisualAcuityRightEyeSequence"],"0123":["SQ","1","VisualAcuityLeftEyeSequence"],"0124":["SQ","1","VisualAcuityBothEyesOpenSequence"],"0125":["CS","1","ViewingDistanceType"],"0135":["SS","2","VisualAcuityModifiers"],"0137":["FD","1","DecimalVisualAcuity"],"0139":["LO","1","OptotypeDetailedDefinition"],"0145":["SQ","1","ReferencedRefractiveMeasurementsSequence"],"0146":["FD","1","SpherePower"],"0147":["FD","1","CylinderPower"],"0201":["CS","1","CornealTopographySurface"],"0202":["FL","2","CornealVertexLocation"],"0203":["FL","1","PupilCentroidXCoordinate"],"0204":["FL","1","PupilCentroidYCoordinate"],"0205":["FL","1","EquivalentPupilRadius"],"0207":["SQ","1","CornealTopographyMapTypeCodeSequence"],"0208":["IS","2-2n","VerticesOfTheOutlineOfPupil"],"0210":["SQ","1","CornealTopographyMappingNormalsSequence"],"0211":["SQ","1","MaximumCornealCurvatureSequence"],"0212":["FL","1","MaximumCornealCurvature"],"0213":["FL","2","MaximumCornealCurvatureLocation"],"0215":["SQ","1","MinimumKeratometricSequence"],"0218":["SQ","1","SimulatedKeratometricCylinderSequence"],"0220":["FL","1","AverageCornealPower"],"0224":["FL","1","CornealISValue"],"0227":["FL","1","AnalyzedArea"],"0230":["FL","1","SurfaceRegularityIndex"],"0232":["FL","1","SurfaceAsymmetryIndex"],"0234":["FL","1","CornealEccentricityIndex"],"0236":["FL","1","KeratoconusPredictionIndex"],"0238":["FL","1","DecimalPotentialVisualAcuity"],"0242":["CS","1","CornealTopographyMapQualityEvaluation"],"0244":["SQ","1","SourceImageCornealProcessedDataSequence"],"0247":["FL","3","CornealPointLocation"],"0248":["CS","1","CornealPointEstimated"],"0249":["FL","1","AxialPower"],"0250":["FL","1","TangentialPower"],"0251":["FL","1","RefractivePower"],"0252":["FL","1","RelativeElevation"],"0253":["FL","1","CornealWavefront"]},"0048":{"0000":["UL","1","GenericGroupLength"],"0001":["FL","1","ImagedVolumeWidth"],"0002":["FL","1","ImagedVolumeHeight"],"0003":["FL","1","ImagedVolumeDepth"],"0006":["UL","1","TotalPixelMatrixColumns"],"0007":["UL","1","TotalPixelMatrixRows"],"0008":["SQ","1","TotalPixelMatrixOriginSequence"],"0010":["CS","1","SpecimenLabelInImage"],"0011":["CS","1","FocusMethod"],"0012":["CS","1","ExtendedDepthOfField"],"0013":["US","1","NumberOfFocalPlanes"],"0014":["FL","1","DistanceBetweenFocalPlanes"],"0015":["US","3","RecommendedAbsentPixelCIELabValue"],"0100":["SQ","1","IlluminatorTypeCodeSequence"],"0102":["DS","6","ImageOrientationSlide"],"0105":["SQ","1","OpticalPathSequence"],"0106":["SH","1","OpticalPathIdentifier"],"0107":["ST","1","OpticalPathDescription"],"0108":["SQ","1","IlluminationColorCodeSequence"],"0110":["SQ","1","SpecimenReferenceSequence"],"0111":["DS","1","CondenserLensPower"],"0112":["DS","1","ObjectiveLensPower"],"0113":["DS","1","ObjectiveLensNumericalAperture"],"0120":["SQ","1","PaletteColorLookupTableSequence"],"0200":["SQ","1","ReferencedImageNavigationSequence"],"0201":["US","2","TopLeftHandCornerOfLocalizerArea"],"0202":["US","2","BottomRightHandCornerOfLocalizerArea"],"0207":["SQ","1","OpticalPathIdentificationSequence"],"021A":["SQ","1","PlanePositionSlideSequence"],"021E":["SL","1","ColumnPositionInTotalImagePixelMatrix"],"021F":["SL","1","RowPositionInTotalImagePixelMatrix"],"0301":["CS","1","PixelOriginInterpretation"],"0302":["UL","1","NumberOfOpticalPaths"],"0303":["UL","1","TotalPixelMatrixFocalPlanes"]},"0050":{"0000":["UL","1","GenericGroupLength"],"0004":["CS","1","CalibrationImage"],"0010":["SQ","1","DeviceSequence"],"0012":["SQ","1","ContainerComponentTypeCodeSequence"],"0013":["FD","1","ContainerComponentThickness"],"0014":["DS","1","DeviceLength"],"0015":["FD","1","ContainerComponentWidth"],"0016":["DS","1","DeviceDiameter"],"0017":["CS","1","DeviceDiameterUnits"],"0018":["DS","1","DeviceVolume"],"0019":["DS","1","InterMarkerDistance"],"001A":["CS","1","ContainerComponentMaterial"],"001B":["LO","1","ContainerComponentID"],"001C":["FD","1","ContainerComponentLength"],"001D":["FD","1","ContainerComponentDiameter"],"001E":["LO","1","ContainerComponentDescription"],"0020":["LO","1","DeviceDescription"],"0021":["ST","1","LongDeviceDescription"]},"0052":{"0000":["UL","1","GenericGroupLength"],"0001":["FL","1","ContrastBolusIngredientPercentByVolume"],"0002":["FD","1","OCTFocalDistance"],"0003":["FD","1","BeamSpotSize"],"0004":["FD","1","EffectiveRefractiveIndex"],"0006":["CS","1","OCTAcquisitionDomain"],"0007":["FD","1","OCTOpticalCenterWavelength"],"0008":["FD","1","AxialResolution"],"0009":["FD","1","RangingDepth"],"0011":["FD","1","ALineRate"],"0012":["US","1","ALinesPerFrame"],"0013":["FD","1","CatheterRotationalRate"],"0014":["FD","1","ALinePixelSpacing"],"0016":["SQ","1","ModeOfPercutaneousAccessSequence"],"0025":["SQ","1","IntravascularOCTFrameTypeSequence"],"0026":["CS","1","OCTZOffsetApplied"],"0027":["SQ","1","IntravascularFrameContentSequence"],"0028":["FD","1","IntravascularLongitudinalDistance"],"0029":["SQ","1","IntravascularOCTFrameContentSequence"],"0030":["SS","1","OCTZOffsetCorrection"],"0031":["CS","1","CatheterDirectionOfRotation"],"0033":["FD","1","SeamLineLocation"],"0034":["FD","1","FirstALineLocation"],"0036":["US","1","SeamLineIndex"],"0038":["US","1","NumberOfPaddedALines"],"0039":["CS","1","InterpolationType"],"003A":["CS","1","RefractiveIndexApplied"]},"0054":{"0000":["UL","1","GenericGroupLength"],"0010":["US","1-n","EnergyWindowVector"],"0011":["US","1","NumberOfEnergyWindows"],"0012":["SQ","1","EnergyWindowInformationSequence"],"0013":["SQ","1","EnergyWindowRangeSequence"],"0014":["DS","1","EnergyWindowLowerLimit"],"0015":["DS","1","EnergyWindowUpperLimit"],"0016":["SQ","1","RadiopharmaceuticalInformationSequence"],"0017":["IS","1","ResidualSyringeCounts"],"0018":["SH","1","EnergyWindowName"],"0020":["US","1-n","DetectorVector"],"0021":["US","1","NumberOfDetectors"],"0022":["SQ","1","DetectorInformationSequence"],"0030":["US","1-n","PhaseVector"],"0031":["US","1","NumberOfPhases"],"0032":["SQ","1","PhaseInformationSequence"],"0033":["US","1","NumberOfFramesInPhase"],"0036":["IS","1","PhaseDelay"],"0038":["IS","1","PauseBetweenFrames"],"0039":["CS","1","PhaseDescription"],"0050":["US","1-n","RotationVector"],"0051":["US","1","NumberOfRotations"],"0052":["SQ","1","RotationInformationSequence"],"0053":["US","1","NumberOfFramesInRotation"],"0060":["US","1-n","RRIntervalVector"],"0061":["US","1","NumberOfRRIntervals"],"0062":["SQ","1","GatedInformationSequence"],"0063":["SQ","1","DataInformationSequence"],"0070":["US","1-n","TimeSlotVector"],"0071":["US","1","NumberOfTimeSlots"],"0072":["SQ","1","TimeSlotInformationSequence"],"0073":["DS","1","TimeSlotTime"],"0080":["US","1-n","SliceVector"],"0081":["US","1","NumberOfSlices"],"0090":["US","1-n","AngularViewVector"],"0100":["US","1-n","TimeSliceVector"],"0101":["US","1","NumberOfTimeSlices"],"0200":["DS","1","StartAngle"],"0202":["CS","1","TypeOfDetectorMotion"],"0210":["IS","1-n","TriggerVector"],"0211":["US","1","NumberOfTriggersInPhase"],"0220":["SQ","1","ViewCodeSequence"],"0222":["SQ","1","ViewModifierCodeSequence"],"0300":["SQ","1","RadionuclideCodeSequence"],"0302":["SQ","1","AdministrationRouteCodeSequence"],"0304":["SQ","1","RadiopharmaceuticalCodeSequence"],"0306":["SQ","1","CalibrationDataSequence"],"0308":["US","1","EnergyWindowNumber"],"0400":["SH","1","ImageID"],"0410":["SQ","1","PatientOrientationCodeSequence"],"0412":["SQ","1","PatientOrientationModifierCodeSequence"],"0414":["SQ","1","PatientGantryRelationshipCodeSequence"],"0500":["CS","1","SliceProgressionDirection"],"0501":["CS","1","ScanProgressionDirection"],1e3:["CS","2","SeriesType"],1001:["CS","1","Units"],1002:["CS","1","CountsSource"],1004:["CS","1","ReprojectionMethod"],1006:["CS","1","SUVType"],1100:["CS","1","RandomsCorrectionMethod"],1101:["LO","1","AttenuationCorrectionMethod"],1102:["CS","1","DecayCorrection"],1103:["LO","1","ReconstructionMethod"],1104:["LO","1","DetectorLinesOfResponseUsed"],1105:["LO","1","ScatterCorrectionMethod"],1200:["DS","1","AxialAcceptance"],1201:["IS","2","AxialMash"],1202:["IS","1","TransverseMash"],1203:["DS","2","DetectorElementSize"],1210:["DS","1","CoincidenceWindowWidth"],1220:["CS","1-n","SecondaryCountsType"],1300:["DS","1","FrameReferenceTime"],1310:["IS","1","PrimaryPromptsCountsAccumulated"],1311:["IS","1-n","SecondaryCountsAccumulated"],1320:["DS","1","SliceSensitivityFactor"],1321:["DS","1","DecayFactor"],1322:["DS","1","DoseCalibrationFactor"],1323:["DS","1","ScatterFractionFactor"],1324:["DS","1","DeadTimeFactor"],1330:["US","1","ImageIndex"],1400:["CS","1-n","CountsIncluded"],1401:["CS","1","DeadTimeCorrectionFlag"]},"0060":{"0000":["UL","1","GenericGroupLength"],3e3:["SQ","1","HistogramSequence"],3002:["US","1","HistogramNumberOfBins"],3004:["xs","1","HistogramFirstBinValue"],3006:["xs","1","HistogramLastBinValue"],3008:["US","1","HistogramBinWidth"],3010:["LO","1","HistogramExplanation"],3020:["UL","1-n","HistogramData"]},"0062":{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","SegmentationType"],"0002":["SQ","1","SegmentSequence"],"0003":["SQ","1","SegmentedPropertyCategoryCodeSequence"],"0004":["US","1","SegmentNumber"],"0005":["LO","1","SegmentLabel"],"0006":["ST","1","SegmentDescription"],"0007":["SQ","1","SegmentationAlgorithmIdentificationSequence"],"0008":["CS","1","SegmentAlgorithmType"],"0009":["LO","1-n","SegmentAlgorithmName"],"000A":["SQ","1","SegmentIdentificationSequence"],"000B":["US","1-n","ReferencedSegmentNumber"],"000C":["US","1","RecommendedDisplayGrayscaleValue"],"000D":["US","3","RecommendedDisplayCIELabValue"],"000E":["US","1","MaximumFractionalValue"],"000F":["SQ","1","SegmentedPropertyTypeCodeSequence"],"0010":["CS","1","SegmentationFractionalType"],"0011":["SQ","1","SegmentedPropertyTypeModifierCodeSequence"],"0012":["SQ","1","UsedSegmentsSequence"],"0013":["CS","1","SegmentsOverlap"],"0020":["UT","1","TrackingID"],"0021":["UI","1","TrackingUID"]},"0064":{"0000":["UL","1","GenericGroupLength"],"0002":["SQ","1","DeformableRegistrationSequence"],"0003":["UI","1","SourceFrameOfReferenceUID"],"0005":["SQ","1","DeformableRegistrationGridSequence"],"0007":["UL","3","GridDimensions"],"0008":["FD","3","GridResolution"],"0009":["OF","1","VectorGridData"],"000F":["SQ","1","PreDeformationMatrixRegistrationSequence"],"0010":["SQ","1","PostDeformationMatrixRegistrationSequence"]},"0066":{"0000":["UL","1","GenericGroupLength"],"0001":["UL","1","NumberOfSurfaces"],"0002":["SQ","1","SurfaceSequence"],"0003":["UL","1","SurfaceNumber"],"0004":["LT","1","SurfaceComments"],"0009":["CS","1","SurfaceProcessing"],"000A":["FL","1","SurfaceProcessingRatio"],"000B":["LO","1","SurfaceProcessingDescription"],"000C":["FL","1","RecommendedPresentationOpacity"],"000D":["CS","1","RecommendedPresentationType"],"000E":["CS","1","FiniteVolume"],"0010":["CS","1","Manifold"],"0011":["SQ","1","SurfacePointsSequence"],"0012":["SQ","1","SurfacePointsNormalsSequence"],"0013":["SQ","1","SurfaceMeshPrimitivesSequence"],"0015":["UL","1","NumberOfSurfacePoints"],"0016":["OF","1","PointCoordinatesData"],"0017":["FL","3","PointPositionAccuracy"],"0018":["FL","1","MeanPointDistance"],"0019":["FL","1","MaximumPointDistance"],"001A":["FL","6","PointsBoundingBoxCoordinates"],"001B":["FL","3","AxisOfRotation"],"001C":["FL","3","CenterOfRotation"],"001E":["UL","1","NumberOfVectors"],"001F":["US","1","VectorDimensionality"],"0020":["FL","1-n","VectorAccuracy"],"0021":["OF","1","VectorCoordinateData"],"0022":["OD","1","DoublePointCoordinatesData"],"0023":["OW","1","TrianglePointIndexList"],"0024":["OW","1","EdgePointIndexList"],"0025":["OW","1","VertexPointIndexList"],"0026":["SQ","1","TriangleStripSequence"],"0027":["SQ","1","TriangleFanSequence"],"0028":["SQ","1","LineSequence"],"0029":["OW","1","PrimitivePointIndexList"],"002A":["UL","1","SurfaceCount"],"002B":["SQ","1","ReferencedSurfaceSequence"],"002C":["UL","1","ReferencedSurfaceNumber"],"002D":["SQ","1","SegmentSurfaceGenerationAlgorithmIdentificationSequence"],"002E":["SQ","1","SegmentSurfaceSourceInstanceSequence"],"002F":["SQ","1","AlgorithmFamilyCodeSequence"],"0030":["SQ","1","AlgorithmNameCodeSequence"],"0031":["LO","1","AlgorithmVersion"],"0032":["LT","1","AlgorithmParameters"],"0034":["SQ","1","FacetSequence"],"0035":["SQ","1","SurfaceProcessingAlgorithmIdentificationSequence"],"0036":["LO","1","AlgorithmName"],"0037":["FL","1","RecommendedPointRadius"],"0038":["FL","1","RecommendedLineThickness"],"0040":["OL","1","LongPrimitivePointIndexList"],"0041":["OL","1","LongTrianglePointIndexList"],"0042":["OL","1","LongEdgePointIndexList"],"0043":["OL","1","LongVertexPointIndexList"],"0101":["SQ","1","TrackSetSequence"],"0102":["SQ","1","TrackSequence"],"0103":["OW","1","RecommendedDisplayCIELabValueList"],"0104":["SQ","1","TrackingAlgorithmIdentificationSequence"],"0105":["UL","1","TrackSetNumber"],"0106":["LO","1","TrackSetLabel"],"0107":["UT","1","TrackSetDescription"],"0108":["SQ","1","TrackSetAnatomicalTypeCodeSequence"],"0121":["SQ","1","MeasurementsSequence"],"0124":["SQ","1","TrackSetStatisticsSequence"],"0125":["OF","1","FloatingPointValues"],"0129":["OL","1","TrackPointIndexList"],"0130":["SQ","1","TrackStatisticsSequence"],"0132":["SQ","1","MeasurementValuesSequence"],"0133":["SQ","1","DiffusionAcquisitionCodeSequence"],"0134":["SQ","1","DiffusionModelCodeSequence"]},"0068":{"0000":["UL","1","GenericGroupLength"],6210:["LO","1","ImplantSize"],6221:["LO","1","ImplantTemplateVersion"],6222:["SQ","1","ReplacedImplantTemplateSequence"],6223:["CS","1","ImplantType"],6224:["SQ","1","DerivationImplantTemplateSequence"],6225:["SQ","1","OriginalImplantTemplateSequence"],6226:["DT","1","EffectiveDateTime"],6230:["SQ","1","ImplantTargetAnatomySequence"],6260:["SQ","1","InformationFromManufacturerSequence"],6265:["SQ","1","NotificationFromManufacturerSequence"],6270:["DT","1","InformationIssueDateTime"],6280:["ST","1","InformationSummary"],"62A0":["SQ","1","ImplantRegulatoryDisapprovalCodeSequence"],"62A5":["FD","1","OverallTemplateSpatialTolerance"],"62C0":["SQ","1","HPGLDocumentSequence"],"62D0":["US","1","HPGLDocumentID"],"62D5":["LO","1","HPGLDocumentLabel"],"62E0":["SQ","1","ViewOrientationCodeSequence"],"62F0":["SQ","1","ViewOrientationModifierCodeSequence"],"62F2":["FD","1","HPGLDocumentScaling"],6300:["OB","1","HPGLDocument"],6310:["US","1","HPGLContourPenNumber"],6320:["SQ","1","HPGLPenSequence"],6330:["US","1","HPGLPenNumber"],6340:["LO","1","HPGLPenLabel"],6345:["ST","1","HPGLPenDescription"],6346:["FD","2","RecommendedRotationPoint"],6347:["FD","4","BoundingRectangle"],6350:["US","1-n","ImplantTemplate3DModelSurfaceNumber"],6360:["SQ","1","SurfaceModelDescriptionSequence"],6380:["LO","1","SurfaceModelLabel"],6390:["FD","1","SurfaceModelScalingFactor"],"63A0":["SQ","1","MaterialsCodeSequence"],"63A4":["SQ","1","CoatingMaterialsCodeSequence"],"63A8":["SQ","1","ImplantTypeCodeSequence"],"63AC":["SQ","1","FixationMethodCodeSequence"],"63B0":["SQ","1","MatingFeatureSetsSequence"],"63C0":["US","1","MatingFeatureSetID"],"63D0":["LO","1","MatingFeatureSetLabel"],"63E0":["SQ","1","MatingFeatureSequence"],"63F0":["US","1","MatingFeatureID"],6400:["SQ","1","MatingFeatureDegreeOfFreedomSequence"],6410:["US","1","DegreeOfFreedomID"],6420:["CS","1","DegreeOfFreedomType"],6430:["SQ","1","TwoDMatingFeatureCoordinatesSequence"],6440:["US","1","ReferencedHPGLDocumentID"],6450:["FD","2","TwoDMatingPoint"],6460:["FD","4","TwoDMatingAxes"],6470:["SQ","1","TwoDDegreeOfFreedomSequence"],6490:["FD","3","ThreeDDegreeOfFreedomAxis"],"64A0":["FD","2","RangeOfFreedom"],"64C0":["FD","3","ThreeDMatingPoint"],"64D0":["FD","9","ThreeDMatingAxes"],"64F0":["FD","3","TwoDDegreeOfFreedomAxis"],6500:["SQ","1","PlanningLandmarkPointSequence"],6510:["SQ","1","PlanningLandmarkLineSequence"],6520:["SQ","1","PlanningLandmarkPlaneSequence"],6530:["US","1","PlanningLandmarkID"],6540:["LO","1","PlanningLandmarkDescription"],6545:["SQ","1","PlanningLandmarkIdentificationCodeSequence"],6550:["SQ","1","TwoDPointCoordinatesSequence"],6560:["FD","2","TwoDPointCoordinates"],6590:["FD","3","ThreeDPointCoordinates"],"65A0":["SQ","1","TwoDLineCoordinatesSequence"],"65B0":["FD","4","TwoDLineCoordinates"],"65D0":["FD","6","ThreeDLineCoordinates"],"65E0":["SQ","1","TwoDPlaneCoordinatesSequence"],"65F0":["FD","4","TwoDPlaneIntersection"],6610:["FD","3","ThreeDPlaneOrigin"],6620:["FD","3","ThreeDPlaneNormal"],7001:["CS","1","ModelModification"],7002:["CS","1","ModelMirroring"],7003:["SQ","1","ModelUsageCodeSequence"],7004:["UI","1","ModelGroupUID"],7005:["UR","1","RelativeURIReferenceWithinEncapsulatedDocument"]},"006A":{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","AnnotationCoordinateType"],"0002":["SQ","1","AnnotationGroupSequence"],"0003":["UI","1","AnnotationGroupUID"],"0005":["LO","1","AnnotationGroupLabel"],"0006":["UT","1","AnnotationGroupDescription"],"0007":["CS","1","AnnotationGroupGenerationType"],"0008":["SQ","1","AnnotationGroupAlgorithmIdentificationSequence"],"0009":["SQ","1","AnnotationPropertyCategoryCodeSequence"],"000A":["SQ","1","AnnotationPropertyTypeCodeSequence"],"000B":["SQ","1","AnnotationPropertyTypeModifierCodeSequence"],"000C":["UL","1","NumberOfAnnotations"],"000D":["CS","1","AnnotationAppliesToAllOpticalPaths"],"000E":["SH","1-n","ReferencedOpticalPathIdentifier"],"000F":["CS","1","AnnotationAppliesToAllZPlanes"],"0010":["FD","1-n","CommonZCoordinateValue"],"0011":["OL","1","AnnotationIndexList"]},"0070":{"0000":["UL","1","GenericGroupLength"],"0001":["SQ","1","GraphicAnnotationSequence"],"0002":["CS","1","GraphicLayer"],"0003":["CS","1","BoundingBoxAnnotationUnits"],"0004":["CS","1","AnchorPointAnnotationUnits"],"0005":["CS","1","GraphicAnnotationUnits"],"0006":["ST","1","UnformattedTextValue"],"0008":["SQ","1","TextObjectSequence"],"0009":["SQ","1","GraphicObjectSequence"],"0010":["FL","2","BoundingBoxTopLeftHandCorner"],"0011":["FL","2","BoundingBoxBottomRightHandCorner"],"0012":["CS","1","BoundingBoxTextHorizontalJustification"],"0014":["FL","2","AnchorPoint"],"0015":["CS","1","AnchorPointVisibility"],"0020":["US","1","GraphicDimensions"],"0021":["US","1","NumberOfGraphicPoints"],"0022":["FL","2-n","GraphicData"],"0023":["CS","1","GraphicType"],"0024":["CS","1","GraphicFilled"],"0040":["IS","1","ImageRotationRetired"],"0041":["CS","1","ImageHorizontalFlip"],"0042":["US","1","ImageRotation"],"0050":["US","2","DisplayedAreaTopLeftHandCornerTrial"],"0051":["US","2","DisplayedAreaBottomRightHandCornerTrial"],"0052":["SL","2","DisplayedAreaTopLeftHandCorner"],"0053":["SL","2","DisplayedAreaBottomRightHandCorner"],"005A":["SQ","1","DisplayedAreaSelectionSequence"],"0060":["SQ","1","GraphicLayerSequence"],"0062":["IS","1","GraphicLayerOrder"],"0066":["US","1","GraphicLayerRecommendedDisplayGrayscaleValue"],"0067":["US","3","GraphicLayerRecommendedDisplayRGBValue"],"0068":["LO","1","GraphicLayerDescription"],"0080":["CS","1","ContentLabel"],"0081":["LO","1","ContentDescription"],"0082":["DA","1","PresentationCreationDate"],"0083":["TM","1","PresentationCreationTime"],"0084":["PN","1","ContentCreatorName"],"0086":["SQ","1","ContentCreatorIdentificationCodeSequence"],"0087":["SQ","1","AlternateContentDescriptionSequence"],"0100":["CS","1","PresentationSizeMode"],"0101":["DS","2","PresentationPixelSpacing"],"0102":["IS","2","PresentationPixelAspectRatio"],"0103":["FL","1","PresentationPixelMagnificationRatio"],"0207":["LO","1","GraphicGroupLabel"],"0208":["ST","1","GraphicGroupDescription"],"0209":["SQ","1","CompoundGraphicSequence"],"0226":["UL","1","CompoundGraphicInstanceID"],"0227":["LO","1","FontName"],"0228":["CS","1","FontNameType"],"0229":["LO","1","CSSFontName"],"0230":["FD","1","RotationAngle"],"0231":["SQ","1","TextStyleSequence"],"0232":["SQ","1","LineStyleSequence"],"0233":["SQ","1","FillStyleSequence"],"0234":["SQ","1","GraphicGroupSequence"],"0241":["US","3","TextColorCIELabValue"],"0242":["CS","1","HorizontalAlignment"],"0243":["CS","1","VerticalAlignment"],"0244":["CS","1","ShadowStyle"],"0245":["FL","1","ShadowOffsetX"],"0246":["FL","1","ShadowOffsetY"],"0247":["US","3","ShadowColorCIELabValue"],"0248":["CS","1","Underlined"],"0249":["CS","1","Bold"],"0250":["CS","1","Italic"],"0251":["US","3","PatternOnColorCIELabValue"],"0252":["US","3","PatternOffColorCIELabValue"],"0253":["FL","1","LineThickness"],"0254":["CS","1","LineDashingStyle"],"0255":["UL","1","LinePattern"],"0256":["OB","1","FillPattern"],"0257":["CS","1","FillMode"],"0258":["FL","1","ShadowOpacity"],"0261":["FL","1","GapLength"],"0262":["FL","1","DiameterOfVisibility"],"0273":["FL","2","RotationPoint"],"0274":["CS","1","TickAlignment"],"0278":["CS","1","ShowTickLabel"],"0279":["CS","1","TickLabelAlignment"],"0282":["CS","1","CompoundGraphicUnits"],"0284":["FL","1","PatternOnOpacity"],"0285":["FL","1","PatternOffOpacity"],"0287":["SQ","1","MajorTicksSequence"],"0288":["FL","1","TickPosition"],"0289":["SH","1","TickLabel"],"0294":["CS","1","CompoundGraphicType"],"0295":["UL","1","GraphicGroupID"],"0306":["CS","1","ShapeType"],"0308":["SQ","1","RegistrationSequence"],"0309":["SQ","1","MatrixRegistrationSequence"],"030A":["SQ","1","MatrixSequence"],"030B":["FD","16","FrameOfReferenceToDisplayedCoordinateSystemTransformationMatrix"],"030C":["CS","1","FrameOfReferenceTransformationMatrixType"],"030D":["SQ","1","RegistrationTypeCodeSequence"],"030F":["ST","1","FiducialDescription"],"0310":["SH","1","FiducialIdentifier"],"0311":["SQ","1","FiducialIdentifierCodeSequence"],"0312":["FD","1","ContourUncertaintyRadius"],"0314":["SQ","1","UsedFiducialsSequence"],"0318":["SQ","1","GraphicCoordinatesDataSequence"],"031A":["UI","1","FiducialUID"],"031B":["UI","1","ReferencedFiducialUID"],"031C":["SQ","1","FiducialSetSequence"],"031E":["SQ","1","FiducialSequence"],"031F":["SQ","1","FiducialsPropertyCategoryCodeSequence"],"0401":["US","3","GraphicLayerRecommendedDisplayCIELabValue"],"0402":["SQ","1","BlendingSequence"],"0403":["FL","1","RelativeOpacity"],"0404":["SQ","1","ReferencedSpatialRegistrationSequence"],"0405":["CS","1","BlendingPosition"],1101:["UI","1","PresentationDisplayCollectionUID"],1102:["UI","1","PresentationSequenceCollectionUID"],1103:["US","1","PresentationSequencePositionIndex"],1104:["SQ","1","RenderedImageReferenceSequence"],1201:["SQ","1","VolumetricPresentationStateInputSequence"],1202:["CS","1","PresentationInputType"],1203:["US","1","InputSequencePositionIndex"],1204:["CS","1","Crop"],1205:["US","1-n","CroppingSpecificationIndex"],1206:["CS","1","CompositingMethod"],1207:["US","1","VolumetricPresentationInputNumber"],1208:["CS","1","ImageVolumeGeometry"],1209:["UI","1","VolumetricPresentationInputSetUID"],"120A":["SQ","1","VolumetricPresentationInputSetSequence"],"120B":["CS","1","GlobalCrop"],"120C":["US","1-n","GlobalCroppingSpecificationIndex"],"120D":["CS","1","RenderingMethod"],1301:["SQ","1","VolumeCroppingSequence"],1302:["CS","1","VolumeCroppingMethod"],1303:["FD","6","BoundingBoxCrop"],1304:["SQ","1","ObliqueCroppingPlaneSequence"],1305:["FD","4","Plane"],1306:["FD","3","PlaneNormal"],1309:["US","1","CroppingSpecificationNumber"],1501:["CS","1","MultiPlanarReconstructionStyle"],1502:["CS","1","MPRThicknessType"],1503:["FD","1","MPRSlabThickness"],1505:["FD","3","MPRTopLeftHandCorner"],1507:["FD","3","MPRViewWidthDirection"],1508:["FD","1","MPRViewWidth"],"150C":["UL","1","NumberOfVolumetricCurvePoints"],"150D":["OD","1","VolumetricCurvePoints"],1511:["FD","3","MPRViewHeightDirection"],1512:["FD","1","MPRViewHeight"],1602:["CS","1","RenderProjection"],1603:["FD","3","ViewpointPosition"],1604:["FD","3","ViewpointLookAtPoint"],1605:["FD","3","ViewpointUpDirection"],1606:["FD","6","RenderFieldOfView"],1607:["FD","1","SamplingStepSize"],1701:["CS","1","ShadingStyle"],1702:["FD","1","AmbientReflectionIntensity"],1703:["FD","3","LightDirection"],1704:["FD","1","DiffuseReflectionIntensity"],1705:["FD","1","SpecularReflectionIntensity"],1706:["FD","1","Shininess"],1801:["SQ","1","PresentationStateClassificationComponentSequence"],1802:["CS","1","ComponentType"],1803:["SQ","1","ComponentInputSequence"],1804:["US","1","VolumetricPresentationInputIndex"],1805:["SQ","1","PresentationStateCompositorComponentSequence"],1806:["SQ","1","WeightingTransferFunctionSequence"],1807:["US","3","WeightingLookupTableDescriptor"],1808:["OB","1","WeightingLookupTableData"],1901:["SQ","1","VolumetricAnnotationSequence"],1903:["SQ","1","ReferencedStructuredContextSequence"],1904:["UI","1","ReferencedContentItem"],1905:["SQ","1","VolumetricPresentationInputAnnotationSequence"],1907:["CS","1","AnnotationClipping"],"1A01":["CS","1","PresentationAnimationStyle"],"1A03":["FD","1","RecommendedAnimationRate"],"1A04":["SQ","1","AnimationCurveSequence"],"1A05":["FD","1","AnimationStepSize"],"1A06":["FD","1","SwivelRange"],"1A07":["OD","1","VolumetricCurveUpDirections"],"1A08":["SQ","1","VolumeStreamSequence"],"1A09":["LO","1","RGBATransferFunctionDescription"],"1B01":["SQ","1","AdvancedBlendingSequence"],"1B02":["US","1","BlendingInputNumber"],"1B03":["SQ","1","BlendingDisplayInputSequence"],"1B04":["SQ","1","BlendingDisplaySequence"],"1B06":["CS","1","BlendingMode"],"1B07":["CS","1","TimeSeriesBlending"],"1B08":["CS","1","GeometryForDisplay"],"1B11":["SQ","1","ThresholdSequence"],"1B12":["SQ","1","ThresholdValueSequence"],"1B13":["CS","1","ThresholdType"],"1B14":["FD","1","ThresholdValue"]},"0072":{"0000":["UL","1","GenericGroupLength"],"0002":["SH","1","HangingProtocolName"],"0004":["LO","1","HangingProtocolDescription"],"0006":["CS","1","HangingProtocolLevel"],"0008":["LO","1","HangingProtocolCreator"],"000A":["DT","1","HangingProtocolCreationDateTime"],"000C":["SQ","1","HangingProtocolDefinitionSequence"],"000E":["SQ","1","HangingProtocolUserIdentificationCodeSequence"],"0010":["LO","1","HangingProtocolUserGroupName"],"0012":["SQ","1","SourceHangingProtocolSequence"],"0014":["US","1","NumberOfPriorsReferenced"],"0020":["SQ","1","ImageSetsSequence"],"0022":["SQ","1","ImageSetSelectorSequence"],"0024":["CS","1","ImageSetSelectorUsageFlag"],"0026":["AT","1","SelectorAttribute"],"0028":["US","1","SelectorValueNumber"],"0030":["SQ","1","TimeBasedImageSetsSequence"],"0032":["US","1","ImageSetNumber"],"0034":["CS","1","ImageSetSelectorCategory"],"0038":["US","2","RelativeTime"],"003A":["CS","1","RelativeTimeUnits"],"003C":["SS","2","AbstractPriorValue"],"003E":["SQ","1","AbstractPriorCodeSequence"],"0040":["LO","1","ImageSetLabel"],"0050":["CS","1","SelectorAttributeVR"],"0052":["AT","1-n","SelectorSequencePointer"],"0054":["LO","1-n","SelectorSequencePointerPrivateCreator"],"0056":["LO","1","SelectorAttributePrivateCreator"],"005E":["AE","1-n","SelectorAEValue"],"005F":["AS","1-n","SelectorASValue"],"0060":["AT","1-n","SelectorATValue"],"0061":["DA","1-n","SelectorDAValue"],"0062":["CS","1-n","SelectorCSValue"],"0063":["DT","1-n","SelectorDTValue"],"0064":["IS","1-n","SelectorISValue"],"0065":["OB","1","SelectorOBValue"],"0066":["LO","1-n","SelectorLOValue"],"0067":["OF","1","SelectorOFValue"],"0068":["LT","1","SelectorLTValue"],"0069":["OW","1","SelectorOWValue"],"006A":["PN","1-n","SelectorPNValue"],"006B":["TM","1-n","SelectorTMValue"],"006C":["SH","1-n","SelectorSHValue"],"006D":["UN","1","SelectorUNValue"],"006E":["ST","1","SelectorSTValue"],"006F":["UC","1-n","SelectorUCValue"],"0070":["UT","1","SelectorUTValue"],"0071":["UR","1","SelectorURValue"],"0072":["DS","1-n","SelectorDSValue"],"0073":["OD","1","SelectorODValue"],"0074":["FD","1-n","SelectorFDValue"],"0075":["OL","1","SelectorOLValue"],"0076":["FL","1-n","SelectorFLValue"],"0078":["UL","1-n","SelectorULValue"],"007A":["US","1-n","SelectorUSValue"],"007C":["SL","1-n","SelectorSLValue"],"007E":["SS","1-n","SelectorSSValue"],"007F":["UI","1-n","SelectorUIValue"],"0080":["SQ","1","SelectorCodeSequenceValue"],"0081":["OV","1","SelectorOVValue"],"0082":["SV","1-n","SelectorSVValue"],"0083":["UV","1-n","SelectorUVValue"],"0100":["US","1","NumberOfScreens"],"0102":["SQ","1","NominalScreenDefinitionSequence"],"0104":["US","1","NumberOfVerticalPixels"],"0106":["US","1","NumberOfHorizontalPixels"],"0108":["FD","4","DisplayEnvironmentSpatialPosition"],"010A":["US","1","ScreenMinimumGrayscaleBitDepth"],"010C":["US","1","ScreenMinimumColorBitDepth"],"010E":["US","1","ApplicationMaximumRepaintTime"],"0200":["SQ","1","DisplaySetsSequence"],"0202":["US","1","DisplaySetNumber"],"0203":["LO","1","DisplaySetLabel"],"0204":["US","1","DisplaySetPresentationGroup"],"0206":["LO","1","DisplaySetPresentationGroupDescription"],"0208":["CS","1","PartialDataDisplayHandling"],"0210":["SQ","1","SynchronizedScrollingSequence"],"0212":["US","2-n","DisplaySetScrollingGroup"],"0214":["SQ","1","NavigationIndicatorSequence"],"0216":["US","1","NavigationDisplaySet"],"0218":["US","1-n","ReferenceDisplaySets"],"0300":["SQ","1","ImageBoxesSequence"],"0302":["US","1","ImageBoxNumber"],"0304":["CS","1","ImageBoxLayoutType"],"0306":["US","1","ImageBoxTileHorizontalDimension"],"0308":["US","1","ImageBoxTileVerticalDimension"],"0310":["CS","1","ImageBoxScrollDirection"],"0312":["CS","1","ImageBoxSmallScrollType"],"0314":["US","1","ImageBoxSmallScrollAmount"],"0316":["CS","1","ImageBoxLargeScrollType"],"0318":["US","1","ImageBoxLargeScrollAmount"],"0320":["US","1","ImageBoxOverlapPriority"],"0330":["FD","1","CineRelativeToRealTime"],"0400":["SQ","1","FilterOperationsSequence"],"0402":["CS","1","FilterByCategory"],"0404":["CS","1","FilterByAttributePresence"],"0406":["CS","1","FilterByOperator"],"0420":["US","3","StructuredDisplayBackgroundCIELabValue"],"0421":["US","3","EmptyImageBoxCIELabValue"],"0422":["SQ","1","StructuredDisplayImageBoxSequence"],"0424":["SQ","1","StructuredDisplayTextBoxSequence"],"0427":["SQ","1","ReferencedFirstFrameSequence"],"0430":["SQ","1","ImageBoxSynchronizationSequence"],"0432":["US","2-n","SynchronizedImageBoxList"],"0434":["CS","1","TypeOfSynchronization"],"0500":["CS","1","BlendingOperationType"],"0510":["CS","1","ReformattingOperationType"],"0512":["FD","1","ReformattingThickness"],"0514":["FD","1","ReformattingInterval"],"0516":["CS","1","ReformattingOperationInitialViewDirection"],"0520":["CS","1-n","ThreeDRenderingType"],"0600":["SQ","1","SortingOperationsSequence"],"0602":["CS","1","SortByCategory"],"0604":["CS","1","SortingDirection"],"0700":["CS","2","DisplaySetPatientOrientation"],"0702":["CS","1","VOIType"],"0704":["CS","1","PseudoColorType"],"0705":["SQ","1","PseudoColorPaletteInstanceReferenceSequence"],"0706":["CS","1","ShowGrayscaleInverted"],"0710":["CS","1","ShowImageTrueSizeFlag"],"0712":["CS","1","ShowGraphicAnnotationFlag"],"0714":["CS","1","ShowPatientDemographicsFlag"],"0716":["CS","1","ShowAcquisitionTechniquesFlag"],"0717":["CS","1","DisplaySetHorizontalJustification"],"0718":["CS","1","DisplaySetVerticalJustification"]},"0074":{"0000":["UL","1","GenericGroupLength"],"0120":["FD","1","ContinuationStartMeterset"],"0121":["FD","1","ContinuationEndMeterset"],1e3:["CS","1","ProcedureStepState"],1002:["SQ","1","ProcedureStepProgressInformationSequence"],1004:["DS","1","ProcedureStepProgress"],1006:["ST","1","ProcedureStepProgressDescription"],1007:["SQ","1","ProcedureStepProgressParametersSequence"],1008:["SQ","1","ProcedureStepCommunicationsURISequence"],"100A":["UR","1","ContactURI"],"100C":["LO","1","ContactDisplayName"],"100E":["SQ","1","ProcedureStepDiscontinuationReasonCodeSequence"],1020:["SQ","1","BeamTaskSequence"],1022:["CS","1","BeamTaskType"],1024:["IS","1","BeamOrderIndexTrial"],1025:["CS","1","AutosequenceFlag"],1026:["FD","1","TableTopVerticalAdjustedPosition"],1027:["FD","1","TableTopLongitudinalAdjustedPosition"],1028:["FD","1","TableTopLateralAdjustedPosition"],"102A":["FD","1","PatientSupportAdjustedAngle"],"102B":["FD","1","TableTopEccentricAdjustedAngle"],"102C":["FD","1","TableTopPitchAdjustedAngle"],"102D":["FD","1","TableTopRollAdjustedAngle"],1030:["SQ","1","DeliveryVerificationImageSequence"],1032:["CS","1","VerificationImageTiming"],1034:["CS","1","DoubleExposureFlag"],1036:["CS","1","DoubleExposureOrdering"],1038:["DS","1","DoubleExposureMetersetTrial"],"103A":["DS","4","DoubleExposureFieldDeltaTrial"],1040:["SQ","1","RelatedReferenceRTImageSequence"],1042:["SQ","1","GeneralMachineVerificationSequence"],1044:["SQ","1","ConventionalMachineVerificationSequence"],1046:["SQ","1","IonMachineVerificationSequence"],1048:["SQ","1","FailedAttributesSequence"],"104A":["SQ","1","OverriddenAttributesSequence"],"104C":["SQ","1","ConventionalControlPointVerificationSequence"],"104E":["SQ","1","IonControlPointVerificationSequence"],1050:["SQ","1","AttributeOccurrenceSequence"],1052:["AT","1","AttributeOccurrencePointer"],1054:["UL","1","AttributeItemSelector"],1056:["LO","1","AttributeOccurrencePrivateCreator"],1057:["IS","1-n","SelectorSequencePointerItems"],1200:["CS","1","ScheduledProcedureStepPriority"],1202:["LO","1","WorklistLabel"],1204:["LO","1","ProcedureStepLabel"],1210:["SQ","1","ScheduledProcessingParametersSequence"],1212:["SQ","1","PerformedProcessingParametersSequence"],1216:["SQ","1","UnifiedProcedureStepPerformedProcedureSequence"],1220:["SQ","1","RelatedProcedureStepSequence"],1222:["LO","1","ProcedureStepRelationshipType"],1224:["SQ","1","ReplacedProcedureStepSequence"],1230:["LO","1","DeletionLock"],1234:["AE","1","ReceivingAE"],1236:["AE","1","RequestingAE"],1238:["LT","1","ReasonForCancellation"],1242:["CS","1","SCPStatus"],1244:["CS","1","SubscriptionListStatus"],1246:["CS","1","UnifiedProcedureStepListStatus"],1324:["UL","1","BeamOrderIndex"],1338:["FD","1","DoubleExposureMeterset"],"133A":["FD","4","DoubleExposureFieldDelta"],1401:["SQ","1","BrachyTaskSequence"],1402:["DS","1","ContinuationStartTotalReferenceAirKerma"],1403:["DS","1","ContinuationEndTotalReferenceAirKerma"],1404:["IS","1","ContinuationPulseNumber"],1405:["SQ","1","ChannelDeliveryOrderSequence"],1406:["IS","1","ReferencedChannelNumber"],1407:["DS","1","StartCumulativeTimeWeight"],1408:["DS","1","EndCumulativeTimeWeight"],1409:["SQ","1","OmittedChannelSequence"],"140A":["CS","1","ReasonForChannelOmission"],"140B":["LO","1","ReasonForChannelOmissionDescription"],"140C":["IS","1","ChannelDeliveryOrderIndex"],"140D":["SQ","1","ChannelDeliveryContinuationSequence"],"140E":["SQ","1","OmittedApplicationSetupSequence"]},"0076":{"0000":["UL","1","GenericGroupLength"],"0001":["LO","1","ImplantAssemblyTemplateName"],"0003":["LO","1","ImplantAssemblyTemplateIssuer"],"0006":["LO","1","ImplantAssemblyTemplateVersion"],"0008":["SQ","1","ReplacedImplantAssemblyTemplateSequence"],"000A":["CS","1","ImplantAssemblyTemplateType"],"000C":["SQ","1","OriginalImplantAssemblyTemplateSequence"],"000E":["SQ","1","DerivationImplantAssemblyTemplateSequence"],"0010":["SQ","1","ImplantAssemblyTemplateTargetAnatomySequence"],"0020":["SQ","1","ProcedureTypeCodeSequence"],"0030":["LO","1","SurgicalTechnique"],"0032":["SQ","1","ComponentTypesSequence"],"0034":["SQ","1","ComponentTypeCodeSequence"],"0036":["CS","1","ExclusiveComponentType"],"0038":["CS","1","MandatoryComponentType"],"0040":["SQ","1","ComponentSequence"],"0055":["US","1","ComponentID"],"0060":["SQ","1","ComponentAssemblySequence"],"0070":["US","1","Component1ReferencedID"],"0080":["US","1","Component1ReferencedMatingFeatureSetID"],"0090":["US","1","Component1ReferencedMatingFeatureID"],"00A0":["US","1","Component2ReferencedID"],"00B0":["US","1","Component2ReferencedMatingFeatureSetID"],"00C0":["US","1","Component2ReferencedMatingFeatureID"]},"0078":{"0000":["UL","1","GenericGroupLength"],"0001":["LO","1","ImplantTemplateGroupName"],"0010":["ST","1","ImplantTemplateGroupDescription"],"0020":["LO","1","ImplantTemplateGroupIssuer"],"0024":["LO","1","ImplantTemplateGroupVersion"],"0026":["SQ","1","ReplacedImplantTemplateGroupSequence"],"0028":["SQ","1","ImplantTemplateGroupTargetAnatomySequence"],"002A":["SQ","1","ImplantTemplateGroupMembersSequence"],"002E":["US","1","ImplantTemplateGroupMemberID"],"0050":["FD","3","ThreeDImplantTemplateGroupMemberMatchingPoint"],"0060":["FD","9","ThreeDImplantTemplateGroupMemberMatchingAxes"],"0070":["SQ","1","ImplantTemplateGroupMemberMatching2DCoordinatesSequence"],"0090":["FD","2","TwoDImplantTemplateGroupMemberMatchingPoint"],"00A0":["FD","4","TwoDImplantTemplateGroupMemberMatchingAxes"],"00B0":["SQ","1","ImplantTemplateGroupVariationDimensionSequence"],"00B2":["LO","1","ImplantTemplateGroupVariationDimensionName"],"00B4":["SQ","1","ImplantTemplateGroupVariationDimensionRankSequence"],"00B6":["US","1","ReferencedImplantTemplateGroupMemberID"],"00B8":["US","1","ImplantTemplateGroupVariationDimensionRank"]},"0080":{"0000":["UL","1","GenericGroupLength"],"0001":["SQ","1","SurfaceScanAcquisitionTypeCodeSequence"],"0002":["SQ","1","SurfaceScanModeCodeSequence"],"0003":["SQ","1","RegistrationMethodCodeSequence"],"0004":["FD","1","ShotDurationTime"],"0005":["FD","1","ShotOffsetTime"],"0006":["US","1-n","SurfacePointPresentationValueData"],"0007":["US","3-3n","SurfacePointColorCIELabValueData"],"0008":["SQ","1","UVMappingSequence"],"0009":["SH","1","TextureLabel"],"0010":["OF","1","UValueData"],"0011":["OF","1","VValueData"],"0012":["SQ","1","ReferencedTextureSequence"],"0013":["SQ","1","ReferencedSurfaceDataSequence"]},"0082":{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","AssessmentSummary"],"0003":["UT","1","AssessmentSummaryDescription"],"0004":["SQ","1","AssessedSOPInstanceSequence"],"0005":["SQ","1","ReferencedComparisonSOPInstanceSequence"],"0006":["UL","1","NumberOfAssessmentObservations"],"0007":["SQ","1","AssessmentObservationsSequence"],"0008":["CS","1","ObservationSignificance"],"000A":["UT","1","ObservationDescription"],"000C":["SQ","1","StructuredConstraintObservationSequence"],"0010":["SQ","1","AssessedAttributeValueSequence"],"0016":["LO","1","AssessmentSetID"],"0017":["SQ","1","AssessmentRequesterSequence"],"0018":["LO","1","SelectorAttributeName"],"0019":["LO","1","SelectorAttributeKeyword"],"0021":["SQ","1","AssessmentTypeCodeSequence"],"0022":["SQ","1","ObservationBasisCodeSequence"],"0023":["LO","1","AssessmentLabel"],"0032":["CS","1","ConstraintType"],"0033":["UT","1","SpecificationSelectionGuidance"],"0034":["SQ","1","ConstraintValueSequence"],"0035":["SQ","1","RecommendedDefaultValueSequence"],"0036":["CS","1","ConstraintViolationSignificance"],"0037":["UT","1","ConstraintViolationCondition"],"0038":["CS","1","ModifiableConstraintFlag"]},"0088":{"0000":["UL","1","GenericGroupLength"],"0130":["SH","1","StorageMediaFileSetID"],"0140":["UI","1","StorageMediaFileSetUID"],"0200":["SQ","1","IconImageSequence"],"0904":["LO","1","TopicTitle"],"0906":["ST","1","TopicSubject"],"0910":["LO","1","TopicAuthor"],"0912":["LO","1-32","TopicKeywords"]},"0100":{"0000":["UL","1","GenericGroupLength"],"0410":["CS","1","SOPInstanceStatus"],"0420":["DT","1","SOPAuthorizationDateTime"],"0424":["LT","1","SOPAuthorizationComment"],"0426":["LO","1","AuthorizationEquipmentCertificationNumber"]},"0400":{"0000":["UL","1","GenericGroupLength"],"0005":["US","1","MACIDNumber"],"0010":["UI","1","MACCalculationTransferSyntaxUID"],"0015":["CS","1","MACAlgorithm"],"0020":["AT","1-n","DataElementsSigned"],"0100":["UI","1","DigitalSignatureUID"],"0105":["DT","1","DigitalSignatureDateTime"],"0110":["CS","1","CertificateType"],"0115":["OB","1","CertificateOfSigner"],"0120":["OB","1","Signature"],"0305":["CS","1","CertifiedTimestampType"],"0310":["OB","1","CertifiedTimestamp"],"0315":["FL","1",""],"0401":["SQ","1","DigitalSignaturePurposeCodeSequence"],"0402":["SQ","1","ReferencedDigitalSignatureSequence"],"0403":["SQ","1","ReferencedSOPInstanceMACSequence"],"0404":["OB","1","MAC"],"0500":["SQ","1","EncryptedAttributesSequence"],"0510":["UI","1","EncryptedContentTransferSyntaxUID"],"0520":["OB","1","EncryptedContent"],"0550":["SQ","1","ModifiedAttributesSequence"],"0551":["SQ","1","NonconformingModifiedAttributesSequence"],"0552":["OB","1","NonconformingDataElementValue"],"0561":["SQ","1","OriginalAttributesSequence"],"0562":["DT","1","AttributeModificationDateTime"],"0563":["LO","1","ModifyingSystem"],"0564":["LO","1","SourceOfPreviousValues"],"0565":["CS","1","ReasonForTheAttributeModification"],"0600":["CS","1","InstanceOriginStatus"]},1e3:{"0000":["UL","1","GenericGroupLength"],"0010":["US","3","EscapeTriplet"],"0011":["US","3","RunLengthTriplet"],"0012":["US","1","HuffmanTableSize"],"0013":["US","3","HuffmanTableTriplet"],"0014":["US","1","ShiftTableSize"],"0015":["US","3","ShiftTableTriplet"]},1010:{"0000":["UL","1","GenericGroupLength"],"0004":["US","1-n","ZonalMap"]},2e3:{"0000":["UL","1","GenericGroupLength"],"0010":["IS","1","NumberOfCopies"],"001E":["SQ","1","PrinterConfigurationSequence"],"0020":["CS","1","PrintPriority"],"0030":["CS","1","MediumType"],"0040":["CS","1","FilmDestination"],"0050":["LO","1","FilmSessionLabel"],"0060":["IS","1","MemoryAllocation"],"0061":["IS","1","MaximumMemoryAllocation"],"0062":["CS","1","ColorImagePrintingFlag"],"0063":["CS","1","CollationFlag"],"0065":["CS","1","AnnotationFlag"],"0067":["CS","1","ImageOverlayFlag"],"0069":["CS","1","PresentationLUTFlag"],"006A":["CS","1","ImageBoxPresentationLUTFlag"],"00A0":["US","1","MemoryBitDepth"],"00A1":["US","1","PrintingBitDepth"],"00A2":["SQ","1","MediaInstalledSequence"],"00A4":["SQ","1","OtherMediaAvailableSequence"],"00A8":["SQ","1","SupportedImageDisplayFormatsSequence"],"0500":["SQ","1","ReferencedFilmBoxSequence"],"0510":["SQ","1","ReferencedStoredPrintSequence"]},2010:{"0000":["UL","1","GenericGroupLength"],"0010":["ST","1","ImageDisplayFormat"],"0030":["CS","1","AnnotationDisplayFormatID"],"0040":["CS","1","FilmOrientation"],"0050":["CS","1","FilmSizeID"],"0052":["CS","1","PrinterResolutionID"],"0054":["CS","1","DefaultPrinterResolutionID"],"0060":["CS","1","MagnificationType"],"0080":["CS","1","SmoothingType"],"00A6":["CS","1","DefaultMagnificationType"],"00A7":["CS","1-n","OtherMagnificationTypesAvailable"],"00A8":["CS","1","DefaultSmoothingType"],"00A9":["CS","1-n","OtherSmoothingTypesAvailable"],"0100":["CS","1","BorderDensity"],"0110":["CS","1","EmptyImageDensity"],"0120":["US","1","MinDensity"],"0130":["US","1","MaxDensity"],"0140":["CS","1","Trim"],"0150":["ST","1","ConfigurationInformation"],"0152":["LT","1","ConfigurationInformationDescription"],"0154":["IS","1","MaximumCollatedFilms"],"015E":["US","1","Illumination"],"0160":["US","1","ReflectedAmbientLight"],"0376":["DS","2","PrinterPixelSpacing"],"0500":["SQ","1","ReferencedFilmSessionSequence"],"0510":["SQ","1","ReferencedImageBoxSequence"],"0520":["SQ","1","ReferencedBasicAnnotationBoxSequence"]},2020:{"0000":["UL","1","GenericGroupLength"],"0010":["US","1","ImageBoxPosition"],"0020":["CS","1","Polarity"],"0030":["DS","1","RequestedImageSize"],"0040":["CS","1","RequestedDecimateCropBehavior"],"0050":["CS","1","RequestedResolutionID"],"00A0":["CS","1","RequestedImageSizeFlag"],"00A2":["CS","1","DecimateCropResult"],"0110":["SQ","1","BasicGrayscaleImageSequence"],"0111":["SQ","1","BasicColorImageSequence"],"0130":["SQ","1","ReferencedImageOverlayBoxSequence"],"0140":["SQ","1","ReferencedVOILUTBoxSequence"]},2030:{"0000":["UL","1","GenericGroupLength"],"0010":["US","1","AnnotationPosition"],"0020":["LO","1","TextString"]},2040:{"0000":["UL","1","GenericGroupLength"],"0010":["SQ","1","ReferencedOverlayPlaneSequence"],"0011":["US","1-99","ReferencedOverlayPlaneGroups"],"0020":["SQ","1","OverlayPixelDataSequence"],"0060":["CS","1","OverlayMagnificationType"],"0070":["CS","1","OverlaySmoothingType"],"0072":["CS","1","OverlayOrImageMagnification"],"0074":["US","1","MagnifyToNumberOfColumns"],"0080":["CS","1","OverlayForegroundDensity"],"0082":["CS","1","OverlayBackgroundDensity"],"0090":["CS","1","OverlayMode"],"0100":["CS","1","ThresholdDensity"],"0500":["SQ","1","ReferencedImageBoxSequenceRetired"]},2050:{"0000":["UL","1","GenericGroupLength"],"0010":["SQ","1","PresentationLUTSequence"],"0020":["CS","1","PresentationLUTShape"],"0500":["SQ","1","ReferencedPresentationLUTSequence"]},2100:{"0000":["UL","1","GenericGroupLength"],"0010":["SH","1","PrintJobID"],"0020":["CS","1","ExecutionStatus"],"0030":["CS","1","ExecutionStatusInfo"],"0040":["DA","1","CreationDate"],"0050":["TM","1","CreationTime"],"0070":["AE","1","Originator"],"0140":["AE","1","DestinationAE"],"0160":["SH","1","OwnerID"],"0170":["IS","1","NumberOfFilms"],"0500":["SQ","1","ReferencedPrintJobSequencePullStoredPrint"]},2110:{"0000":["UL","1","GenericGroupLength"],"0010":["CS","1","PrinterStatus"],"0020":["CS","1","PrinterStatusInfo"],"0030":["LO","1","PrinterName"],"0099":["SH","1","PrintQueueID"]},2120:{"0000":["UL","1","GenericGroupLength"],"0010":["CS","1","QueueStatus"],"0050":["SQ","1","PrintJobDescriptionSequence"],"0070":["SQ","1","ReferencedPrintJobSequence"]},2130:{"0000":["UL","1","GenericGroupLength"],"0010":["SQ","1","PrintManagementCapabilitiesSequence"],"0015":["SQ","1","PrinterCharacteristicsSequence"],"0030":["SQ","1","FilmBoxContentSequence"],"0040":["SQ","1","ImageBoxContentSequence"],"0050":["SQ","1","AnnotationContentSequence"],"0060":["SQ","1","ImageOverlayBoxContentSequence"],"0080":["SQ","1","PresentationLUTContentSequence"],"00A0":["SQ","1","ProposedStudySequence"],"00C0":["SQ","1","OriginalImageSequence"]},2200:{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","LabelUsingInformationExtractedFromInstances"],"0002":["UT","1","LabelText"],"0003":["CS","1","LabelStyleSelection"],"0004":["LT","1","MediaDisposition"],"0005":["LT","1","BarcodeValue"],"0006":["CS","1","BarcodeSymbology"],"0007":["CS","1","AllowMediaSplitting"],"0008":["CS","1","IncludeNonDICOMObjects"],"0009":["CS","1","IncludeDisplayApplication"],"000A":["CS","1","PreserveCompositeInstancesAfterMediaCreation"],"000B":["US","1","TotalNumberOfPiecesOfMediaCreated"],"000C":["LO","1","RequestedMediaApplicationProfile"],"000D":["SQ","1","ReferencedStorageMediaSequence"],"000E":["AT","1-n","FailureAttributes"],"000F":["CS","1","AllowLossyCompression"],"0020":["CS","1","RequestPriority"]},3002:{"0000":["UL","1","GenericGroupLength"],"0002":["SH","1","RTImageLabel"],"0003":["LO","1","RTImageName"],"0004":["ST","1","RTImageDescription"],"000A":["CS","1","ReportedValuesOrigin"],"000C":["CS","1","RTImagePlane"],"000D":["DS","3","XRayImageReceptorTranslation"],"000E":["DS","1","XRayImageReceptorAngle"],"0010":["DS","6","RTImageOrientation"],"0011":["DS","2","ImagePlanePixelSpacing"],"0012":["DS","2","RTImagePosition"],"0020":["SH","1","RadiationMachineName"],"0022":["DS","1","RadiationMachineSAD"],"0024":["DS","1","RadiationMachineSSD"],"0026":["DS","1","RTImageSID"],"0028":["DS","1","SourceToReferenceObjectDistance"],"0029":["IS","1","FractionNumber"],"0030":["SQ","1","ExposureSequence"],"0032":["DS","1","MetersetExposure"],"0034":["DS","4","DiaphragmPosition"],"0040":["SQ","1","FluenceMapSequence"],"0041":["CS","1","FluenceDataSource"],"0042":["DS","1","FluenceDataScale"],"0050":["SQ","1","PrimaryFluenceModeSequence"],"0051":["CS","1","FluenceMode"],"0052":["SH","1","FluenceModeID"]},3004:{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","DVHType"],"0002":["CS","1","DoseUnits"],"0004":["CS","1","DoseType"],"0005":["CS","1","SpatialTransformOfDose"],"0006":["LO","1","DoseComment"],"0008":["DS","3","NormalizationPoint"],"000A":["CS","1","DoseSummationType"],"000C":["DS","2-n","GridFrameOffsetVector"],"000E":["DS","1","DoseGridScaling"],"0010":["SQ","1","RTDoseROISequence"],"0012":["DS","1","DoseValue"],"0014":["CS","1-3","TissueHeterogeneityCorrection"],"0040":["DS","3","DVHNormalizationPoint"],"0042":["DS","1","DVHNormalizationDoseValue"],"0050":["SQ","1","DVHSequence"],"0052":["DS","1","DVHDoseScaling"],"0054":["CS","1","DVHVolumeUnits"],"0056":["IS","1","DVHNumberOfBins"],"0058":["DS","2-2n","DVHData"],"0060":["SQ","1","DVHReferencedROISequence"],"0062":["CS","1","DVHROIContributionType"],"0070":["DS","1","DVHMinimumDose"],"0072":["DS","1","DVHMaximumDose"],"0074":["DS","1","DVHMeanDose"]},3006:{"0000":["UL","1","GenericGroupLength"],"0002":["SH","1","StructureSetLabel"],"0004":["LO","1","StructureSetName"],"0006":["ST","1","StructureSetDescription"],"0008":["DA","1","StructureSetDate"],"0009":["TM","1","StructureSetTime"],"0010":["SQ","1","ReferencedFrameOfReferenceSequence"],"0012":["SQ","1","RTReferencedStudySequence"],"0014":["SQ","1","RTReferencedSeriesSequence"],"0016":["SQ","1","ContourImageSequence"],"0018":["SQ","1","PredecessorStructureSetSequence"],"0020":["SQ","1","StructureSetROISequence"],"0022":["IS","1","ROINumber"],"0024":["UI","1","ReferencedFrameOfReferenceUID"],"0026":["LO","1","ROIName"],"0028":["ST","1","ROIDescription"],"002A":["IS","3","ROIDisplayColor"],"002C":["DS","1","ROIVolume"],"0030":["SQ","1","RTRelatedROISequence"],"0033":["CS","1","RTROIRelationship"],"0036":["CS","1","ROIGenerationAlgorithm"],"0037":["SQ","1","ROIDerivationAlgorithmIdentificationSequence"],"0038":["LO","1","ROIGenerationDescription"],"0039":["SQ","1","ROIContourSequence"],"0040":["SQ","1","ContourSequence"],"0042":["CS","1","ContourGeometricType"],"0044":["DS","1","ContourSlabThickness"],"0045":["DS","3","ContourOffsetVector"],"0046":["IS","1","NumberOfContourPoints"],"0048":["IS","1","ContourNumber"],"0049":["IS","1-n","AttachedContours"],"004A":["SQ","1","SourcePixelPlanesCharacteristicsSequence"],"0050":["DS","3-3n","ContourData"],"0080":["SQ","1","RTROIObservationsSequence"],"0082":["IS","1","ObservationNumber"],"0084":["IS","1","ReferencedROINumber"],"0085":["SH","1","ROIObservationLabel"],"0086":["SQ","1","RTROIIdentificationCodeSequence"],"0088":["ST","1","ROIObservationDescription"],"00A0":["SQ","1","RelatedRTROIObservationsSequence"],"00A4":["CS","1","RTROIInterpretedType"],"00A6":["PN","1","ROIInterpreter"],"00B0":["SQ","1","ROIPhysicalPropertiesSequence"],"00B2":["CS","1","ROIPhysicalProperty"],"00B4":["DS","1","ROIPhysicalPropertyValue"],"00B6":["SQ","1","ROIElementalCompositionSequence"],"00B7":["US","1","ROIElementalCompositionAtomicNumber"],"00B8":["FL","1","ROIElementalCompositionAtomicMassFraction"],"00B9":["SQ","1","AdditionalRTROIIdentificationCodeSequence"],"00C0":["SQ","1","FrameOfReferenceRelationshipSequence"],"00C2":["UI","1","RelatedFrameOfReferenceUID"],"00C4":["CS","1","FrameOfReferenceTransformationType"],"00C6":["DS","16","FrameOfReferenceTransformationMatrix"],"00C8":["LO","1","FrameOfReferenceTransformationComment"],"00C9":["SQ","1","PatientLocationCoordinatesSequence"],"00CA":["SQ","1","PatientLocationCoordinatesCodeSequence"],"00CB":["SQ","1","PatientSupportPositionSequence"]},3008:{"0000":["UL","1","GenericGroupLength"],"0010":["SQ","1","MeasuredDoseReferenceSequence"],"0012":["ST","1","MeasuredDoseDescription"],"0014":["CS","1","MeasuredDoseType"],"0016":["DS","1","MeasuredDoseValue"],"0020":["SQ","1","TreatmentSessionBeamSequence"],"0021":["SQ","1","TreatmentSessionIonBeamSequence"],"0022":["IS","1","CurrentFractionNumber"],"0024":["DA","1","TreatmentControlPointDate"],"0025":["TM","1","TreatmentControlPointTime"],"002A":["CS","1","TreatmentTerminationStatus"],"002B":["SH","1","TreatmentTerminationCode"],"002C":["CS","1","TreatmentVerificationStatus"],"0030":["SQ","1","ReferencedTreatmentRecordSequence"],"0032":["DS","1","SpecifiedPrimaryMeterset"],"0033":["DS","1","SpecifiedSecondaryMeterset"],"0036":["DS","1","DeliveredPrimaryMeterset"],"0037":["DS","1","DeliveredSecondaryMeterset"],"003A":["DS","1","SpecifiedTreatmentTime"],"003B":["DS","1","DeliveredTreatmentTime"],"0040":["SQ","1","ControlPointDeliverySequence"],"0041":["SQ","1","IonControlPointDeliverySequence"],"0042":["DS","1","SpecifiedMeterset"],"0044":["DS","1","DeliveredMeterset"],"0045":["FL","1","MetersetRateSet"],"0046":["FL","1","MetersetRateDelivered"],"0047":["FL","1-n","ScanSpotMetersetsDelivered"],"0048":["DS","1","DoseRateDelivered"],"0050":["SQ","1","TreatmentSummaryCalculatedDoseReferenceSequence"],"0052":["DS","1","CumulativeDoseToDoseReference"],"0054":["DA","1","FirstTreatmentDate"],"0056":["DA","1","MostRecentTreatmentDate"],"005A":["IS","1","NumberOfFractionsDelivered"],"0060":["SQ","1","OverrideSequence"],"0061":["AT","1","ParameterSequencePointer"],"0062":["AT","1","OverrideParameterPointer"],"0063":["IS","1","ParameterItemIndex"],"0064":["IS","1","MeasuredDoseReferenceNumber"],"0065":["AT","1","ParameterPointer"],"0066":["ST","1","OverrideReason"],"0067":["US","1","ParameterValueNumber"],"0068":["SQ","1","CorrectedParameterSequence"],"006A":["FL","1","CorrectionValue"],"0070":["SQ","1","CalculatedDoseReferenceSequence"],"0072":["IS","1","CalculatedDoseReferenceNumber"],"0074":["ST","1","CalculatedDoseReferenceDescription"],"0076":["DS","1","CalculatedDoseReferenceDoseValue"],"0078":["DS","1","StartMeterset"],"007A":["DS","1","EndMeterset"],"0080":["SQ","1","ReferencedMeasuredDoseReferenceSequence"],"0082":["IS","1","ReferencedMeasuredDoseReferenceNumber"],"0090":["SQ","1","ReferencedCalculatedDoseReferenceSequence"],"0092":["IS","1","ReferencedCalculatedDoseReferenceNumber"],"00A0":["SQ","1","BeamLimitingDeviceLeafPairsSequence"],"00B0":["SQ","1","RecordedWedgeSequence"],"00C0":["SQ","1","RecordedCompensatorSequence"],"00D0":["SQ","1","RecordedBlockSequence"],"00D1":["SQ","1","RecordedBlockSlabSequence"],"00E0":["SQ","1","TreatmentSummaryMeasuredDoseReferenceSequence"],"00F0":["SQ","1","RecordedSnoutSequence"],"00F2":["SQ","1","RecordedRangeShifterSequence"],"00F4":["SQ","1","RecordedLateralSpreadingDeviceSequence"],"00F6":["SQ","1","RecordedRangeModulatorSequence"],"0100":["SQ","1","RecordedSourceSequence"],"0105":["LO","1","SourceSerialNumber"],"0110":["SQ","1","TreatmentSessionApplicationSetupSequence"],"0116":["CS","1","ApplicationSetupCheck"],"0120":["SQ","1","RecordedBrachyAccessoryDeviceSequence"],"0122":["IS","1","ReferencedBrachyAccessoryDeviceNumber"],"0130":["SQ","1","RecordedChannelSequence"],"0132":["DS","1","SpecifiedChannelTotalTime"],"0134":["DS","1","DeliveredChannelTotalTime"],"0136":["IS","1","SpecifiedNumberOfPulses"],"0138":["IS","1","DeliveredNumberOfPulses"],"013A":["DS","1","SpecifiedPulseRepetitionInterval"],"013C":["DS","1","DeliveredPulseRepetitionInterval"],"0140":["SQ","1","RecordedSourceApplicatorSequence"],"0142":["IS","1","ReferencedSourceApplicatorNumber"],"0150":["SQ","1","RecordedChannelShieldSequence"],"0152":["IS","1","ReferencedChannelShieldNumber"],"0160":["SQ","1","BrachyControlPointDeliveredSequence"],"0162":["DA","1","SafePositionExitDate"],"0164":["TM","1","SafePositionExitTime"],"0166":["DA","1","SafePositionReturnDate"],"0168":["TM","1","SafePositionReturnTime"],"0171":["SQ","1","PulseSpecificBrachyControlPointDeliveredSequence"],"0172":["US","1","PulseNumber"],"0173":["SQ","1","BrachyPulseControlPointDeliveredSequence"],"0200":["CS","1","CurrentTreatmentStatus"],"0202":["ST","1","TreatmentStatusComment"],"0220":["SQ","1","FractionGroupSummarySequence"],"0223":["IS","1","ReferencedFractionNumber"],"0224":["CS","1","FractionGroupType"],"0230":["CS","1","BeamStopperPosition"],"0240":["SQ","1","FractionStatusSummarySequence"],"0250":["DA","1","TreatmentDate"],"0251":["TM","1","TreatmentTime"]},"300A":{"0000":["UL","1","GenericGroupLength"],"0002":["SH","1","RTPlanLabel"],"0003":["LO","1","RTPlanName"],"0004":["ST","1","RTPlanDescription"],"0006":["DA","1","RTPlanDate"],"0007":["TM","1","RTPlanTime"],"0009":["LO","1-n","TreatmentProtocols"],"000A":["CS","1","PlanIntent"],"000B":["LO","1-n","TreatmentSites"],"000C":["CS","1","RTPlanGeometry"],"000E":["ST","1","PrescriptionDescription"],"0010":["SQ","1","DoseReferenceSequence"],"0012":["IS","1","DoseReferenceNumber"],"0013":["UI","1","DoseReferenceUID"],"0014":["CS","1","DoseReferenceStructureType"],"0015":["CS","1","NominalBeamEnergyUnit"],"0016":["LO","1","DoseReferenceDescription"],"0018":["DS","3","DoseReferencePointCoordinates"],"001A":["DS","1","NominalPriorDose"],"0020":["CS","1","DoseReferenceType"],"0021":["DS","1","ConstraintWeight"],"0022":["DS","1","DeliveryWarningDose"],"0023":["DS","1","DeliveryMaximumDose"],"0025":["DS","1","TargetMinimumDose"],"0026":["DS","1","TargetPrescriptionDose"],"0027":["DS","1","TargetMaximumDose"],"0028":["DS","1","TargetUnderdoseVolumeFraction"],"002A":["DS","1","OrganAtRiskFullVolumeDose"],"002B":["DS","1","OrganAtRiskLimitDose"],"002C":["DS","1","OrganAtRiskMaximumDose"],"002D":["DS","1","OrganAtRiskOverdoseVolumeFraction"],"0040":["SQ","1","ToleranceTableSequence"],"0042":["IS","1","ToleranceTableNumber"],"0043":["SH","1","ToleranceTableLabel"],"0044":["DS","1","GantryAngleTolerance"],"0046":["DS","1","BeamLimitingDeviceAngleTolerance"],"0048":["SQ","1","BeamLimitingDeviceToleranceSequence"],"004A":["DS","1","BeamLimitingDevicePositionTolerance"],"004B":["FL","1","SnoutPositionTolerance"],"004C":["DS","1","PatientSupportAngleTolerance"],"004E":["DS","1","TableTopEccentricAngleTolerance"],"004F":["FL","1","TableTopPitchAngleTolerance"],"0050":["FL","1","TableTopRollAngleTolerance"],"0051":["DS","1","TableTopVerticalPositionTolerance"],"0052":["DS","1","TableTopLongitudinalPositionTolerance"],"0053":["DS","1","TableTopLateralPositionTolerance"],"0055":["CS","1","RTPlanRelationship"],"0070":["SQ","1","FractionGroupSequence"],"0071":["IS","1","FractionGroupNumber"],"0072":["LO","1","FractionGroupDescription"],"0078":["IS","1","NumberOfFractionsPlanned"],"0079":["IS","1","NumberOfFractionPatternDigitsPerDay"],"007A":["IS","1","RepeatFractionCycleLength"],"007B":["LT","1","FractionPattern"],"0080":["IS","1","NumberOfBeams"],"0082":["DS","3","BeamDoseSpecificationPoint"],"0083":["UI","1","ReferencedDoseReferenceUID"],"0084":["DS","1","BeamDose"],"0086":["DS","1","BeamMeterset"],"0088":["FL","1","BeamDosePointDepth"],"0089":["FL","1","BeamDosePointEquivalentDepth"],"008A":["FL","1","BeamDosePointSSD"],"008B":["CS","1","BeamDoseMeaning"],"008C":["SQ","1","BeamDoseVerificationControlPointSequence"],"008D":["FL","1","AverageBeamDosePointDepth"],"008E":["FL","1","AverageBeamDosePointEquivalentDepth"],"008F":["FL","1","AverageBeamDosePointSSD"],"0090":["CS","1","BeamDoseType"],"0091":["DS","1","AlternateBeamDose"],"0092":["CS","1","AlternateBeamDoseType"],"0093":["CS","1","DepthValueAveragingFlag"],"0094":["DS","1","BeamDosePointSourceToExternalContourDistance"],"00A0":["IS","1","NumberOfBrachyApplicationSetups"],"00A2":["DS","3","BrachyApplicationSetupDoseSpecificationPoint"],"00A4":["DS","1","BrachyApplicationSetupDose"],"00B0":["SQ","1","BeamSequence"],"00B2":["SH","1","TreatmentMachineName"],"00B3":["CS","1","PrimaryDosimeterUnit"],"00B4":["DS","1","SourceAxisDistance"],"00B6":["SQ","1","BeamLimitingDeviceSequence"],"00B8":["CS","1","RTBeamLimitingDeviceType"],"00BA":["DS","1","SourceToBeamLimitingDeviceDistance"],"00BB":["FL","1","IsocenterToBeamLimitingDeviceDistance"],"00BC":["IS","1","NumberOfLeafJawPairs"],"00BE":["DS","3-n","LeafPositionBoundaries"],"00C0":["IS","1","BeamNumber"],"00C2":["LO","1","BeamName"],"00C3":["ST","1","BeamDescription"],"00C4":["CS","1","BeamType"],"00C5":["FD","1","BeamDeliveryDurationLimit"],"00C6":["CS","1","RadiationType"],"00C7":["CS","1","HighDoseTechniqueType"],"00C8":["IS","1","ReferenceImageNumber"],"00CA":["SQ","1","PlannedVerificationImageSequence"],"00CC":["LO","1-n","ImagingDeviceSpecificAcquisitionParameters"],"00CE":["CS","1","TreatmentDeliveryType"],"00D0":["IS","1","NumberOfWedges"],"00D1":["SQ","1","WedgeSequence"],"00D2":["IS","1","WedgeNumber"],"00D3":["CS","1","WedgeType"],"00D4":["SH","1","WedgeID"],"00D5":["IS","1","WedgeAngle"],"00D6":["DS","1","WedgeFactor"],"00D7":["FL","1","TotalWedgeTrayWaterEquivalentThickness"],"00D8":["DS","1","WedgeOrientation"],"00D9":["FL","1","IsocenterToWedgeTrayDistance"],"00DA":["DS","1","SourceToWedgeTrayDistance"],"00DB":["FL","1","WedgeThinEdgePosition"],"00DC":["SH","1","BolusID"],"00DD":["ST","1","BolusDescription"],"00DE":["DS","1","EffectiveWedgeAngle"],"00E0":["IS","1","NumberOfCompensators"],"00E1":["SH","1","MaterialID"],"00E2":["DS","1","TotalCompensatorTrayFactor"],"00E3":["SQ","1","CompensatorSequence"],"00E4":["IS","1","CompensatorNumber"],"00E5":["SH","1","CompensatorID"],"00E6":["DS","1","SourceToCompensatorTrayDistance"],"00E7":["IS","1","CompensatorRows"],"00E8":["IS","1","CompensatorColumns"],"00E9":["DS","2","CompensatorPixelSpacing"],"00EA":["DS","2","CompensatorPosition"],"00EB":["DS","1-n","CompensatorTransmissionData"],"00EC":["DS","1-n","CompensatorThicknessData"],"00ED":["IS","1","NumberOfBoli"],"00EE":["CS","1","CompensatorType"],"00EF":["SH","1","CompensatorTrayID"],"00F0":["IS","1","NumberOfBlocks"],"00F2":["DS","1","TotalBlockTrayFactor"],"00F3":["FL","1","TotalBlockTrayWaterEquivalentThickness"],"00F4":["SQ","1","BlockSequence"],"00F5":["SH","1","BlockTrayID"],"00F6":["DS","1","SourceToBlockTrayDistance"],"00F7":["FL","1","IsocenterToBlockTrayDistance"],"00F8":["CS","1","BlockType"],"00F9":["LO","1","AccessoryCode"],"00FA":["CS","1","BlockDivergence"],"00FB":["CS","1","BlockMountingPosition"],"00FC":["IS","1","BlockNumber"],"00FE":["LO","1","BlockName"],"0100":["DS","1","BlockThickness"],"0102":["DS","1","BlockTransmission"],"0104":["IS","1","BlockNumberOfPoints"],"0106":["DS","2-2n","BlockData"],"0107":["SQ","1","ApplicatorSequence"],"0108":["SH","1","ApplicatorID"],"0109":["CS","1","ApplicatorType"],"010A":["LO","1","ApplicatorDescription"],"010C":["DS","1","CumulativeDoseReferenceCoefficient"],"010E":["DS","1","FinalCumulativeMetersetWeight"],"0110":["IS","1","NumberOfControlPoints"],"0111":["SQ","1","ControlPointSequence"],"0112":["IS","1","ControlPointIndex"],"0114":["DS","1","NominalBeamEnergy"],"0115":["DS","1","DoseRateSet"],"0116":["SQ","1","WedgePositionSequence"],"0118":["CS","1","WedgePosition"],"011A":["SQ","1","BeamLimitingDevicePositionSequence"],"011C":["DS","2-2n","LeafJawPositions"],"011E":["DS","1","GantryAngle"],"011F":["CS","1","GantryRotationDirection"],"0120":["DS","1","BeamLimitingDeviceAngle"],"0121":["CS","1","BeamLimitingDeviceRotationDirection"],"0122":["DS","1","PatientSupportAngle"],"0123":["CS","1","PatientSupportRotationDirection"],"0124":["DS","1","TableTopEccentricAxisDistance"],"0125":["DS","1","TableTopEccentricAngle"],"0126":["CS","1","TableTopEccentricRotationDirection"],"0128":["DS","1","TableTopVerticalPosition"],"0129":["DS","1","TableTopLongitudinalPosition"],"012A":["DS","1","TableTopLateralPosition"],"012C":["DS","3","IsocenterPosition"],"012E":["DS","3","SurfaceEntryPoint"],"0130":["DS","1","SourceToSurfaceDistance"],"0131":["FL","1","AverageBeamDosePointSourceToExternalContourDistance"],"0132":["FL","1","SourceToExternalContourDistance"],"0133":["FL","3","ExternalContourEntryPoint"],"0134":["DS","1","CumulativeMetersetWeight"],"0140":["FL","1","TableTopPitchAngle"],"0142":["CS","1","TableTopPitchRotationDirection"],"0144":["FL","1","TableTopRollAngle"],"0146":["CS","1","TableTopRollRotationDirection"],"0148":["FL","1","HeadFixationAngle"],"014A":["FL","1","GantryPitchAngle"],"014C":["CS","1","GantryPitchRotationDirection"],"014E":["FL","1","GantryPitchAngleTolerance"],"0150":["CS","1","FixationEye"],"0151":["DS","1","ChairHeadFramePosition"],"0152":["DS","1","HeadFixationAngleTolerance"],"0153":["DS","1","ChairHeadFramePositionTolerance"],"0154":["DS","1","FixationLightAzimuthalAngleTolerance"],"0155":["DS","1","FixationLightPolarAngleTolerance"],"0180":["SQ","1","PatientSetupSequence"],"0182":["IS","1","PatientSetupNumber"],"0183":["LO","1","PatientSetupLabel"],"0184":["LO","1","PatientAdditionalPosition"],"0190":["SQ","1","FixationDeviceSequence"],"0192":["CS","1","FixationDeviceType"],"0194":["SH","1","FixationDeviceLabel"],"0196":["ST","1","FixationDeviceDescription"],"0198":["SH","1","FixationDevicePosition"],"0199":["FL","1","FixationDevicePitchAngle"],"019A":["FL","1","FixationDeviceRollAngle"],"01A0":["SQ","1","ShieldingDeviceSequence"],"01A2":["CS","1","ShieldingDeviceType"],"01A4":["SH","1","ShieldingDeviceLabel"],"01A6":["ST","1","ShieldingDeviceDescription"],"01A8":["SH","1","ShieldingDevicePosition"],"01B0":["CS","1","SetupTechnique"],"01B2":["ST","1","SetupTechniqueDescription"],"01B4":["SQ","1","SetupDeviceSequence"],"01B6":["CS","1","SetupDeviceType"],"01B8":["SH","1","SetupDeviceLabel"],"01BA":["ST","1","SetupDeviceDescription"],"01BC":["DS","1","SetupDeviceParameter"],"01D0":["ST","1","SetupReferenceDescription"],"01D2":["DS","1","TableTopVerticalSetupDisplacement"],"01D4":["DS","1","TableTopLongitudinalSetupDisplacement"],"01D6":["DS","1","TableTopLateralSetupDisplacement"],"0200":["CS","1","BrachyTreatmentTechnique"],"0202":["CS","1","BrachyTreatmentType"],"0206":["SQ","1","TreatmentMachineSequence"],"0210":["SQ","1","SourceSequence"],"0212":["IS","1","SourceNumber"],"0214":["CS","1","SourceType"],"0216":["LO","1","SourceManufacturer"],"0218":["DS","1","ActiveSourceDiameter"],"021A":["DS","1","ActiveSourceLength"],"021B":["SH","1","SourceModelID"],"021C":["LO","1","SourceDescription"],"0222":["DS","1","SourceEncapsulationNominalThickness"],"0224":["DS","1","SourceEncapsulationNominalTransmission"],"0226":["LO","1","SourceIsotopeName"],"0228":["DS","1","SourceIsotopeHalfLife"],"0229":["CS","1","SourceStrengthUnits"],"022A":["DS","1","ReferenceAirKermaRate"],"022B":["DS","1","SourceStrength"],"022C":["DA","1","SourceStrengthReferenceDate"],"022E":["TM","1","SourceStrengthReferenceTime"],"0230":["SQ","1","ApplicationSetupSequence"],"0232":["CS","1","ApplicationSetupType"],"0234":["IS","1","ApplicationSetupNumber"],"0236":["LO","1","ApplicationSetupName"],"0238":["LO","1","ApplicationSetupManufacturer"],"0240":["IS","1","TemplateNumber"],"0242":["SH","1","TemplateType"],"0244":["LO","1","TemplateName"],"0250":["DS","1","TotalReferenceAirKerma"],"0260":["SQ","1","BrachyAccessoryDeviceSequence"],"0262":["IS","1","BrachyAccessoryDeviceNumber"],"0263":["SH","1","BrachyAccessoryDeviceID"],"0264":["CS","1","BrachyAccessoryDeviceType"],"0266":["LO","1","BrachyAccessoryDeviceName"],"026A":["DS","1","BrachyAccessoryDeviceNominalThickness"],"026C":["DS","1","BrachyAccessoryDeviceNominalTransmission"],"0271":["DS","1","ChannelEffectiveLength"],"0272":["DS","1","ChannelInnerLength"],"0273":["SH","1","AfterloaderChannelID"],"0274":["DS","1","SourceApplicatorTipLength"],"0280":["SQ","1","ChannelSequence"],"0282":["IS","1","ChannelNumber"],"0284":["DS","1","ChannelLength"],"0286":["DS","1","ChannelTotalTime"],"0288":["CS","1","SourceMovementType"],"028A":["IS","1","NumberOfPulses"],"028C":["DS","1","PulseRepetitionInterval"],"0290":["IS","1","SourceApplicatorNumber"],"0291":["SH","1","SourceApplicatorID"],"0292":["CS","1","SourceApplicatorType"],"0294":["LO","1","SourceApplicatorName"],"0296":["DS","1","SourceApplicatorLength"],"0298":["LO","1","SourceApplicatorManufacturer"],"029C":["DS","1","SourceApplicatorWallNominalThickness"],"029E":["DS","1","SourceApplicatorWallNominalTransmission"],"02A0":["DS","1","SourceApplicatorStepSize"],"02A1":["IS","1","ApplicatorShapeReferencedROINumber"],"02A2":["IS","1","TransferTubeNumber"],"02A4":["DS","1","TransferTubeLength"],"02B0":["SQ","1","ChannelShieldSequence"],"02B2":["IS","1","ChannelShieldNumber"],"02B3":["SH","1","ChannelShieldID"],"02B4":["LO","1","ChannelShieldName"],"02B8":["DS","1","ChannelShieldNominalThickness"],"02BA":["DS","1","ChannelShieldNominalTransmission"],"02C8":["DS","1","FinalCumulativeTimeWeight"],"02D0":["SQ","1","BrachyControlPointSequence"],"02D2":["DS","1","ControlPointRelativePosition"],"02D4":["DS","3","ControlPoint3DPosition"],"02D6":["DS","1","CumulativeTimeWeight"],"02E0":["CS","1","CompensatorDivergence"],"02E1":["CS","1","CompensatorMountingPosition"],"02E2":["DS","1-n","SourceToCompensatorDistance"],"02E3":["FL","1","TotalCompensatorTrayWaterEquivalentThickness"],"02E4":["FL","1","IsocenterToCompensatorTrayDistance"],"02E5":["FL","1","CompensatorColumnOffset"],"02E6":["FL","1-n","IsocenterToCompensatorDistances"],"02E7":["FL","1","CompensatorRelativeStoppingPowerRatio"],"02E8":["FL","1","CompensatorMillingToolDiameter"],"02EA":["SQ","1","IonRangeCompensatorSequence"],"02EB":["LT","1","CompensatorDescription"],"0302":["IS","1","RadiationMassNumber"],"0304":["IS","1","RadiationAtomicNumber"],"0306":["SS","1","RadiationChargeState"],"0308":["CS","1","ScanMode"],"0309":["CS","1","ModulatedScanModeType"],"030A":["FL","2","VirtualSourceAxisDistances"],"030C":["SQ","1","SnoutSequence"],"030D":["FL","1","SnoutPosition"],"030F":["SH","1","SnoutID"],"0312":["IS","1","NumberOfRangeShifters"],"0314":["SQ","1","RangeShifterSequence"],"0316":["IS","1","RangeShifterNumber"],"0318":["SH","1","RangeShifterID"],"0320":["CS","1","RangeShifterType"],"0322":["LO","1","RangeShifterDescription"],"0330":["IS","1","NumberOfLateralSpreadingDevices"],"0332":["SQ","1","LateralSpreadingDeviceSequence"],"0334":["IS","1","LateralSpreadingDeviceNumber"],"0336":["SH","1","LateralSpreadingDeviceID"],"0338":["CS","1","LateralSpreadingDeviceType"],"033A":["LO","1","LateralSpreadingDeviceDescription"],"033C":["FL","1","LateralSpreadingDeviceWaterEquivalentThickness"],"0340":["IS","1","NumberOfRangeModulators"],"0342":["SQ","1","RangeModulatorSequence"],"0344":["IS","1","RangeModulatorNumber"],"0346":["SH","1","RangeModulatorID"],"0348":["CS","1","RangeModulatorType"],"034A":["LO","1","RangeModulatorDescription"],"034C":["SH","1","BeamCurrentModulationID"],"0350":["CS","1","PatientSupportType"],"0352":["SH","1","PatientSupportID"],"0354":["LO","1","PatientSupportAccessoryCode"],"0355":["LO","1","TrayAccessoryCode"],"0356":["FL","1","FixationLightAzimuthalAngle"],"0358":["FL","1","FixationLightPolarAngle"],"035A":["FL","1","MetersetRate"],"0360":["SQ","1","RangeShifterSettingsSequence"],"0362":["LO","1","RangeShifterSetting"],"0364":["FL","1","IsocenterToRangeShifterDistance"],"0366":["FL","1","RangeShifterWaterEquivalentThickness"],"0370":["SQ","1","LateralSpreadingDeviceSettingsSequence"],"0372":["LO","1","LateralSpreadingDeviceSetting"],"0374":["FL","1","IsocenterToLateralSpreadingDeviceDistance"],"0380":["SQ","1","RangeModulatorSettingsSequence"],"0382":["FL","1","RangeModulatorGatingStartValue"],"0384":["FL","1","RangeModulatorGatingStopValue"],"0386":["FL","1","RangeModulatorGatingStartWaterEquivalentThickness"],"0388":["FL","1","RangeModulatorGatingStopWaterEquivalentThickness"],"038A":["FL","1","IsocenterToRangeModulatorDistance"],"038F":["FL","1-n","ScanSpotTimeOffset"],"0390":["SH","1","ScanSpotTuneID"],"0391":["IS","1-n","ScanSpotPrescribedIndices"],"0392":["IS","1","NumberOfScanSpotPositions"],"0393":["CS","1","ScanSpotReordered"],"0394":["FL","1-n","ScanSpotPositionMap"],"0395":["CS","1","ScanSpotReorderingAllowed"],"0396":["FL","1-n","ScanSpotMetersetWeights"],"0398":["FL","2","ScanningSpotSize"],"0399":["FL","2-2n","ScanSpotSizesDelivered"],"039A":["IS","1","NumberOfPaintings"],"03A0":["SQ","1","IonToleranceTableSequence"],"03A2":["SQ","1","IonBeamSequence"],"03A4":["SQ","1","IonBeamLimitingDeviceSequence"],"03A6":["SQ","1","IonBlockSequence"],"03A8":["SQ","1","IonControlPointSequence"],"03AA":["SQ","1","IonWedgeSequence"],"03AC":["SQ","1","IonWedgePositionSequence"],"0401":["SQ","1","ReferencedSetupImageSequence"],"0402":["ST","1","SetupImageComment"],"0410":["SQ","1","MotionSynchronizationSequence"],"0412":["FL","3","ControlPointOrientation"],"0420":["SQ","1","GeneralAccessorySequence"],"0421":["SH","1","GeneralAccessoryID"],"0422":["ST","1","GeneralAccessoryDescription"],"0423":["CS","1","GeneralAccessoryType"],"0424":["IS","1","GeneralAccessoryNumber"],"0425":["FL","1","SourceToGeneralAccessoryDistance"],"0426":["DS","1","IsocenterToGeneralAccessoryDistance"],"0431":["SQ","1","ApplicatorGeometrySequence"],"0432":["CS","1","ApplicatorApertureShape"],"0433":["FL","1","ApplicatorOpening"],"0434":["FL","1","ApplicatorOpeningX"],"0435":["FL","1","ApplicatorOpeningY"],"0436":["FL","1","SourceToApplicatorMountingPositionDistance"],"0440":["IS","1","NumberOfBlockSlabItems"],"0441":["SQ","1","BlockSlabSequence"],"0442":["DS","1","BlockSlabThickness"],"0443":["US","1","BlockSlabNumber"],"0450":["SQ","1","DeviceMotionControlSequence"],"0451":["CS","1","DeviceMotionExecutionMode"],"0452":["CS","1","DeviceMotionObservationMode"],"0453":["SQ","1","DeviceMotionParameterCodeSequence"],"0501":["FL","1","DistalDepthFraction"],"0502":["FL","1","DistalDepth"],"0503":["FL","2","NominalRangeModulationFractions"],"0504":["FL","2","NominalRangeModulatedRegionDepths"],"0505":["SQ","1","DepthDoseParametersSequence"],"0506":["SQ","1","DeliveredDepthDoseParametersSequence"],"0507":["FL","1","DeliveredDistalDepthFraction"],"0508":["FL","1","DeliveredDistalDepth"],"0509":["FL","2","DeliveredNominalRangeModulationFractions"],"0510":["FL","2","DeliveredNominalRangeModulatedRegionDepths"],"0511":["CS","1","DeliveredReferenceDoseDefinition"],"0512":["CS","1","ReferenceDoseDefinition"],"0600":["US","1","RTControlPointIndex"],"0601":["US","1","RadiationGenerationModeIndex"],"0602":["US","1","ReferencedDefinedDeviceIndex"],"0603":["US","1","RadiationDoseIdentificationIndex"],"0604":["US","1","NumberOfRTControlPoints"],"0605":["US","1","ReferencedRadiationGenerationModeIndex"],"0606":["US","1","TreatmentPositionIndex"],"0607":["US","1","ReferencedDeviceIndex"],"0608":["LO","1","TreatmentPositionGroupLabel"],"0609":["UI","1","TreatmentPositionGroupUID"],"060A":["SQ","1","TreatmentPositionGroupSequence"],"060B":["US","1","ReferencedTreatmentPositionIndex"],"060C":["US","1","ReferencedRadiationDoseIdentificationIndex"],"060D":["FD","1","RTAccessoryHolderWaterEquivalentThickness"],"060E":["US","1","ReferencedRTAccessoryHolderDeviceIndex"],"060F":["CS","1","RTAccessoryHolderSlotExistenceFlag"],"0610":["SQ","1","RTAccessoryHolderSlotSequence"],"0611":["LO","1","RTAccessoryHolderSlotID"],"0612":["FD","1","RTAccessoryHolderSlotDistance"],"0613":["FD","1","RTAccessorySlotDistance"],"0614":["SQ","1","RTAccessoryHolderDefinitionSequence"],"0615":["LO","1","RTAccessoryDeviceSlotID"],"0616":["SQ","1","RTRadiationSequence"],"0617":["SQ","1","RadiationDoseSequence"],"0618":["SQ","1","RadiationDoseIdentificationSequence"],"0619":["LO","1","RadiationDoseIdentificationLabel"],"061A":["CS","1","ReferenceDoseType"],"061B":["CS","1","PrimaryDoseValueIndicator"],"061C":["SQ","1","DoseValuesSequence"],"061D":["CS","1-n","DoseValuePurpose"],"061E":["FD","3","ReferenceDosePointCoordinates"],"061F":["SQ","1","RadiationDoseValuesParametersSequence"],"0620":["SQ","1","MetersetToDoseMappingSequence"],"0621":["SQ","1","ExpectedInVivoMeasurementValuesSequence"],"0622":["US","1","ExpectedInVivoMeasurementValueIndex"],"0623":["LO","1","RadiationDoseInVivoMeasurementLabel"],"0624":["FD","2","RadiationDoseCentralAxisDisplacement"],"0625":["FD","1","RadiationDoseValue"],"0626":["FD","1","RadiationDoseSourceToSkinDistance"],"0627":["FD","3","RadiationDoseMeasurementPointCoordinates"],"0628":["FD","1","RadiationDoseSourceToExternalContourDistance"],"0629":["SQ","1","RTToleranceSetSequence"],"062A":["LO","1","RTToleranceSetLabel"],"062B":["SQ","1","AttributeToleranceValuesSequence"],"062C":["FD","1","ToleranceValue"],"062D":["SQ","1","PatientSupportPositionToleranceSequence"],"062E":["FD","1","TreatmentTimeLimit"],"062F":["SQ","1","CArmPhotonElectronControlPointSequence"],"0630":["SQ","1","ReferencedRTRadiationSequence"],"0631":["SQ","1","ReferencedRTInstanceSequence"],"0632":["SQ","1","ReferencedRTPatientSetupSequence"],"0634":["FD","1","SourceToPatientSurfaceDistance"],"0635":["SQ","1","TreatmentMachineSpecialModeCodeSequence"],"0636":["US","1","IntendedNumberOfFractions"],"0637":["CS","1","RTRadiationSetIntent"],"0638":["CS","1","RTRadiationPhysicalAndGeometricContentDetailFlag"],"0639":["CS","1","RTRecordFlag"],"063A":["SQ","1","TreatmentDeviceIdentificationSequence"],"063B":["SQ","1","ReferencedRTPhysicianIntentSequence"],"063C":["FD","1","CumulativeMeterset"],"063D":["FD","1","DeliveryRate"],"063E":["SQ","1","DeliveryRateUnitSequence"],"063F":["SQ","1","TreatmentPositionSequence"],"0640":["FD","1","RadiationSourceAxisDistance"],"0641":["US","1","NumberOfRTBeamLimitingDevices"],"0642":["FD","1","RTBeamLimitingDeviceProximalDistance"],"0643":["FD","1","RTBeamLimitingDeviceDistalDistance"],"0644":["SQ","1","ParallelRTBeamDelimiterDeviceOrientationLabelCodeSequence"],"0645":["FD","1","BeamModifierOrientationAngle"],"0646":["SQ","1","FixedRTBeamDelimiterDeviceSequence"],"0647":["SQ","1","ParallelRTBeamDelimiterDeviceSequence"],"0648":["US","1","NumberOfParallelRTBeamDelimiters"],"0649":["FD","2-n","ParallelRTBeamDelimiterBoundaries"],"064A":["FD","2-n","ParallelRTBeamDelimiterPositions"],"064B":["FD","2","RTBeamLimitingDeviceOffset"],"064C":["SQ","1","RTBeamDelimiterGeometrySequence"],"064D":["SQ","1","RTBeamLimitingDeviceDefinitionSequence"],"064E":["CS","1","ParallelRTBeamDelimiterOpeningMode"],"064F":["CS","1-n","ParallelRTBeamDelimiterLeafMountingSide"],"0650":["UI","1","PatientSetupUID"],"0651":["SQ","1","WedgeDefinitionSequence"],"0652":["FD","1","RadiationBeamWedgeAngle"],"0653":["FD","1","RadiationBeamWedgeThinEdgeDistance"],"0654":["FD","1","RadiationBeamEffectiveWedgeAngle"],"0655":["US","1","NumberOfWedgePositions"],"0656":["SQ","1","RTBeamLimitingDeviceOpeningSequence"],"0657":["US","1","NumberOfRTBeamLimitingDeviceOpenings"],"0658":["SQ","1","RadiationDosimeterUnitSequence"],"0659":["SQ","1","RTDeviceDistanceReferenceLocationCodeSequence"],"065A":["SQ","1","RadiationDeviceConfigurationAndCommissioningKeySequence"],"065B":["SQ","1","PatientSupportPositionParameterSequence"],"065C":["CS","1","PatientSupportPositionSpecificationMethod"],"065D":["SQ","1","PatientSupportPositionDeviceParameterSequence"],"065E":["US","1","DeviceOrderIndex"],"065F":["US","1","PatientSupportPositionParameterOrderIndex"],"0660":["SQ","1","PatientSupportPositionDeviceToleranceSequence"],"0661":["US","1","PatientSupportPositionToleranceOrderIndex"],"0662":["SQ","1","CompensatorDefinitionSequence"],"0663":["CS","1","CompensatorMapOrientation"],"0664":["OF","1","CompensatorProximalThicknessMap"],"0665":["OF","1","CompensatorDistalThicknessMap"],"0666":["FD","1","CompensatorBasePlaneOffset"],"0667":["SQ","1","CompensatorShapeFabricationCodeSequence"],"0668":["SQ","1","CompensatorShapeSequence"],"0669":["FD","1","RadiationBeamCompensatorMillingToolDiameter"],"066A":["SQ","1","BlockDefinitionSequence"],"066B":["OF","1","BlockEdgeData"],"066C":["CS","1","BlockOrientation"],"066D":["FD","1","RadiationBeamBlockThickness"],"066E":["FD","1","RadiationBeamBlockSlabThickness"],"066F":["SQ","1","BlockEdgeDataSequence"],"0670":["US","1","NumberOfRTAccessoryHolders"],"0671":["SQ","1","GeneralAccessoryDefinitionSequence"],"0672":["US","1","NumberOfGeneralAccessories"],"0673":["SQ","1","BolusDefinitionSequence"],"0674":["US","1","NumberOfBoluses"],"0675":["UI","1","EquipmentFrameOfReferenceUID"],"0676":["ST","1","EquipmentFrameOfReferenceDescription"],"0677":["SQ","1","EquipmentReferencePointCoordinatesSequence"],"0678":["SQ","1","EquipmentReferencePointCodeSequence"],"0679":["FD","1","RTBeamLimitingDeviceAngle"],"067A":["FD","1","SourceRollAngle"],"067B":["SQ","1","RadiationGenerationModeSequence"],"067C":["SH","1","RadiationGenerationModeLabel"],"067D":["ST","1","RadiationGenerationModeDescription"],"067E":["SQ","1","RadiationGenerationModeMachineCodeSequence"],"067F":["SQ","1","RadiationTypeCodeSequence"],"0680":["DS","1","NominalEnergy"],"0681":["DS","1","MinimumNominalEnergy"],"0682":["DS","1","MaximumNominalEnergy"],"0683":["SQ","1","RadiationFluenceModifierCodeSequence"],"0684":["SQ","1","EnergyUnitCodeSequence"],"0685":["US","1","NumberOfRadiationGenerationModes"],"0686":["SQ","1","PatientSupportDevicesSequence"],"0687":["US","1","NumberOfPatientSupportDevices"],"0688":["FD","1","RTBeamModifierDefinitionDistance"],"0689":["SQ","1","BeamAreaLimitSequence"],"068A":["SQ","1","ReferencedRTPrescriptionSequence"],"0700":["UI","1","TreatmentSessionUID"],"0701":["CS","1","RTRadiationUsage"],"0702":["SQ","1","ReferencedRTRadiationSetSequence"],"0703":["SQ","1","ReferencedRTRadiationRecordSequence"],"0704":["US","1","RTRadiationSetDeliveryNumber"],"0705":["US","1","ClinicalFractionNumber"],"0706":["CS","1","RTTreatmentFractionCompletionStatus"],"0707":["CS","1","RTRadiationSetUsage"],"0708":["CS","1","TreatmentDeliveryContinuationFlag"],"0709":["CS","1","TreatmentRecordContentOrigin"],"0714":["CS","1","RTTreatmentTerminationStatus"],"0715":["SQ","1","RTTreatmentTerminationReasonCodeSequence"],"0716":["SQ","1","MachineSpecificTreatmentTerminationCodeSequence"],"0722":["SQ","1","RTRadiationSalvageRecordControlPointSequence"],"0723":["CS","1","StartingMetersetValueKnownFlag"],"0730":["ST","1","TreatmentTerminationDescription"],"0731":["SQ","1","TreatmentToleranceViolationSequence"],"0732":["CS","1","TreatmentToleranceViolationCategory"],"0733":["SQ","1","TreatmentToleranceViolationAttributeSequence"],"0734":["ST","1","TreatmentToleranceViolationDescription"],"0735":["ST","1","TreatmentToleranceViolationIdentification"],"0736":["DT","1","TreatmentToleranceViolationDateTime"],"073A":["DT","1","RecordedRTControlPointDateTime"],"073B":["US","1","ReferencedRadiationRTControlPointIndex"],"073E":["SQ","1","AlternateValueSequence"],"073F":["SQ","1","ConfirmationSequence"],"0740":["SQ","1","InterlockSequence"],"0741":["DT","1","InterlockDateTime"],"0742":["ST","1","InterlockDescription"],"0743":["SQ","1","InterlockOriginatingDeviceSequence"],"0744":["SQ","1","InterlockCodeSequence"],"0745":["SQ","1","InterlockResolutionCodeSequence"],"0746":["SQ","1","InterlockResolutionUserSequence"],"0760":["DT","1","OverrideDateTime"],"0761":["SQ","1","TreatmentToleranceViolationTypeCodeSequence"],"0762":["SQ","1","TreatmentToleranceViolationCauseCodeSequence"],"0772":["SQ","1","MeasuredMetersetToDoseMappingSequence"],"0773":["US","1","ReferencedExpectedInVivoMeasurementValueIndex"],"0774":["SQ","1","DoseMeasurementDeviceCodeSequence"],"0780":["SQ","1","AdditionalParameterRecordingInstanceSequence"],"0782":["US","1",""],"0783":["ST","1","InterlockOriginDescription"],"0784":["SQ","1","RTPatientPositionScopeSequence"],"0785":["UI","1","ReferencedTreatmentPositionGroupUID"],"0786":["US","1","RadiationOrderIndex"],"0787":["SQ","1","OmittedRadiationSequence"],"0788":["SQ","1","ReasonForOmissionCodeSequence"],"0789":["SQ","1","RTDeliveryStartPatientPositionSequence"],"078A":["SQ","1","RTTreatmentPreparationPatientPositionSequence"],"078B":["SQ","1","ReferencedRTTreatmentPreparationSequence"],"078C":["SQ","1","ReferencedPatientSetupPhotoSequence"],"078D":["SQ","1","PatientTreatmentPreparationMethodCodeSequence"],"078E":["LT","1","PatientTreatmentPreparationProcedureParameterDescription"],"078F":["SQ","1","PatientTreatmentPreparationDeviceSequence"],"0790":["SQ","1","PatientTreatmentPreparationProcedureSequence"],"0791":["SQ","1","PatientTreatmentPreparationProcedureCodeSequence"],"0792":["LT","1","PatientTreatmentPreparationMethodDescription"],"0793":["SQ","1","PatientTreatmentPreparationProcedureParameterSequence"],"0794":["LT","1","PatientSetupPhotoDescription"],"0795":["US","1","PatientTreatmentPreparationProcedureIndex"],"0796":["US","1","ReferencedPatientSetupProcedureIndex"],"0797":["SQ","1","RTRadiationTaskSequence"],"0798":["SQ","1","RTPatientPositionDisplacementSequence"],"0799":["SQ","1","RTPatientPositionSequence"],"079A":["LO","1","DisplacementReferenceLabel"],"079B":["FD","16","DisplacementMatrix"],"079C":["SQ","1","PatientSupportDisplacementSequence"],"079D":["SQ","1","DisplacementReferenceLocationCodeSequence"],"079E":["CS","1","RTRadiationSetDeliveryUsage"]},"300C":{"0000":["UL","1","GenericGroupLength"],"0002":["SQ","1","ReferencedRTPlanSequence"],"0004":["SQ","1","ReferencedBeamSequence"],"0006":["IS","1","ReferencedBeamNumber"],"0007":["IS","1","ReferencedReferenceImageNumber"],"0008":["DS","1","StartCumulativeMetersetWeight"],"0009":["DS","1","EndCumulativeMetersetWeight"],"000A":["SQ","1","ReferencedBrachyApplicationSetupSequence"],"000C":["IS","1","ReferencedBrachyApplicationSetupNumber"],"000E":["IS","1","ReferencedSourceNumber"],"0020":["SQ","1","ReferencedFractionGroupSequence"],"0022":["IS","1","ReferencedFractionGroupNumber"],"0040":["SQ","1","ReferencedVerificationImageSequence"],"0042":["SQ","1","ReferencedReferenceImageSequence"],"0050":["SQ","1","ReferencedDoseReferenceSequence"],"0051":["IS","1","ReferencedDoseReferenceNumber"],"0055":["SQ","1","BrachyReferencedDoseReferenceSequence"],"0060":["SQ","1","ReferencedStructureSetSequence"],"006A":["IS","1","ReferencedPatientSetupNumber"],"0080":["SQ","1","ReferencedDoseSequence"],"00A0":["IS","1","ReferencedToleranceTableNumber"],"00B0":["SQ","1","ReferencedBolusSequence"],"00C0":["IS","1","ReferencedWedgeNumber"],"00D0":["IS","1","ReferencedCompensatorNumber"],"00E0":["IS","1","ReferencedBlockNumber"],"00F0":["IS","1","ReferencedControlPointIndex"],"00F2":["SQ","1","ReferencedControlPointSequence"],"00F4":["IS","1","ReferencedStartControlPointIndex"],"00F6":["IS","1","ReferencedStopControlPointIndex"],"0100":["IS","1","ReferencedRangeShifterNumber"],"0102":["IS","1","ReferencedLateralSpreadingDeviceNumber"],"0104":["IS","1","ReferencedRangeModulatorNumber"],"0111":["SQ","1","OmittedBeamTaskSequence"],"0112":["CS","1","ReasonForOmission"],"0113":["LO","1","ReasonForOmissionDescription"],"0114":["SQ","1","PrescriptionOverviewSequence"],"0115":["FL","1","TotalPrescriptionDose"],"0116":["SQ","1","PlanOverviewSequence"],"0117":["US","1","PlanOverviewIndex"],"0118":["US","1","ReferencedPlanOverviewIndex"],"0119":["US","1","NumberOfFractionsIncluded"],"0120":["SQ","1","DoseCalibrationConditionsSequence"],"0121":["FD","1","AbsorbedDoseToMetersetRatio"],"0122":["FD","2","DelineatedRadiationFieldSize"],"0123":["CS","1","DoseCalibrationConditionsVerifiedFlag"],"0124":["FD","1","CalibrationReferencePointDepth"],"0125":["SQ","1","GatingBeamHoldTransitionSequence"],"0126":["CS","1","BeamHoldTransition"],"0127":["DT","1","BeamHoldTransitionDateTime"],"0128":["SQ","1","BeamHoldOriginatingDeviceSequence"]},"300E":{"0000":["UL","1","GenericGroupLength"],"0002":["CS","1","ApprovalStatus"],"0004":["DA","1","ReviewDate"],"0005":["TM","1","ReviewTime"],"0008":["PN","1","ReviewerName"]},3010:{"0000":["UL","1","GenericGroupLength"],"0001":["SQ","1","RadiobiologicalDoseEffectSequence"],"0002":["CS","1","RadiobiologicalDoseEffectFlag"],"0003":["SQ","1","EffectiveDoseCalculationMethodCategoryCodeSequence"],"0004":["SQ","1","EffectiveDoseCalculationMethodCodeSequence"],"0005":["LO","1","EffectiveDoseCalculationMethodDescription"],"0006":["UI","1","ConceptualVolumeUID"],"0007":["SQ","1","OriginatingSOPInstanceReferenceSequence"],"0008":["SQ","1","ConceptualVolumeConstituentSequence"],"0009":["SQ","1","EquivalentConceptualVolumeInstanceReferenceSequence"],"000A":["SQ","1","EquivalentConceptualVolumesSequence"],"000B":["UI","1","ReferencedConceptualVolumeUID"],"000C":["UT","1","ConceptualVolumeCombinationExpression"],"000D":["US","1","ConceptualVolumeConstituentIndex"],"000E":["CS","1","ConceptualVolumeCombinationFlag"],"000F":["ST","1","ConceptualVolumeCombinationDescription"],"0010":["CS","1","ConceptualVolumeSegmentationDefinedFlag"],"0011":["SQ","1","ConceptualVolumeSegmentationReferenceSequence"],"0012":["SQ","1","ConceptualVolumeConstituentSegmentationReferenceSequence"],"0013":["UI","1","ConstituentConceptualVolumeUID"],"0014":["SQ","1","DerivationConceptualVolumeSequence"],"0015":["UI","1","SourceConceptualVolumeUID"],"0016":["SQ","1","ConceptualVolumeDerivationAlgorithmSequence"],"0017":["ST","1","ConceptualVolumeDescription"],"0018":["SQ","1","SourceConceptualVolumeSequence"],"0019":["SQ","1","AuthorIdentificationSequence"],"001A":["LO","1","ManufacturerModelVersion"],"001B":["UC","1","DeviceAlternateIdentifier"],"001C":["CS","1","DeviceAlternateIdentifierType"],"001D":["LT","1","DeviceAlternateIdentifierFormat"],"001E":["LO","1","SegmentationCreationTemplateLabel"],"001F":["UI","1","SegmentationTemplateUID"],"0020":["US","1","ReferencedSegmentReferenceIndex"],"0021":["SQ","1","SegmentReferenceSequence"],"0022":["US","1","SegmentReferenceIndex"],"0023":["SQ","1","DirectSegmentReferenceSequence"],"0024":["SQ","1","CombinationSegmentReferenceSequence"],"0025":["SQ","1","ConceptualVolumeSequence"],"0026":["SQ","1","SegmentedRTAccessoryDeviceSequence"],"0027":["SQ","1","SegmentCharacteristicsSequence"],"0028":["SQ","1","RelatedSegmentCharacteristicsSequence"],"0029":["US","1","SegmentCharacteristicsPrecedence"],"002A":["SQ","1","RTSegmentAnnotationSequence"],"002B":["SQ","1","SegmentAnnotationCategoryCodeSequence"],"002C":["SQ","1","SegmentAnnotationTypeCodeSequence"],"002D":["LO","1","DeviceLabel"],"002E":["SQ","1","DeviceTypeCodeSequence"],"002F":["SQ","1","SegmentAnnotationTypeModifierCodeSequence"],"0030":["SQ","1","PatientEquipmentRelationshipCodeSequence"],"0031":["UI","1","ReferencedFiducialsUID"],"0032":["SQ","1","PatientTreatmentOrientationSequence"],"0033":["SH","1","UserContentLabel"],"0034":["LO","1","UserContentLongLabel"],"0035":["SH","1","EntityLabel"],"0036":["LO","1","EntityName"],"0037":["ST","1","EntityDescription"],"0038":["LO","1","EntityLongLabel"],"0039":["US","1","DeviceIndex"],"003A":["US","1","RTTreatmentPhaseIndex"],"003B":["UI","1","RTTreatmentPhaseUID"],"003C":["US","1","RTPrescriptionIndex"],"003D":["US","1","RTSegmentAnnotationIndex"],"003E":["US","1","BasisRTTreatmentPhaseIndex"],"003F":["US","1","RelatedRTTreatmentPhaseIndex"],"0040":["US","1","ReferencedRTTreatmentPhaseIndex"],"0041":["US","1","ReferencedRTPrescriptionIndex"],"0042":["US","1","ReferencedParentRTPrescriptionIndex"],"0043":["ST","1","ManufacturerDeviceIdentifier"],"0044":["SQ","1","InstanceLevelReferencedPerformedProcedureStepSequence"],"0045":["CS","1","RTTreatmentPhaseIntentPresenceFlag"],"0046":["CS","1","RadiotherapyTreatmentType"],"0047":["CS","1-n","TeletherapyRadiationType"],"0048":["CS","1-n","BrachytherapySourceType"],"0049":["SQ","1","ReferencedRTTreatmentPhaseSequence"],"004A":["SQ","1","ReferencedDirectSegmentInstanceSequence"],"004B":["SQ","1","IntendedRTTreatmentPhaseSequence"],"004C":["DA","1","IntendedPhaseStartDate"],"004D":["DA","1","IntendedPhaseEndDate"],"004E":["SQ","1","RTTreatmentPhaseIntervalSequence"],"004F":["CS","1","TemporalRelationshipIntervalAnchor"],"0050":["FD","1","MinimumNumberOfIntervalDays"],"0051":["FD","1","MaximumNumberOfIntervalDays"],"0052":["UI","1-n","PertinentSOPClassesInStudy"],"0053":["UI","1-n","PertinentSOPClassesInSeries"],"0054":["LO","1","RTPrescriptionLabel"],"0055":["SQ","1","RTPhysicianIntentPredecessorSequence"],"0056":["LO","1","RTTreatmentApproachLabel"],"0057":["SQ","1","RTPhysicianIntentSequence"],"0058":["US","1","RTPhysicianIntentIndex"],"0059":["CS","1","RTTreatmentIntentType"],"005A":["UT","1","RTPhysicianIntentNarrative"],"005B":["SQ","1","RTProtocolCodeSequence"],"005C":["ST","1","ReasonForSuperseding"],"005D":["SQ","1","RTDiagnosisCodeSequence"],"005E":["US","1","ReferencedRTPhysicianIntentIndex"],"005F":["SQ","1","RTPhysicianIntentInputInstanceSequence"],"0060":["SQ","1","RTAnatomicPrescriptionSequence"],"0061":["UT","1","PriorTreatmentDoseDescription"],"0062":["SQ","1","PriorTreatmentReferenceSequence"],"0063":["CS","1","DosimetricObjectiveEvaluationScope"],"0064":["SQ","1","TherapeuticRoleCategoryCodeSequence"],"0065":["SQ","1","TherapeuticRoleTypeCodeSequence"],"0066":["US","1","ConceptualVolumeOptimizationPrecedence"],"0067":["SQ","1","ConceptualVolumeCategoryCodeSequence"],"0068":["CS","1","ConceptualVolumeBlockingConstraint"],"0069":["SQ","1","ConceptualVolumeTypeCodeSequence"],"006A":["SQ","1","ConceptualVolumeTypeModifierCodeSequence"],"006B":["SQ","1","RTPrescriptionSequence"],"006C":["SQ","1","DosimetricObjectiveSequence"],"006D":["SQ","1","DosimetricObjectiveTypeCodeSequence"],"006E":["UI","1","DosimetricObjectiveUID"],"006F":["UI","1","ReferencedDosimetricObjectiveUID"],"0070":["SQ","1","DosimetricObjectiveParameterSequence"],"0071":["SQ","1","ReferencedDosimetricObjectivesSequence"],"0073":["CS","1","AbsoluteDosimetricObjectiveFlag"],"0074":["FD","1","DosimetricObjectiveWeight"],"0075":["CS","1","DosimetricObjectivePurpose"],"0076":["SQ","1","PlanningInputInformationSequence"],"0077":["LO","1","TreatmentSite"],"0078":["SQ","1","TreatmentSiteCodeSequence"],"0079":["SQ","1","FractionPatternSequence"],"007A":["UT","1","TreatmentTechniqueNotes"],"007B":["UT","1","PrescriptionNotes"],"007C":["IS","1","NumberOfIntervalFractions"],"007D":["US","1","NumberOfFractions"],"007E":["US","1","IntendedDeliveryDuration"],"007F":["UT","1","FractionationNotes"],"0080":["SQ","1","RTTreatmentTechniqueCodeSequence"],"0081":["SQ","1","PrescriptionNotesSequence"],"0082":["SQ","1","FractionBasedRelationshipSequence"],"0083":["CS","1","FractionBasedRelationshipIntervalAnchor"],"0084":["FD","1","MinimumHoursBetweenFractions"],"0085":["TM","1-n","IntendedFractionStartTime"],"0086":["LT","1","IntendedStartDayOfWeek"],"0087":["SQ","1","WeekdayFractionPatternSequence"],"0088":["SQ","1","DeliveryTimeStructureCodeSequence"],"0089":["SQ","1","TreatmentSiteModifierCodeSequence"],"0090":["CS","1","RoboticBaseLocationIndicator"],"0091":["SQ","1","RoboticPathNodeSetCodeSequence"],"0092":["UL","1","RoboticNodeIdentifier"],"0093":["FD","3","RTTreatmentSourceCoordinates"],"0094":["FD","1","RadiationSourceCoordinateSystemYawAngle"],"0095":["FD","1","RadiationSourceCoordinateSystemRollAngle"],"0096":["FD","1","RadiationSourceCoordinateSystemPitchAngle"],"0097":["SQ","1","RoboticPathControlPointSequence"],"0098":["SQ","1","TomotherapeuticControlPointSequence"],"0099":["FD","1-n","TomotherapeuticLeafOpenDurations"],"009A":["FD","1-n","TomotherapeuticLeafInitialClosedDurations"]},4e3:{"0000":["UL","1","GenericGroupLength"],"0010":["LT","1","Arbitrary"],4e3:["LT","1","TextComments"]},4008:{"0000":["UL","1","GenericGroupLength"],"0040":["SH","1","ResultsID"],"0042":["LO","1","ResultsIDIssuer"],"0050":["SQ","1","ReferencedInterpretationSequence"],"00FF":["CS","1","ReportProductionStatusTrial"],"0100":["DA","1","InterpretationRecordedDate"],"0101":["TM","1","InterpretationRecordedTime"],"0102":["PN","1","InterpretationRecorder"],"0103":["LO","1","ReferenceToRecordedSound"],"0108":["DA","1","InterpretationTranscriptionDate"],"0109":["TM","1","InterpretationTranscriptionTime"],"010A":["PN","1","InterpretationTranscriber"],"010B":["ST","1","InterpretationText"],"010C":["PN","1","InterpretationAuthor"],"0111":["SQ","1","InterpretationApproverSequence"],"0112":["DA","1","InterpretationApprovalDate"],"0113":["TM","1","InterpretationApprovalTime"],"0114":["PN","1","PhysicianApprovingInterpretation"],"0115":["LT","1","InterpretationDiagnosisDescription"],"0117":["SQ","1","InterpretationDiagnosisCodeSequence"],"0118":["SQ","1","ResultsDistributionListSequence"],"0119":["PN","1","DistributionName"],"011A":["LO","1","DistributionAddress"],"0200":["SH","1","InterpretationID"],"0202":["LO","1","InterpretationIDIssuer"],"0210":["CS","1","InterpretationTypeID"],"0212":["CS","1","InterpretationStatusID"],"0300":["ST","1","Impressions"],4e3:["ST","1","ResultsComments"]},4010:{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","LowEnergyDetectors"],"0002":["CS","1","HighEnergyDetectors"],"0004":["SQ","1","DetectorGeometrySequence"],1001:["SQ","1","ThreatROIVoxelSequence"],1004:["FL","3","ThreatROIBase"],1005:["FL","3","ThreatROIExtents"],1006:["OB","1","ThreatROIBitmap"],1007:["SH","1","RouteSegmentID"],1008:["CS","1","GantryType"],1009:["CS","1","OOIOwnerType"],"100A":["SQ","1","RouteSegmentSequence"],1010:["US","1","PotentialThreatObjectID"],1011:["SQ","1","ThreatSequence"],1012:["CS","1","ThreatCategory"],1013:["LT","1","ThreatCategoryDescription"],1014:["CS","1","ATDAbilityAssessment"],1015:["CS","1","ATDAssessmentFlag"],1016:["FL","1","ATDAssessmentProbability"],1017:["FL","1","Mass"],1018:["FL","1","Density"],1019:["FL","1","ZEffective"],"101A":["SH","1","BoardingPassID"],"101B":["FL","3","CenterOfMass"],"101C":["FL","3","CenterOfPTO"],"101D":["FL","6-n","BoundingPolygon"],"101E":["SH","1","RouteSegmentStartLocationID"],"101F":["SH","1","RouteSegmentEndLocationID"],1020:["CS","1","RouteSegmentLocationIDType"],1021:["CS","1-n","AbortReason"],1023:["FL","1","VolumeOfPTO"],1024:["CS","1","AbortFlag"],1025:["DT","1","RouteSegmentStartTime"],1026:["DT","1","RouteSegmentEndTime"],1027:["CS","1","TDRType"],1028:["CS","1","InternationalRouteSegment"],1029:["LO","1-n","ThreatDetectionAlgorithmAndVersion"],"102A":["SH","1","AssignedLocation"],"102B":["DT","1","AlarmDecisionTime"],1031:["CS","1","AlarmDecision"],1033:["US","1","NumberOfTotalObjects"],1034:["US","1","NumberOfAlarmObjects"],1037:["SQ","1","PTORepresentationSequence"],1038:["SQ","1","ATDAssessmentSequence"],1039:["CS","1","TIPType"],"103A":["CS","1","DICOSVersion"],1041:["DT","1","OOIOwnerCreationTime"],1042:["CS","1","OOIType"],1043:["FL","3","OOISize"],1044:["CS","1","AcquisitionStatus"],1045:["SQ","1","BasisMaterialsCodeSequence"],1046:["CS","1","PhantomType"],1047:["SQ","1","OOIOwnerSequence"],1048:["CS","1","ScanType"],1051:["LO","1","ItineraryID"],1052:["SH","1","ItineraryIDType"],1053:["LO","1","ItineraryIDAssigningAuthority"],1054:["SH","1","RouteID"],1055:["SH","1","RouteIDAssigningAuthority"],1056:["CS","1","InboundArrivalType"],1058:["SH","1","CarrierID"],1059:["CS","1","CarrierIDAssigningAuthority"],1060:["FL","3","SourceOrientation"],1061:["FL","3","SourcePosition"],1062:["FL","1","BeltHeight"],1064:["SQ","1","AlgorithmRoutingCodeSequence"],1067:["CS","1","TransportClassification"],1068:["LT","1","OOITypeDescriptor"],1069:["FL","1","TotalProcessingTime"],"106C":["OB","1","DetectorCalibrationData"],"106D":["CS","1","AdditionalScreeningPerformed"],"106E":["CS","1","AdditionalInspectionSelectionCriteria"],"106F":["SQ","1","AdditionalInspectionMethodSequence"],1070:["CS","1","AITDeviceType"],1071:["SQ","1","QRMeasurementsSequence"],1072:["SQ","1","TargetMaterialSequence"],1073:["FD","1","SNRThreshold"],1075:["DS","1","ImageScaleRepresentation"],1076:["SQ","1","ReferencedPTOSequence"],1077:["SQ","1","ReferencedTDRInstanceSequence"],1078:["ST","1","PTOLocationDescription"],1079:["SQ","1","AnomalyLocatorIndicatorSequence"],"107A":["FL","3","AnomalyLocatorIndicator"],"107B":["SQ","1","PTORegionSequence"],"107C":["CS","1","InspectionSelectionCriteria"],"107D":["SQ","1","SecondaryInspectionMethodSequence"],"107E":["DS","6","PRCSToRCSOrientation"]},"4FFE":{"0000":["UL","1","GenericGroupLength"],"0001":["SQ","1","MACParametersSequence"]},5e3:{"0000":["UL","1","GenericGroupLength"],"0005":["US","1","CurveDimensions"],"0010":["US","1","NumberOfPoints"],"0020":["CS","1","TypeOfData"],"0022":["LO","1","CurveDescription"],"0030":["SH","1-n","AxisUnits"],"0040":["SH","1-n","AxisLabels"],"0103":["US","1","DataValueRepresentation"],"0104":["US","1-n","MinimumCoordinateValue"],"0105":["US","1-n","MaximumCoordinateValue"],"0106":["SH","1-n","CurveRange"],"0110":["US","1-n","CurveDataDescriptor"],"0112":["US","1-n","CoordinateStartValue"],"0114":["US","1-n","CoordinateStepValue"],1001:["CS","1","CurveActivationLayer"],2e3:["US","1","AudioType"],2002:["US","1","AudioSampleFormat"],2004:["US","1","NumberOfChannels"],2006:["UL","1","NumberOfSamples"],2008:["UL","1","SampleRate"],"200A":["UL","1","TotalTime"],"200C":["ox","1","AudioSampleData"],"200E":["LT","1","AudioComments"],2500:["LO","1","CurveLabel"],2600:["SQ","1","CurveReferencedOverlaySequence"],2610:["US","1","CurveReferencedOverlayGroup"],3e3:["ox","1","CurveData"]},5200:{"0000":["UL","1","GenericGroupLength"],9229:["SQ","1","SharedFunctionalGroupsSequence"],9230:["SQ","1","PerFrameFunctionalGroupsSequence"]},5400:{"0000":["UL","1","GenericGroupLength"],"0100":["SQ","1","WaveformSequence"],"0110":["ox","1","ChannelMinimumValue"],"0112":["ox","1","ChannelMaximumValue"],1004:["US","1","WaveformBitsAllocated"],1006:["CS","1","WaveformSampleInterpretation"],"100A":["ox","1","WaveformPaddingValue"],1010:["ox","1","WaveformData"]},5600:{"0000":["UL","1","GenericGroupLength"],"0010":["OF","1","FirstOrderPhaseCorrectionAngle"],"0020":["OF","1","SpectroscopyData"]},6e3:{"0000":["UL","1","GenericGroupLength"],"0010":["US","1","OverlayRows"],"0011":["US","1","OverlayColumns"],"0012":["US","1","OverlayPlanes"],"0015":["IS","1","NumberOfFramesInOverlay"],"0022":["LO","1","OverlayDescription"],"0040":["CS","1","OverlayType"],"0045":["LO","1","OverlaySubtype"],"0050":["SS","2","OverlayOrigin"],"0051":["US","1","ImageFrameOrigin"],"0052":["US","1","OverlayPlaneOrigin"],"0060":["CS","1","OverlayCompressionCode"],"0061":["SH","1","OverlayCompressionOriginator"],"0062":["SH","1","OverlayCompressionLabel"],"0063":["CS","1","OverlayCompressionDescription"],"0066":["AT","1-n","OverlayCompressionStepPointers"],"0068":["US","1","OverlayRepeatInterval"],"0069":["US","1","OverlayBitsGrouped"],"0100":["US","1","OverlayBitsAllocated"],"0102":["US","1","OverlayBitPosition"],"0110":["CS","1","OverlayFormat"],"0200":["US","1","OverlayLocation"],"0800":["CS","1-n","OverlayCodeLabel"],"0802":["US","1","OverlayNumberOfTables"],"0803":["AT","1-n","OverlayCodeTableLocation"],"0804":["US","1","OverlayBitsForCodeWord"],1001:["CS","1","OverlayActivationLayer"],1100:["US","1","OverlayDescriptorGray"],1101:["US","1","OverlayDescriptorRed"],1102:["US","1","OverlayDescriptorGreen"],1103:["US","1","OverlayDescriptorBlue"],1200:["US","1-n","OverlaysGray"],1201:["US","1-n","OverlaysRed"],1202:["US","1-n","OverlaysGreen"],1203:["US","1-n","OverlaysBlue"],1301:["IS","1","ROIArea"],1302:["DS","1","ROIMean"],1303:["DS","1","ROIStandardDeviation"],1500:["LO","1","OverlayLabel"],3e3:["ox","1","OverlayData"],4e3:["LT","1","OverlayComments"]},"7F00":{"0000":["UL","1","GenericGroupLength"],"0010":["ox","1","VariablePixelData"],"0011":["US","1","VariableNextDataGroup"],"0020":["OW","1","VariableCoefficientsSDVN"],"0030":["OW","1","VariableCoefficientsSDHN"],"0040":["OW","1","VariableCoefficientsSDDN"]},"7FE0":{"0000":["UL","1","GenericGroupLength"],"0001":["OV","1","ExtendedOffsetTable"],"0002":["OV","1","ExtendedOffsetTableLengths"],"0008":["OF","1","FloatPixelData"],"0009":["OD","1","DoubleFloatPixelData"],"0010":["ox","1","PixelData"],"0020":["OW","1","CoefficientsSDVN"],"0030":["OW","1","CoefficientsSDHN"],"0040":["OW","1","CoefficientsSDDN"]},FFFA:{"0000":["UL","1","GenericGroupLength"],FFFA:["SQ","1","DigitalSignaturesSequence"]},FFFC:{"0000":["UL","1","GenericGroupLength"],FFFC:["OB","1","DataSetTrailingPadding"]},FFFE:{"0000":["UL","1","GenericGroupLength"],E000:["NONE","1","Item"],E00D:["NONE","1","ItemDelimitationItem"],E0DD:["NONE","1","SequenceDelimitationItem"]}};function Z(e,t){j[e]=t}const _={"0000":"Command","0002":"Meta Element","0004":"File Set","0008":"Identifying","0009":"SPI Identifying","0010":"Patient","0012":"Clinical Trial","0018":"Acquisition","0019":"SPI Acquisition","0020":"Image","0021":"SPI Image","0022":"Ophtalmology","0028":"Image Presentation","0032":"Study","0038":"Visit","003A":"Waveform","0040":"Procedure","0042":"Encapsulated Document","0050":"Device Informations","0054":"Nuclear Medicine","0060":"Histogram","0070":"Presentation State","0072":"Hanging Protocol","0088":"Storage","0100":"Authorization","0400":"Digital Signature",1e3:"Code Table",1010:"Zonal Map",2e3:"Film Session",2010:"Film Box",2020:"Image Box",2030:"Annotation",2040:"Overlay Box",2050:"Presentation LUT",2100:"Print Job",2110:"Printer",2120:"Queue",2130:"Print Content",2200:"Media Creation",3002:"RT Image",3004:"RT Dose",3006:"RT StructureSet",3008:"RT Treatment","300A":"RT Plan","300C":"RT Relationship","300E":"RT Approval",4e3:"Text",4008:"Results","4FFE":"MAC Parameters",5e3:"Curve",5002:"Curve",5004:"Curve",5006:"Curve",5008:"Curve","500A":"Curve","500C":"Curve","500E":"Curve",5400:"Waveform Data",6e3:"Overlays",6002:"Overlays",6004:"Overlays",6008:"Overlays","600A":"Overlays","600C":"Overlays","600E":"Overlays",FFFC:"Generic","7FE0":"Pixel Data",FFFF:"Unknown"},K={OB:!0,OD:!0,OF:!0,OL:!0,OV:!0,OW:!0,SQ:!0,SV:!0,UC:!0,UN:!0,UR:!0,UT:!0,UV:!0,ox:!0};function J(e){return void 0!==K[e]}const $={SH:!0,LO:!0,UC:!0,ST:!0,LT:!0,UT:!0,PN:!0};function ee(e){return void 0!==$[e]}const te={AE:"string",AS:"string",AT:void 0,CS:"string",DA:"string",DS:"string",DT:"string",FL:"Float32",FD:"Float64",IS:"string",LO:"string",LT:"string",OB:"Uint8",OD:"Uint64",OF:"Uint32",OL:"Uint32",OV:"Uint64",OW:"Uint16",PN:"string",SH:"string",SL:"Int32",SQ:void 0,SS:"Int16",ST:"string",SV:"Int64",TM:"string",UC:"string",UI:"string",UL:"Uint32",UN:"Uint8",UR:"string",US:"Uint16",UT:"string",UV:"Uint64"},ne={"1.2.840.10008.1.2":"Implicit VR Little Endian","1.2.840.10008.1.2.1":"Explicit VR Little Endian","1.2.840.10008.1.2.1.98":"Encapsulated Uncompressed Explicit VR Little Endian","1.2.840.10008.1.2.1.99":"Deflated Explicit VR Little Endian","1.2.840.10008.1.2.2":"Explicit VR Big Endian (Retired)","1.2.840.10008.1.2.4.50":"JPEG Baseline (Process 1)","1.2.840.10008.1.2.4.51":"JPEG Extended (Process 2 & 4)","1.2.840.10008.1.2.4.52":"JPEG Extended (Process 3 & 5) (Retired)","1.2.840.10008.1.2.4.53":"JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) (Retired)","1.2.840.10008.1.2.4.54":"JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9) (Retired)","1.2.840.10008.1.2.4.55":"JPEG Full Progression, Non-Hierarchical (Process 10 & 12) (Retired)","1.2.840.10008.1.2.4.56":"JPEG Full Progression, Non-Hierarchical (Process 11 & 13) (Retired)","1.2.840.10008.1.2.4.57":"JPEG Lossless, Non-Hierarchical (Process 14)","1.2.840.10008.1.2.4.58":"JPEG Lossless, Non-Hierarchical (Process 15) (Retired)","1.2.840.10008.1.2.4.59":"JPEG Extended, Hierarchical (Process 16 & 18) (Retired)","1.2.840.10008.1.2.4.60":"JPEG Extended, Hierarchical (Process 17 & 19) (Retired)","1.2.840.10008.1.2.4.61":"JPEG Spectral Selection, Hierarchical (Process 20 & 22) (Retired)","1.2.840.10008.1.2.4.62":"JPEG Spectral Selection, Hierarchical (Process 21 & 23) (Retired)","1.2.840.10008.1.2.4.63":"JPEG Full Progression, Hierarchical (Process 24 & 26) (Retired)","1.2.840.10008.1.2.4.64":"JPEG Full Progression, Hierarchical (Process 25 & 27) (Retired)","1.2.840.10008.1.2.4.65":"JPEG Lossless, Hierarchical (Process 28) (Retired)","1.2.840.10008.1.2.4.66":"JPEG Lossless, Hierarchical (Process 29) (Retired)","1.2.840.10008.1.2.4.70":"JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1])","1.2.840.10008.1.2.4.80":"JPEG-LS Lossless Image Compression","1.2.840.10008.1.2.4.81":"JPEG-LS Lossy (Near-Lossless) Image Compression","1.2.840.10008.1.2.4.90":"JPEG 2000 Image Compression (Lossless Only)","1.2.840.10008.1.2.4.91":"JPEG 2000 Image Compression","1.2.840.10008.1.2.4.92":"JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)","1.2.840.10008.1.2.4.93":"JPEG 2000 Part 2 Multi-component Image Compression","1.2.840.10008.1.2.4.94":"JPIP Referenced","1.2.840.10008.1.2.4.95":"JPIP Referenced Deflate","1.2.840.10008.1.2.4.100":"MPEG2 Main Profile / Main Level","1.2.840.10008.1.2.4.101":"MPEG2 Main Profile / High Level","1.2.840.10008.1.2.4.102":"MPEG-4 AVC/H.264 High Profile / Level 4.1","1.2.840.10008.1.2.4.103":"MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1","1.2.840.10008.1.2.4.104":"MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video","1.2.840.10008.1.2.4.105":"MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video","1.2.840.10008.1.2.4.106":"MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2","1.2.840.10008.1.2.4.107":"HEVC/H.265 Main Profile / Level 5.1","1.2.840.10008.1.2.4.108":"HEVC/H.265 Main 10 Profile / Level 5.1","1.2.840.10008.1.2.5":"RLE Lossless","1.2.840.10008.1.2.6.1":"RFC 2557 MIME encapsulation (Retired)","1.2.840.10008.1.2.6.2":"XML Encoding (Retired)","1.2.840.10008.1.2.7.1":"SMPTE ST 2110-20 Uncompressed Progressive Active Video","1.2.840.10008.1.2.7.2":"SMPTE ST 2110-20 Uncompressed Interlaced Active Video","1.2.840.10008.1.2.7.3":"SMPTE ST 2110-30 PCM Digital Audio","1.2.840.10008.1.20":"Papyrus 3 Implicit VR Little Endian (Retired)"},ie="1.2.840.10008.1.2",re="1.2.840.10008.1.2.1",oe="1.2.840.10008.1.2.2",ae="1.2.840.10008.1.2.4.50",se="1.2.840.10008.1.2.4.51",le="1.2.840.10008.1.2.4.57",ce="1.2.840.10008.1.2.4.70",ue="1.2.840.10008.1.2.5";class de{#L;#P;constructor(e,t){if(!e||void 0===e)throw new Error("Cannot create tag with no group.");if(4!==e.length)throw new Error("Cannot create tag with badly sized group: "+e);if(!t||void 0===t)throw new Error("Cannot create tag with no element.");if(4!==t.length)throw new Error("Cannot create tag with badly sized element: "+t);this.#L=e,this.#P=t}getGroup(){return this.#L}getElement(){return this.#P}toString(){return this.getKey()+": "+this.getNameFromDictionary()}equals(e){return null!=e&&this.#L===e.getGroup()&&this.#P===e.getElement()}getKey(){return this.#L+this.#P}getGroupName(){return _[this.#L]}isWithVR(){return!("FFFE"===this.#L&&("E000"===this.#P||"E00D"===this.#P||"E0DD"===this.#P))}isPrivate(){return parseInt(this.#L,16)%2==1}#w(){let e;return void 0!==j[this.#L]&&void 0!==j[this.#L][this.#P]&&(e=j[this.#L][this.#P]),e}getVrFromDictionary(){let e;const t=this.#w();return void 0!==t&&(e=t[0]),e}getNameFromDictionary(){let e;const t=this.#w();return void 0!==t&&(e=t[2]),e}}function he(e,t){let n=parseInt(e.getGroup(),16)-parseInt(t.getGroup(),16);return 0===n&&(n=parseInt(e.getElement(),16)-parseInt(t.getElement(),16)),n}function Se(e){if(!e||void 0===e)throw new Error("Cannot create tag with no key.");if(8!==e.length)throw new Error("Cannot create tag with badly sized key: "+e);return new de(e.substring(0,4),e.substring(4,8))}function ge(){return new de("FFFE","E000")}function pe(e){return"FFFEE000"===e.getKey()}function me(e){return"FFFEE00D"===e.getKey()}function fe(e){return"FFFEE0DD"===e.getKey()}function De(){return new de("7FE0","0010")}function ye(e){return"7FE00010"===e.getKey()}function Ce(e){if(null==e)return null;let t=null,n=null;const i=j,r=Object.keys(i);let o,a=null,s=!1;for(let o=0,l=r.length;o<l;++o){t=r[o],a=Object.keys(i[t]);for(let r=0,o=a.length;r<o;++r)if(n=a[r],i[t][n][2]===e){s=!0;break}if(s)break}return s&&(o=new de(t,n)),o}class ve{vr;value;tag;vl;undefinedLength;startOffset;endOffset;items;constructor(e){this.vr=e}}function Ie(e,t){let n;return void 0!==e[t]&&(n=e[t].value[0]),n}function Te(e){const t=e.byteLength,n=new Uint8Array(e.buffer,e.byteOffset,t),i=e.BYTES_PER_ELEMENT;let r;for(let e=0;e<t;e+=i)for(let t=e+i-1,o=e;t>o;t--,o++)r=n[o],n[o]=n[t],n[t]=r}class Le{#O;#A=!0;#b=function(){return new Int8Array(new Int16Array([1]).buffer)[0]>0}();#x;#R;constructor(e,t){this.#O=e,void 0!==t&&(this.#A=t),this.#x=this.#A!==this.#b,this.#R=new DataView(e)}readUint16(e){return this.#R.getUint16(e,this.#A)}readInt16(e){return this.#R.getInt16(e,this.#A)}readUint32(e){return this.#R.getUint32(e,this.#A)}readBigUint64(e){return this.#R.getBigUint64(e,this.#A)}readInt32(e){return this.#R.getInt32(e,this.#A)}readBigInt64(e){return this.#R.getBigInt64(e,this.#A)}readFloat32(e){return this.#R.getFloat32(e,this.#A)}readFloat64(e){return this.#R.getFloat64(e,this.#A)}readBinaryArray(e,t){const n=new Uint8Array(this.#O,e,t),i=8*n.length,r=new Uint8Array(i);let o=0,a=0;for(let e=0;e<i;++e)o=e%8,a=Math.floor(e/8),r[e]=255*!!(n[a]&1<<o);return r}readUint8Array(e,t){return new Uint8Array(this.#O,e,t)}readInt8Array(e,t){return new Int8Array(this.#O,e,t)}readUint16Array(e,t){const n=Uint16Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Uint16Array(this.#O,e,i),this.#x&&Te(r);else{r=new Uint16Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readUint16(t),t+=n}return r}readInt16Array(e,t){const n=Int16Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Int16Array(this.#O,e,i),this.#x&&Te(r);else{r=new Int16Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readInt16(t),t+=n}return r}readUint32Array(e,t){const n=Uint32Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Uint32Array(this.#O,e,i),this.#x&&Te(r);else{r=new Uint32Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readUint32(t),t+=n}return r}readUint64Array(e,t){const n=BigUint64Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new BigUint64Array(this.#O,e,i),this.#x&&Te(r);else{r=new BigUint64Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readBigUint64(t),t+=n}return r}readInt32Array(e,t){const n=Int32Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Int32Array(this.#O,e,i),this.#x&&Te(r);else{r=new Int32Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readInt32(t),t+=n}return r}readInt64Array(e,t){const n=BigInt64Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new BigInt64Array(this.#O,e,i),this.#x&&Te(r);else{r=new BigInt64Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readBigInt64(t),t+=n}return r}readFloat32Array(e,t){const n=Float32Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Float32Array(this.#O,e,i),this.#x&&Te(r);else{r=new Float32Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readFloat32(t),t+=n}return r}readFloat64Array(e,t){const n=Float64Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Float64Array(this.#O,e,i),this.#x&&Te(r);else{r=new Float64Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readFloat64(t),t+=n}return r}readHex(e){const t=this.readUint16(e).toString(16);return"0000".substring(0,4-t.length)+t.toUpperCase()}}function Pe(){return"0.35.0-beta.11"}function we(e){return!(e.byteLength<132)&&"DICM"===new Uint8Array(e,128,4).reduce((function(e,t){return e+String.fromCharCode(t)}),"")}const Oe=String.fromCharCode("u200B");class Ae{decode(e){let t="";for(let n=0,i=e.length;n<i;++n)t+=String.fromCharCode(e[n]);return t}}function be(e){if(!e)return null;const t={L:"R",R:"L",A:"P",P:"A",H:"F",F:"H"};let n="";for(let i=0;i<e.length;i++){const r=t[e.substring(i,i+1)];r&&(n+=r)}return n}function xe(e){return e===ie}function Re(e){return e===oe}function Fe(e){return e===ae||e===se}function Ee(e){return e===le||e===ce}function qe(e){return null!==e.match(/1.2.840.10008.1.2.4.9/)}function Ue(e){return e===ue}function Me(e,t,n){let i=null;try{1===e||8===e?i=0===t?new Uint8Array(n):new Int8Array(n):16===e?i=0===t?new Uint16Array(n):new Int16Array(n):32===e&&(i=0===t?new Uint32Array(n):new Int32Array(n))}catch(e){if(e instanceof RangeError){const e=Math.floor(Math.log(n)/Math.log(2));c.error("Cannot allocate array of size: "+n+" (>2^"+e+").")}}return i}function Qe(e,t){return t?8:J(e)?12:8}const Ve="00280008",Ne="00280100",Be="00280103",Ge="7FE00010";class ke{#F={};#E;#q=new Ae;#U=this.#q;#M(e){return this.#q.decode(e)}#Q(e){return this.#U.decode(e)}getDefaultCharacterSet(){return this.#E}setDefaultCharacterSet(e){this.#E=e}setDecoderCharacterSet(e){this.#U=new TextDecoder(e)}getDicomElements(){return this.#F}safeGet(e){return Ie(this.#F,e)}#V(e,t){const n=e.readHex(t);t+=Uint16Array.BYTES_PER_ELEMENT;const i=e.readHex(t);return t+=Uint16Array.BYTES_PER_ELEMENT,{tag:new de(n,i),endOffset:t}}#N(e,t,n){const i={};let r=this.#B(e,t,n);if(t=r.endOffset,fe(r.tag))return{data:i,endOffset:r.endOffset,isSeqDelim:!0};if(i[r.tag.getKey()]={tag:r.tag,vr:"NONE",vl:r.vl,undefinedLength:r.undefinedLength},r.undefinedLength){let o=!1;for(;!o;)r=this.#B(e,t,n),t=r.endOffset,o=me(r.tag),o||(i[r.tag.getKey()]=r)}else{const o=t;for(t-=r.vl;t<o;)r=this.#B(e,t,n),t=r.endOffset,i[r.tag.getKey()]=r}return{data:i,endOffset:t,isSeqDelim:!1}}#G(e,t,n){const i=[];let r=this.#B(e,t,n);const o=r.vl;t=r.endOffset;let a=!1;for(;!a;)r=this.#B(e,t,n),t=r.endOffset,a=fe(r.tag),a||(r.vr="OB",i.push(r));return{data:i,endOffset:t,offsetTableVl:o}}#B(e,t,n,i){const r=this.#V(e,t),o=r.tag;if(void 0!==i&&o.equals(i)){const e=new ve("");return e.tag=o,e}t=r.endOffset;let a=null,s=!1;o.isWithVR()?n?(a=o.getVrFromDictionary(),void 0===a&&(a="UN"),s=!0):(a=this.#M(e.readUint8Array(t,2)),t+=2*Uint8Array.BYTES_PER_ELEMENT,s=J(a),s&&(t+=2*Uint8Array.BYTES_PER_ELEMENT)):(a="NONE",s=!0),function(e){return Object.keys(te).concat(["NONE","ox","xx","xs"]).includes(e)}(a)||(c.warn("Unknown VR: "+a+" (for tag "+o.getKey()+"), treating as 'UN'"),a="UN");let l=0;s?(l=e.readUint32(t),t+=Uint32Array.BYTES_PER_ELEMENT):(l=e.readUint16(t),t+=Uint16Array.BYTES_PER_ELEMENT);let u=!1;4294967295===l&&(u=!0,l=0),o.isPrivate()&&"UN"===a&&0===l&&(a="SQ");let d,h=t,S=h+l;if(ye(o)&&u){const i=this.#G(e,t,n);t=i.endOffset,h+=i.offsetTableVl,d=i.data,S=t,l=t-h}else if("SQ"===a){let i;if(d=[],u){let r=!1;for(;!r;)i=this.#N(e,t,n),r=i.isSeqDelim,t=i.endOffset,r||d.push(i.data);S=t,l=t-h}else if(0!==l){const r=t+l;for(;t<r;)i=this.#N(e,t,n),d.push(i.data),t=i.endOffset;S=t,l=t-h}}const g=new ve(a);return g.tag=o,g.vl=l,g.startOffset=h,g.endOffset=S,u&&(g.undefinedLength=u),d&&(g.items=d),g}#k(e,t,n,i){const r=e.tag,o=e.vl,a=e.vr,s=e.startOffset;let l=null;const u=te[a];if(ye(r))if(e.undefinedLength){l=[];for(let r=0;r<e.items.length;++r)l.push(this.#k(e.items[r],t,n,i));delete e.items}else if(i>8&&"OB"===a&&(c.warn("Reading DICOM pixel data with bitsAllocated>8 and OB VR, treating as OW"),e.vr="OW"),l=[],1===i)l.push(t.readBinaryArray(s,o));else if(8===i)0===n?l.push(t.readUint8Array(s,o)):l.push(t.readInt8Array(s,o));else{if(16!==i)throw new Error("Unsupported bits allocated: "+i);0===n?l.push(t.readUint16Array(s,o)):l.push(t.readInt16Array(s,o))}else if(void 0!==u)if("Uint8"===u)l=t.readUint8Array(s,o);else if("Uint16"===u)l=t.readUint16Array(s,o),"O"!==a[0]&&(l=Array.from(l));else if("Uint32"===u)l=t.readUint32Array(s,o),"O"!==a[0]&&(l=Array.from(l));else if("Uint64"===u)l=t.readUint64Array(s,o);else if("Int16"===u)l=Array.from(t.readInt16Array(s,o));else if("Int32"===u)l=Array.from(t.readInt32Array(s,o));else if("Int64"===u)l=t.readInt64Array(s,o);else if("Float32"===u)l=Array.from(t.readFloat32Array(s,o));else if("Float64"===u)l=Array.from(t.readFloat64Array(s,o));else{if("string"!==u)throw new Error("Unknown VR type: "+u);{const e=t.readUint8Array(s,o);l=ee(a)?this.#Q(e):this.#M(e),l=function(e){let t=e;const n=e.length-1;return e[n]===Oe&&(t=e.substring(0,n)),t=t.trim(),t}(l).split("\\")}}else if("xx"===a)l=Array.from(t.readUint16Array(s,o));else if("ox"===a)l=8===i?0===n?Array.from(t.readUint8Array(s,o)):Array.from(t.readInt8Array(s,o)):0===n?Array.from(t.readUint16Array(s,o)):Array.from(t.readInt16Array(s,o));else if("xs"===a)l=0===n?Array.from(t.readUint16Array(s,o)):Array.from(t.readInt16Array(s,o));else if("AT"===a){const e=t.readUint16Array(s,o);l=[];for(let t=0,n=e.length;t<n;t+=2){const n=e[t].toString(16),i=e[t+1].toString(16);let r="(";r+="0000".substring(0,4-n.length)+n.toUpperCase(),r+=",",r+="0000".substring(0,4-i.length)+i.toUpperCase(),r+=")",l.push(r)}}else if("SQ"===a){l=[];for(let r=0;r<e.items.length;++r){const o=e.items[r],a={},s=Object.keys(o);let c=i,u=n;for(let e=0;e<s.length;++e){let n=o[Ne];void 0!==n&&void 0!==n.value&&(c=n.value[0]),n=o[Be],void 0!==n&&void 0!==n.value&&(u=n.value[0]);const i=o[s[e]];i.value=this.#k(i,t,u,c),delete i.tag,delete i.vl,delete i.startOffset,delete i.endOffset,a[s[e]]=i}l.push(a)}delete e.items}else"NONE"===a||c.warn("Unknown VR: "+a+" (for tag "+e.tag.getKey()+")"),l=[];return l}#H(e,t,n,i){const r=Object.keys(e);for(let o=0;o<r.length;++o){const a=e[r[o]];void 0===a.value&&(a.value=this.#k(a,t,n,i)),delete a.tag,delete a.vl,delete a.startOffset,delete a.endOffset}}parse(e,t){let n=0,i="",r=null;const o=new Le(e);let a=new Le(e);n=128;const s=this.#M(o.readUint8Array(n,4));if(n+=4*Uint8Array.BYTES_PER_ELEMENT,"DICM"===s){r=this.#B(o,n,!1),r.value=this.#k(r,o),n=r.endOffset,this.#F[r.tag.getKey()]=r;const e=n+r.value[0];for(;n<e;)r=this.#B(o,n,!1),n=r.endOffset,this.#F[r.tag.getKey()]=r;if(r=this.#F["00020010"],void 0===r)throw new Error("Not a valid DICOM file (no TransferSyntaxUID found)");r.value=this.#k(r,o),i=r.value[0]}else{c.warn("No DICM prefix, trying to guess tansfer syntax."),r=this.#B(a,0,!1);const e=function(e){const t="0008",n=e.tag.getGroup();if("0800"!==n&&n!==t)throw new Error("Not a valid DICOM file (no magic DICM word found and first element not in 0008 group)");const i=e.vr,r=i.charCodeAt(0),o=i.charCodeAt(1),a=!(r>=65&&r<=90&&o>=65&&o<=90);let s=null;if(n===t)s=a?ie:re;else{if(a)throw new Error("Not a valid DICOM file (no magic DICM word foundand implicit VR big endian detected)");s=oe}const l=new ve("UI");return l.tag=new de("0002","0010"),l.value=[s],l.vl=l.value[0].length,l.startOffset=e.startOffset,l.endOffset=l.startOffset+l.vl,l}(r);this.#F[e.tag.getKey()]=e,i=e.value[0],n=0}if(!function(e){return e===ie||e===re||e===oe||Fe(e)||Ee(e)||qe(e)||Ue(e)}(i))throw new Error("Unsupported DICOM transfer syntax: '"+i+"' ("+function(e){let t="Unknown";return void 0!==ne[e]&&(t=ne[e]),t}(i)+")");let l=!1;xe(i)&&(l=!0),Re(i)&&(a=new Le(e,!1));let u=!1;for(;n<e.byteLength;){if(r=this.#B(a,n,l,t),void 0!==t&&r.tag.equals(t)){u=!0;break}n=r.endOffset;const e=r.tag.getKey();void 0===this.#F[e]?this.#F[e]=r:c.warn("Not saving duplicate tag: "+e)}if(isNaN(n))throw new Error("Problem while parsing, bad offset");u||e.byteLength===n||c.warn("Did not reach the end of the buffer: "+n+" != "+e.byteLength);let d=0,h=16;if(void 0!==this.#F[Ge]&&(r=this.#F[Be],void 0!==r?(r.value=this.#k(r,a),d=r.value[0]):c.warn("Reading DICOM pixel data with default pixelRepresentation."),r=this.#F[Ne],void 0!==r?(r.value=this.#k(r,a),h=r.value[0]):c.warn("Reading DICOM pixel data with default bitsAllocated.")),void 0!==this.#E&&this.setDecoderCharacterSet(this.#E),r=this.#F["00080005"],void 0!==r){let e;r.value=this.#k(r,a),1===r.value.length?e=r.value[0]:(e=r.value[1],c.warn("Unsupported character set with code extensions: '"+e+"'.")),this.setDecoderCharacterSet(function(e){let t="utf-8";return"ISO_IR 100"===e?t="iso-8859-1":"ISO_IR 101"===e?t="iso-8859-2":"ISO_IR 109"===e?t="iso-8859-3":"ISO_IR 110"===e?t="iso-8859-4":"ISO_IR 144"===e?t="iso-8859-5":"ISO_IR 127"===e?t="iso-8859-6":"ISO_IR 126"===e?t="iso-8859-7":"ISO_IR 138"===e?t="iso-8859-8":"ISO_IR 148"===e?t="iso-8859-9":"ISO_IR 13"===e?t="shift-jis":"ISO_IR 166"===e?t="iso-8859-11":"ISO 2022 IR 87"===e?t="iso-2022-jp":"ISO 2022 IR 149"===e||"ISO 2022 IR 58"===e||("ISO_IR 192"===e?t="utf-8":"GB18030"===e?t="gb18030":"GB2312"===e?t="gb2312":"GBK"===e&&(t="chinese")),t}(e))}if(this.#H(this.#F,a,d,h),r=this.#F[Ge],void 0!==r&&r.undefinedLength){let e=1;void 0!==this.#F[Ve]&&(e=Number(this.#F[Ve].value[0]));const t=r.value;if(t.length>1&&t.length>e){const n=t.length/e,i=[];let o=0;for(let r=0;r<e;++r){o=r*n;let e=0;for(let i=0;i<n;++i)e+=t[o+i].length;const a=new t[0].constructor(e);let s=0;for(let e=0;e<n;++e)a.set(t[o+e],s),s+=t[o+e].length;i[r]=a}r.value=i}}}}class He{#z={};add(e,t){void 0===this.#z[e]&&(this.#z[e]=[]),this.#z[e].push(t)}remove(e,t){if(void 0===this.#z[e])return;let n=0;for(let i=0;i<this.#z[e].length;++i)this.#z[e][i]===t&&(++n,this.#z[e].splice(i,1));0===n&&c.debug("No callback found on remove listener for type "+e)}fireEvent=e=>{if(void 0===this.#z[e.type])return;const t=this.#z[e.type].slice();for(let n=0;n<t.length;++n)t[n](e)}}function ze(e,t,n,i,r,o,a,s){void 0===a&&(a=!1),void 0===s&&(s=!1);let l=t;a?(o*=-1,s?l-=(r-1)*i:i*=-1):s&&(l+=(r-1)*i,i*=-1);const c=o-r*i;let u=0,d=0;return{next:function(){if(u<n){const t={value:e(l),done:!1,index:l};return l+=i,++u,++d,d===r&&(d=0,l+=c),t}return{done:!0,index:l}}}}function We(e){const t=[];let n=e.next();for(;!n.done;)t.push(n.value),n=e.next();return t}function Ye(e,t,n,i){const r=e.getGeometry().getSize();let o=2;i&&void 0!==i&&(o=i.getColAbsMax(2).index);const a=t.getValues(),l=new s(a.map((function(e,t){return t===o||t>2?e:0})));let c=r.indexToOffset(l);void 0===n&&(n=!1);let u=null;u=n?function(t){return e.getRescaledValueAtOffset(t)}:function(t){return e.getValueAtOffset(t)};const d=r.get(0),h=r.get(1),S=r.get(2);let g=r.getDimSize(2);const p=e.getNumberOfComponents(),m=1===e.getPlanarConfiguration(),f=function(e,t,n,i,r,o,a,s){return 1===p?ze(e,t,n,i,r,o,a,s):3===p?function(e,t,n,i,r,o,a,s,l){const c=[];return l?(c.push(ze(e,t,n,i,r,o,a,s)),c.push(ze(e,t+n*i,n,i,r,o,a,s)),c.push(ze(e,t+2*n*i,n,i,r,o,a,s))):(i*=3,o*=3,c.push(ze(e,t,n,i,r,o,a,s)),c.push(ze(e,t+1,n,i,r,o,a,s)),c.push(ze(e,t+2,n,i,r,o,a,s))),{next:function(){const e=c[0].next(),t=c[1].next(),n=c[2].next();return e.done?{done:!0,index:n.index}:{value:[e.value,t.value,n.value],done:!1,index:[e.index,t.index,n.index]}}}}(e,3*t,n,i,r,o,a,s,m):void 0};let D=null;if(i&&void 0!==i){const e=i.getColAbsMax(0),t=i.getColAbsMax(2),n=!1,r=!1;let o=null;if(2===t.index)o=d*h,D=0===e.index?f(u,c,o,1,d,d,n,r):f(u,c,o,d,h,1,n,r);else if(0===t.index)o=S*h,D=1===e.index?f(u,c,o,d,h,g,n,r):f(u,c,o,g,S,d,n,r);else{if(1!==t.index)throw new Error("Unknown direction: "+t.index);o=S*d,D=0===e.index?f(u,c,o,1,d,g,n,r):f(u,c,o,g,S,1,n,r)}}else if(1===e.getNumberOfComponents())D=function(e,t,n,i){void 0===i&&(i=1);let r=t;return{next:function(){if(r<n){const t={value:e(r),done:!1,index:r};return r+=i,t}return{done:!0,index:n}}}}(u,c,c+g);else{if(3!==e.getNumberOfComponents())throw new Error("Unsupported number of components: "+e.getNumberOfComponents());c*=3,g*=3,D=function(e,t,n,i,r){void 0===i&&(i=1),void 0===r&&(r=!1);let o=t,a=1;r?a=(n-t)/3:i*=3;let s=o+a,l=o+2*a;return{next:function(){if(o<n){const t={value:[e(o),e(s),e(l)],done:!1,index:[o,s,l]};return o+=i,s+=i,l+=i,t}return{done:!0,index:[n]}}}}(u,c,c+g,1,m)}return D}function Xe(e,t){let n=0,i=0;return{next:function(){if(n<t){i+1<e.length&&n>=e[i+1].index&&++i;const t={value:e[i].value,done:!1,index:n};return++n,t}return{done:!0,index:t}}}}class je{#h;#W;constructor(e,t){this.#h=e,this.#W=t}getSlope(){return this.#h}getIntercept(){return this.#W}apply(e){return e*this.#h+this.#W}equals(e){return null!=e&&this.getSlope()===e.getSlope()&&this.getIntercept()===e.getIntercept()}isID(){return 1===this.getSlope()&&0===this.getIntercept()}}class Ze{#e;constructor(e){if(!e||void 0===e)throw new Error("Cannot create size with no values.");if(0===e.length)throw new Error("Cannot create size with empty values.");if(!e.every((function(e){return!isNaN(e)&&0!==e})))throw new Error("Cannot create size with non number or zero values.");this.#e=e}get(e){return this.#e[e]}length(){return this.#e.length}toString(){return"("+this.#e.toString()+")"}getValues(){return this.#e.slice()}moreThanOne(e){return this.length()>=e+1&&1!==this.get(e)}canScroll3D(e){let t=2;return void 0!==e&&(t=e.getThirdColMajorDirection()),this.moreThanOne(t)}canScroll(e){let t=this.canScroll3D(e);for(let e=3;e<this.length();++e)t=t||this.moreThanOne(e);return t}getDimSize(e,t){if(e>this.length())return null;if(void 0===t)t=0;else if(t<0||t>e)throw new Error("Invalid start value for getDimSize");let n=1;for(let i=t;i<e;++i)n*=this.get(i);return n}getTotalSize(e){return this.getDimSize(this.length(),e)}equals(e){if(!e)return!1;const t=this.length();if(t!==e.length())return!1;for(let n=0;n<t;++n)if(this.get(n)!==e.get(n))return!1;return!0}isInBounds(e,t){if(!e)return!1;const n=this.length();if(n!==e.length())return!1;if(void 0===t){t=[];for(let e=0;e<n;++e)t.push(e)}else for(let e=0;e<n;++e)if(t[e]>n-1)throw new Error("Wrong input dir value: "+t[e]);for(let n=0;n<t.length;++n)if(i=e.get(t[n]),r=this.get(t[n]),!(i>=0&&i<r))return!1;var i,r;return!0}indexToOffset(e,t){if(e.length()<this.length())throw new Error("Incompatible index and size length");if(void 0===t)t=0;else if(t<0||t>this.length()-1)throw new Error("Invalid start value for indexToOffset");let n=0;for(let i=t;i<this.length();++i)n+=e.get(i)*this.getDimSize(i,t);return n}offsetToIndex(e){const t=new Array(this.length());let n=e,i=0;for(let e=this.length()-1;e>0;--e)i=this.getDimSize(e),t[e]=Math.floor(n/i),n-=t[e]*i;return t[0]=n,new s(t)}get2D(){return{x:this.get(0),y:this.get(1)}}}class _e{min;max;mean;stdDev;median;p25;p75;constructor(e,t,n,i){this.min=e,this.max=t,this.mean=n,this.stdDev=i}}function Ke(e,t){return function(e){return null!=e&&(e.includes("median")||e.includes("p25")||e.includes("p75"))}(t)?function(e){const t=Je(e);return e.sort((function(e,t){return e-t})),t.median=$e(e,.5),t.p25=$e(e,.25),t.p75=$e(e,.75),t}(e):Je(e)}function Je(e){let t=e[0],n=t,i=0,r=0,o=0;const a=e.length;for(let s=0;s<a;++s)o=e[s],o<t?t=o:o>n&&(n=o),i+=o,r+=o*o;const s=i/a;let l=r/a-s*s;l<0&&(l=0);const c=Math.sqrt(l);return new _e(t,n,s,c)}function $e(e,t){if(0===e.length)throw new Error("Empty array provided for percentile calculation.");if(t<0||t>1)throw new Error("Invalid ratio provided for percentile calculation: "+t);if(0===t)return e[0];if(1===t)return e[e.length-1];const n=(e.length-1)*t,i=Math.floor(n),r=e[i];return r+(e[i+1]-r)*(n-i)}function et(){return Math.random().toString(36).substring(2,15)}class tt{min;max;constructor(e,t){this.min=e,this.max=t}}class nt{#e;constructor(e){if(!e||void 0===e)throw new Error("Cannot create spacing with no values.");if(0===e.length)throw new Error("Cannot create spacing with empty values.");if(!e.every((function(e){return!isNaN(e)&&0!==e})))throw new Error("Cannot create spacing with non number or zero values.");this.#e=e}get(e){return this.#e[e]}length(){return this.#e.length}toString(){return"("+this.#e.toString()+")"}getValues(){return this.#e.slice()}equals(e){if(!e)return!1;const t=this.length();if(t!==e.length())return!1;for(let n=0;n<t;++n)if(this.get(n)!==e.get(n))return!1;return!0}get2D(){return{x:this.get(0),y:this.get(1)}}}class it{#Y;#X;#j;#Z={};#_;#K=b();#J=!1;constructor(e,t,n,i,r){this.#Y=e,this.#X=t,this.#j=n,void 0!==r&&(this.#_=r,this.#Z[r]=e),void 0!==i&&(this.#K=i)}getInitialTime(){return this.#_}getCurrentTotalNumberOfSlices(){const e=Object.keys(this.#Z);if(0===e.length)return this.#Y.length;let t=0;for(let n=0;n<e.length;++n)t+=this.#Z[e[n]].length;return t}hasSlicesAtTime(e){return void 0!==this.#Z[e]}getCurrentNumberOfSlicesBeforeTime(e){const t=Object.keys(this.#Z);if(0===t.length)return;let n=0;for(let i=0;i<t.length;++i){const r=t[i];if(parseInt(r,10)===e)break;n+=this.#Z[r].length}return n}getOrigin(){return this.#Y[0]}getOrigins(){return this.#Y}includesOrigin(e,t){for(let n=0;n<this.#Y.length;++n)if(this.#Y[n].isSimilar(e,t))return!0;return!1}getSize(e){let t=this.#X;if(e&&void 0!==e){let n=rt([this.#X.get(0),this.#X.get(1),this.#X.get(2)],e);n=n.map(Math.abs),t=new Ze(n.concat(this.#X.getValues().slice(3)))}return t}#$(){const e=function(e){if(e.length<=1)return;const t=[];for(let n=0;n<e.length-1;++n){const i=e[n],r=e[n+1],o=i.getDistance(r);if(0===o)throw new Error("Zero slice spacing "+i.toString()+" "+r.toString());t.push(o)}const n=Je(t),i=B(n.mean,4);return n.stdDev>w&&c.warn("Varying slice spacing, value: "+i+" (mean: "+n.mean+", min: "+n.min+", max: "+n.max+", stdDev: "+n.stdDev+")"),i}(this.#Y);if(void 0!==e&&this.#j.get(2)!==e){c.trace("Using geometric spacing "+e+" instead of tag spacing "+this.#j.get(2));const t=this.#j.getValues();t[2]=e,this.#j=new nt(t)}}getSpacing(e){this.#J&&(this.#$(),this.#J=!1);let t=this.#j;if(e&&void 0!==e){let n=rt([this.#j.get(0),this.#j.get(1),this.#j.get(2)],e);n=n.map(Math.abs),t=new nt(n)}return t}getRealSpacing(){return this.getSpacing(this.#K.getInverse().asOneAndZeros())}getOrientation(){return this.#K}getSliceIndex(e,t){let n=this.#Y;void 0!==t&&(n=this.#Z[t]);const i=e.getClosest(n),r=n[i],o=e.minus(r);return new P(this.#K.get(0,2),this.#K.get(1,2),this.#K.get(2,2)).isCodirectional(o)?i+1:i}appendOrigin(e,t,n){const i=function(t){return t.equals(e)};if(void 0!==n){if(void 0!==this.#Z[n].find(i))throw new Error("Cannot append same time origin twice");this.#Z[n].splice(t,0,e)}if(void 0===n||n===this.#_){if(void 0!==this.#Y.find(i))throw new Error("Cannot append same origin twice");this.#J=!0,this.#Y.splice(t,0,e);const n=this.#X.getValues();n[2]+=1,this.#X=new Ze(n)}}appendFrame(e,t){this.#Z[t]=[e];const n=this.#X.getValues(),i=this.#j.getValues();4===n.length?n[3]+=1:(n.push(2),i.push(1)),this.#X=new Ze(n),this.#j=new nt(i)}toString(){return"Origin: "+this.getOrigin()+", Size: "+this.getSize()+", Spacing: "+this.getSpacing()+", Orientation: "+this.getOrientation()}equals(e){return null!==e&&this.getOrigin().equals(e.getOrigin())&&this.getSize().equals(e.getSize())&&this.getSpacing().equals(e.getSpacing())}isInBounds(e){return this.isIndexInBounds(this.worldToIndex(e))}isIndexInBounds(e,t){return this.getSize().isInBounds(e,t)}getRange(){const e=this.getSize().length(),t=new Array(e);t.fill(0);const n=new s(t),i=new s(this.getSize().getValues());return[this.indexToWorld(n),this.indexToWorld(i)]}indexToWorld(e){const t=this.getSpacing(),n=new F(e.get(0)*t.get(0),e.get(1)*t.get(1),e.get(2)*t.get(2)),i=this.getOrientation().multiplyPoint3D(n),r=e.getValues(),o=this.getOrigin();return r[0]=o.getX()+i.getX(),r[1]=o.getY()+i.getY(),r[2]=o.getZ()+i.getZ(),new E(r)}pointToWorld(e){const t=this.getSpacing(),n=new F(e.getX()*t.get(0),e.getY()*t.get(1),e.getZ()*t.get(2)),i=this.getOrientation().multiplyPoint3D(n),r=this.getOrigin();return new F(r.getX()+i.getX(),r.getY()+i.getY(),r.getZ()+i.getZ())}worldToIndex(e){const t=this.getOrigin(),n=new F(e.get(0)-t.getX(),e.get(1)-t.getY(),e.get(2)-t.getZ()),i=this.getOrientation().getInverse().multiplyPoint3D(n),r=e.getValues(),o=this.getSpacing();return r[0]=Math.round(i.getX()/o.get(0)),r[1]=Math.round(i.getY()/o.get(1)),r[2]=Math.round(i.getZ()/o.get(2)),new s(r)}worldToPoint(e){const t=this.getOrigin(),n=new F(e.get(0)-t.getX(),e.get(1)-t.getY(),e.get(2)-t.getZ()),i=this.getOrientation().getInverse().multiplyPoint3D(n),r=e.getValues(),o=this.getSpacing();return r[0]=i.getX()/o.get(0),r[1]=i.getY()/o.get(1),r[2]=i.getZ()/o.get(2),new F(r[0],r[1],r[2])}}function rt(e,t){return t.getInverse().multiplyArray3D(e)}function ot(e,t){return t.multiplyArray3D(e)}function at(e){return("0"+e).slice(-2)}function st(e){if(void 0===e)return;if(1!==e.value.length)return;const t=e.value[0];let n=4,i=6;return 10===t.length&&(n=5,i=8),{year:parseInt(t.substring(0,4),10),monthIndex:t.length>=n+2?parseInt(t.substring(n,n+2),10)-1:0,day:t.length===i+2?parseInt(t.substring(i,i+2),10):0}}function lt(e){if(void 0===e)return;if(1!==e.value.length)return;const t=e.value[0],n=parseInt(t.substring(0,2),10),i=t.length>=4?parseInt(t.substring(2,4),10):0,r=t.length>=6?parseInt(t.substring(4,6),10):0,o=t.length>=8?t.substring(7,10):0;return{hours:n,minutes:i,seconds:r,milliseconds:0===o?0:parseInt(o,10)*Math.pow(10,3-o.length)}}function ct(e){return{year:e.getFullYear().toString(),monthIndex:at((e.getMonth()+1).toString()),day:at(e.getDate().toString())}}function ut(e){return{hours:at(e.getHours().toString()),minutes:at(e.getMinutes().toString()),seconds:at(e.getSeconds().toString())}}function dt(e){return e.year+e.monthIndex+e.day}function ht(e){return e.hours+e.minutes+e.seconds}function St(){return new A([1,0,0,0,0,1,0,-1,0])}const gt={Axial:"axial",Coronal:"coronal",Sagittal:"sagittal"};function pt(e){let t;return e===gt.Axial?t=b():e===gt.Coronal?t=St():e===gt.Sagittal&&(t=new A([0,0,-1,1,0,0,0,-1,0])),t}function mt(e){const t=new P(e.get(0,0),e.get(1,0),e.get(2,0)),n=new P(e.get(0,1),e.get(1,1),e.get(2,1)),i=new P(e.get(0,2),e.get(1,2),e.get(2,2));return ft(t)+ft(n)+ft(i)}function ft(e){let t=new P(Math.abs(e.getX()),Math.abs(e.getY()),Math.abs(e.getZ())),n="";const i=e.getX()<0?"R":"L",r=e.getY()<0?"A":"P",o=e.getZ()<0?"I":"S",a=1e-4;for(let e=0;e<3;e++)if(t.getX()>a&&t.getX()>t.getY()&&t.getX()>t.getZ())n+=i,t=new P(0,t.getY(),t.getZ());else if(t.getY()>a&&t.getY()>t.getX()&&t.getY()>t.getZ())n+=r,t=new P(t.getX(),0,t.getZ());else{if(!(t.getZ()>a&&t.getZ()>t.getX()&&t.getZ()>t.getY()))break;n+=o,t=new P(t.getX(),t.getY(),0)}return n}function Dt(e){let t;const n=yt(e);return void 0!==n&&(t=function(e){let t;return["LPS","LAI","RPI","RAS","ALS","ARI","PLI","PRS"].includes(e)?t=gt.Axial:["LSA","LIP","RSP","RIA","ILA","IRP","SLP","SRA"].includes(e)?t=gt.Coronal:["PSL","PIR","ASR","AIL","IAR","IPL","SAL","SPR"].includes(e)&&(t=gt.Sagittal),t}(mt(n.asOneAndZeros()))),t}function yt(e){let t;if(void 0!==e&&6===e.length){const n=new P(e[0],e[1],e[2]),i=new P(e[3],e[4],e[5]),r=n.crossProduct(i);t=new A([n.getX(),i.getX(),r.getX(),n.getY(),i.getY(),r.getY(),n.getZ(),i.getZ(),r.getZ()])}return t}function Ct(e,t){let n=b();return void 0!==t&&(n=e.asOneAndZeros().getInverse().multiply(t)),n.getAbs()}function vt(e){const t=e["00280010"];if(void 0===t)throw new Error("Missing DICOM image number of rows");if(0===t.value.length)throw new Error("Empty DICOM image number of rows");const n=e["00280011"];if(void 0===n)throw new Error("Missing DICOM image number of columns");if(0===n.value.length)throw new Error("Empty DICOM image number of columns");return[n.value[0],t.value[0]]}function It(e){if(void 0===e["00280030"])return null;const t=e["00280030"],n=[parseFloat(t.value[1]),parseFloat(t.value[0])];return void 0!==e["00180088"]&&n.push(parseFloat(e["00180088"].value[0])),new nt(n)}function Tt(e){return void 0!==e&&null!==e.match(/MONOCHROME/)}function Lt(e,t,n){let i="";if(void 0===e)i+=" "+t+" is undefined,";else if(0===e.value.length)i+=" "+t+" is empty,";else if(void 0!==n)for(let r=0;r<n.length;++r)e.value.includes(n[r])||(i+=" "+t+" does not contain "+n[r]+" (value: "+e.value+"),");return i}class Pt{#ee;#te;getWarning(){return this.#ee}checkElements(e){let t;this.#ee=void 0,vt(e);const n=e["00080060"];if(void 0!==n&&(t=n.value[0],"PT"===t)){const t=function(e){const t=e["00280004"],n=e["00020010"],i=e["00280002"];let r=1;if(void 0!==i&&(r=i.value[0]),void 0!==t&&void 0!==n){let e=t.value[0].toUpperCase();const i=n.value[0],o=qe(i),a=Fe(i),s=Ee(i);return(o||a||s)&&"MONOCHROME1"!==e&&"MONOCHROME2"!==e&&(e="RGB"),"RGB"===e&&1===r&&(e="PALETTE COLOR"),e}}(e),n=function(e){const t=e["00080016"];if(void 0!==t)return t.value[0]}(e);if(function(e){return!e&&/^1\.2\.840\.10008\.5\.1\.4\.1\.1\.7/.test(e)}(n)||!Tt(t))return this.#ee;const i=function(e){let t="";const n={};let i;t+=Lt(e["00280051"],"Corrected Image (00280051)",["ATTN","DECY"]),t+=Lt(e["00541102"],"Decay Correction (00541102)",["START"]),t+=Lt(e["00541001"],"Units (00541001)",["BQML"]);const r=e["00101030"],o=Lt(r," PatientWeight (00101030)");if(0===o.length){const e=parseFloat(r.value[0]);isNaN(e)?t+=" PatientWeight is not a number":i=e}else t+=o;const a=function(e){let t,n="";const i=st(e["00080021"]);let r,o,a;const s=e["00540016"];if(n+=Lt(s,"RadiopharmaceuticalInformationSequence (00540016)"),void 0!==s){1!==s.value.length&&c.warn("Found more than 1 istopes in RadiopharmaceuticalInformation Sequence.");const e="RadionuclideTotalDose (00181074)",l=s.value[0]["00181074"];if(t=Lt(l,e),0===t.length){const e=parseFloat(l.value[0]);isNaN(e)?n+=" TotalDose is not a number":r=e}else n+=t;const u="RadionuclideHalfLife (00181075)",d=s.value[0]["00181075"];if(t=Lt(d,u),0===t.length){const e=parseFloat(d.value[0]);isNaN(e)?n+=" HalfLife is not a number":o=e}else n+=t;const h=s.value[0]["00181078"];let S,g;if(void 0===h)S=i,g=lt(s.value[0]["00181072"]);else{const e=function(e){if(void 0===e)return;if(1!==e.value.length)return;const t=e.value[0].split("&")[0],n=new ve("DA");n.value=[t.substring(0,8)];const i=st(n),r=new ve("TM");return r.value=[t.substring(8)],{date:i,time:t.length>=9?lt(r):void 0}}(h);S=e.date,g=e.time}void 0===g&&(g={hours:0,minutes:0,seconds:0,milliseconds:0}),a=new Date(S.year,S.monthIndex,S.day,g.hours,g.minutes,g.seconds,g.milliseconds)}const l=lt(e["00080031"]);let u=new Date(i.year,i.monthIndex,i.day,l.hours,l.minutes,l.seconds,l.milliseconds);const d=e["00080022"],h=e["00080032"];if(void 0!==d&&void 0!==h){const t=st(d),i=lt(h),r=new Date(t.year,t.monthIndex,t.day,i.hours,i.minutes,i.seconds,i.milliseconds);if(u>r){const a="Series date/time is after Aquisition date/time (diff="+(u.getTime()-r.getTime()).toString()+"ms) ";c.debug(a);let s=0;const l="FrameReferenceTime (00541300)",d=e["00541300"];n+=Lt(d,l),void 0!==d&&(s=d.value[0]);let h=0;const S="ActualFrameDuration (0018,1242)",g=e["00181242"];if(n+=Lt(g,S),void 0!==g&&(h=g.value[0]),s>0&&h>0){h/=1e3,s/=1e3;const e=Math.log(2)/o,n=e*h,r=1/e*Math.log(n/(1-Math.exp(-n)))-s;u=new Date(t.year,t.monthIndex,t.day,i.hours,i.minutes,i.seconds+r,i.milliseconds)}}}let S;if(void 0!==u&&void 0!==a&&void 0!==r&&void 0!==o){const e=(u.getTime()-a.getTime())/1e3;S=r*Math.pow(2,-e/o)}return{value:S,warning:n}}(e);return t+=a.warning,0!==t.length?n.warning="Cannot calculate PET SUV:"+t:n.value=1e3*i/a.value,n}(e);this.#te=i.value,this.#ee=i.warning}return this.#ee}create(e,t,n){const i=vt(e),r=[i[0],i[1],1],o=e["00280008"];if(void 0!==o){const e=parseInt(o.value[0],10);e>1&&r.push(e)}const a=new Ze(r),s=function(e){let t=1,n=1;const i=["00280030","00181164","00182010","00280034"];for(let r=0;r<i.length;++r){const o=e[i[r]];if(o&&2===o.value.length){t=parseFloat(o.value[0]),n=parseFloat(o.value[1]);break}}return 0===n&&(c.warn("Zero column spacing."),n=1),0===t&&(c.warn("Zero row spacing."),t=1),new nt([n,t,1])}(e),l=e["00020010"].value[0],d=qe(l),h=Fe(l),S=Ee(l),g=e["00200032"];let p=new Array(0,0,0);void 0!==g&&(p=[parseFloat(g.value[0]),parseFloat(g.value[1]),parseFloat(g.value[2])]);const f=function(e){const t=e["00200037"];let n;return void 0!==t&&(n=yt(t.value.map((e=>parseFloat(e))))),n}(e),D=new F(p[0],p[1],p[2]),y=(C=e,void 0!==L.getTagTime?L.getTagTime(C):void 0);var C;const v=new it([D],a,s,f,y);let I;const T=e["00080018"];void 0!==T&&(I=T.value[0]);let P=1;const w=e["00280002"];void 0!==w&&(P=w.value[0]);const O=a.getTotalSize()*P;if(O!==t.length){if(c.warn("Badly sized pixel buffer: "+t.length+" != "+O),!(O<t.length))throw new Error("Underestimated buffer size, can't fix it...");t=t.slice(0,a.getTotalSize())}const A=new Un(v,t,[I]),b=e["00280004"];if(void 0!==b){let e=b.value[0].toUpperCase();(d||h||S)&&"MONOCHROME1"!==e&&"MONOCHROME2"!==e&&(e="RGB"),"RGB"===e&&1===P&&(e="PALETTE COLOR"),A.setPhotometricInterpretation(e)}const x=e["00280006"];void 0!==x&&A.setPlanarConfiguration(x.value[0]);let R=1;const E=e["00281053"];if(void 0!==E){const e=parseFloat(E.value[0]);isNaN(e)||(R=e)}let q=0;const U=e["00281052"];if(void 0!==U){const e=parseFloat(U.value[0]);isNaN(e)||(q=e)}const M={numberOfFiles:n},Q=e["00080060"];void 0!==Q&&(M.Modality=Q.value[0]);let V=!1,N=1;void 0!==this.#te&&(V=!0,N=this.#te,c.info("Applying PET SUV calibration: "+N),R*=N,q*=N);const B=new je(R,q);A.setRescaleSlopeAndIntercept(B);const G=function(t){return Ie(e,t)};if(M.TransferSyntaxUID=G("00020010"),M.MediaStorageSOPClassUID=G("00020002"),M.SOPClassUID=G("00080016"),M.Modality=G("00080060"),M.ImageType=G("00080008"),M.SamplesPerPixel=G("00280002"),M.PhotometricInterpretation=G("00280004"),M.PixelRepresentation=G("00280103"),M.BitsAllocated=G("00280100"),M.BitsStored=G("00280101"),M.HighBit=G("00280102"),M.StudyDate=G("00080020"),M.StudyTime=G("00080030"),M.StudyInstanceUID=G("0020000D"),M.StudyID=G("00200010"),M.SeriesInstanceUID=G("0020000E"),M.SeriesNumber=G("00200011"),M.ReferringPhysicianName=G("00080090"),M.PatientName=G("00100010"),M.PatientID=G("00100020"),M.PatientBirthDate=G("00100030"),M.PatientSex=G("00100040"),M.Manufacturer=G("00080070"),M.ManufacturerModelName=G("00081090"),M.DeviceSerialNumber=G("00181000"),M.SoftwareVersions=G("00181020"),M.ImageOrientationPatient=G("00200037"),M.FrameOfReferenceUID=G("00200052"),M.IsSigned=1===M.PixelRepresentation,V)M.pixelUnit="SUV";else{const t=function(e){return void 0!==L.getTagPixelUnit?L.getTagPixelUnit(e):function(e){let t;const n=["00281054","00541001"];for(let i=0;i<n.length;++i){const r=e[n[i]];if(void 0!==r){t=r.value[0];break}}if(void 0===t){const n=e["00080060"];void 0!==n&&"CT"===n.value[0]&&(t="HU")}return t}(e)}(e);void 0!==t&&(M.pixelUnit=t)}const k={},H=e["00281050"],z=e["00281051"],W=e["00281055"];if(void 0!==H&&void 0!==z){let e;for(let t=0;t<H.value.length;++t){const n=parseFloat(H.value[t]);let i=parseFloat(z.value[t]);n&&i&&0!==i&&(e="",void 0!==W&&(e=W.value[t]),""===e&&(e="Default"+t),i*=N,i<1&&(i=1),k[e]={wl:[new u(n*N,i)],name:e}),0===i&&c.warn("Zero window width found in DICOM.")}}if(M.windowPresets=k,"PALETTE COLOR"===A.getPhotometricInterpretation()){const t=e["00281201"],n=e["00281202"],i=e["00281203"];let r,o,a;const s=e["00281101"];if(void 0!==s&&3===s.value.length)if(16===s.value[2]){let l=!1,u=s.value[0];0===u&&(u=65536);const d=t.vl;if(d!==2*u&&(l=!0,c.info("16bits lut but size is not double. desc: "+u+" vl: "+d)),8===parseInt(e["00280100"].value[0],10)&&(l=!0,c.info("Scaling 16bits color lut since bits allocated is 8.")),l){const e=function(e){return e>>8};r=t.value.map(e),o=n.value.map(e),a=i.value.map(e)}}else if(8===s.value[2]){c.info("Scaling 16bits color lut since the lut descriptor is 8.");let e=t.value.slice(0);r=Array.from(new Uint8Array(e.buffer)),e=n.value.slice(0),o=Array.from(new Uint8Array(e.buffer)),e=i.value.slice(0),a=Array.from(new Uint8Array(e.buffer))}A.setPaletteColourMap(new m(r,o,a))}const Y=e["00082144"];return void 0!==Y&&(M.RecommendedDisplayFrameRate=parseInt(Y.value[0],10)),A.setMeta(M),A}}class wt{#A=!0;#R;constructor(e,t){void 0!==t&&(this.#A=t),this.#R=new DataView(e)}writeUint8(e,t){return this.#R.setUint8(e,t),e+Uint8Array.BYTES_PER_ELEMENT}writeInt8(e,t){return this.#R.setInt8(e,t),e+Int8Array.BYTES_PER_ELEMENT}writeUint16(e,t){return this.#R.setUint16(e,t,this.#A),e+Uint16Array.BYTES_PER_ELEMENT}writeInt16(e,t){return this.#R.setInt16(e,t,this.#A),e+Int16Array.BYTES_PER_ELEMENT}writeUint32(e,t){return this.#R.setUint32(e,t,this.#A),e+Uint32Array.BYTES_PER_ELEMENT}writeUint64(e,t){return this.#R.setBigUint64(e,t,this.#A),e+BigUint64Array.BYTES_PER_ELEMENT}writeInt32(e,t){return this.#R.setInt32(e,t,this.#A),e+Int32Array.BYTES_PER_ELEMENT}writeInt64(e,t){return this.#R.setBigInt64(e,t,this.#A),e+BigInt64Array.BYTES_PER_ELEMENT}writeFloat32(e,t){return this.#R.setFloat32(e,t,this.#A),e+Float32Array.BYTES_PER_ELEMENT}writeFloat64(e,t){return this.#R.setFloat64(e,t,this.#A),e+Float64Array.BYTES_PER_ELEMENT}writeHex(e,t){const n=parseInt(t,16);return this.#R.setUint16(e,n,this.#A),e+Uint16Array.BYTES_PER_ELEMENT}writeBinaryArray(e,t){if(t.length%8!=0)throw new Error("Cannot write boolean array as binary.");let n=null,i=null;for(let r=0,o=t.length;r<o;r+=8){n=0;for(let e=0;e<8;++e)i=0===t[r+e]?0:1,n+=i<<e;e=this.writeUint8(e,n)}return e}writeUint8Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeUint8(e,t[n]);return e}writeInt8Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeInt8(e,t[n]);return e}writeUint16Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeUint16(e,t[n]);return e}writeInt16Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeInt16(e,t[n]);return e}writeUint32Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeUint32(e,t[n]);return e}writeUint64Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeUint64(e,t[n]);return e}writeInt32Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeInt32(e,t[n]);return e}writeInt64Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeInt64(e,t[n]);return e}writeFloat32Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeFloat32(e,t[n]);return e}writeFloat64Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeFloat64(e,t[n]);return e}}let Ot=0;class At{action;value;constructor(e){this.action=e}}const bt={copy:function(e){return e},remove:function(){return null},clear:function(e){return e.value=[],e},replace:function(e,t){return e.value=[t],e}};function xt(e){const t="1.2.826.0.1.3680043.9.7278.1.";let n="";if("ImplementationClassUID"===e)n=t+"0.35.0-beta.11";else{const i="."+(new Date).toISOString().replace(/\D/g,"").substring(0,14);Ot+=1;const r="."+Ot;n=t;const o=29+r.length+i.length,a=Math.min(e.length,64-o);if(a>1){let t="";for(let n=0;n<a;++n)t+=e.charCodeAt(n);n+=t.substring(0,a)}n+=i+r}return n}function Rt(e){return e%2==0}function Ft(e){const t=te[e];return void 0!==t&&"string"===t}function Et(e,t){const n=new Uint8Array(e.length+1);return n.set(e),n.set(t,e.length),n}class qt{encode(e){const t=new Uint8Array(e.length);for(let n=0,i=e.length;n<i;++n)t[n]=e.charCodeAt(n);return t}}const Ut="00080005",Mt="00280100";class Qt{#ne=!1;#ie=!0;#re={default:{action:"copy",value:null}};#oe=this.#re;#ae=[];#se=new qt;#le=this.#se;setUseUnVrForPrivateSq(e){this.#ne=e}setFixUnknownVR(e){this.#ie=e}setRules(e,t){if(this.#oe=e,this.#ae=[],t){const t=Object.keys(e);for(const n of t){const t=e[n];if("replace"===t.action&&void 0!==t.value&&null!==t.value){let e,t=!1;if(8===n.length&&(t=void 0!==Se(n).getNameFromDictionary()),t)e=n;else{const t=Ce(n);void 0!==t&&(e=t.getKey())}void 0!==e&&this.#ae.push(e)}}}}#ce(e){return this.#se.encode(e)}#ue(e){return this.#le.encode(e)}useSpecialTextEncoder(){this.#le=new TextEncoder}getElementToWrite(e){const t=e.tag.getGroupName(),n=e.tag.getNameFromDictionary();let i;return i=void 0!==this.#oe[e.tag.getKey()]?this.#oe[e.tag.getKey()]:void 0!==n&&void 0!==this.#oe[n]?this.#oe[n]:void 0!==this.#oe[t]?this.#oe[t]:this.#oe.default,bt[i.action](e,i.value)}#de(e,t,n,i){let r;for(let o=0;o<n.length;++o){if(r=n[o],0===r.length)continue;let a=!1;const s=r.find((e=>pe(e.tag)));void 0!==s&&void 0!==s.undefinedLength&&(a=s.undefinedLength);const l=new ve("NONE");l.vl=a?4294967295:s.vl,l.tag=ge(),l.value=[],t=this.#he(e,l,t,i);for(const n of r)pe(n.tag)||me(n.tag)||(t=this.#he(e,n,t,i));if(a){const n=new ve("NONE");n.vl=0,n.tag=new de("FFFE","E00D"),n.value=[],t=this.#he(e,n,t,i)}}return t}#Se(e,t,n,i,r){const o=n;if("NONE"===t.vr);else if(i instanceof Uint8Array)n=i.length===8*t.vl?e.writeBinaryArray(n,i):e.writeUint8Array(n,i);else if(i instanceof Int8Array)n=e.writeInt8Array(n,i);else if(i instanceof Uint16Array)n=e.writeUint16Array(n,i);else if(i instanceof Int16Array)n=e.writeInt16Array(n,i);else if(i instanceof Uint32Array)n=e.writeUint32Array(n,i);else if(i instanceof Int32Array)n=e.writeInt32Array(n,i);else if(i instanceof BigUint64Array)n=e.writeUint64Array(n,i);else if(i instanceof BigInt64Array)n=e.writeInt64Array(n,i);else{const o=te[t.vr];if(void 0!==o)if("Uint8"===o)n=e.writeUint8Array(n,i);else if("Uint16"===o)n=e.writeUint16Array(n,i);else if("Int16"===o)n=e.writeInt16Array(n,i);else if("Uint32"===o)n=e.writeUint32Array(n,i);else if("Int32"===o)n=e.writeInt32Array(n,i);else if("Uint64"===o)n=e.writeUint64Array(n,i);else if("Int64"===o)n=e.writeInt64Array(n,i);else if("Float32"===o)n=e.writeFloat32Array(n,i);else if("Float64"===o)n=e.writeFloat64Array(n,i);else{if("string"!==o)throw new Error("Unknown VR type: "+o);n=e.writeUint8Array(n,i)}else if("SQ"===t.vr)n=this.#de(e,n,i,r);else if("AT"===t.vr)for(let t=0;t<i.length;++t){const r=i[t]+"",o=r.substring(1,5),a=r.substring(6,10),s=[parseInt(o,16),parseInt(a,16)];n=e.writeUint16Array(n,s)}else"xs"===t.vr?n=i instanceof Int16Array?e.writeInt16Array(n,i):e.writeUint16Array(n,i):c.warn("Unknown VR: "+t.vr)}if("SQ"!==t.vr&&"NONE"!==t.vr){const e=n-o;if(e!==t.vl){let n="Offset difference and VL are not equal: "+e+" != "+t.vl;n+=" (",void 0!==t.tag&&(n+=t.tag+", "),n+="vr:"+t.vr+")",c.warn(n)}}return n}#ge(e,t,n,i,r){let o=!1;if(void 0!==t.undefinedLength&&(o=t.undefinedLength),o){const o={};o.FFFEE000={tag:ge(),vr:"NONE",vl:0,value:[]};for(let e=0;e<i.length;++e)o[e]={tag:ge(),vr:t.vr,vl:i[e].length,value:i[e]};n=this.#de(e,n,[o],r)}else{let o=i[0];i.length>1&&(o=function(e){const t=e.length,n=e[0].length;if(void 0===n)return e;const i=t*n,r=new e[0].constructor(i);for(let i=0;i<t;i++){const t=i*n;r.set(e[i],t)}return r}(i)),n=this.#Se(e,t,n,o,r)}return n}#he(e,t,n,i){const r=t.tag.isWithVR(),o=!(!i&&r)||J(t.vr);n=e.writeHex(n,t.tag.getGroup()),n=e.writeHex(n,t.tag.getElement());let a=t.vr;this.#ne&&t.tag.isPrivate()&&"SQ"===a&&(c.warn("Write element using VR=UN for private sequence."),a="UN"),r&&!i&&(n=e.writeUint8Array(n,this.#ce(a)),o&&(n+=2));let s=!1;("SQ"===t.vr||ye(t.tag))&&void 0!==t.undefinedLength&&(s=t.undefinedLength);let l=!1;pe(t.tag)&&void 0!==t.undefinedLength&&(l=t.undefinedLength);let u=t.vl;(s||l)&&(u=4294967295),n=o?e.writeUint32(n,u):e.writeUint16(n,u);let d=t.value;if(void 0===d&&(d=[]),n=ye(t.tag)?this.#ge(e,t,n,d,i):this.#Se(e,t,n,d,i),s){const t=new ve("NONE");t.vl=0,t.tag=new de("FFFE","E0DD"),t.value=[],n=this.#he(e,t,n,i)}return n}getBuffer(e){const t=e["00020010"].value[0],n=xe(t),i=Re(t);if(void 0!==e[Ut]){const t=e[Ut].value[0];void 0!==t&&"ISO-IR 6"!==t&&(c.debug("Change charset to UTF, was: "+t),this.useSpecialTextEncoder(),e[Ut].value=["ISO_IR 192"])}let r;void 0!==e[Mt]&&(r=e[Mt].value[0]);let o=132,a=0;const s=[],l=[];let u,d,h=0;const S=new de("0002","0000"),g=new de("0002","0001"),p=new de("0002","0012"),m=new de("0002","0013"),f=this.#ae.slice(),D=Object.keys(e);for(let t=0,c=D.length;t<c;++t){const c=e[D[t]];if(c.tag=Se(D[t]),u=this.getElementToWrite(c),!(null===u||S.equals(u.tag)||g.equals(u.tag)||p.equals(u.tag)||m.equals(u.tag))){a=0;const e=f.indexOf(u.tag.getKey());-1!==e&&f.splice(e,1),this.#ie&&Vt(u,!i),this.#pe(u,u.value,n,r),d=u.tag.getGroupName(),a+=Qe(u.vr,"Meta Element"!==d&&n),a+=u.vl,"Meta Element"===d?(s.push(u),h+=a):l.push(u),o+=a}}for(const e of f){const t=Se(e),i=new ve(t.getVrFromDictionary());let r;if(i.tag=t,void 0!==this.#oe[e])r=this.#oe[e].value;else{const e=t.getNameFromDictionary();r=this.#oe[e].value}let a=Qe(i.vr,n);a+=this.#pe(i,[r],n),l.push(i),o+=a}const y=Nt("FileMetaInformationVersion");let C=Qe(y.vr,!1);C+=this.#pe(y,[0,1],!1),s.push(y),h+=C,o+=C;const v=Nt("ImplementationClassUID");let I=Qe(v.vr,!1);const T=xt("ImplementationClassUID").replace("-beta",".99");I+=this.#pe(v,[T],!1),s.push(v),h+=I,o+=I;const L=Nt("ImplementationVersionName");let P=Qe(L.vr,!1);const w="DWV_"+"0.35.0-beta.11".replace("-beta",".99");P+=this.#pe(L,[w],!1),s.push(L),h+=P,o+=P;const O=function(e,t){return he(e.tag,t.tag)};s.sort(O),l.sort(O);const A=Nt("FileMetaInformationGroupLength");let b=Qe(A.vr,!1);b+=this.#pe(A,new Uint32Array([h]),!1),o+=b;const x=new ArrayBuffer(o),R=new wt(x),F=new wt(x,!i);let E=128;E=R.writeUint8Array(E,this.#ce("DICM")),E=this.#he(R,A,E,!1);for(let e=0,t=s.length;e<t;++e)E=this.#he(R,s[e],E,!1);const q=132+b+h;E!==q&&c.warn("Bad size calculation... meta offset: "+E+", calculated size:"+q+" (diff:"+(E-q)+")");for(let e=0,t=l.length;e<t;++e)E=this.#he(F,l[e],E,n);return E!==o&&c.warn("Bad size calculation... final offset: "+E+", calculated size:"+o+" (diff:"+(E-o)+")"),x}#pe(e,t,n,i){let r=0;if("SQ"===e.vr){if(null!==t&&0!==t){const o=[];let a=!1;void 0!==e.undefinedLength&&(a=e.undefinedLength,delete e.undefinedLength);for(let e=0;e<t.length;++e){const s=t[e],l=[];let c=0;if(null===s||0===s)continue;let u=i;const d=s[Mt];void 0!==d&&void 0!==d.value&&(u=d.value[0]);const h=Object.keys(s);for(let e=0,t=h.length;e<t;++e){const t=h[e],i=s[t];i.tag=Se(t),pe(i.tag)||(c+=this.#pe(i,i.value,n,u),l.push(i),c+=Qe(i.vr,n))}const S={tag:ge(),vr:"NONE",vl:c,value:[]};a&&(S.undefinedLength=a),l.push(S),c+=Qe(S.vr,n),a&&(c+=Qe("NONE",n));const g=function(e,t){return he(e.tag,t.tag)};l.sort(g),r+=c,o.push(l)}a&&(r+=Qe("NONE",n)),e.value=o,e.vl=r,a&&(e.undefinedLength=a)}}else{if(Ft(o=e.vr)||"OB"===o){const n=function(e){let t="";return Ft(e)&&(t="UI"===e?"\0":" "),t}(e.vr);if(Ft(e.vr)){let i;ee(e.vr)?(t=this.#ue(t.join("\\")),i=this.#ue(n)):(t=this.#ce(t.join("\\")),i=this.#ce(n)),Rt(t.length)||(t=Et(t,i))}else"OB"===e.vr&&(t=function(e){if(null==e||void 0===e.length)throw new Error("Cannot pad undefined or null OB value.");if(0!==e.length&&void 0!==e[0].length){let t=0;for(let n=0;n<e.length;++n)t+=e[n].length;Rt(t)||(e[e.length-1]=Et(e[e.length-1],[0]))}else Rt(e.length)||(e=Et(e,[0]));return e}(t))}if(r=0,"AT"===e.vr)r=4*t.length;else if("xs"===e.vr)r=t.length*Uint16Array.BYTES_PER_ELEMENT;else if(function(e){const t=te[e];return void 0!==t&&"string"!==t}(e.vr)||"ox"===e.vr){if(ye(e.tag)&&Array.isArray(t)){r=0;for(let e=0;e<t.length;++e)r+=t[e].length}else r=t.length;const o=te[e.vr];if(ye(e.tag)||"ox"===e.vr)if(e.undefinedLength){const e=Qe("NONE",n);r+=e,r+=e*t.length,r+=e}else void 0!==i&&(1===i?r/=8:16===i&&(r*=Uint16Array.BYTES_PER_ELEMENT));else{if(void 0===o)throw new Error("Unsupported element: "+e.vr);{const e=function(e){let t;return"Uint8"===e?t=Uint8Array.BYTES_PER_ELEMENT:"Uint16"===e?t=Uint16Array.BYTES_PER_ELEMENT:"Int16"===e?t=Int16Array.BYTES_PER_ELEMENT:"Uint32"===e?t=Uint32Array.BYTES_PER_ELEMENT:"Int32"===e?t=Int32Array.BYTES_PER_ELEMENT:"Float32"===e?t=Float32Array.BYTES_PER_ELEMENT:"Float64"===e?t=Float64Array.BYTES_PER_ELEMENT:"Uint64"===e?t=BigUint64Array.BYTES_PER_ELEMENT:"Int64"===e&&(t=BigInt64Array.BYTES_PER_ELEMENT),t}(o);if(void 0===e)throw new Error("Unknown bytes per element for VR type: "+o);r*=e}}}else r=t.length;e.value=t,e.vl=r}var o;return r}}function Vt(e,t){if("UN"===e.vr){const n=e.tag.getVrFromDictionary();if(void 0!==n&&e.vr!==n){e.vr=n;const i=te[e.vr];if(void 0!==i&&"Uint8"!==i&&"string"!==i){const n=function(e,t,n){let i;if(void 0===e.buffer)return i;const r=new Le(e.buffer,n),o=e.byteOffset,a=e.length,s=te[t];return"Uint16"===s?i=r.readUint16Array(o,a):"Uint32"===s?i=r.readUint32Array(o,a):"Uint64"===s?i=r.readUint64Array(o,a):"Int16"===s?i=Array.from(r.readInt16Array(o,a)):"Int32"===s?i=Array.from(r.readInt32Array(o,a)):"Int64"===s?i=r.readInt64Array(o,a):"Float32"===s?i=Array.from(r.readFloat32Array(o,a)):"Float64"===s&&(i=Array.from(r.readFloat64Array(o,a))),i}(e.value,e.vr,t);void 0!==n&&(e.value=n)}c.info("Element "+e.tag.getGroup()+" "+e.tag.getElement()+" VR changed from UN to "+e.vr)}}}function Nt(e){const t=Ce(e),n=new ve(t.getVrFromDictionary());return n.tag=t,n}function Bt(e){const t=Object.keys(e),n={};for(let i=0,r=t.length;i<r;++i){const r=Ce(t[i]);if(void 0===r)continue;const o=r.getVrFromDictionary();let a,s=!1;const l=e[t[i]];if("SQ"===o){const e=[];if(void 0!==l.undefinedLength&&(s=l.undefinedLength),void 0!==l.value&&null!==l.value)for(let t=0;t<l.value.length;++t)e.push(Bt(l.value[t]));else c.trace("Undefined or null simpleTag SQ value.");a=e}else a=Array.isArray(l)?l:[l];const u=new ve(o);u.tag=r,u.value=a,s&&(u.undefinedLength=s),n[r.getKey()]=u}return n}const Gt={CodeValue:"00080100",CodingSchemeDesignator:"00080102",CodeMeaning:"00080104",LongCodeValue:"00080119",URNCodeValue:"00080120"};class kt{meaning;value;longValue;urnValue;schemeDesignator;constructor(e){this.meaning=e}toString(){return"("+this.value+", "+this.schemeDesignator+", '"+this.meaning+"')"}}function Ht(e,t){return Object.keys(e).length===Object.keys(t).length&&Object.keys(e).every((n=>Object.prototype.hasOwnProperty.call(t,n)&&e[n]===t[n]))}function zt(e){const t=new kt(e[Gt.CodeMeaning].value[0]);if(void 0!==e[Gt.CodeValue])t.value=e[Gt.CodeValue].value[0];else if(void 0!==e[Gt.LongCodeValue])t.longValue=e[Gt.LongCodeValue].value[0];else{if(void 0===e[Gt.URNCodeValue])throw new Error("Invalid code with no value, no long value and no urn value.");t.urnValue=e[Gt.URNCodeValue].value[0]}if(void 0!==t.value||void 0!==t.longValue){if(void 0===e[Gt.CodingSchemeDesignator])throw new Error("No coding sheme designator when code value or long value is present");t.schemeDesignator=e[Gt.CodingSchemeDesignator].value[0]}return t}function Wt(e){const t={};return void 0!==e.value?t.CodeValue=e.value:void 0!==e.longValue?t.LongCodeValue=e.longValue:void 0!==e.urnValue&&(t.URNCodeValue=e.urnValue),void 0!==e.schemeDesignator&&(t.CodingSchemeDesignator=e.schemeDesignator),t.CodeMeaning=e.meaning,t}const Yt={111030:"Image Region",112039:"Tracking Identifier",112040:"Tracking Unique Identifier",113048:"Pixel by pixel Maximum",113049:"Pixel by pixel mean",113051:"Pixel by pixel Minimum",113061:"Standard Deviation",113076:"Segmentation",121055:"Path",121207:"Height",121322:"Source image for image processing operation",121324:"Source Image",122438:"Reference Points",125007:"Measurement Group",125309:"Short label",128773:"Reference Geometry"},Xt={1483009:"Angle",42798e3:"Area",103355008:"Width",103339001:"Long axis",103340004:"Short axis",131190003:"Radius",261665006:"Unknown",410668003:"Length",718499004:"Color"},jt={1:"No units",mm:"Millimeter",deg:"Degree - plane angle",cm2:"Square centimeter","cm2/ml":"Square centimeter per milliliter","/cm":"Per centimeter","g/ml":"Gram per milliliter","g/ml{SUVbw}":"Standardized Uptake Value body weight","mg/ml":"Milligram per milliliter","umol/ml":"Micromole per milliliter","Bq/ml":"Becquerels per milliliter","mg/min/ml":"Milligrams per minute per milliliter","umol/min/ml":"Micromole per minute per milliliter","ml/min/g":"Milliliter per minute per gram","ml/g":"Milliliter per gram","ml/min/ml":"Milliliter per minute per milliliter","ml/ml":"Milliliter per milliliter","%":"Percentage","[hnsf'U]":"Hounsfield unit","10*23/ml":"Electron density","{counts}":"Counts","{counts}/s":"Counts per second","{propcounts}":"Proportional to counts","{propcounts}/s":"Proportional to counts per second"};function Zt(e,t){let n,i;return"DCM"===t?n=Yt[e]:"SCT"===t?n=Xt[e]:"UCUM"===t&&(n=jt[e]),void 0!==n&&(i=new kt(n),i.schemeDesignator=t,i.value=e),i}function _t(){return Zt("125007","DCM")}function Kt(){return Zt("128773","DCM")}function Jt(){return Zt("121324","DCM")}function $t(){return Zt("112039","DCM")}function en(){return Zt("125309","DCM")}function tn(){return Zt("122438","DCM")}function nn(){return Zt("718499004","SCT")}const rn={angle:{key:"1483009",scheme:"SCT"},length:{key:"410668003",scheme:"SCT"},surface:{key:"42798000",scheme:"SCT"},height:{key:"121207",scheme:"DCM"},width:{key:"103355008",scheme:"SCT"},radius:{key:"131190003",scheme:"SCT"},a:{key:"103339001",scheme:"SCT"},b:{key:"103340004",scheme:"SCT"},min:{key:"113051",scheme:"DCM"},max:{key:"113048",scheme:"DCM"},mean:{key:"113049",scheme:"DCM"},stddev:{key:"113061",scheme:"DCM"}};function on(e){let t;for(const n in rn){const i=rn[n];if(i.scheme===e.schemeDesignator&&i.key===e.value){t=n;break}}return t}const an={"unit.mm":"mm","unit.cm2":"cm2","unit.degree":"deg",HU:"[hnsf'U]",MGML:"mg/ml",ED:"10*23/ml",PCT:"%",CNTS:"{counts}",NONE:"1",CM2:"cm2",CM2ML:"cm2/ml",PCNT:"%",CPS:"{counts}/s",BQML:"Bq/ml",MGMINML:"mg/min/ml",UMOLMINML:"umol/min/ml",MLMING:"ml/min/g",MLG:"ml/g","1CM":"/cm",UMOLML:"umol/ml",PROPCNTS:"{propcounts}",PROPCPS:"{propcounts}/s",MLMINML:"ml/min/ml",MLML:"ml/ml",GML:"g/ml",SUV:"g/ml{SUVbw}"};function sn(e){let t;for(const n in an){const i=an[n];if("UCUM"===e.schemeDesignator&&i===e.value){t=n;break}}return t}const ln="00620005",cn="00620009",un="0062000C",dn="0062000D",hn="00620003",Sn="0062000F",gn="00620020";class pn{number;label;algorithmType;algorithmName;displayValue;displayRGBValue;propertyTypeCode;propertyCategoryCode;trackingUid;trackingId;constructor(e,t,n){this.number=e,this.label=t,this.algorithmType=n}}function mn(e){const t=new pn(e["00620004"].value[0],e[ln]?e[ln].value[0]:"n/a",e["00620008"].value[0]);if(void 0!==e[cn]&&(t.algorithmName=e[cn].value[0]),void 0!==e[un])t.displayValue=e[un].value[0];else if(void 0!==e[dn]){const i=e[dn].value,r=function(e){return function(e){function t(e){let t=null;return t=e<=.0031308?12.92*e:1.055*Math.pow(e,.416666667)-.055,Math.min(1,Math.max(0,t))}const n=e.x/100,i=e.y/100,r=e.z/100;return{r:Math.round(255*t(3.2406*n-1.5372*i-.4986*r)),g:Math.round(255*t(-.9689*n+1.8758*i+.0415*r)),b:Math.round(255*t(.0557*n-.204*i+1.057*r))}}(function(e){function t(e){let t=null;return t=e>.206896552?Math.pow(e,3):.128418549*e-.017712903,t}const n=v,i=(e.l+16)/116;return{x:n.x*t(i+e.a/500),y:n.y*t(i),z:n.z*t(i-e.b/200)}}(e))}({l:.001525902*(n={l:i[0],a:i[1],b:i[2]}).l,a:.003891051*n.a-128,b:.003891051*n.b-128});t.displayRGBValue=r}var n;if(void 0===e[hn])throw new Error("Missing Segmented Property Category Code Sequence.");if(t.propertyCategoryCode=zt(e[hn].value[0]),void 0===e[Sn])throw new Error("Missing Segmented Property Type Code Sequence.");return t.propertyTypeCode=zt(e[Sn].value[0]),void 0!==e[gn]&&(t.trackingId=e[gn].value[0],t.trackingUid=e["00620021"].value[0]),t}function fn(e){let t=e.algorithmType;void 0===t&&(t="MANUAL");const n={SegmentNumber:e.number,SegmentLabel:e.label,SegmentAlgorithmType:t};if("MANUAL"!==t&&void 0!==e.algorithmName&&(n.SegmentAlgorithmName=e.algorithmName),e.displayRGBValue){const t=C(I(e.displayRGBValue));n.RecommendedDisplayCIELabValue=[Math.round(t.l),Math.round(t.a),Math.round(t.b)]}else n.RecommendedDisplayGrayscaleValue=e.displayValue;return e.propertyCategoryCode&&(n.SegmentedPropertyCategoryCodeSequence={value:[Wt(e.propertyCategoryCode)]}),e.propertyTypeCode&&(n.SegmentedPropertyTypeCodeSequence={value:[Wt(e.propertyTypeCode)]}),e.trackingId&&(n.TrackingID=e.trackingId,n.TrackingUID=e.trackingUid),n}const Dn="00089124",yn="00082112",Cn="00081150",vn="00081155",In="00209116",Tn="00289110";class Ln{dimIndex;imagePosPat;derivationImages;refSegmentNumber;imageOrientationPatient;spacing;constructor(e,t,n,i){this.dimIndex=e,this.imagePosPat=t,this.derivationImages=n,this.refSegmentNumber=i}}function Pn(e){const t=[];if(void 0!==e[Dn]){const n=e[Dn].value;for(let e=0;e<n.length;++e){const i=[];if(void 0!==n[e][yn]){const t=n[e][yn].value;for(let e=0;e<t.length;++e){const n={};void 0!==t[e][Cn]&&(n.referencedSOPClassUID=t[e][Cn].value[0]),void 0!==t[e][vn]&&(n.referencedSOPInstanceUID=t[e][vn].value[0]),i.push(n)}}t.push({sourceImages:i})}}const n=e["00209111"].value[0]["00209157"].value,i=e["0062000A"].value,r=parseInt(i[0]["0062000B"].value[0],0),o=e["00209113"].value[0]["00200032"].value;for(let e=0;e<o.length;++e)o[e]=parseFloat(o[e]);const a=new Ln(n,o,t,r);if(void 0!==e[In]){const t=e[In];if(0!==t.value.length){const e=t.value[0]["00200037"].value;void 0!==e&&(a.imageOrientationPatient=e)}}if(void 0!==e[Tn]){const t=e[Tn];if(0!==t.value.length){const e=It(t.value[0]);void 0!==e&&(a.spacing=e)}else c.warn("No shared functional group pixel measure sequence items.")}return a}function wn(e){const t={FrameContentSequence:{value:[{DimensionIndexValues:e.dimIndex}]},PlanePositionSequence:{value:[{ImagePositionPatient:e.imagePosPat}]},SegmentIdentificationSequence:{value:[{ReferencedSegmentNumber:e.refSegmentNumber}]}};if(void 0!==e.derivationImages){const n=Wt(Zt("121322","DCM")),i=Wt(Zt("113076","DCM")),r=[];for(const t of e.derivationImages){const e=[];for(const i of t.sourceImages)e.push({PurposeOfReferenceCodeSequence:{value:[n]},ReferencedSOPClassUID:i.referencedSOPClassUID,ReferencedSOPInstanceUID:i.referencedSOPInstanceUID});r.push({DerivationCodeSequence:{value:[i]},SourceImageSequence:{value:e}})}t.DerivationImageSequence={value:r}}return t}function On(e,t){return JSON.stringify(e)===JSON.stringify(t)}function An(e,t){const n=e[t.tag];if(1===t.type||2===t.type){if(void 0===n)throw new Error("Missing or empty "+t.name)}else if(void 0===n)return;let i,r=!1;if(i=1===n.value.length?n.value[0]:n.value,Array.isArray(i))for(let e=0;e<t.enum.length;++e){if(!Array.isArray(t.enum[e]))throw new Error("Cannot compare array and non array tag value.");if(k(t.enum[e],i)){r=!0;break}}else r=t.enum.includes(i);if(!r)throw new Error("Unsupported "+t.name+" value: "+i)}function bn(e,t,n){const i=e.getGeometry().getSize().getDimSize(2),r={};for(let o=0;o<i;++o){const a=n+o,s=e.getValueAtOffset(a);for(const e of t){const t=e.number-1;s===e.number&&(void 0===r[t]&&(r[t]=new Uint8Array(i)),r[t][o]=1)}}return r}const xn=[{name:"TransferSyntaxUID",tag:"00020010",type:"1",enum:[ie,re,oe]},{name:"MediaStorageSOPClassUID",tag:"00020002",type:"1",enum:["1.2.840.10008.5.1.4.1.1.66.4"]},{name:"SOPClassUID",tag:"00020002",type:"1",enum:["1.2.840.10008.5.1.4.1.1.66.4"]},{name:"Modality",tag:"00080060",type:"1",enum:["SEG"]},{name:"SegmentationType",tag:"00620001",type:"1",enum:["BINARY"]},{name:"DimensionOrganizationType",tag:"00209311",type:"3",enum:["3D"]},{name:"ImageType",tag:"00080008",type:"1",enum:[["DERIVED","PRIMARY"]]},{name:"SamplesPerPixel",tag:"00280002",type:"1",enum:[1]},{name:"PhotometricInterpretation",tag:"00280004",type:"1",enum:["MONOCHROME2"]},{name:"PixelRepresentation",tag:"00280103",type:"1",enum:[0]},{name:"BitsAllocated",tag:"00280100",type:"1",enum:[1]},{name:"BitsStored",tag:"00280101",type:"1",enum:[1]},{name:"HighBit",tag:"00280102",type:"1",enum:[0]}];function Rn(){const e={};for(let t=0;t<xn.length;++t){const n=xn[t];e[n.name]=n.enum[0]}return e}class Fn{#ee;getWarning(){return this.#ee}checkElements(e){}create(e,t){for(let t=0;t<xn.length;++t)An(e,xn[t]);const n=vt(e),i=new Ze([n[0],n[1],1]),r=i.getTotalSize();let o=1;const a=e["00280008"];if(void 0!==a&&(o=parseInt(a.value[0],10)),o!==t.length/r)throw new Error("Buffer and numberOfFrames meta are not equal."+o+" "+t.length/r);const l=function(e){const t=e["00209221"];if(void 0===t||1!==t.value.length)throw new Error("Unsupported dimension organization sequence length");const n=t.value[0]["00209164"].value[0],i=[],r=e["00209222"];if(void 0!==r){const e=r.value;if(2!==e.length)throw new Error("Unsupported dimension index sequence length");let t;for(let r=0;r<e.length;++r){const o=e[r]["00209164"].value[0];if(o!==n)throw new Error("Dimension Index Sequence contains a unknown Dimension Organization");t=e[r]["00209165"].value[0];const a={DimensionOrganizationUID:o,DimensionIndexPointer:t};void 0!==e[r]["00209421"]&&(a.DimensionDescriptionLabel=e[r]["00209421"].value[0]),i.push(a)}if("(0020,0032)"!==t)throw new Error("Unsupported non image position as last index")}return{organizations:{value:[{DimensionOrganizationUID:n}]},indices:{value:i}}}(e),u=e["00620002"];if(void 0===u)throw new Error("Missing or empty segmentation sequence");const d=[],h=[0],S=[0],g=[0];for(let e=0;e<u.value.length;++e){const t=mn(u.value[e]);void 0!==t.displayRGBValue&&(h[t.number]=t.displayRGBValue.r,S[t.number]=t.displayRGBValue.g,g[t.number]=t.displayRGBValue.b),d.push(t)}let p,f,D,y=!1;h.length>1&&(y=!0,p=new m(h,S,g));const C=e[52009229];if(void 0!==C){const e=C.value[0];if(void 0!==e["00209116"]){const t=e["00209116"];0!==t.value.length?D=t.value[0]["00200037"].value:c.warn("No shared functional group plane orientation sequence items.")}if(void 0!==e["00289110"]){const t=e["00289110"];0!==t.value.length?f=It(t.value[0]):c.warn("No shared functional group pixel measure sequence items.")}}const v=function(e,t){return e.some((function(e){return On(t,e)}))},I=function(e,t){return e.findIndex((function(e){return On(t,e)}))},T=e[52009230];if(void 0===T)throw new Error("Missing or empty per frame functional sequence");if(o!==T.value.length)throw new Error("perFrameFuncGroupSequence meta and numberOfFrames are not equal.");const L=[];for(let e=0;e<T.value.length;++e)L.push(Pn(T.value[e]));const O=[];for(let e=0;e<L.length;++e){if(v(O,L[e].imagePosPat)||O.push(L[e].imagePosPat),void 0!==L[e].imageOrientationPatient)if(void 0===D)D=L[e].imageOrientationPatient;else if(!k(D,L[e].imageOrientationPatient))throw new Error("Unsupported multi orientation dicom seg.");if(void 0!==L[e].spacing)if(void 0===f)f=L[e].spacing;else if(!f.equals(L[e].spacing))throw new Error("Unsupported multi resolution dicom seg.")}if(void 0===f)throw new Error("No spacing found for DICOM SEG");if(3!==f.length())throw new Error("Incomplete spacing found for DICOM SEG");if(void 0===D)throw new Error("No imageOrientationPatient found for DICOM SEG");if(6!==D.length)throw new Error("Incomplete imageOrientationPatient found for DICOM SEG");const b=new P(parseFloat(D[0]),parseFloat(D[1]),parseFloat(D[2])),x=new P(parseFloat(D[3]),parseFloat(D[4]),parseFloat(D[5])),R=b.crossProduct(x),E=new A([b.getX(),x.getX(),R.getX(),b.getY(),x.getY(),R.getY(),b.getZ(),x.getZ(),R.getZ()]);O.sort(function(e){const t=e.getInverse();return function(e,n){const i=t.multiplyArray3D(e),r=t.multiplyArray3D(n);return i[2]-r[2]}}(E));const q=function(e){return new F(e[0],e[1],e[2])},U=[];for(let e=0;e<O.length;++e)U.push(q(O[e]));const M=new it([U[0]],i,f,E),Q=function(e){let t=e>w;return t&&(t=e>10*w,t?(t=e>100*w,t||c.warn("Using larger+ real world epsilon in SEG pos pat adding")):c.warn("Using larger real world epsilon in SEG pos pat adding")),t},V=[];V.push(O[0]);let N=0;for(let e=1;e<O.length;++e){++N;let t=new s([0,0,N]),n=M.indexToWorld(t).get3D();const i=U[e];let r=i.getDistance(n);const o=r;for(;Q(r);)if(c.debug("Adding intermediate pos pats for DICOM seg at "+n.toString()),V.push([n.getX(),n.getY(),n.getZ()]),++N,t=new s([0,0,N]),n=M.indexToWorld(t).get3D(),r=i.getDistance(n),r>o)throw new Error("Test distance is increasing when adding intermediate pos pats");V.push(O[e])}const B=V.length,G=new it([U[0]],i,f,E),H=["0"];for(let e=1;e<B;++e)G.appendOrigin(q(V[e]),e),H.push(e.toString());const z=function(e){return function(t){return t.number===e}},W=new t.constructor(r*B);W.fill(0);let Y=null,X=null;for(let e=0;e<L.length;++e){N=I(V,L[e].imagePosPat),X=r*e,Y=r*N;const n=d.find(z(L[e].refSegmentNumber));for(let e=0;e<r;++e)if(0!==t[X+e]){W[Y+e]=y?n.number:n.displayValue}}const j=new Un(G,W,H);y&&(j.setPhotometricInterpretation("PALETTE COLOR"),j.setPaletteColourMap(p));const Z=Rn(),_=function(t){return Ie(e,t)};Z.StudyDate=_("00080020"),Z.StudyTime=_("00080030"),Z.StudyInstanceUID=_("0020000D"),Z.StudyID=_("00200010"),Z.SeriesDate=_("00080021"),Z.SeriesTime=_("00080031"),Z.SeriesInstanceUID=_("0020000E"),Z.SeriesNumber=_("00200011"),Z.ReferringPhysicianName=_("00080090"),Z.PatientName=_("00100010"),Z.PatientID=_("00100020"),Z.PatientBirthDate=_("00100030"),Z.PatientSex=_("00100040"),Z.Manufacturer=_("00080070"),Z.ManufacturerModelName=_("00081090"),Z.DeviceSerialNumber=_("00181000"),Z.SoftwareVersions=_("00181020"),Z.DimensionOrganizationSequence=l.organizations,Z.DimensionIndexSequence=l.indices,Z.custom={segments:d,frameInfos:L,SOPInstanceUID:e["00080018"].value[0]},Z.numberOfFiles=B;const K=e["00200052"];K&&(Z.FrameOfReferenceUID=K.value[0]);const J=e["00282110"];return J&&(Z.LossyImageCompression=J.value[0]),j.setMeta(Z),j}toDicom(e,t,n,i){const r=e.getMeta();void 0===t&&(t=r.segments);const o=e.getGeometry(),a=o.getSize();r.Rows=a.get(1),r.Columns=a.get(0);const s=new Date;r.ContentDate=dt(ct(s)),r.ContentTime=ht(ut(s)),void 0!==n&&(r.StudyInstanceUID=n.getMeta().StudyInstanceUID);const l=[];for(const e of t)l.push(fn(e));var u,d;r.SegmentSequence={value:l},r.SharedFunctionalGroupsSequence={value:[{PlaneOrientationSequence:{value:[(d=o.getOrientation(),{ImageOrientationPatient:[d.get(0,0),d.get(1,0),d.get(2,0),d.get(0,1),d.get(1,1),d.get(2,1)]})]},PixelMeasuresSequence:{value:[(u=o.getSpacing(),{SpacingBetweenSlices:u.get(2),PixelSpacing:[u.get(1),u.get(0)]})]}}]};const h=function(e,t){const n=e.getGeometry().getSize(),i=n.getDimSize(2),r={};for(let o=0;o<n.get(2);++o){const n=bn(e,t,o*i),a=Object.keys(n);for(const e of a)void 0===r[e]&&(r[e]={}),r[e][o]=n[e]}return r}(e,t),S=[],g=[],p=[];for(const i of t){const t=i.number,r=t-1;if(void 0===h[r])continue;const o=Object.keys(h[r]);for(let i=o.length-1;i>=0;--i){const a=Number.parseInt(o[i],10);g.push(h[r][a]);const s=e.getGeometry().getOrigins()[a],l=[s.getX(),s.getY(),s.getZ()],c={dimIndex:[t,o.length-i],imagePosPat:l,refSegmentNumber:t};if(void 0!==n){const e=n.getGeometry().worldToIndex(new E([s.getX(),s.getY(),s.getZ()]));c.derivationImages=[{sourceImages:[{referencedSOPInstanceUID:n.getImageUid(e),referencedSOPClassUID:n.getMeta().SOPClassUID}]}],p.push({ReferencedSOPInstanceUID:n.getImageUid(e),ReferencedSOPClassUID:n.getMeta().SOPClassUID})}S.push(c)}}r.NumberOfFrames=g.length.toString();const m=[];for(const e of S)m.push(wn(e));if(r.PerFrameFunctionalGroupsSequence={value:m},void 0!==n){const e=[];e.push({ReferencedInstanceSequence:{value:p},SeriesInstanceUID:n.getMeta().SeriesInstanceUID}),r.ReferencedSeriesSequence={value:e}}void 0!==i&&function(e,t){const n=Object.keys(t);for(const i of n)void 0!==e[i]&&c.trace("Overwritting tag: "+i),e[i]=t[i]}(r,i);const f=Bt(r),D=a.getDimSize(2),y=g.length*D/8,C=new ve("OB");return C.tag=new de("7FE0","0010"),C.vl=y,C.value=g,f["7FE00010"]=C,f}}function En(e){return(new Pt).create(e,e["7FE00010"].value[0],1)}function qn(e){return(new Fn).create(e,e["7FE00010"].value[0])}class Un{#me;#O;#fe;#n=new je(1,0);#De=null;#ye=!0;#Ce=!0;#ve="MONOCHROME2";#Ie;#Te=0;#Le;#Pe={};#we=null;#Oe=null;#Ae=null;#be=new He;constructor(e,t,n){this.#me=e,this.#O=t,this.#fe=n,this.#Le=this.#O.length/this.#me.getSize().getTotalSize()}getImageUid(e){let t=this.#fe[0];return 1!==this.#fe.length&&void 0!==e&&(t=this.#fe[this.getSecondaryOffset(e)]),t}getOriginForImageUid(e){let t;const n=this.#fe.indexOf(e);return-1!==n&&(t=this.getGeometry().getOrigins()[n]),t}includesImageUid(e){return this.#fe.includes(e)}containsImageUids(e){return function(e,t){if(null===e||null===t||void 0===e||void 0===t)return!1;if(0===e.length||0===t.length||t.length>e.length)return!1;for(const n of t)if(!e.includes(n))return!1;return!0}(this.#fe,e)}getGeometry(){return this.#me}getBuffer(){return this.#O}canQuantify(){return 1===this.getNumberOfComponents()}canWindowLevel(){return this.isMonochrome()}isMonochrome(){return Tt(this.getPhotometricInterpretation())}canScroll(e){const t=this.getGeometry().getSize();let n=1;return void 0!==this.#Pe.numberOfFiles&&(n=this.#Pe.numberOfFiles),t.canScroll(e)||1!==n}#xe(){return this.#me.getSize().getTotalSize(2)}getSecondaryOffset(e){return this.#me.getSize().indexToOffset(e,2)}getRescaleSlopeAndIntercept(e){let t=this.#n;if(!this.isConstantRSI()){if(void 0===e)throw new Error("Cannot get non constant RSI with empty slice index.");const n=this.getSecondaryOffset(e);void 0!==this.#De[n]?t=this.#De[n]:c.warn("undefined non constant rsi at "+n)}return t}#Re(e){return this.#De[e]}setRescaleSlopeAndIntercept(e,t){if(this.#ye=this.#ye&&e.isID(),this.#Ce){if(!this.#n.equals(e))if(void 0===t)this.#n=e;else{this.#Ce=!1,this.#De=[];for(let e=0,t=this.#xe();e<t;++e)this.#De.push(this.#n);this.#n=null,this.#De.splice(t,0,e)}}else{if(void 0===t)throw new Error("Cannot store non constant RSI with empty slice index.");this.#De.splice(t,0,e)}}isIdentityRSI(){return this.#ye}isConstantRSI(){return this.#Ce}getPhotometricInterpretation(){return this.#ve}setPhotometricInterpretation(e){this.#ve=e}setPaletteColourMap(e){this.#Ie=e,this.#Fe({type:"imagecontentchange"})}getPaletteColourMap(){return this.#Ie}updatePaletteColourMap(e,t){this.#Ie.red[e]=t.r,this.#Ie.green[e]=t.g,this.#Ie.blue[e]=t.b,this.#Fe({type:"imagecontentchange"})}getPlanarConfiguration(){return this.#Te}setPlanarConfiguration(e){this.#Te=e}getNumberOfComponents(){return this.#Le}getMeta(){return this.#Pe}setMeta(e){this.#Pe=e}getValueAtOffset(e){return this.#O[e]}getOffsets(e){let t;if("number"==typeof e){if(1!==this.#Le)throw new Error("Number of components is not 1 for getting single value.");t=[e]}else if(void 0!==e.r&&void 0!==e.g&&void 0!==e.b){if(3!==this.#Le)throw new Error("Number of components is not 3 for getting RGB value.");t=[e.r,e.g,e.b]}const n=[];let i;for(let e=0;e<this.#O.length;e+=this.#Le){i=!0;for(let n=0;n<this.#Le;++n)if(this.#O[e+n]!==t[n]){i=!1;break}i&&n.push(e)}return n}hasValues(e){if(void 0===e||0===e.length)return[];const t=[];for(let n=0;n<e.length;++n)1===this.#Le?t.push([e[n]]):3===this.#Le&&t.push([e[n].r,e[n].g,e[n].b]);let n;1===this.#Le?n=function(e,t){return e[0]===t[0]}:3===this.#Le&&(n=function(e,t){return e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2]});const i=function(e){return function(t){return n(t,e)}},r=new Array(e.length);r.fill(!1);const o=t.slice();let a,s;for(let e=0,n=this.#O.length;e<n;e+=this.#Le){s=[];for(let n=0;n<o.length;++n){a=!0;for(let t=0;t<this.#Le;++t)if(this.#O[e+t]!==o[n][t]){a=!1;break}a&&(r[t.findIndex(i(o[n]))]=!0,s.push(n))}for(let e=0;e<s.length;++e)o.splice(s[e],1);if(0===o.length)break}return r}clone(){const e=this.#O.slice(0),t=new Un(this.getGeometry(),e,this.#fe);if(this.isConstantRSI())t.setRescaleSlopeAndIntercept(this.getRescaleSlopeAndIntercept());else for(let e=0;e<this.#xe();++e)t.setRescaleSlopeAndIntercept(this.#Re(e),e);return t.setPhotometricInterpretation(this.getPhotometricInterpretation()),t.setPlanarConfiguration(this.getPlanarConfiguration()),t.setMeta(this.getMeta()),t}#Ee(e){let t=this.#O;if(this.#O=Me(8*this.#O.BYTES_PER_ELEMENT,this.#Pe.IsSigned?1:0,e),null===this.#O)throw new Error("Cannot reallocate data for image.");this.#O.set(t),t=null}appendSlice(e){if(null===e)throw new Error("Cannot append null slice");const t=e.getGeometry().getSize();let n=this.#me.getSize();if(1!==t.get(2))throw new Error("Cannot append more than one slice");if(n.get(0)!==t.get(0))throw new Error("Cannot append a slice with different number of columns");if(n.get(1)!==t.get(1))throw new Error("Cannot append a slice with different number of rows");if(!this.#me.getOrientation().equals(e.getGeometry().getOrientation(),1e-4))throw new Error("Cannot append a slice with different orientation");if(this.#ve!==e.getPhotometricInterpretation())throw new Error("Cannot append a slice with different photometric interpretation");for(const t in this.#Pe)if("windowPresets"!==t&&"numberOfFiles"!==t&&"custom"!==t&&this.#Pe[t]!==e.getMeta()[t])throw new Error("Cannot append a slice with different "+t+": "+this.#Pe[t]+" != "+e.getMeta()[t]);const i=e.getDataRange(),r=this.getDataRange();this.#we={min:Math.min(i.min,r.min),max:Math.max(i.max,r.max)};const o=e.getRescaledDataRange(),a=this.getRescaledDataRange();this.#Oe={min:Math.min(o.min,a.min),max:Math.max(o.max,a.max)};const l=e.getGeometry().getInitialTime();let c=!1;void 0===l||this.#me.hasSlicesAtTime(l)||(this.appendFrame(l,e.getGeometry().getOrigin()),n=this.#me.getSize(),c=!0);const u=function(e,t){const n=t.getInitialTime(),i=[];return i.push(0),i.push(0),i.push(e.getSliceIndex(t.getOrigin(),n)),void 0!==n&&i.push(n),new s(i)}(this.#me,e.getGeometry()),d=this.#Le*n.getDimSize(2);if(void 0===this.#Pe.numberOfFiles)throw new Error("Missing number of files for buffer manipulation.");const h=d*this.#Pe.numberOfFiles;this.#O.length!==h&&this.#Ee(h);const S=u.get(2);let g=S;void 0!==l&&(g+=this.#me.getCurrentNumberOfSlicesBeforeTime(l));const p=g*d,m=this.#me.getCurrentTotalNumberOfSlices()*d;p<m&&this.#O.set(this.#O.subarray(p,m),p+d),this.#O.set(e.getBuffer(),p),c||this.#me.appendOrigin(e.getGeometry().getOrigin(),S,l),this.setRescaleSlopeAndIntercept(e.getRescaleSlopeAndIntercept(),g);const f=this.#fe.length;if(this.#fe.splice(g,0,e.getImageUid()),void 0!==this.#Pe.windowPresets){const t=this.#Pe.windowPresets,n=e.getMeta().windowPresets,i=Object.keys(n);let r=null;for(let e=0;e<i.length;++e){r=i[e];const o=n[r],a=t[r];if(void 0!==a){if((void 0===a.perslice||!1===a.perslice)&&!a.wl[0].equals(o.wl[0])){a.perslice=!0;for(let e=0;e<f-1;++e)a.wl.push(a.wl[0])}void 0!==a.perslice&&!0===a.perslice&&t[r].wl.splice(g,0,o.wl[0])}else t[r]=n[r]}}this.#Fe({type:"imagegeometrychange"})}appendFrameBuffer(e,t){const n=this.#me.getSize(),i=this.#Le*n.getDimSize(2);if(void 0===this.#Pe.numberOfFiles)throw new Error("Missing number of files for frame buffer manipulation.");const r=i*this.#Pe.numberOfFiles;this.#O.length!==r&&this.#Ee(r),t>=this.#Pe.numberOfFiles?c.warn("Ignoring frame at index "+t+" (size: "+this.#Pe.numberOfFiles+")"):(this.#O.set(e,i*t),this.appendFrame(t,new F(0,0,0)))}appendFrame(e,t){this.#me.appendFrame(t,e),this.#Fe({type:"appendframe"})}getDataRange(){return this.#we||(this.#we=this.calculateDataRange()),this.#we}getRescaledDataRange(){return this.#Oe||(this.#Oe=this.calculateRescaledDataRange()),this.#Oe}getHistogram(){if(!this.#Ae){const e=this.calculateHistogram();this.#we=e.dataRange,this.#Oe=e.rescaledDataRange,this.#Ae=e.histogram}return this.#Ae}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)};setAtOffsets(e,t){let n,i;if("number"==typeof t){if(1!==this.#Le)throw new Error("Number of components is not 1 for setting single value.");n=[t]}else if(void 0!==t.r&&void 0!==t.g&&void 0!==t.b){if(3!==this.#Le)throw new Error("Number of components is not 3 for setting RGB value.");n=[t.r,t.g,t.b]}for(let t=0,r=e.length;t<r;++t){i=e[t];for(let e=0;e<this.#Le;++e)this.#O[i+e]=n[e]}this.#Fe({type:"imagecontentchange"})}setAtOffsetsAndGetOriginals(e,t){const n=[];for(let i=0;i<e.length;++i){const r=e[i];let o=r[0],a=this.#O[o];const s=[];s.push({index:0,value:a});for(let e=0;e<r.length;++e){o=r[e];const n=this.#O[o];a!==n&&(s.push({index:e,value:n}),a=n),this.#O[o]=t}n.push(s)}return this.#Fe({type:"imagecontentchange"}),n}setAtOffsetsWithIterator(e,t){const n=Array.isArray(t);for(let i=0;i<e.length;++i){const r=e[i];let o;o=Xe(n?t[i]:[{index:0,value:t}],r.length);let a=o.next();for(;!a.done;){const e=r[a.index];this.#O[e]=a.value,a=o.next()}}this.#Fe({type:"imagecontentchange"})}getValue(e,t,n,i){const r=new s([e,t,n,i||0]);return this.getValueAtOffset(this.getGeometry().getSize().indexToOffset(r))}getValueAtIndex(e){return this.getValueAtOffset(this.getGeometry().getSize().indexToOffset(e))}getRescaledValue(e,t,n,i){void 0===i&&(i=0);let r=this.getValue(e,t,n,i);if(!this.isIdentityRSI())if(this.isConstantRSI())r=this.getRescaleSlopeAndIntercept().apply(r);else{const o=new s([e,t,n,i]);r=this.getRescaleSlopeAndIntercept(o).apply(r)}return r}getRescaledValueAtIndex(e){return this.getRescaledValueAtOffset(this.getGeometry().getSize().indexToOffset(e))}getRescaledValueAtOffset(e){let t=this.getValueAtOffset(e);if(!this.isIdentityRSI())if(this.isConstantRSI())t=this.getRescaleSlopeAndIntercept().apply(t);else{const n=this.getGeometry().getSize().offsetToIndex(e);t=this.getRescaleSlopeAndIntercept(n).apply(t)}return t}calculateDataRange(){let e=this.getValueAtOffset(0),t=e,n=0;const i=this.getGeometry().getSize();let r=i.getTotalSize();i.length()>=3&&(r=i.getDimSize(3));for(let i=0;i<r;++i)n=this.getValueAtOffset(i),n>t&&(t=n),n<e&&(e=n);return{min:e,max:t}}calculateRescaledDataRange(){if(this.isIdentityRSI())return this.getDataRange();if(this.isConstantRSI()){const e=this.getDataRange(),t=this.getRescaleSlopeAndIntercept().apply(e.min),n=this.getRescaleSlopeAndIntercept().apply(e.max);return{min:t<n?t:n,max:t>n?t:n}}{let e=this.getRescaledValueAtOffset(0),t=e,n=0;const i=this.getGeometry().getSize();let r=i.getTotalSize();3===i.length()&&(r=i.getDimSize(3));for(let i=0;i<r;++i)n=this.getRescaledValueAtOffset(i),n>t&&(t=n),n<e&&(e=n);return{min:e,max:t}}}calculateHistogram(){const e=this.getGeometry().getSize(),t=[];let n=this.getValueAtOffset(0),i=n,r=0,o=this.getRescaledValueAtOffset(0),a=o,s=0;for(let l=0,c=e.getTotalSize();l<c;++l)r=this.getValueAtOffset(l),r>i&&(i=r),r<n&&(n=r),s=this.getRescaledValueAtOffset(l),s>a&&(a=s),s<o&&(o=s),t[s]=(t[s]||0)+1;const l={min:n,max:i},c={min:o,max:a},u=[];for(let e=o;e<=a;++e)u.push([e,t[e]||0]);return{dataRange:l,rescaledDataRange:c,histogram:u}}convolute2D(e){if(9!==e.length)throw new Error("The convolution matrix does not have a length of 9; it has "+e.length);const t=this.clone(),n=t.getBuffer(),i=this.getGeometry().getSize(),r=i.getDimSize(2)*this.getNumberOfComponents();for(let t=0;t<i.get(2);++t)this.convoluteBuffer(e,n,t*r);return t}convoluteBuffer(e,t,n){const i=this.getGeometry().getSize(),r=i.get(0),o=i.get(1),a=this.getNumberOfComponents();let s=1,l=1;3===a&&(0===this.getPlanarConfiguration()?s=3:l=i.getDimSize(2));const c=[];c[0]=(-r-1)*s,c[1]=-r*s,c[2]=(1-r)*s,c[3]=-s,c[4]=0,c[5]=1*s,c[6]=(r-1)*s,c[7]=r*s,c[8]=(r+1)*s;const u=[];u[0]=c[4],u[1]=c[4],u[2]=c[5],u[3]=c[4],u[4]=c[4],u[5]=c[5],u[6]=c[7],u[7]=c[7],u[8]=c[8];const d=[];d[0]=c[1],d[1]=c[1],d[2]=c[2],d[3]=c[4],d[4]=c[4],d[5]=c[5],d[6]=c[7],d[7]=c[7],d[8]=c[8];const h=[];h[0]=c[1],h[1]=c[1],h[2]=c[2],h[3]=c[4],h[4]=c[4],h[5]=c[5],h[6]=c[4],h[7]=c[4],h[8]=c[5];const S=[];S[0]=c[3],S[1]=c[4],S[2]=c[5],S[3]=c[3],S[4]=c[4],S[5]=c[5],S[6]=c[6],S[7]=c[7],S[8]=c[8];const g=[];g[0]=c[0],g[1]=c[1],g[2]=c[2],g[3]=c[3],g[4]=c[4],g[5]=c[5],g[6]=c[3],g[7]=c[4],g[8]=c[5];const p=[];p[0]=c[3],p[1]=c[4],p[2]=c[4],p[3]=c[3],p[4]=c[4],p[5]=c[4],p[6]=c[6],p[7]=c[7],p[8]=c[7];const m=[];m[0]=c[0],m[1]=c[1],m[2]=c[1],m[3]=c[3],m[4]=c[4],m[5]=c[4],m[6]=c[6],m[7]=c[7],m[8]=c[7];const f=[];f[0]=c[0],f[1]=c[1],f[2]=c[1],f[3]=c[3],f[4]=c[4],f[5]=c[4],f[6]=c[3],f[7]=c[4],f[8]=c[4];let D=n,y=0,C=[];for(let n=0;n<a;++n){D+=n*l;for(let n=0;n<o;++n)for(let i=0;i<r;++i){C=c,0===i&&0===n?C=u:0===i&&n===o-1?C=h:i===r-1&&0===n?C=p:i===r-1&&n===o-1?C=f:0===i&&n!==o-1&&0!==n?C=d:i===r-1&&n!==o-1&&0!==n?C=m:0!==i&&i!==r-1&&0===n?C=S:0!==i&&i!==r-1&&n===o-1&&(C=g),y=0;for(let t=0;t<9;++t)y+=this.getValueAtOffset(D+C[t])*e[t];t[D]=y,D+=s}}}transform(e){const t=this.clone(),n=t.getBuffer();for(let i=0,r=n.length;i<r;++i)n[i]=e(t.getValueAtOffset(i));return t}compose(e,t){const n=this.clone(),i=n.getBuffer();for(let n=0,r=i.length;n<r;++n)i[n]=Math.floor(t(this.getValueAtOffset(n),e.getValueAtOffset(n)));return n}}const Mn={CT:{mediastinum:new u(40,400),lung:new u(-500,1500),bone:new u(500,2e3),brain:new u(40,80),head:new u(90,350)}};class Qn{create(e,t){const n=new Bn(t);"MONOCHROME1"===t.getPhotometricInterpretation()&&n.setColourMap("invPlain");let i={};void 0!==t.getMeta().windowPresets&&(i=t.getMeta().windowPresets),i.minmax={name:"minmax"};const r=t.getMeta().Modality;let o;o=void 0!==L.wlPresets&&void 0!==L.wlPresets[r]?L.wlPresets[r]:Mn[r];for(const e in o){const t=o[e];i[e]={wl:[new u(t.center,t.width)],name:e}}return n.setWindowPresets(i),n.init(),n}}const Vn=["wlchange","wlpresetadd","colourmapchange","positionchange","opacitychange","alphafuncchange"];function Nn(e,t){return(new Qn).create(e,t)}class Bn{#qe;#Ue;#Ce;#Me={minmax:{name:"minmax"}};#Qe=null;#Ve;#Ne="plain";#Be=null;#K;#be=new He;constructor(e){this.#qe=e,this.#qe.addEventListener("appendframe",(()=>{const e=this.getCurrentIndex();if(3===e.length()){const t=e.getValues();t.push(0),this.setCurrentIndex(new s(t))}}))}getImage(){return this.#qe}setImage(e){this.#qe=e}getOrientation(){return this.#K}setOrientation(e){this.#K=e}init(){this.setInitialIndex()}setInitialIndex(){const e=this.#qe.getGeometry().getSize(),t=new Array(e.length());t.fill(0),t[0]=Math.floor(e.get(0)/2),t[1]=Math.floor(e.get(1)/2),t[2]=Math.floor(e.get(2)/2),this.setCurrentIndex(new s(t),!0)}getPlaybackMilliseconds(e){return e||(e=10),Math.round(1e3/e)}#Ge=function(e,t){return 255};getAlphaFunction(){return this.#Ge}setAlphaFunction(e){this.#Ge=e,this.#Fe({type:"alphafuncchange"})}#ke(){if(this.#Qe&&void 0!==this.#Me[this.#Qe]&&void 0!==this.#Me[this.#Qe].perslice&&!0===this.#Me[this.#Qe].perslice){this.getCurrentIndex()||this.setInitialIndex();const e=this.getCurrentIndex(),t=this.#qe.getSecondaryOffset(e),n=this.#Me[this.#Qe].wl[t];this.setWindowLevel(n,this.#Qe,!0)}if(void 0===this.#Ve&&this.setWindowLevelPresetById(0,!0),void 0===this.#Ce||this.#qe.isConstantRSI()!==this.#Ce){let e,t;this.#Ce=this.#qe.isConstantRSI(),this.#Ce?(e=this.#qe.getRescaleSlopeAndIntercept(),t=!0):(e=new je(1,0),t=!1);const n=new l(e,this.#qe.getMeta().BitsStored);this.#Ue=new h(n,this.#qe.getMeta().IsSigned,t)}const e=this.#Ue.getVoiLut();let t;if(void 0!==e&&(t=e.getWindowLevel()),void 0===e||!this.#Ve.equals(t)){const e=new d(this.#Ve);this.#Ue.setVoiLut(e)}return this.#Ue}getWindowPresets(){return this.#Me}getWindowPresetsNames(){return Object.keys(this.#Me)}setWindowPresets(e){this.#Me=e}addWindowPresets(e){const t=Object.keys(e);let n=null;for(let i=0;i<t.length;++i)if(n=t[i],void 0!==this.#Me[n]){if(void 0!==this.#Me[n].perslice&&!0===this.#Me[n].perslice)throw new Error("Cannot add perslice preset");this.#Me[n]=e[n]}else this.#Me[n]=e[n],this.#Fe({type:"wlpresetadd",name:n})}getCurrentWindowPresetName(){return this.#Qe}getColourMap(){return this.#Ne}#He(){return f[this.#Ne]}setColourMap(e){if(!f[e])throw new Error("Unknown colour map: '"+e+"'");this.#Ne=e,this.#Fe({type:"colourmapchange",value:[e]})}getCurrentPosition(){return this.#Be}getCurrentIndex(){const e=this.getCurrentPosition();return e?this.getImage().getGeometry().worldToIndex(e):null}getCurrentImageUid(){return this.#qe.getImageUid(this.getCurrentIndex())}getOriginForImageUid(e){return this.#qe.getOriginForImageUid(e)}includesImageUid(e){return this.#qe.includesImageUid(e)}isPositionInBounds(e){void 0===e&&(e=this.#Be);const t=this.#qe.getGeometry(),n=t.worldToIndex(e),i=[this.getScrollDimIndex()];return 4===n.length()&&i.push(3),t.isIndexInBounds(n,i)}getOrigin(e){const t=this.#qe.getGeometry();let n=0;return void 0!==e&&(n=t.worldToIndex(e).get(2)),t.getOrigins()[n]}setCurrentIndex(e,t){const n=this.#qe.getGeometry().indexToWorld(e);return this.setCurrentPosition(n,t)}setCurrentPosition(e,t){void 0===t&&(t=!1);const n=this.#qe.getGeometry(),i=n.worldToIndex(e),r=[this.getScrollDimIndex()];if(4===i.length()&&r.push(3),!n.isIndexInBounds(i,r))return this.#Be=e,t||this.#Fe({type:"positionchange",value:[i.getValues(),e.getValues()],valid:!1}),!1;let o=null,a=null;if(this.getCurrentPosition()&&(a=this.getCurrentIndex()),a)if(a.canCompare(i))o=a.compare(i);else{o=[];const e=Math.min(a.length(),i.length());for(let t=0;t<e;++t)a.get(t)!==i.get(t)&&o.push(t);const t=Math.max(a.length(),i.length());for(let n=e;n<t;++n)o.push(n)}else{o=[];for(let e=0;e<i.length();++e)o.push(e)}if(this.#Be=e,!t){const t={type:"positionchange",value:[i.getValues(),e.getValues()],diffDims:o,data:{imageUid:this.#qe.getImageUid(i)}};if(this.#qe.canQuantify()){const e=this.#qe.getRescaledValueAtIndex(i);t.value.push(e)}this.#Fe(t)}return!0}setWindowLevel(e,t,n){if(void 0===t&&(t="manual"),"manual"!==t&&void 0===this.#Me[t])throw new Error("Unknown window level preset: '"+t+"'");void 0===n&&(n=!1);const i=!e.equals(this.#Ve),r=this.#Qe!==t;(i||r)&&(this.#Ve=e,this.#Qe=t,"manual"===t&&(void 0!==this.#Me[t]?this.#Me[t].wl[0]=e:this.addWindowPresets({manual:{wl:[e],name:"manual"}})),this.#Fe({type:"wlchange",value:[e.center,e.width,t],wc:e.center,ww:e.width,skipGenerate:n}))}getWindowLevel(){return this.#ke().getVoiLut().getWindowLevel()}setWindowLevelPreset(e,t){const n=this.getWindowPresets()[e];if(void 0===n)throw new Error("Unknown window level preset: '"+e+"'");"minmax"===e&&void 0===n.wl&&(n.wl=[this.getWindowLevelMinMax()]);let i=n.wl[0];if(void 0!==n.perslice&&!0===n.perslice){const e=this.#qe.getSecondaryOffset(this.getCurrentIndex());i=n.wl[e]}this.setWindowLevel(i,e,t)}setWindowLevelPresetById(e,t){const n=Object.keys(this.getWindowPresets());this.setWindowLevelPreset(n[e],t)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)};getWindowLevelMinMax(){const e=this.getImage().getRescaledDataRange(),t=e.min;let n=e.max-t;return n<1&&(c.warn("Zero or negative window width, defaulting to one."),n=1),new u(t+n/2,n)}setWindowLevelMinMax(){const e=this.getWindowLevelMinMax();this.setWindowLevel(e,"minmax")}generateImageData(e,t){void 0===t&&(this.getCurrentIndex()||this.setInitialIndex(),t=this.getCurrentIndex());const n=this.getImage(),i=!n.isConstantRSI(),r=Ye(n,t,i,this.getOrientation()),o=n.getPhotometricInterpretation();switch(o){case"MONOCHROME1":case"MONOCHROME2":!function(e,t,n,i,r){let o=0,a=0,s=t.next();for(;!s.done;)a=i.getValue(s.value),e.data[o]=r.red[a],e.data[o+1]=r.green[a],e.data[o+2]=r.blue[a],e.data[o+3]=n(s.value,s.index),o+=4,s=t.next()}(e,r,this.getAlphaFunction(),this.#ke(),this.#He());break;case"PALETTE COLOR":!function(e,t,n,i,r){const o=function(e){return e>>8};r&&c.info("Scaling 16bits data to 8bits.");let a=0,s=0,l=t.next();for(;!l.done;)s=l.value,r?(e.data[a]=o(i.red[s]),e.data[a+1]=o(i.green[s]),e.data[a+2]=o(i.blue[s])):(e.data[a]=i.red[s],e.data[a+1]=i.green[s],e.data[a+2]=i.blue[s]),e.data[a+3]=n(s,l.index),a+=4,l=t.next()}(e,r,this.getAlphaFunction(),n.getPaletteColourMap(),16===n.getMeta().BitsStored);break;case"RGB":!function(e,t,n){let i=0,r=t.next();for(;!r.done;)e.data[i]=r.value[0],e.data[i+1]=r.value[1],e.data[i+2]=r.value[2],e.data[i+3]=n(r.value,r.index),i+=4,r=t.next()}(e,r,this.getAlphaFunction());break;case"YBR_FULL":!function(e,t,n){let i=0,r=null,o=t.next();for(;!o.done;)a=o.value[0],s=o.value[1],r={r:a+1.402*((l=o.value[2])-128),g:a-.34414*(s-128)-.71414*(l-128),b:a+1.772*(s-128)},e.data[i]=r.r,e.data[i+1]=r.g,e.data[i+2]=r.b,e.data[i+3]=n(o.value,o.index),i+=4,o=t.next();var a,s,l}(e,r,this.getAlphaFunction());break;default:throw new Error("Unsupported photometric interpretation: "+o)}}getScrollDimIndex(){let e=null;const t=this.getOrientation();return e=void 0!==t?t.getThirdColMajorDirection():2,e}isAquisitionOrientation(){return x(this.#K)}}class Gn{#ze;#j;#We;#Ye;#Xe;constructor(e,t){this.#ze=e,this.#j=e.getRealSpacing(),this.#We=e.getOrientation(),this.#Ye=t,this.#Xe=function(e,t){let n=e.asOneAndZeros().multiply(t);return e.asOneAndZeros().getAbs().equals(St().getAbs())&&(n=n.getAbs()),n}(this.#We,t)}getViewOrientation(){return this.#Ye}getTargetOrientation(){return this.#Xe}getOffset3DFromPlaneOffset(e){const t=new P(e.x,e.y,0),n=this.getTargetDeOrientedVector3D(t);return new P(n.getX()*this.#j.get(0),n.getY()*this.#j.get(1),n.getZ()*this.#j.get(2))}getPlaneOffsetFromOffset3D(e){const t=new P(e.x/this.#j.get(0),e.y/this.#j.get(1),e.z/this.#j.get(2)),n=this.getTargetOrientedVector3D(t);return{x:n.getX(),y:n.getY()}}getTargetOrientedVector3D(e){let t=e;return void 0!==this.#Xe&&(t=this.#Xe.getInverse().multiplyVector3D(e)),t}getTargetDeOrientedVector3D(e){let t=e;return void 0!==this.#Xe&&(t=this.#Xe.multiplyVector3D(e)),t}getTargetDeOrientedPoint3D(e){let t=e;return void 0!==this.#Xe&&(t=this.#Xe.multiplyPoint3D(e)),t}getImageOrientedVector3D(e){let t=e;if(void 0!==this.#Ye){const n=ot([e.getX(),e.getY(),e.getZ()],this.#Ye);t=new P(n[0],n[1],n[2])}return t}getImageOrientedPoint3D(e){let t=e;if(void 0!==this.#Ye){const n=ot([e.getX(),e.getY(),e.getZ()],this.#Ye);t=new F(n[0],n[1],n[2])}return t}getImageDeOrientedVector3D(e){let t=e;if(void 0!==this.#Ye){const n=rt([e.getX(),e.getY(),e.getZ()],this.#Ye);t=new P(n[0],n[1],n[2])}return t}getImageDeOrientedPoint3D(e){let t=e;if(void 0!==this.#Ye){const n=rt([e.getX(),e.getY(),e.getZ()],this.#Ye);t=new F(n[0],n[1],n[2])}return t}getPositionFromPlanePoint(e,t){const n=new F(e.getX(),e.getY(),t),i=this.getImageOrientedPoint3D(n);return this.#ze.pointToWorld(i)}getPlanePointFromPosition(e){const t=this.#ze.worldToPoint(e);return this.getImageDeOrientedPoint3D(t)}getCosines(){return[(e=this.#Xe).get(0,0),e.get(1,0),e.get(2,0),e.get(0,1),e.get(1,1),e.get(2,1)];var e}getPlanePoints(e){const t=this.worldToIndex(e),n=this.indexToWorld(t),i=this.getPlanePointFromPosition(n),r=this.getPositionFromPlanePoint(new R(0,0),i.getZ()),o=this.#ze.getOrigins(),a=o[r.getClosest(o)],s=r.getValues(),l=a.getValues(),c=this.getNativeScrollDimIndex();s[c]=l[c];const u=this.getCosines();return[new F(s[0],s[1],s[2]),new F(u[0],u[1],u[2]),new F(u[3],u[4],u[5])]}worldToIndex(e){return this.#ze.worldToIndex(e)}indexToWorld(e){return this.#ze.indexToWorld(e)}isAquisitionOrientation(){return x(this.#Ye)}getTargetOrientedPositiveXYZ(e){const t=rt([e.x,e.y,e.z],this.#Xe);return{x:t[0],y:t[1],z:t[2]}}getScrollDimIndex(){let e=null;return e=void 0!==this.#Ye?this.#Ye.getThirdColMajorDirection():2,e}getNativeScrollDimIndex(){let e=null;return e=void 0!==this.#We?this.#We.getThirdColMajorDirection():2,e}}class kn{#R;constructor(e){this.#R=e}getCurrentPosition(){return this.#R.getCurrentPosition()}setCurrentPosition(e,t){let n=!1;return void 0!==e&&(n=this.#R.setCurrentPosition(e,t)),n}}class Hn{#je;#me;#Ze;constructor(e){this.#je=new kn(e),this.#me=e.getImage().getGeometry(),this.#Ze=e.getScrollDimIndex()}getGeometry(){return this.#me}getScrollDimIndex(){return this.#Ze}getMaximumDimValue(e){return this.#me.getSize().get(e)-1}getMaximumScrollValue(){return this.getMaximumDimValue(this.#Ze)}getCurrentPosition(){return this.#je.getCurrentPosition()}getCurrentPositionDimValue(e){return this.getCurrentIndex().get(e)}getCurrentPositionScrollValue(){return this.getCurrentPositionDimValue(this.#Ze)}getCurrentPositionAtDimValue(e,t){const n=this.getCurrentIndex().getValues();return n[e]=t,this.#me.indexToWorld(new s(n))}getCurrentPositionAtScrollValue(e){return this.getCurrentPositionAtDimValue(this.#Ze,e)}getCurrentIndex(){return this.#me.worldToIndex(this.getCurrentPosition())}setCurrentPosition(e,t){let n=!1;return void 0!==e&&(n=this.#je.setCurrentPosition(e,t)),n}setCurrentPositionSafe(e,t){let n=!1;return this.isPositionInBounds(e)&&(n=this.setCurrentPosition(e,t)),n}merge(e){if(this.#Ze!==e.getScrollDimIndex())throw new Error("Cannot merge helper of a view with different orientation");this.#me=function(e,t){const n=function(e,t){return e.map(((e,n)=>Math.min(e,t[n])))},i=new Ze((r=e.getSize().getValues(),o=t.getSize().getValues(),r.map(((e,t)=>Math.max(e,o[t])))));var r,o;const a=new nt(n(e.getSpacing().getValues(),t.getSpacing().getValues())),s=e.getRange(),l=t.getRange(),c=n(s[0].getValues(),l[0].getValues()),u=[];for(let e=0;e<i.get(2);++e){const t=c.slice();t[2]=c[2]+e*a.get(2),u.push(new F(t[0],t[1],t[2]))}return new it(u,i,a,e.getOrientation())}(this.#me,e.getGeometry())}isPositionInBounds(e){const t=this.#me.worldToIndex(e),n=[this.#Ze];return 4===t.length()&&n.push(3),this.#me.isIndexInBounds(t,n)}getIncrementPosition(e){const t=this.getCurrentIndex().next(e);return this.#me.indexToWorld(t)}getDecrementPosition(e){const t=this.getCurrentIndex().previous(e);return this.#me.indexToWorld(t)}incrementPosition(e){return this.setCurrentPositionSafe(this.getIncrementPosition(e))}decrementPosition(e){return this.setCurrentPositionSafe(this.getDecrementPosition(e))}incrementPositionAlongScroll(){return this.incrementPosition(this.#Ze)}decrementPositionAlongScroll(){return this.decrementPosition(this.#Ze)}}class zn{#R;#_e;#Ke;#Je;#$e=!1;constructor(e){if(void 0===e.getImage())throw new Error("View does not have an image, cannot setup controller");this.#R=e,this.#_e=new Gn(e.getImage().getGeometry(),e.getOrientation()),this.#Ke=new Hn(e),"SEG"===e.getImage().getMeta().Modality&&(this.#$e=!0)}getPlaneHelper(){return this.#_e}isMask(){return this.#$e}initialise(){this.setWindowLevelPresetById(0),this.setCurrentPosition(this.getPositionFromPlanePoint(new R(0,0)))}getModality(){return this.#R.getImage().getMeta().Modality}getWindowLevelPresetsNames(){return this.#R.getWindowPresetsNames()}addWindowLevelPresets(e){return this.#R.addWindowPresets(e)}setWindowLevelPreset(e){this.#R.setWindowLevelPreset(e)}setWindowLevelPresetById(e){this.#R.setWindowLevelPresetById(e)}isPlaying(){return void 0!==this.#Je}getPositionHelper(){return this.#Ke}getCurrentPosition(){return this.#Ke.getCurrentPosition()}getCurrentIndex(){return this.#Ke.getCurrentIndex()}getCurrentImageUid(){return this.#R.getCurrentImageUid()}getOriginForImageUid(e){return this.#R.getOriginForImageUid(e)}includesImageUid(e){return this.#R.includesImageUid(e)}getCurrentOrientedIndex(){let e=this.getCurrentIndex();if(void 0!==this.#R.getOrientation()){const t=this.#_e.getImageDeOrientedVector3D(new P(e.get(0),e.get(1),e.get(2)));e=new s([t.getX(),t.getY(),t.getZ()])}return e}getScrollDimIndex(){return this.#R.getScrollDimIndex()}getCurrentIndexScrollValue(){return this.getCurrentIndex().get(this.#R.getScrollDimIndex())}getOrigin(e){return this.#R.getOrigin(e)}isAquisitionOrientation(){return this.#R.isAquisitionOrientation()}getPlanePoints(e){return this.#_e.getPlanePoints(e)}getCurrentScrollPosition(){const e=this.#R.getScrollDimIndex();return this.#R.getCurrentPosition().get(e)}generateImageData(e,t){this.#R.generateImageData(e,t)}setImage(e){this.#R.setImage(e)}get2DSpacing(){return this.#R.getImage().getGeometry().getSpacing(this.#R.getOrientation()).get2D()}getRescaledImageValue(e){const t=this.#R.getImage();if(!t.canQuantify())return;const n=t.getGeometry(),i=n.worldToIndex(e);let r;return n.isIndexInBounds(i)&&(r=t.getRescaledValueAtIndex(i)),r}getPixelUnit(){return this.#R.getImage().getMeta().pixelUnit}#et(e,t,n,i){const r=We(Ye(e,t,n,i)),o=e.getGeometry().getSize(i).getValues();o[2]=1;const a=new Ze(o),s=e.getGeometry().getSpacing(i).getValues();s[2]=1;const l=new nt(s),c=new F(0,0,0),u=new it([c],a,l);return new Un(u,r)}getImageRegionValues(e,t,n){let i=this.#R.getImage();const r=this.#R.getOrientation();let o=n,a=!0;x(r)||(i=this.#et(i,o,a,r),o=new s([0,0,0]),a=!1);const l=function(e,t,n,i,r){if(1!==e.getNumberOfComponents())throw new Error("Unsupported number of components for region iterator: "+e.getNumberOfComponents());void 0===n&&(n=!1);let o=null;o=n?function(t){return e.getRescaledValueAtOffset(t)}:function(t){return e.getValueAtOffset(t)};const a=e.getGeometry().getSize();void 0===i&&(i=new R(0,0)),void 0===r&&(r=new R(a.get(0)-1,a.get(1)));const s=a.indexToOffset(t.getWithNew2D(i.getX(),i.getY())),l=a.indexToOffset(t.getWithNew2D(r.getX(),r.getY()-1)),c=Math.max(1,r.getX()-i.getX());return function(e,t,n,i,r,o){let a=t,s=0;return{next:function(){if(a<n){const t={value:e(a),done:!1,index:a};return s+=1,a+=1,s===r&&(s=0,a+=o),t}return{done:!0,index:n}}}}(o,s,l+1,0,c,a.get(0)-c)}(i,o,a,e,t);let c=[];return l&&(c=We(l)),c}getImageVariableRegionValues(e,t){let n=this.#R.getImage();const i=this.#R.getOrientation();let r=t,o=!0;x(i)||(n=this.#et(n,r,o,i),r=new s([0,0,0]),o=!1);const a=function(e,t,n,i){if(1!==e.getNumberOfComponents())throw new Error("Unsupported number of components for region iterator: "+e.getNumberOfComponents());void 0===n&&(n=!1);let r=null;r=n?function(t){return e.getRescaledValueAtOffset(t)}:function(t){return e.getValueAtOffset(t)};const o=e.getGeometry().getSize(),a=[];let s,l=null,c=null,u=null;for(let e=0;e<i.length;++e){s=i[e];const t=s[1][0]-s[0][0];0!==t&&(u=e,l||(l=s[0]),a.push([s[0][0],t,o.get(0)-s[1][0]]))}if(null!==u&&(c=i[u][1]),0!==a.length)return function(e,t,n,i,r){let o=t,a=0,s=0;return{next:function(){if(o<n){const t={value:e(o),done:!1,index:o};return s+=1,o+=1,s===r[a][1]&&(s=0,o+=r[a][2],a+=1,a<r.length&&(o+=r[a][0])),t}return{done:!0,index:n}}}}(r,o.indexToOffset(t.getWithNew2D(l[0],l[1])),o.indexToOffset(t.getWithNew2D(c[0],c[1]))+1,0,a)}(n,r,o,e);let l=[];return a&&(l=We(a)),l}canQuantifyImage(){return this.#R.getImage().canQuantify()}canWindowLevel(){return this.isMonochrome()}isMonochrome(){return this.#R.getImage().isMonochrome()}canScroll(){return this.#R.getImage().canScroll(this.#R.getOrientation())}getImageSize(){return this.#R.getImage().getGeometry().getSize(this.#R.getOrientation())}moreThanOne(e){return this.getImageSize().moreThanOne(e)}getImageWorldSize(){const e=this.#R.getImage().getGeometry(),t=e.getSize(this.#R.getOrientation()).get2D(),n=e.getSpacing(this.#R.getOrientation()).get2D();return{x:t.x*n.x,y:t.y*n.y}}getImageRescaledDataRange(){return this.#R.getImage().getRescaledDataRange()}equalImageMeta(e){const t=this.#R.getImage().getMeta(),n=Object.keys(e);for(let i=0;i<n.length;++i){const r=n[i];if(void 0===t[r])return!1;if(t[r]!==e[r])return!1}return!0}isPositionInBounds(e){return this.#R.isPositionInBounds(e)}setCurrentPosition(e,t){return this.#R.setCurrentPosition(e,t)}getPositionFromPlanePoint(e,t){void 0===t&&(t=this.getCurrentIndexScrollValue());const n=new F(e.getX(),e.getY(),t),i=this.#_e.getImageOrientedPoint3D(n),r=this.#R.getImage().getGeometry().pointToWorld(i);return this.getCurrentPosition().mergeWith3D(r)}getPlanePositionFromPosition(e){const t=this.#R.getImage().getGeometry().worldToPoint(e),n=this.#_e.getImageDeOrientedPoint3D(t);return new R(n.getX(),n.getY())}getIndexFromPosition(e){return this.#R.getImage().getGeometry().worldToIndex(e)}setCurrentIndex(e,t){return this.#R.setCurrentIndex(e,t)}getPlanePositionFromPlanePoint(e){const t=this.getCurrentIndexScrollValue(),n=new F(e.getX(),e.getY(),t),i=this.#_e.getTargetDeOrientedPoint3D(n),r=this.#R.getImage().getGeometry().getRealSpacing();return new F(i.getX()*r.get(0),i.getY()*r.get(1),i.getZ()*r.get(2))}getOffset3DFromPlaneOffset(e){return this.#_e.getOffset3DFromPlaneOffset(e)}play(){if(this.canScroll())if(void 0===this.#Je){const e=this.#R.getImage(),t=e.getMeta().RecommendedDisplayFrameRate,n=this.#R.getPlaybackMilliseconds(t),i=e.getGeometry().getSize().canScroll3D();this.#Je=window.setInterval((()=>{let e=!1;if(e=i?this.#Ke.incrementPositionAlongScroll():this.#Ke.incrementPosition(3),!e){const e=this.getCurrentIndex().getValues(),t=this.#R.getOrientation();i?e[t.getThirdColMajorDirection()]=0:e[3]=0;const n=new s(e),r=this.#R.getImage().getGeometry();this.setCurrentPosition(r.indexToWorld(n))}}),n)}else this.stop()}stop(){void 0!==this.#Je&&(clearInterval(this.#Je),this.#Je=void 0)}getWindowLevel(){return this.#R.getWindowLevel()}getCurrentWindowPresetName(){return this.#R.getCurrentWindowPresetName()}setWindowLevel(e){this.#R.setWindowLevel(e)}getColourMap(){return this.#R.getColourMap()}setColourMap(e){this.#R.setColourMap(e)}setViewAlphaFunction(e){this.#R.setAlphaFunction(e)}bindImageAndLayer(e){const t=this.#R.getImage();t.addEventListener("imagecontentchange",e.onimagecontentchange),t.addEventListener("imagegeometrychange",e.onimagegeometrychange)}unbindImageAndLayer(e){const t=this.#R.getImage();t.removeEventListener("imagecontentchange",e.onimagecontentchange),t.removeEventListener("imagegeometrychange",e.onimagegeometrychange)}}const Wn=["mousedown","mousemove","mouseup","mouseout","wheel","dblclick","touchstart","touchmove","touchend"];function Yn(e){let t=0,n=0;if(0!==e.length&&void 0!==e[0].target){let i=e[0].target.offsetParent;for(;i;)isNaN(i.offsetLeft)||(t+=i.offsetLeft),isNaN(i.offsetTop)||(n+=i.offsetTop),i=i.offsetParent}else c.debug("No touch target offset parent.");const i=[];for(let r=0;r<e.length;++r)i.push(new R(e[r].pageX-t,e[r].pageY-n));return i}function Xn(e){let t=[];return void 0!==e.targetTouches&&0!==e.targetTouches.length?t=Yn(e.targetTouches):void 0!==e.changedTouches&&0!==e.changedTouches.length&&(t=Yn(e.changedTouches)),t}function jn(e){return new R(e.offsetX,e.offsetY)}function Zn(e,t){const n=document.createElement("canvas");n.width=e,n.height=t;const i=document.createElement("canvas");i.width=1,i.height=1;const r=n.getContext("2d"),o=i.getContext("2d");return r&&(r.fillRect(e-1,t-1,1,1),o.drawImage(n,e-1,t-1,1,1,0,0,1,1)),o&&0!==o.getImageData(0,0,1,1).data[3]}class _n{#tt;#nt=null;#it=null;#rt=null;#ot=null;#at=!0;#st=null;#lt;#ct;#ut=1;#dt={x:1,y:1};#ht={x:1,y:1};#St={x:1,y:1,z:1};#gt={x:0,y:0};#pt={x:0,y:0};#mt={x:0,y:0};#ft={x:0,y:0};#Dt={x:0,y:0};#yt=null;#Ct;#be=new He;#vt=!1;#It;#Tt;constructor(e){this.#tt=e,this.#tt.className+=" viewLayer"}getDataId(){return this.#Ct}getScale(){return this.#dt}getAbsoluteZoomOffset(){return{x:this.#ft.x*this.#ht.x,y:this.#ft.y*this.#ht.y}}setImageSmoothing(e){this.#vt=e}setView(e,t){this.#Ct=t,e.addEventListener("wlchange",this.#Lt),e.addEventListener("colourmapchange",this.#Pt),e.addEventListener("positionchange",this.#wt),e.addEventListener("alphafuncchange",this.#Ot);for(let t=0;t<Vn.length;++t)e.addEventListener(Vn[t],this.#Fe);this.#nt=new zn(e),this.bindImage()}getViewController(){return this.#nt}getImageData(){return this.#st}onimageset=e=>{this.#Ct===e.dataid&&(this.#nt.setImage(e.value[0]),this.#At(this.#nt.getImageSize().get2D()),this.#yt=!0)};bindImage(){this.#nt&&this.#nt.bindImageAndLayer(this)}unbindImage(){this.#nt&&this.#nt.unbindImageAndLayer(this)}onimagecontentchange=e=>{this.#Ct===e.dataid&&(this.#at=this.#nt.isPositionInBounds(),this.#yt=!0,this.draw())};onimagegeometrychange=e=>{if(this.#Ct===e.dataid){const e=this.#nt.getImageSize().get2D();if(this.#lt.x!==e.x||this.#lt.y!==e.y){if(void 0!==this.#It&&void 0!==this.#Tt){const e=this.#nt.getOrigin(),t=this.#Tt.minus(e),n=this.#nt.getOrigin(this.#nt.getCurrentPosition()),i=this.#It.minus(n);this.setBaseOffset(t,i)}this.#At(e),this.#yt=!0,this.draw()}}};getId(){return this.#tt.id}removeFromDOM(){this.#tt.remove()}getBaseSize(){return this.#lt}getImageWorldSize(){return this.#nt.getImageWorldSize()}getOpacity(){return this.#ut}setOpacity(e){if(e===this.#ut)return;this.#ut=Math.min(Math.max(e,0),1);const t={type:"opacitychange",value:[this.#ut]};this.#Fe(t)}addFlipOffsetX(){this.#Dt.x+=this.#it.width/this.#dt.x,this.#gt.x+=this.#Dt.x}addFlipOffsetY(){this.#Dt.y+=this.#it.height/this.#dt.y,this.#gt.y+=this.#Dt.y}flipScaleX(){this.#St.x*=-1}flipScaleY(){this.#St.y*=-1}flipScaleZ(){this.#St.z*=-1}setScale(e,t){const n=this.#nt.getPlaneHelper(),i=n.getTargetOrientedPositiveXYZ({x:e.x*this.#St.x,y:e.y*this.#St.y,z:e.z*this.#St.z}),r={x:this.#ht.x*i.x,y:this.#ht.y*i.y};if(1===Math.abs(e.x)&&1===Math.abs(e.y)&&1===Math.abs(e.z)){const e={x:this.#gt.x-this.#ft.x,y:this.#gt.y-this.#ft.y};this.#ft={x:0,y:0},this.#gt=e}else if(void 0!==t){let e=n.getPlaneOffsetFromOffset3D({x:t.getX(),y:t.getY(),z:t.getZ()});e={x:e.x+this.#pt.x,y:e.y+this.#pt.y};const i=Ji(this.#gt,this.#dt,r,e),o={x:this.#ft.x+i.x-this.#gt.x,y:this.#ft.y+i.y-this.#gt.y};this.#ft=o,this.#gt=i}this.#dt=r}initScale(e,t){const n=this.#nt.getPlaneHelper().getTargetOrientedPositiveXYZ({x:e.x*this.#St.x,y:e.y*this.#St.y,z:e.z*this.#St.z}),i={x:this.#ht.x*n.x,y:this.#ht.y*n.y};this.#dt=i,this.#ft={x:t.x/this.#ht.x,y:t.y/this.#ht.y},this.#gt={x:this.#gt.x+this.#ft.x,y:this.#gt.y+this.#ft.y}}setBaseOffset(e,t,n,i){const r=this.#nt.getPlaneHelper(),o=r.getNativeScrollDimIndex(),a=r.getPlaneOffsetFromOffset3D({x:0===o?e.getX():t.getX(),y:1===o?e.getY():t.getY(),z:2===o?e.getZ():t.getZ()}),s=this.#pt.x!==a.x||this.#pt.y!==a.y;return void 0!==n&&void 0!==i&&(this.#It=n,this.#Tt=i),s&&(this.#gt={x:this.#gt.x-this.#pt.x+a.x,y:this.#gt.y-this.#pt.y+a.y},this.#pt=a),s}setOffset(e){const t=this.#nt.getPlaneHelper().getPlaneOffsetFromOffset3D(e);this.#gt={x:t.x+this.#mt.x+this.#pt.x+this.#ft.x+this.#Dt.x,y:t.y+this.#mt.y+this.#pt.y+this.#ft.y+this.#Dt.y}}displayToPlaneIndex(e){const t=this.displayToPlanePos(e);return new s([Math.floor(t.getX()),Math.floor(t.getY())])}displayToPlaneScale(e){return new R(e.getX()/this.#dt.x,e.getY()/this.#dt.y)}displayToPlanePos(e){const t=this.displayToPlaneScale(e);return new R(t.getX()+this.#gt.x,t.getY()+this.#gt.y)}planePosToDisplay(e){let t=(e.getX()-this.#gt.x+this.#pt.x)*this.#dt.x,n=(e.getY()-this.#gt.y+this.#pt.y)*this.#dt.y;return(t<0||t>=this.#it.width)&&(t=void 0),(n<0||n>=this.#it.height)&&(n=void 0),new R(t,n)}displayToMainPlanePos(e){const t=this.displayToPlanePos(e);return new R(t.getX()-this.#pt.x,t.getY()-this.#pt.y)}display(e){this.#tt.style.display=e?"":"none"}isVisible(){return""===this.#tt.style.display}draw(){if(!this.#at)return;let e={type:"renderstart",layerid:this.getId(),dataid:this.getDataId()};this.#Fe(e),this.#yt&&this.#bt(),this.#ot.globalAlpha=this.#ut,this.clear(),this.#ot.setTransform(this.#dt.x,0,0,this.#dt.y,-1*this.#gt.x*this.#dt.x,-1*this.#gt.y*this.#dt.y),this.#ot.imageSmoothingEnabled=this.#vt,this.#ot.drawImage(this.#rt,0,0),e={type:"renderend",layerid:this.getId(),dataid:this.getDataId()},this.#Fe(e)}initialise(e,t,n){this.#ct=t,this.#ut=Math.min(Math.max(n,0),1),this.#it=document.createElement("canvas"),this.#tt.appendChild(this.#it),this.#it.getContext?(this.#ot=this.#it.getContext("2d"),this.#ot?(this.#rt=document.createElement("canvas"),this.#At(e),this.#yt=!0):alert("Error: failed to get the 2D context.")):alert("Error: no canvas.getContext method.")}#At(e){if(!Zn(e.x,e.y))throw new Error("Cannot create canvas with size "+e.x+", "+e.y);this.#lt=e,this.#rt.width=this.#lt.x,this.#rt.height=this.#lt.y,this.#ot.clearRect(0,0,this.#lt.x,this.#lt.y),this.#st=this.#ot.createImageData(this.#lt.x,this.#lt.y)}fitToContainer(e,t,n){let i=!1;if(this.#it.width!==e.x||this.#it.height!==e.y){if(!Zn(e.x,e.y))throw new Error("Cannot resize canvas "+e.x+", "+e.y);this.#it.width=e.x,this.#it.height=e.y,i=!0}const r={x:t*this.#ct.x,y:t*this.#ct.y},o={x:this.#dt.x*r.x/this.#ht.x,y:this.#dt.y*r.y/this.#ht.y};this.#dt.x===o.x&&this.#dt.y===o.y||(this.#ht=r,this.#dt=o,i=!0);const a={x:n.x/r.x,y:n.y/r.y},s={x:e.x/r.x,y:e.y/r.y},l={x:0!==this.#Dt.x?s.x:0,y:0!==this.#Dt.y?s.y:0};this.#mt.x===a.x&&this.#mt.y===a.y&&this.#Dt.x===l.x&&this.#Dt.y===l.y||(this.#gt={x:this.#gt.x+a.x-this.#mt.x+l.x-this.#Dt.x,y:this.#gt.y+a.y-this.#mt.y+l.y-this.#Dt.y},this.#Dt=l,this.#mt=a,i=!0),i&&this.draw()}bindInteraction(){this.#tt.style.pointerEvents="auto";const e=Wn;for(let t=0;t<e.length;++t){const n=e[t],i="wheel"!==n;this.#tt.addEventListener(n,this.#Fe,{passive:i})}}unbindInteraction(){this.#tt.style.pointerEvents="none";const e=Wn;for(let t=0;t<e.length;++t)this.#tt.removeEventListener(e[t],this.#Fe)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{e.srclayerid=this.getId(),e.dataid=this.#Ct,this.#be.fireEvent(e)};#bt(){this.#nt.generateImageData(this.#st),this.#rt.getContext("2d").putImageData(this.#st,0,0),this.#yt=!1}#Lt=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#yt=!0,this.draw())};#Pt=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#yt=!0,this.draw())};#wt=e=>{if(void 0===e.skipGenerate||!0!==e.skipGenerate){let t=!0;if(void 0!==e.valid&&(t=e.valid),t){const t=[0,1,2],n=t.indexOf(this.#nt.getScrollDimIndex());t.splice(n,1),0===e.diffDims.filter((function(e){return-1===t.indexOf(e)})).length&&this.#at||(this.#at=!0,this.#yt=!0,this.draw())}else this.#at&&(this.#at=!1,this.clear())}};#Ot=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#yt=!0,this.draw())};setCurrentPosition(e,t){return this.#nt.setCurrentPosition(e)}clear(){this.#ot.save(),this.#ot.setTransform(1,0,0,1,0,0),this.#ot.clearRect(0,0,this.#it.width,this.#it.height),this.#ot.restore()}}class Kn{#xt=0;getSum(){return this.#xt}add(e){this.#xt+=function(e){if(void 0===e.wheelDeltaY)return-e.deltaY;{const t=45;return e.wheelDeltaY>t?1:e.wheelDeltaY<-t?-1:-e.deltaY/60}}(e)}clear(){this.#xt=0}isTick(){return Math.abs(this.#xt)>=1}}class Jn{#Rt;#Ft=new Kn;constructor(e){this.#Rt=e}wheel(e){this.#Ft.add(e);const t=this.#Ft.getSum()>=0;if(!this.#Ft.isTick())return;this.#Ft.clear(),e.preventDefault();const n=Ki(e),i=this.#Rt.getLayerGroupByDivId(n.groupDivId),r=i.getPositionHelper();i.canScroll()?t?r.incrementPositionAlongScroll():r.decrementPositionAlongScroll():i.moreThanOne(3)&&(t?r.incrementPosition(3):r.decrementPosition(3))}}class $n{#Et;#qt;constructor(e,t){this.#Et=e,this.#qt=t}getBegin(){return this.#Et}getEnd(){return this.#qt}equals(e){return null!==e&&this.getBegin().equals(e.getBegin())&&this.getEnd().equals(e.getEnd())}getDeltaX(){return this.getEnd().getX()-this.getBegin().getX()}getDeltaY(){return this.getEnd().getY()-this.getBegin().getY()}getLength(){return Math.sqrt(this.getDeltaX()*this.getDeltaX()+this.getDeltaY()*this.getDeltaY())}getWorldLength(e){let t=null;if(null!==e){const n=this.getDeltaX()*e.x,i=this.getDeltaY()*e.y;t=Math.sqrt(n*n+i*i)}return t}getMidpoint(){return new R((this.getBegin().getX()+this.getEnd().getX())/2,(this.getBegin().getY()+this.getEnd().getY())/2)}getCentroid(){return this.getMidpoint()}getSlope(){return this.getDeltaY()/this.getDeltaX()}getIntercept(){return(this.getEnd().getX()*this.getBegin().getY()-this.getBegin().getX()*this.getEnd().getY())/this.getDeltaX()}getInclination(){return 180-180*Math.atan2(this.getDeltaY(),this.getDeltaX())/Math.PI}quantify(e){const t={},n=e.get2DSpacing(),i=this.getWorldLength(n);return null!==i&&(t.length={value:i,unit:"unit.mm"}),t}}function ei(e,t){const n=e.getDeltaX(),i=e.getDeltaY(),r=t.getDeltaX(),o=t.getDeltaY(),a=n*r+i*o,s=n*o-i*r;return 360-(180-180*Math.atan2(s,a)/Math.PI)}function ti(e,t){const n=e.getDeltaX(),i=e.getDeltaY();return n*t.getDeltaX()+i*t.getDeltaY()==0}function ni(e,t,n,i){void 0===i&&(i={x:1,y:1});const r=-i.x*i.x/(i.y*i.y*e.getSlope());return ri(r,t.getY()-r*t.getX(),t,n,i)}function ii(e,t,n,i){const r=ri(e.getSlope(),e.getIntercept(),e.getBegin(),t,i);let o;return o=function(e,t){const n=Math.min(t.getBegin().getX(),t.getEnd().getX()),i=Math.max(t.getBegin().getX(),t.getEnd().getX()),r=Math.min(t.getBegin().getY(),t.getEnd().getY()),o=Math.max(t.getBegin().getY(),t.getEnd().getY());return e.getX()>=n&&e.getX()<=i&&e.getY()>=r&&e.getY()<=o}(r.getBegin(),e)?r.getBegin():r.getEnd(),ni(e,o,n,i)}function ri(e,t,n,i,r){void 0===r&&(r={x:1,y:1});let o=0,a=0,s=0,l=0;if(O(e,0,w))o=n.getX()-i/(2*r.x),a=n.getY(),s=n.getX()+i/(2*r.x),l=n.getY();else if(Math.abs(e)>1e6)o=n.getX(),a=n.getY()-i/(2*r.y),s=n.getX(),l=n.getY()+i/(2*r.y);else{const c=r.x*r.x,u=r.y*r.y,d=i/(2*Math.sqrt(c+u*e*e));o=n.getX()-d,a=e*o+t,s=n.getX()+d,l=e*s+t}return new $n(new R(o,a),new R(s,l))}var oi=o(944),ai=o.n(oi);class si{#Ut;#Mt;constructor(e,t){this.#Ut=e,this.#Mt=t}getName(){return"AddAnnotation-"+this.#Ut.id}execute(){this.#Mt.addAnnotation(this.#Ut)}undo(){this.#Mt.removeAnnotation(this.#Ut.id)}}class li{#Ut;#Mt;constructor(e,t){this.#Ut=e,this.#Mt=t}getName(){return"RemoveAnnotation-"+this.#Ut.id}execute(){this.#Mt.removeAnnotation(this.#Ut.id)}undo(){this.#Mt.addAnnotation(this.#Ut)}}class ci{#Ut;#Mt;#Qt;#Vt;constructor(e,t,n,i){this.#Ut=e,this.#Mt=i,this.#Qt=t,this.#Vt=n}getName(){return"UpdateAnnotation-"+this.#Ut.id}execute(){const e=Object.keys(this.#Vt);for(const t of e)this.#Ut[t]=this.#Vt[t];this.#Mt.updateAnnotation(this.#Ut,e)}undo(){const e=Object.keys(this.#Qt);for(const t of e)this.#Ut[t]=this.#Qt[t];this.#Mt.updateAnnotation(this.#Ut,e)}}class ui{#Nt=10;#Bt="Verdana";#Gt="#fff";#kt="#ffff80";#Ht={x:1,y:1};#zt={x:1,y:1};#Wt=2;#Yt={x:.25,y:.25};#Xt=.2;#jt=3;getFontFamily(){return this.#Bt}getFontSize(){return this.#Nt}getStrokeWidth(){return this.#Wt}getTextColour(){return this.#Gt}getLineColour(){return this.#kt}setLineColour(e){this.#kt=e}setBaseScale(e){this.#Ht=e}setZoomScale(e){this.#zt=e}getBaseScale(){return this.#Ht}getZoomScale(){return this.#zt}scale(e){return e/this.#Ht.x}applyZoomScale(e){return{x:e/this.#zt.x,y:e/this.#zt.y}}applyZoomRatio(e){return e*this.#zt.x/this.#zt.y}getShadowOffset(){return this.#Yt}getTagOpacity(){return this.#Xt}getTextPadding(){return this.#jt}getFontStr(){return"normal "+this.getFontSize()+"px sans-serif"}getLineHeight(){return this.getFontSize()+this.getFontSize()/5}getScaledFontSize(){return this.scale(this.getFontSize())}getScaledStrokeWidth(){return this.scale(this.getStrokeWidth())}getShadowLineColour(){return e=this.getLineColour(),n=e,.001172549*(t={r:parseInt(n.substring(1,3),16),g:parseInt(n.substring(3,5),16),b:parseInt(n.substring(5,7),16)}).r+.002301961*t.g+447059e-9*t.b<.5?"#fff":"#000";var e,t,n}}const di={arrow:{"*":""},circle:{"*":"{surface}"},ellipse:{"*":"{surface}"},protractor:{"*":"{angle}"},rectangle:{"*":"{surface}"},roi:{"*":""},ruler:{"*":"{length}"}};function hi(e){return"label"===e.name()}function Si(e){return"shape"===e.name()}function gi(e){return"position-group"===e.name()}function pi(e){const t=e.getChildren(Si)[0];if(t instanceof ai().Line)return t}function mi(e,t){const n=e.getChildren((function(e){return e.id()==="anchor"+t}))[0];if(n instanceof ai().Ellipse)return n}function fi(e){return function(t){return t.id()===e}}function Di(e,t,n,i){const r=i.applyZoomScale(6),o={x:Math.abs(r.x),y:Math.abs(r.y)};return new(ai().Ellipse)({x:e,y:t,stroke:"#999",fill:"rgba(100,100,100,0.7",strokeWidth:i.getStrokeWidth(),strokeScaleEnabled:!1,radius:o,radiusX:o.x,radiusY:o.y,name:"anchor",id:n.toString(),dragOnTop:!1,draggable:!0,visible:!1})}function yi(e){return parseInt(e.substring(6),10)}class Ci{#Rt;#Zt;constructor(e,t){this.#Rt=e,this.#Zt=t}#_t=null;#Kt=null;#Jt;#Ut;#$t=!1;setShape(e,t,n){if(this.#Kt=e,this.#Jt=t,this.#Ut=n,this.#Kt){if(this.#en(),this.#_t=n.getFactory(),null===this.#_t)throw new Error("Could not find a factory to update shape.");this.#tn()}}getShape(){return this.#Kt}getAnnotation(){return this.#Ut}isActive(){return this.#$t}enable(){this.#$t=!0,this.#Kt&&(this.#nn(!0),this.#Kt.getLayer()&&this.#Kt.getLayer().draw())}disable(){this.#$t=!1,this.#Kt&&(this.#nn(!1),this.#Kt.getLayer()&&this.#Kt.getLayer().draw())}reset(){this.#Kt=void 0,this.#Jt=void 0,this.#Ut=void 0}resetAnchors(){this.#en(),this.#tn(),this.#nn(!0)}#in(e){this.#Kt&&this.#Kt.getParent()&&this.#Kt.getParent().find(".anchor").forEach(e)}#nn(e){this.#in((function(t){t.visible(e)}))}setAnchorsActive(e){let t=null;t=e?e=>{this.#rn(e)}:e=>{this.#on(e)},this.#in(t)}#en(){this.#in((function(e){e.remove()}))}#tn(){if(!this.#Kt||!this.#Kt.getLayer())return;const e=this.#Kt.getParent(),t=this.#_t.getAnchors(this.#Kt,this.#Rt.getStyle());for(let n=0;n<t.length;++n)this.#rn(t[n]),e.add(t[n])}#rn(e){let t;e.on("dragstart.edit",(e=>{e.cancelBubble=!0,t={mathShape:this.#Ut.mathShape,referencePoints:this.#Ut.referencePoints}})),e.on("dragmove.edit",(e=>{const t=e.target;t instanceof ai().Shape&&(function(e,t){const n=t.getParent();!function(e,t,n){let i=!1;e.x()<t.getX()?(e.x(t.getX()),i=!0):e.x()>n.getX()&&(e.x(n.getX()),i=!0),e.y()<t.getY()?(e.y(t.getY()),i=!0):e.y()>n.getY()&&(e.y(n.getY()),i=!0)}(t,new R(-n.x(),-n.y()),new R(e.x-n.x(),e.y-n.y()))}(this.#Jt.getBaseSize(),t),void 0!==this.#_t.constrainAnchorMove&&this.#_t.constrainAnchorMove(t),this.#_t.updateAnnotationOnAnchorMove(this.#Ut,t),this.#_t.updateShapeGroupOnAnchorMove(this.#Ut,t,this.#Rt.getStyle()),t.getLayer()?t.getLayer().draw():c.warn("No layer to draw the anchor!"),e.cancelBubble=!0)})),e.on("dragend.edit",(e=>{const n={mathShape:this.#Ut.mathShape,referencePoints:this.#Ut.referencePoints},i=new ci(this.#Ut,t,n,this.#Jt.getDrawController());this.#Rt.addToUndoStack(i),this.#Zt({type:"annotationupdate",data:this.#Ut,dataid:this.#Jt.getDataId(),keys:Object.keys(n)}),t={mathShape:n.mathShape,referencePoints:n.referencePoints},e.cancelBubble=!0})),e.on("mousedown touchstart",(e=>{e.target.moveToTop()})),e.on("mouseover.edit",(e=>{const t=e.target;t instanceof ai().Shape&&(t.stroke("#ddd"),t.getLayer()?t.getLayer().draw():c.warn("No layer to draw the anchor!"))})),e.on("mouseout.edit",(e=>{const t=e.target;t instanceof ai().Shape&&(t.stroke("#999"),t.getLayer()?t.getLayer().draw():c.warn("No layer to draw the anchor!"))}))}#on(e){e.off("dragstart.edit"),e.off("dragmove.edit"),e.off("dragend.edit"),e.off("mousedown touchstart"),e.off("mouseover.edit"),e.off("mouseout.edit")}}class vi{#an;constructor(){this.createTrashIcon()}createTrashIcon(){this.#an=new(ai().Group);const e=new(ai().Line)({points:[-10,-10,10,10],stroke:"red"}),t=new(ai().Line)({points:[10,-10,-10,10],stroke:"red"});this.#an.width(20),this.#an.height(20),this.#an.add(e),this.#an.add(t)}activate(e){const t=e.getKonvaStage(),n=t.scale(),i=e.getKonvaLayer(),r={x:1/n.x,y:1/n.y};this.#an.x(t.offset().x+t.width()/(2*n.x)),this.#an.y(t.offset().y+t.height()/(15*n.y)),this.#an.scale(r),i.add(this.#an),i.draw()}changeChildrenColourOnTrashHover(e,t,n){if(this.isOverTrash(e))return this.changeGroupChildrenColour(this.#an,"orange"),void this.changeGroupChildrenColour(t,"red");this.changeGroupChildrenColour(this.#an,"red"),this.changeGroupChildrenColour(t,n)}changeGroupChildrenColour(e,t){e.getChildren().forEach((function(e){e instanceof ai().Shape&&void 0!==e.stroke&&e.stroke(t)}))}remove(){this.#an.remove()}isOverTrash(e){const t=this.#an.width()*Math.abs(this.#an.scaleX())/2,n=this.#an.height()*Math.abs(this.#an.scaleY())/2;return Math.abs(e.x-this.#an.x())<t&&Math.abs(e.y-this.#an.y())<n}}class Ii{#Rt;#sn;#an;#ln="pointer";#cn;#un;#Zt;constructor(e,t){this.#Rt=e,this.#Zt=t,this.#sn=new Ci(e,t),this.#an=new vi}setEditorShape(e,t){const n=t.getDrawController();e&&e instanceof ai().Shape&&e!==this.#sn.getShape()&&n.isAnnotationGroupEditable()&&(this.#sn.disable(),this.#sn.setShape(e,t,t.getDrawController().getAnnotation(e.getParent().id())),this.#sn.enable())}getEditorShapeGroup(){let e;if(!this.#sn.isActive()||(e=this.#sn.getShape().getParent(),e instanceof ai().Group))return e}getEditorAnnotation(){let e;return this.#sn.isActive()&&(e=this.#sn.getAnnotation()),e}disableAndResetEditor(){this.#sn.disable(),this.#sn.reset()}#dn(e,t){const n=t.getKonvaStage();return{x:n.offset().x+e.x/n.scale().x,y:n.offset().y+e.y/n.scale().y}}storeMouseOverCursor(e){this.#ln=e}#hn(){this.#cn=document.body.style.cursor,document.body.style.cursor=this.#ln,this.#un.opacity(.75)}onMouseOutShapeGroup(){void 0!==this.#cn&&(document.body.style.cursor=this.#cn,this.#cn=void 0),void 0!==this.#un&&this.#un.opacity(1)}#Sn(e){e.on("mouseover",(()=>{this.#un=e,this.#hn()})),e.on("mouseout",(()=>{this.onMouseOutShapeGroup(),this.#un=void 0}))}#gn(e){e.off("mouseover"),e.off("mouseout")}addShapeGroupListeners(e,t,n){this.#Sn(e),this.#pn(e,t,n),this.#mn(e,t,n),e.on("dblclick",(()=>{const e=t.textExpr,i=t=>{const i=t.textExpr,r=new ci(t,{textExpr:e},{textExpr:i},n.getDrawController());this.#Rt.addToUndoStack(r),r.execute()};void 0!==L.openRoiDialog?L.openRoiDialog(t,i):function(e,t){const n=prompt("Label",e.textExpr);null!==n&&(e.textExpr=n,t(e))}(t,i)}))}#pn(e,t,n){const i=n.getKonvaLayer(),r=e.getChildren(Si)[0];if(!(r instanceof ai().Shape))return;let o,a,s,l;r.draggable(!0),r.on("dragstart.draw",(e=>{l=r.stroke(),o={x:r.x(),y:r.y()},a={x:e.target.x(),y:e.target.y()},s={mathShape:t.mathShape,referencePoints:t.referencePoints},this.#an.activate(n),this.#sn.setAnchorsActive(!1),i.draw()})),r.on("dragmove.draw",(o=>{const s=function(e,t){return{min:new R(0,0),max:new R(e.x-Math.abs(t.width()),e.y-Math.abs(t.height()))}}(n.getBaseSize(),r);if(s&&!function(e,t,n){const i=e.getClientRect({relativeTo:e.getParent()});return i.x>t.getX()&&i.x<n.getX()&&i.y>t.getY()&&i.y<n.getY()}(r,s.min,s.max))return r.x(a.x),void r.y(a.y);const c={x:o.target.x()-a.x,y:o.target.y()-a.y},u=e.getChildren(),d=void 0===t.labelPosition;for(const e of u)e===o.target||"label"===e.name()&&!d||"connector"===e.name()||e.move(c);a={x:o.target.x(),y:o.target.y()};const h=t.getFactory();h.updateAnnotationOnTranslation(t,c),h.updateLabelContent(t,e,this.#Rt.getStyle()),h.updateConnector(e);const S=jn(o.evt),g={x:S.getX(),y:S.getY()},p=this.#dn(g,n);this.#an.changeChildrenColourOnTrashHover(p,e,l),i.draw()})),r.on("dragend.draw",(a=>{if(this.#an.remove(),void 0===a||void 0===a.evt)return;const c=r.x(),u=r.y(),d=jn(a.evt),h={x:d.getX(),y:d.getY()},S=this.#dn(h,n);if(this.#an.isOverTrash(S)){e.x(o.x),e.y(o.y),this.#sn.disable(),this.#sn.reset(),this.#an.changeGroupChildrenColour(e,l),t.mathShape=s.mathShape,t.referencePoints=s.referencePoints;const i=new li(t,n.getDrawController());this.#Rt.addToUndoStack(i),i.execute(),this.onMouseOutShapeGroup()}else{const e={x:c-o.x,y:u-o.y};if(0!==e.x||0!==e.y){const e={mathShape:t.mathShape,referencePoints:t.referencePoints},i=new ci(t,s,e,n.getDrawController());this.#Rt.addToUndoStack(i),this.#Zt({type:"annotationupdate",data:t,dataid:n.getDataId(),keys:Object.keys(e)}),s={mathShape:e.mathShape,referencePoints:e.referencePoints}}this.#sn.setAnchorsActive(!0),this.#sn.resetAnchors()}i.draw(),o={x:r.x(),y:r.y()}}))}#mn(e,t,n){const i=e.getChildren(hi)[0];if(!(i instanceof ai().Label))return;let r,o;i.draggable(!0),i.on("dragstart.draw",(()=>{r={x:i.x(),y:i.y()},o=t.labelPosition})),i.on("dragmove.draw",(()=>{t.getFactory().updateConnector(e)})),i.on("dragend.draw",(()=>{const e=i.x()-r.x,a=i.y()-r.y;if(0!==e||0!==a){const e=new R(i.x(),i.y());t.labelPosition=e;const r=new ci(t,{labelPosition:o},{labelPosition:e},n.getDrawController());this.#Rt.addToUndoStack(r),this.#Zt({type:"annotationupdate",data:t,dataid:n.getDataId(),keys:["labelPosition"]}),o=e}r={x:i.x(),y:i.y()}}))}removeShapeListeners(e){this.#gn(e),e.off("dblclick");const t=e.getChildren(Si)[0];t instanceof ai().Shape&&(t.draggable(!1),t.off("dragstart.draw"),t.off("dragmove.draw"),t.off("dragend.draw"));const n=e.getChildren(hi)[0];n instanceof ai().Label&&(n.draggable(!1),n.off("dragstart.draw"),n.off("dragend.draw"))}}class Ti{#fn=[];constructor(e){void 0!==e&&(this.#fn=e)}getPoint(e){return this.#fn[e]}getPoints(){return this.#fn}getLength(){return this.#fn.length}addPoint(e){this.#fn.push(e)}addPoints(e){this.#fn=this.#fn.concat(e)}getCentroid(){let e=0,t=0,n=0;for(let i=0;i<this.#fn.length;++i){const r=this.#fn[i];let o;o=i===this.#fn.length-1?this.#fn[0]:this.#fn[i+1];const a=r.getX()*o.getY()-o.getX()*r.getY();e+=a,t+=(r.getX()+o.getX())*a,n+=(r.getY()+o.getY())*a}e*=.5;const i=1/(6*e);return t*=i,n*=i,new R(t,n)}}var Li=o(324),Pi=o.n(Li);class wi{constructor(e,t){this.pointArray=e?e.slice():[],this.controlPointIndexArray=t?t.slice():[]}getPoint(e){return this.pointArray[e]}isControlPoint(e){const t=this.pointArray.indexOf(e);if(-1!==t)return-1!==this.controlPointIndexArray.indexOf(t);throw new Error("Error: isControlPoint called with not in list point.")}getLength(){return this.pointArray.length}addPoint(e){this.pointArray.push(e)}addControlPoint(e){const t=this.pointArray.indexOf(e);if(-1===t)throw new Error("Cannot mark a non registered point as control point.");this.controlPointIndexArray.push(t)}addPoints(e){this.pointArray=this.pointArray.concat(e)}appenPath(e){const t=this.pointArray.length;this.pointArray=this.pointArray.concat(e.pointArray);const n=[];for(let i=0;i<e.controlPointIndexArray.length;++i)n[i]=e.controlPointIndexArray[i]+t;this.controlPointIndexArray=this.controlPointIndexArray.concat(n)}}class Oi{constructor(e,t){this.bucketCount=1<<e,this.mask=this.bucketCount-1,this.size=0,this.loc=0,this.cost=void 0!==t?t:function(e){return e},this.buckets=this.buildArray(this.bucketCount)}push(e){const t=this.getBucket(e);e.next=this.buckets[t],this.buckets[t]=e,this.size++}pop(){if(0===this.size)throw new Error("Cannot pop, bucketQueue is empty.");for(;null===this.buckets[this.loc];)this.loc=(this.loc+1)%this.bucketCount;const e=this.buckets[this.loc];return this.buckets[this.loc]=e.next,e.next=null,this.size--,e}remove(e){if(!e)return!1;const t=this.getBucket(e);let n=this.buckets[t];for(;null!==n&&(null===n.next||e.x!==n.next.x||e.y!==n.next.y);)n=n.next;return null!==n&&(n.next=n.next.next,this.size--,!0)}isEmpty(){return 0===this.size}getBucket(e){return this.cost(e)&this.mask}buildArray(e){const t=new Array(e);for(let e=0;e<t.length;e++)t[e]=null;return t}}const Ai=2/(3*Math.PI);function bi(e,t,n,i,r){const o=e[i][n],a=t[i][n];let s=Math.sqrt(o*o+a*a);s=Math.max(s,1e-100),r.x=o/s,r.y=a/s}class xi{constructor(){this.width=-1,this.height=-1,this.curPoint=null,this.searchGranBits=8,this.searchGran=1<<this.searchGranBits,this.pointsPerPost=500,this.greyscale=null,this.laplace=null,this.gradient=null,this.gradX=null,this.gradY=null,this.parents=null,this.working=!1,this.trained=!1,this.trainingPoints=null,this.edgeWidth=2,this.trainingLength=32,this.edgeGran=256,this.edgeTraining=null,this.gradPointsNeeded=32,this.gradGran=1024,this.gradTraining=null,this.insideGran=256,this.insideTraining=null,this.outsideGran=256,this.outsideTraining=null}getTrainingIdx(e,t){return Math.round((e-1)*t)}getTrainedEdge(e){return this.edgeTraining[this.getTrainingIdx(this.edgeGran,e)]}getTrainedGrad(e){return this.gradTraining[this.getTrainingIdx(this.gradGran,e)]}getTrainedInside(e){return this.insideTraining[this.getTrainingIdx(this.insideGran,e)]}getTrainedOutside(e){return this.outsideTraining[this.getTrainingIdx(this.outsideGran,e)]}setWorking(e){this.working=e}setDimensions(e,t){this.width=e,this.height=t}setData(e){if(-1===this.width||-1===this.height)throw new Error("Dimensions have not been set.");this.greyscale=function(e,t,n){const i={data:[]};for(let r=0;r<n;r++){i.data[r]=[];for(let n=0;n<t;n++){const o=4*(r*t+n);i.data[r][n]=(e[o]+e[o+1]+e[o+2])/765}}return i.dx=function(e,t){return e+1===this.data[t].length&&e--,this.data[t][e+1]-this.data[t][e]},i.dy=function(e,t){return t+1===this.data.length&&t--,this.data[t][e]-this.data[t+1][e]},i.gradMagnitude=function(e,t){const n=this.dx(e,t),i=this.dy(e,t);return Math.sqrt(n*n+i*i)},i.laplace=function(e,t){let n=-16*this.data[t][e];return n+=this.data[t-2][e],n+=this.data[t-1][e-1]+2*this.data[t-1][e]+this.data[t-1][e+1],n+=this.data[t][e-2]+2*this.data[t][e-1]+2*this.data[t][e+1]+this.data[t][e+2],n+=this.data[t+1][e-1]+2*this.data[t+1][e]+this.data[t+1][e+1],n+=this.data[t+2][e],n},i}(e,this.width,this.height),this.laplace=function(e){const t=[];t[0]=[],t[1]=[];for(let n=1;n<e.data.length;n++)t[0][n]=1,t[1][n]=1;for(let n=2;n<e.data.length-2;n++){t[n]=[],t[n][0]=1,t[n][1]=1;for(let i=2;i<e.data[n].length-2;i++)t[n][i]=e.laplace(i,n)>.33?0:1;t[n][e.data[n].length-2]=1,t[n][e.data[n].length-1]=1}t[e.data.length-2]=[],t[e.data.length-1]=[];for(let n=1;n<e.data.length;n++)t[e.data.length-2][n]=1,t[e.data.length-1][n]=1;return t}(this.greyscale),this.gradient=function(e){const t=[];let n=0,i=0,r=0;for(r=0;r<e.data.length-1;r++){for(t[r]=[],i=0;i<e.data[r].length-1;i++)t[r][i]=e.gradMagnitude(i,r),n=Math.max(t[r][i],n);t[r][e.data[r].length-1]=t[r][e.data.length-2]}t[e.data.length-1]=[];for(let n=0;n<t[0].length;n++)t[e.data.length-1][n]=t[e.data.length-2][n];for(r=0;r<t.length;r++)for(i=0;i<t[r].length;i++)t[r][i]=1-t[r][i]/n;return t}(this.greyscale),this.gradX=function(e){const t=[];for(let n=0;n<e.data.length;n++){t[n]=[];for(let i=0;i<e.data[n].length-1;i++)t[n][i]=e.dx(i,n);t[n][e.data[n].length-1]=t[n][e.data[n].length-2]}return t}(this.greyscale),this.gradY=function(e){const t=[];for(let n=0;n<e.data.length-1;n++){t[n]=[];for(let i=0;i<e.data[n].length;i++)t[n][i]=e.dy(i,n)}t[e.data.length-1]=[];for(let n=0;n<e.data[0].length;n++)t[e.data.length-1][n]=t[e.data.length-2][n];return t}(this.greyscale);const t=function(e,t,n,i){const r={inside:[],outside:[]},o={x:-1,y:-1};for(let a=0;a<t.length;a++){r.inside[a]=[],r.outside[a]=[];for(let s=0;s<t[a].length;s++){bi(t,n,s,a,o);let l=Math.round(s+e*o.y),c=Math.round(a-e*o.x),u=Math.round(s-e*o.y),d=Math.round(a+e*o.x);l=Math.max(Math.min(l,t[a].length-1),0),u=Math.max(Math.min(u,t[a].length-1),0),c=Math.max(Math.min(c,t.length-1),0),d=Math.max(Math.min(d,t.length-1),0),r.inside[a][s]=i.data[c][l],r.outside[a][s]=i.data[d][u]}}return r}(this.edgeWidth,this.gradX,this.gradY,this.greyscale);this.inside=t.inside,this.outside=t.outside,this.edgeTraining=[],this.gradTraining=[],this.insideTraining=[],this.outsideTraining=[]}findTrainingPoints(e){const t=[];if(null!==this.parents)for(let n=0;n<this.trainingLength&&e;n++)t.push(e),e=this.parents[e.y][e.x];return t}resetTraining(){this.trained=!1}doTraining(e){if(this.trainingPoints=this.findTrainingPoints(e),this.trainingPoints.length<8)return;const t=[];this.calculateTraining(t,this.edgeGran,this.greyscale,this.edgeTraining),this.calculateTraining(t,this.gradGran,this.gradient,this.gradTraining),this.calculateTraining(t,this.insideGran,this.inside,this.insideTraining),this.calculateTraining(t,this.outsideGran,this.outside,this.outsideTraining),this.trainingPoints.length<this.gradPointsNeeded&&this.addInStaticGrad(this.trainingPoints.length,this.gradPointsNeeded),this.trained=!0}calculateTraining(e,t,n,i){let r=0;for(e.length=t,r=0;r<t;r++)e[r]=0;let o=1;for(r=0;r<this.trainingPoints.length;r++){const i=this.trainingPoints[r],a=this.getTrainingIdx(t,n[i.y][i.x]);e[a]+=1,o=Math.max(o,e[a])}for(r=0;r<t;r++)e[r]=1-e[r]/o;!function(e,t){t[0]=.4*e[0]+.5*e[1]+.1*e[1],t[1]=.25*e[0]+.4*e[1]+.25*e[2]+.1*e[3];for(let n=2;n<e.length-2;n++)t[n]=.05*e[n-2]+.25*e[n-1]+.4*e[n]+.25*e[n+1]+.05*e[n+2];const n=e.length;t[n-2]=.25*e[n-1]+.4*e[n-2]+.25*e[n-3]+.1*e[n-4],t[n-1]=.4*e[n-1]+.5*e[n-2]+.1*e[n-3]}(e,i)}addInStaticGrad(e,t){for(let n=0;n<this.gradGran;n++)this.gradTraining[n]=Math.min(this.gradTraining[n],1-n*(t-e)/(t*this.gradGran))}gradDirection(e,t,n,i){return function(e,t,n,i,r,o){const a={x:-1,y:-1},s={x:-1,y:-1};bi(e,t,n,i,a),bi(e,t,r,o,s);let l=a.y*(r-n)-a.x*(o-i),c=s.y*(r-n)-s.x*(o-i);return l<0&&(l=-l,c=-c),n!==r&&i!==o&&(l*=Math.SQRT1_2,c*=Math.SQRT1_2),Ai*(Math.acos(l)+Math.acos(c))}(this.gradX,this.gradY,e,t,n,i)}dist(e,t,n,i){let r=this.gradient[i][n];e!==n&&t!==i||(r*=Math.SQRT1_2);const o=this.laplace[i][n],a=this.gradDirection(e,t,n,i);return this.trained?.3*this.getTrainedGrad(r)+.3*o+.1*(a+this.getTrainedEdge(this.greyscale.data[t][e])+this.getTrainedInside(this.inside[t][e])+this.getTrainedOutside(this.outside[t][e])):.43*r+.43*o+.11*a}adj(e){const t=[],n=Math.max(e.x-1,0),i=Math.max(e.y-1,0),r=Math.min(e.x+1,this.greyscale.data[0].length-1),o=Math.min(e.y+1,this.greyscale.data.length-1);let a=0;for(let s=i;s<=o;s++)for(let i=n;i<=r;i++)i===e.x&&s===e.y||(t[a++]={x:i,y:s});return t}#Dn=e=>Math.round(this.searchGran*this.cost[e.y][e.x]);setPoint(e){this.setWorking(!0),this.curPoint=e;let t=0,n=0;for(this.visited=[],n=0;n<this.height;n++)for(this.visited[n]=[],t=0;t<this.width;t++)this.visited[n][t]=!1;for(this.parents=[],n=0;n<this.height;n++)this.parents[n]=[];for(this.cost=[],n=0;n<this.height;n++)for(this.cost[n]=[],t=0;t<this.width;t++)this.cost[n][t]=Number.MAX_VALUE;this.cost[e.y][e.x]=0,this.pq=new Oi(this.searchGranBits,this.#Dn),this.pq.push(e)}doWork(){if(!this.working)return;this.timeout=null;let e=0;const t=[];for(;!this.pq.isEmpty()&&e<this.pointsPerPost;){const n=this.pq.pop();t.push(n),t.push(this.parents[n.y][n.x]),this.visited[n.y][n.x]=!0;const i=this.adj(n);for(let e=0;e<i.length;e++){const t=i[e],r=this.cost[n.y][n.x]+this.dist(n.x,n.y,t.x,t.y);r<this.cost[t.y][t.x]&&(this.cost[t.y][t.x]!==Number.MAX_VALUE&&this.pq.remove(t),this.cost[t.y][t.x]=r,this.parents[t.y][t.x]=n,this.pq.push(t))}e++}return t}}class Ri{#yn;constructor(e){this.#yn=e}getPosition(e){let t=e.labelPosition;return void 0===t&&(t=this.#yn(e)),t}create(e,t){const n=new(ai().Text)({fontSize:t.getFontSize(),fontFamily:t.getFontFamily(),fill:e.colour,padding:t.getTextPadding(),shadowColor:t.getShadowLineColour(),shadowOffset:t.getShadowOffset(),name:"text"}),i=e.getText();n.setText(i);const r=t.applyZoomScale(1),o={x:2*r.x,y:2*r.y},a=this.getPosition(e),s=new(ai().Label)({x:a.getX(),y:a.getY(),scale:o,visible:0!==i.length,name:"label"});return s.add(n),s.add(new(ai().Tag)({fill:e.colour,opacity:t.getTagOpacity()})),s}updatePosition(e,t){const n=t.getChildren((function(e){return"label"===e.name()}))[0];if(!(n instanceof ai().Label))return;const i=this.getPosition(e);n.position({x:i.getX(),y:i.getY()})}getLabelAnchorsPosition(e){const t=e.x(),n=e.y(),i=e.width()*e.scale().x,r=e.height()*e.scale().y;return[new R(t+i/2,n),new R(t,n+r/2),new R(t+i/2,n+r),new R(t+i,n+r/2)]}getClosestPoints(e,t){let n=e[0].getDistance(t[0]),i=e[0],r=t[0];for(const o of e)for(const e of t){const t=o.getDistance(e);t<n&&(n=t,i=o,r=e)}return[i,r]}getConnector(e,t,n){const i=this.getLabelAnchorsPosition(t),r=this.getClosestPoints(e,i);return new(ai().Line)({points:[r[0].getX(),r[0].getY(),r[1].getX(),r[1].getY()],stroke:t.getText().fill(),strokeWidth:n.getStrokeWidth(),strokeScaleEnabled:!1,visible:t.visible(),dash:[10,7],name:"connector"})}updateConnector(e,t){const n=e.getChildren((function(e){return"label"===e.name()}))[0];if(!(n instanceof ai().Label))return;const i=this.getLabelAnchorsPosition(n),r=this.getClosestPoints(t,i),o=e.getChildren((function(e){return"connector"===e.name()}))[0];o instanceof ai().Line&&o.points([r[0].getX(),r[0].getY(),r[1].getX(),r[1].getY()])}updateContent(e,t){const n=t.getChildren((function(e){return"label"===e.name()}))[0];if(!(n instanceof ai().Label))return;const i=e.getText();n.getText().setText(i),n.visible()&&n.visible(0!==i.length)}}class Fi{#Cn;#vn;constructor(e,t){this.#Cn=e,this.#vn=t}getCenter(){return this.#Cn}getCentroid(){return this.#Cn}getRadius(){return this.#vn}equals(e){return null!==e&&this.getCenter().equals(e.getCenter())&&this.getRadius()===e.getRadius()}getSurface(){return Math.PI*this.getRadius()*this.getRadius()}getWorldSurface(e){return function(e,t,n){let i=null;return null!==t&&null!==n&&(i=e*t*n),i}(this.getSurface(),e.x,e.y)}getRound(){const e=this.getCenter().getX(),t=this.getCenter().getY(),n=this.getRadius(),i=Math.pow(n,2),r=t+n,o=[];for(let a=t-n;a<r;++a){const n=i-Math.pow(a-t,2);if(Math.abs(n)<1e-7)continue;const r=Math.sqrt(n);r<.5||o.push([[Math.round(e-r),Math.round(a)],[Math.round(e+r),Math.round(a)]])}return o}quantify(e,t,n){const i={},r=e.get2DSpacing();i.radius={value:this.getRadius()*r.x,unit:"unit.mm"};const o=this.getWorldSurface(r);if(null!==o&&(i.surface={value:o/100,unit:"unit.cm2"}),e.canQuantifyImage()){const r=this.getRound();if(0!==r.length){const o=e.getImageVariableRegionValues(r,t),a=e.getPixelUnit(),s=Ke(o,n);i.min={value:s.min,unit:a},i.max={value:s.max,unit:a},i.mean={value:s.mean,unit:a},i.stdDev={value:s.stdDev,unit:a},void 0!==s.median&&(i.median={value:s.median,unit:a}),void 0!==s.p25&&(i.p25={value:s.p25,unit:a}),void 0!==s.p75&&(i.p75={value:s.p75,unit:a})}}return i}}class Ei{#Cn;#In;#Tn;constructor(e,t,n){this.#Cn=e,this.#In=t,this.#Tn=n}getCenter(){return this.#Cn}getCentroid(){return this.#Cn}getA(){return this.#In}getB(){return this.#Tn}equals(e){return null!==e&&this.getCenter().equals(e.getCenter())&&this.getA()===e.getA()&&this.getB()===e.getB()}getSurface(){return Math.PI*this.getA()*this.getB()}getWorldSurface(e){return function(e,t,n){let i=null;return null!==t&&null!==n&&(i=e*t*n),i}(this.getSurface(),e.x,e.y)}getRound(){const e=this.getCenter().getX(),t=this.getCenter().getY(),n=this.getA(),i=this.getB(),r=n/i,o=Math.pow(i,2),a=t+i,s=[];for(let n=t-i;n<a;++n){const i=o-Math.pow(n-t,2);if(Math.abs(i)<1e-7)continue;const a=r*Math.sqrt(i);a<.5||s.push([[Math.round(e-a),Math.round(n)],[Math.round(e+a),Math.round(n)]])}return s}quantify(e,t,n){const i={},r=e.get2DSpacing();i.a={value:this.getA()*r.x,unit:"unit.mm"},i.b={value:this.getB()*r.y,unit:"unit.mm"};const o=this.getWorldSurface(r);if(null!==o&&(i.surface={value:o/100,unit:"unit.cm2"}),e.canQuantifyImage()){const r=this.getRound();if(0!==r.length){const o=e.getImageVariableRegionValues(r,t),a=e.getPixelUnit(),s=Ke(o,n);i.min={value:s.min,unit:a},i.max={value:s.max,unit:a},i.mean={value:s.mean,unit:a},i.stdDev={value:s.stdDev,unit:a},void 0!==s.median&&(i.median={value:s.median,unit:a}),void 0!==s.p25&&(i.p25={value:s.p25,unit:a}),void 0!==s.p75&&(i.p75={value:s.p75,unit:a})}}return i}}function qi(e,t,n){const i=e.getValues(),r=i.slice(),o=[],a=t[0],l=t[1],c=a/l,u=Math.pow(l,2),d=n[0],h=n[1];for(let e=0;e<l;++e){const t=Math.round(c*Math.sqrt(u-Math.pow(e,2))),n=i[h]+e,a=i[h]-e;for(let e=0;e<t;++e){const t=i[d]+e,l=i[d]-e;r[d]=t,r[h]=n,o.push(new s(r.slice())),a!==n&&(r[h]=a,o.push(new s(r.slice()))),l!==t&&(r[d]=l,r[h]=n,o.push(new s(r.slice())),a!==n&&(r[h]=a,o.push(new s(r.slice()))))}}return o}class Ui{#fn;constructor(e){if(e.length>3)throw new Error("Too many points for a protractor");this.#fn=e.slice(0,3)}getPoint(e){return this.#fn[e]}getLength(){return this.#fn.length}getCentroid(){return this.#fn[1]}quantify(e,t){const n={};if(3===this.#fn.length){let e=ei(new $n(this.#fn[0],this.#fn[1]),new $n(this.#fn[1],this.#fn[2]));e>180&&(e=360-e),n.angle={value:e,unit:"unit.degree"}}return n}}class Mi{#Et;#qt;constructor(e,t){this.#Et=new R(Math.min(e.getX(),t.getX()),Math.min(e.getY(),t.getY())),this.#qt=new R(Math.max(e.getX(),t.getX()),Math.max(e.getY(),t.getY()))}getBegin(){return this.#Et}getEnd(){return this.#qt}equals(e){return null!==e&&this.getBegin().equals(e.getBegin())&&this.getEnd().equals(e.getEnd())}getSurface(){const e=this.getBegin(),t=this.getEnd();return Math.abs(t.getX()-e.getX())*Math.abs(t.getY()-e.getY())}getWorldSurface(e){return function(e,t,n){let i=null;return null!==t&&null!==n&&(i=e*t*n),i}(this.getSurface(),e.x,e.y)}getRealWidth(){return this.getEnd().getX()-this.getBegin().getX()}getRealHeight(){return this.getEnd().getY()-this.getBegin().getY()}getWidth(){return Math.abs(this.getRealWidth())}getHeight(){return Math.abs(this.getRealHeight())}getRound(){return{min:new R(Math.round(this.getBegin().getX()),Math.round(this.getBegin().getY())),max:new R(Math.round(this.getEnd().getX()),Math.round(this.getEnd().getY()))}}getCentroid(){return new R(this.getBegin().getX()+this.getWidth()/2,this.getBegin().getY()+this.getHeight()/2)}quantify(e,t,n){const i={},r=e.get2DSpacing();i.width={value:this.getWidth()*r.x,unit:"unit.mm"},i.height={value:this.getHeight()*r.y,unit:"unit.mm"};const o=this.getWorldSurface(r);if(null!==o&&(i.surface={value:o/100,unit:"unit.cm2"}),e.canQuantifyImage()){const r=this.getRound(),o=e.getImageRegionValues(r.min,r.max,t),a=e.getPixelUnit(),s=Ke(o,n);i.min={value:s.min,unit:a},i.max={value:s.max,unit:a},i.mean={value:s.mean,unit:a},i.stdDev={value:s.stdDev,unit:a},void 0!==s.median&&(i.median={value:s.median,unit:a}),void 0!==s.p25&&(i.p25={value:s.p25,unit:a}),void 0!==s.p75&&(i.p75={value:s.p75,unit:a})}return i}}function Qi(e,t,n){const i=e.getValues(),r=i.slice(),o=[],a=t[0],l=Math.floor(a/2),c=t[1],u=Math.floor(c/2),d=n[0],h=n[1];for(let e=0;e<c;++e){r[h]=i[h]-u+e;for(let e=0;e<a;++e)r[d]=i[d]-l+e,o.push(new s(r.slice()))}return o}class Vi{#Ln=0;#Pn=0;getMin(){return this.#Ln}setMin(e){this.#Ln=e}getMax(){return this.#Pn}setMax(e){this.#Pn=e}getName(){return"Threshold"}#wn=null;setOriginalImage(e){this.#wn=e}getOriginalImage(){return this.#wn}update(){const e=this.getOriginalImage(),t=e.getDataRange().min;return e.transform((e=>e<this.getMin()||e>this.getMax()?t:e))}}class Ni{getName(){return"Sharpen"}#wn=null;setOriginalImage(e){this.#wn=e}getOriginalImage(){return this.#wn}update(){return this.getOriginalImage().convolute2D([0,-1,0,-1,5,-1,0,-1,0])}}class Bi{getName(){return"Sobel"}#wn=null;setOriginalImage(e){this.#wn=e}getOriginalImage(){return this.#wn}update(){const e=this.getOriginalImage(),t=e.convolute2D([1,0,-1,2,0,-2,1,0,-1]),n=e.convolute2D([1,2,1,0,0,0,-1,-2,-1]);return t.compose(n,(function(e,t){return Math.sqrt(e*e+t*t)}))}}class Gi{#On;#Ct;#Rt;constructor(e,t,n){this.#On=e,this.#Ct=t,this.#Rt=n}getName(){return"Filter-"+this.#On.getName()}execute(){this.#Rt.setImage(this.#Ct,this.#On.update()),this.#Rt.render(this.#Ct);const e={type:"filterrun",id:this.getName(),dataId:this.#Ct};this.onExecute(e)}undo(){this.#Rt.setImage(this.#Ct,this.#On.getOriginalImage()),this.#Rt.render(this.#Ct);const e={type:"filterundo",id:this.getName(),dataid:this.#Ct};this.onUndo(e)}onExecute(e){}onUndo(e){}}const ki={},Hi={},zi={WindowLevel:class{#Rt;#An=!1;#bn;#xn;constructor(e){this.#Rt=e,this.#xn=new Jn(e)}#Rn(e,t){const n=this.#Rt.getLayerGroupByDivId(t).getActiveViewLayer();void 0!==n&&n.getViewController().isMonochrome()&&(this.#An=!0,this.#bn=e)}#Fn(e,t){if(!this.#An)return;const n=this.#Rt.getLayerGroupByDivId(t).getActiveViewLayer();if(void 0===n)return;const i=n.getViewController(),r=e.getX()-this.#bn.getX(),o=this.#bn.getY()-e.getY(),a=i.getImageRescaledDataRange(),s=.01*(a.max-a.min),l=i.getWindowLevel().center,c=i.getWindowLevel().width,d=l+Math.round(o*s);let h=c+Math.round(r*s);var S;h=(S=h)<1?1:S;const g=new u(d,h);i.setWindowLevel(g),this.#bn=e}#En(){this.#An&&(this.#An=!1)}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Rn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup=e=>{this.#En()};mouseout=e=>{this.#En()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Rn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchend=e=>{this.#En()};dblclick=e=>{const t=Ki(e),n=jn(e),i=this.#Rt.getLayerGroupByDivId(t.groupDivId).getActiveViewLayer();if(void 0===i)return;const r=i.displayToPlaneIndex(n),o=i.getViewController();if(!o.isMonochrome())return;const a=this.#Rt.getData(i.getDataId()).image,s=new u(a.getRescaledValueAtIndex(o.getCurrentIndex().getWithNew2D(r.get(0),r.get(1))),o.getWindowLevel().width);o.setWindowLevel(s)};wheel=e=>{this.#xn.wheel(e)};keydown=e=>{e.context="WindowLevel",this.#Rt.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Scroll:class{#Rt;#An=!1;#bn;#xn;#qn;#Un=!1;#Mn;constructor(e){this.#Rt=e,this.#xn=new Jn(e)}#Qn(e){let t=e.getActiveViewLayer();if(void 0===t){const n=e.getActiveDrawLayer();if(void 0===n)return void c.warn("No draw layer to do scroll");t=e.getViewLayerById(n.getReferenceLayerId())}return t}#Rn(e,t){this.#Vn();const n=this.#Rt.getLayerGroupByDivId(t),i=this.#Qn(n);if(void 0===i)return void c.warn("No view layer to start scroll");const r=i.getViewController();r.isPlaying()&&r.stop();const o=i.displayToPlanePos(e),a=r.getPositionFromPlanePoint(o);r.setCurrentPosition(a),this.#An=!0,this.#bn=e}#Fn(e,t){if(!this.#An)return void(this.#Un&&this.#Nn(e,t));const n=this.#Rt.getLayerGroupByDivId(t),i=n.getPositionHelper(),r=e.getY()-this.#bn.getY(),o=Math.abs(r)>15,a=e.getX()-this.#bn.getX(),s=Math.abs(a)>15;o&&n.canScroll()?r>0?i.decrementPositionAlongScroll():i.incrementPositionAlongScroll():s&&n.moreThanOne(3)&&(a>0?i.incrementPosition(3):i.decrementPosition(3)),(s||o)&&(this.#bn=e)}#En(){this.#An&&(this.#An=!1)}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Rn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup=e=>{this.#En()};mouseout=e=>{this.#En(),this.#Vn()};touchstart=e=>{this.#qn=setTimeout((()=>{this.dblclick(e)}),500);const t=Xn(e),n=Ki(e);this.#Rn(t[0],n.groupDivId)};touchmove=e=>{null!==this.#qn&&(clearTimeout(this.#qn),this.#qn=null);const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchend=e=>{null!==this.#qn&&(clearTimeout(this.#qn),this.#qn=null),this.#En()};wheel=e=>{this.#xn.wheel(e)};keydown=e=>{e.context="Scroll",this.#Rt.onKeydown(e)};dblclick=e=>{const t=Ki(e),n=this.#Rt.getLayerGroupByDivId(t.groupDivId).getActiveViewLayer();void 0!==n&&n.getViewController().play()};#Nn(e,t){const n=this.#Rt.getLayerGroupByDivId(t);this.#Mn=t,n.showTooltip(e)}#Vn(){void 0!==this.#Mn&&(this.#Rt.getLayerGroupByDivId(this.#Mn).removeTooltipDiv(),this.#Mn=void 0)}activate(e){e||this.#Vn()}setFeatures(e){void 0!==e.displayTooltip&&(this.#Un=e.displayTooltip)}init(){}},ZoomAndPan:class{#Rt;#An=!1;#bn;#Bn;#Gn;#kn;constructor(e){this.#Rt=e}#Qn(e){let t=e.getActiveViewLayer();if(void 0===t){const n=e.getActiveDrawLayer();if(void 0===n)return void c.warn("No draw layer to do zoom/pan");t=e.getViewLayerById(n.getReferenceLayerId())}return t}#Rn(e){this.#An=!0,this.#bn=e,this.#Bn=!1}#Hn=e=>{this.#An=!0,this.#bn=e[0],this.#Bn=!1,this.#Gn=new $n(e[0],e[1]),this.#kn=this.#Gn.getMidpoint()};#Fn(e,t){if(!this.#An)return;this.#Bn=!0;const n=e.getX()-this.#bn.getX(),i=e.getY()-this.#bn.getY(),r=this.#Rt.getLayerGroupByDivId(t),o=this.#Qn(r);if(void 0===o)return void c.warn("No view layer to update zoom/pan");const a=o.getViewController(),s=o.displayToPlaneScale(new R(n,i)),l=a.getOffset3DFromPlaneOffset({x:s.getX(),y:s.getY()});r.addTranslation({x:l.getX(),y:l.getY(),z:l.getZ()}),r.draw(),this.#bn=e}#zn=(e,t)=>{if(!this.#An)return;this.#Bn=!0;const n=new $n(e[0],e[1]).getLength()/this.#Gn.getLength(),i=this.#Rt.getLayerGroupByDivId(t),r=i.getPositionHelper();if(1===n){const t=e[0].getY()-this.#bn.getY();if(Math.abs(t)<15)return;i.canScroll()&&(t>0?r.incrementPositionAlongScroll():r.decrementPositionAlongScroll())}else{const e=(n-1)/10;if(Math.abs(e)%.1<=.05&&void 0!==this.#kn){const t=this.#Qn(i);if(void 0===t)return void c.warn("No view layer to do touch zoom/pan");const n=t.getViewController(),r=t.displayToMainPlanePos(this.#kn),o=n.getPlanePositionFromPlanePoint(r);i.addScale(e,o),i.draw()}}};#Wn(e,t){const n=this.#Rt.getLayerGroupByDivId(t),i=this.#Qn(n);if(void 0===i)return void c.warn("No view layer to set current position");const r=i.getViewController(),o=i.displayToPlanePos(e),a=r.getPositionFromPlanePoint(o);r.setCurrentPosition(a)}#En(){this.#An&&(this.#An=!1)}mousedown=e=>{const t=jn(e);this.#Rn(t)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup=e=>{if(!this.#Bn){const t=jn(e),n=Ki(e);this.#Wn(t,n.groupDivId)}this.#En()};mouseout=e=>{this.#En()};touchstart=e=>{const t=Xn(e);1===t.length?this.#Rn(t[0]):2===t.length&&this.#Hn(t)};touchmove=e=>{const t=Xn(e),n=Ki(e);1===t.length?this.#Fn(t[0],n.groupDivId):2===t.length&&this.#zn(t,n.groupDivId)};touchend=e=>{if(!this.#Bn){const t=jn(e),n=Ki(e);this.#Wn(t,n.groupDivId)}this.#En()};wheel=e=>{e.preventDefault();const t=-e.deltaY/500,n=Ki(e),i=jn(e),r=this.#Rt.getLayerGroupByDivId(n.groupDivId),o=this.#Qn(r);if(void 0===o)return void c.warn("No view layer to do wheel zoom/pan");const a=o.getViewController(),s=o.displayToMainPlanePos(i),l=a.getPlanePositionFromPlanePoint(s);r.addScale(t,l),r.draw()};keydown=e=>{e.context="ZoomAndPan",this.#Rt.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Opacity:class{#Rt;#An=!1;#bn;#xn;constructor(e){this.#Rt=e,this.#xn=new Jn(e)}#Rn(e){this.#An=!0,this.#bn=e}#Fn(e,t){if(!this.#An)return;const n=e.getX()-this.#bn.getX();if(Math.abs(n)>15){const i=this.#Rt.getLayerGroupByDivId(t).getActiveLayer(),r=i.getOpacity();i.setOpacity(r+n/200),i.draw(),this.#bn=e}}#En(){this.#An&&(this.#An=!1)}mousedown=e=>{const t=jn(e);this.#Rn(t)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup=e=>{this.#En()};mouseout=e=>{this.#En()};touchstart=e=>{const t=Xn(e);this.#Rn(t[0])};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchend=e=>{this.#En()};wheel=e=>{this.#xn.wheel(e)};keydown=e=>{e.context="Opacity",this.#Rt.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Draw:class{#Rt;#xn;#Yn;#Xn=!1;#jn=null;#_t=null;#Zn=null;#_n;#fn=[];#Kn=null;#Jn=!0;#$n=[];#ei;#ti=!1;#z={};#ni=!1;#ii=[];constructor(e){this.#Rt=e,this.#xn=new Jn(e),this.#ei=new Ii(e,this.#Fe),this.#Yn=e.getStyle()}#ri(e,t){const n=this.#Rt.getLayerGroupByDivId(t);let i=n.getActiveDrawLayer();if(void 0===i){const e=n.getActiveViewLayer().getDataId(),r=this.#Rt.getData(e).image.getMeta().SeriesInstanceUID;if(this.#$n.includes(r))return void this.#Fe({type:"warn",message:"Cannot create draw layer, data is in black list"});const o=this.#Rt.createAnnotationData(e);this.#Rt.addAndRenderAnnotationData(o,t,e),i=n.getActiveDrawLayer(),i.setShapeHandler(this.#ei),n.setActiveLayerByDataId(i.getDataId())}const r=i.getDrawController().getAnnotationGroup(),o=i.getKonvaStage();if(this.#Yn.setZoomScale(o.scale()),r.isEditable()){const t=o.getIntersection({x:e.getX(),y:e.getY()});t?this.#oi(i,t):this.#ai(n,e)}}#Qn(e){const t=e.getActiveDrawLayer();if(void 0!==t)return e.getViewLayerById(t.getReferenceLayerId());c.warn("No draw layer to do draw")}#ai(e,t){this.#ei.disableAndResetEditor(),this.#si();const n=this.#Qn(e);void 0!==n?(this.#Kn=n.displayToPlanePos(t),this.#fn.push(this.#Kn)):c.warn("No view layer to start shape")}#si(){this.#Xn=!0,this.#_t=new this.#jn[this.#_n],this.#fn=[]}#li(){this.#Xn=!1,this.#fn=[]}#oi(e,t){let n=t.getParent();t instanceof ai().Tag&&(n=n.getParent());const i=n.find(".shape")[0];i instanceof ai().Shape&&(this.#Fe({type:"annotationselect",annotationid:n.id(),dataid:e.getDataId()}),this.#ei.setEditorShape(i,e))}#ci(e,t){const n=this.#Rt.getLayerGroupByDivId(t),i=this.#Qn(n);if(void 0===i)return void c.warn("No view layer to update shape");const r=i.displayToPlanePos(e);(Math.abs(r.getX()-this.#Kn.getX())>0||Math.abs(r.getY()-this.#Kn.getY())>0)&&(this.#ni&&this.#fn.pop(),this.#Kn=r,this.#ni=!0,this.#fn.push(this.#Kn),this.#ui(this.#fn,n))}#di(e){if(0!==this.#fn.length){if(this.#fn.length===this.#_t.getNPoints()){const t=this.#Rt.getLayerGroupByDivId(e);this.#hi(this.#fn,t),this.#li()}this.#ni=!1}else c.warn("Draw mouseup but no points...")}mousedown=e=>{if(this.#Xn)return;const t=jn(e),n=Ki(e);this.#ri(t,n.groupDivId)};mousemove=e=>{if(!this.#Xn)return;const t=jn(e),n=Ki(e);this.#ci(t,n.groupDivId)};mouseup=e=>{if(!this.#Xn)return;const t=Ki(e);this.#di(t.groupDivId)};dblclick=e=>{if(this.#_t&&void 0!==this.#_t.getNPoints())return;if(!this.#Xn)return;if(0===this.#fn.length)return void c.warn("Draw dblclick but no points...");const t=Ki(e),n=this.#Rt.getLayerGroupByDivId(t.groupDivId);this.#hi(this.#fn,n),this.#li()};mouseout=e=>{if(!this.#Xn)return;const t=Ki(e);this.#di(t.groupDivId)};touchstart=e=>{if(this.#Xn)return;const t=Xn(e),n=Ki(e);this.#ri(t[0],n.groupDivId)};touchmove=e=>{if(!this.#Xn)return;const t=Ki(e),n=Xn(e),i=this.#Rt.getLayerGroupByDivId(t.groupDivId),r=this.#Qn(i);if(void 0===r)return void c.warn("No view layer to handle touch move");const o=r.displayToPlanePos(n[0]);(Math.abs(o.getX()-this.#Kn.getX())>0||Math.abs(o.getY()-this.#Kn.getY())>0)&&(1!==this.#fn.length&&this.#fn.pop(),this.#Kn=o,this.#fn.push(this.#Kn),this.#fn.length<this.#_t.getNPoints()&&(clearTimeout(this.timer),this.timer=setTimeout((()=>{this.#fn.push(this.#Kn)}),this.#_t.getTimeout())),this.#ui(this.#fn,i))};touchend=e=>{this.dblclick(e)};wheel=e=>{this.#Jn&&this.#xn.wheel(e)};keydown=e=>{this.#Xn||(e.context="Draw",this.#Rt.onKeydown(e));const t=this.#ei.getEditorAnnotation();if(("Delete"===e.key||"Backspace"===e.key)&&void 0!==t){const e=this.#Rt.getActiveLayerGroup().getActiveDrawLayer();if(void 0===e)return void c.warn("No draw layer to handle key down");const n=e.getDrawController(),i=new li(t,n);this.#Rt.addToUndoStack(i),i.execute(),this.#ei.onMouseOutShapeGroup()}if("Escape"===e.key&&null!==this.#Zn){const e=this.#Zn.getLayer();this.#Zn.destroy(),this.#Zn=null,this.#li(),e.draw()}};#ui(e,t){this.#Zn&&(this.#Zn.destroy(),this.#Zn=null);const n=t.getActiveDrawLayer();if(void 0===n)return void c.warn("No draw layer to handle new points");const i=n.getDrawController(),r=n.getKonvaLayer(),o=t.getViewLayerById(n.getReferenceLayerId());if(void 0===o)return void c.warn("No view layer to handle new points");const a=o.getViewController();if(this.#ti){const e=["#ffff80","#ff80ff","#80ffff","#80ff80","8080ff","ff8080"],t=n.getId(),i=t.substring(t.length-1),r=e[parseInt(i,10)-1];void 0!==r&&this.#Yn.setLineColour(r)}const s=new Yi,l=i.getAnnotationGroup().getColour();s.colour=void 0!==l?l:this.#Yn.getLineColour(),s.init(a),this.#_t.setAnnotationMathShape(s,e),this.#Zn=this.#_t.createShapeGroup(s,this.#Yn),n.setLabelVisibility(this.#Zn),this.#Zn.getChildren(Si)[0].listening(!1),r.listening(!1),r.add(this.#Zn),r.draw()}#hi(e,t){this.#Zn&&(this.#Zn.destroy(),this.#Zn=null);const n=t.getActiveDrawLayer();if(void 0===n)return void c.warn("No draw layer to handle final points");const i=n.getKonvaLayer(),r=n.getDrawController(),o=t.getViewLayerById(n.getReferenceLayerId());if(void 0===o)return void c.warn("No view layer to handle final points");const a=o.getViewController(),s=new Yi,l=r.getAnnotationGroup().getColour();s.colour=void 0!==l?l:this.#Yn.getLineColour(),s.id=et(),s.init(a),this.#_t.setAnnotationMathShape(s,e);const u=new si(s,r);this.#Rt.addToUndoStack(u),u.execute(),i.listening(!0)}#Si(e){const t=e.getId();return void 0===this.#ii[t]&&(this.#ii[t]=()=>{e.activateCurrentPositionShapes(!0)}),this.#ii[t]}#gi(e,t){e.setShapeHandler(this.#ei),e.activateCurrentPositionShapes(t),t?this.#Rt.addEventListener("positionchange",this.#Si(e)):this.#Rt.removeEventListener("positionchange",this.#Si(e))}activate(e){e||this.#ei.onMouseOutShapeGroup();const t=this.#Rt.getDrawLayers();for(const n of t)void 0!==n&&this.#gi(n,e);this.#Rt.addEventListener("drawlayeradd",(t=>{const n=this.#Rt.getDrawLayers((function(e){return e.getId()===t.layerid}));1===n.length&&this.#gi(n[0],e)}))}setOptions(e){this.#jn=e}getOptionsType(){return"factory"}setFeatures(e){if(void 0!==e.autoShapeColour&&(this.#ti=e.autoShapeColour),void 0!==e.shapeColour&&(this.#Yn.setLineColour(e.shapeColour),this.#ti=!1),void 0!==e.shapeName){if(!this.hasShape(e.shapeName))throw new Error("Unknown shape: '"+e.shapeName+"'");this.#_n=e.shapeName}void 0!==e.mouseOverCursor&&this.#ei.storeMouseOverCursor(e.mouseOverCursor),void 0!==e.withScroll&&(this.#Jn=e.withScroll),void 0!==e.blacklist&&(this.#$n=e.blacklist)}init(){}getEventNames(){return["annotationupdate","annotationselect","warn"]}addEventListener(e,t){void 0===this.#z[e]&&(this.#z[e]=[]),this.#z[e].push(t)}removeEventListener(e,t){if(void 0!==this.#z[e])for(let n=0;n<this.#z[e].length;++n)this.#z[e][n]===t&&this.#z[e].splice(n,1)}#Fe=e=>{if(void 0!==this.#z[e.type])for(let t=0;t<this.#z[e.type].length;++t)this.#z[e.type][t](e)};hasShape(e){return void 0!==this.#jn[e]}},Filter:class{#Rt;constructor(e){this.#Rt=e}#pi=null;#mi=0;#be=new He;activate(e){for(const t in this.#pi)e?(this.#pi[t].addEventListener("filterrun",this.#Fe),this.#pi[t].addEventListener("filter-undo",this.#Fe)):(this.#pi[t].removeEventListener("filterrun",this.#Fe),this.#pi[t].removeEventListener("filter-undo",this.#Fe))}setOptions(e){this.#pi={};for(const t in e)this.#pi[t]=new e[t](this.#Rt)}getOptionsType(){return"instance"}init(){for(const e in this.#pi)this.#pi[e].init()}keydown=e=>{e.context="Filter",this.#Rt.onKeydown(e)};getEventNames(){return["filterrun","filterundo"]}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)};getSelectedFilter(){return this.#mi}setFeatures(e){if(void 0!==e.filterName){if(!this.hasFilter(e.filterName))throw new Error("Unknown filter: '"+e.filterName+"'");this.#mi&&this.#mi.activate(!1),this.#mi=this.#pi[e.filterName],this.#mi.activate(!0)}if(void 0!==e.run&&e.run){let t={};void 0!==e.runArgs&&(t=e.runArgs),this.getSelectedFilter().run(t)}}getFilterList(){return this.#pi}hasFilter(e){return this.#pi[e]}},Floodfill:class{#Rt;constructor(e){this.#Rt=e}#fi=5;#Di=0;#yi=2e3;#Ci=null;#vi=null;#Ii=10;#Ti=null;#An=!1;#Ut;#Li;#Pi=null;#wi=[];#Oi=!1;#Yn=new ui;#be=new He;setExtend(e){this.#Oi=e}getExtend(){return this.#Oi}#Qn(e){const t=e.getActiveDrawLayer();if(void 0!==t)return e.getViewLayerById(t.getReferenceLayerId());c.warn("No draw layer to do floodfill")}#Ai=(e,t)=>{const n=this.#Rt.getLayerGroupByDivId(t),i=this.#Qn(n);if(void 0===i)return void c.warn("No view layer to get index");const r=i.displayToPlaneIndex(e);return{x:r.get(0),y:r.get(1)}};#bi(e,t,n){this.#wi=[];const i={data:this.#Ci.data,width:this.#Ci.width,height:this.#Ci.height,bytes:4};this.#vi=Pi().floodFill(i,e.x,e.y,t),this.#vi=Pi().gaussBlurOnlyBorder(this.#vi,this.#fi);let r=Pi().traceContours(this.#vi);if(r=Pi().simplifyContours(r,this.#Di,this.#yi),r.length>0&&r[0].points[0].x){if(n)return r[0].points;for(let e=0,t=r[0].points.length;e<t;e++)this.#wi.push(new R(r[0].points[e].x,r[0].points[e].y));return this.#wi}return[]}#xi(e,t,n){if(this.#Pi=this.#bi(e,t,!1),0!==this.#Pi.length){const e=n.getActiveDrawLayer();if(void 0===e)return c.warn("No draw layer to paint border"),!1;const t=e.getDrawController(),i=new Ti(this.#Pi);let r;if(void 0===this.#Ut){this.#Ut=new Yi,this.#Ut.colour=this.#Yn.getLineColour(),this.#Ut.id=et();const o=n.getViewLayerById(e.getReferenceLayerId());if(void 0===o)return c.warn("No view layer to paint border"),!1;const a=o.getViewController();this.#Ut.init(a),this.#Ut.mathShape=i,r=new si(this.#Ut,t)}else{const e=this.#Ut.mathShape;r=new ci(this.#Ut,{mathShape:e},{mathShape:i},t)}this.#Rt.addToUndoStack(r),r.execute()}return 0!==this.#Pi.length}extend(e,t,n){if(!this.#Li)throw"'initialpoint' not found. User must click before use extend!";const i=n.getPositionHelper(),r=this.#Qn(n);if(void 0===r)return void c.warn("No view layer to extend floodfill");const o=r.getViewController(),a=o.getCurrentIndex(),s=o.getImageSize(),l=this.#Ti||this.#Ii;for(let e=a.get(2),r=t||s.get(2);e<r&&this.#xi(this.#Li,l,n);e++)i.incrementPositionAlongScroll();o.setCurrentIndex(a);for(let t=a.get(2),r=e||0;t>r&&this.#xi(this.#Li,l,n);t--)i.decrementPositionAlongScroll();o.setCurrentIndex(a)}onThresholdChange(e){}#Rn(e,t){const n=this.#Rt.getLayerGroupByDivId(t);let i,r=n.getActiveDrawLayer();if(void 0===r){i=n.getActiveViewLayer();const e=i.getDataId(),o=this.#Rt.createAnnotationData(e);this.#Rt.addAndRenderAnnotationData(o,t,e),r=n.getActiveDrawLayer(),n.setActiveLayerByDataId(r.getDataId())}else if(i=n.getViewLayerById(r.getReferenceLayerId()),void 0===i)return void c.warn("No view layer to start floodfill");this.#Ci=i.getImageData(),this.#Ci?(this.#Yn.setZoomScale(r.getKonvaLayer().getAbsoluteScale()),this.#An=!0,this.#Li=this.#Ai(e,t),this.#xi(this.#Li,this.#Ii,n),this.onThresholdChange(this.#Ii)):c.error("No image found")}#Fn(e,t){if(!this.#An)return;const n=this.#Ai(e,t);this.#Ti=Math.round(Math.sqrt(Math.pow(this.#Li.x-n.x,2)+Math.pow(this.#Li.y-n.y,2))/2),this.#Ti=this.#Ti<this.#Ii?this.#Ii:this.#Ti-this.#Ii,this.#xi(this.#Li,this.#Ti,this.#Rt.getLayerGroupByDivId(t)),this.onThresholdChange(this.#Ti)}#En(){this.#An&&(this.#An=!1)}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Rn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup=e=>{this.#En()};mouseout=e=>{this.#En()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Rn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchend=e=>{this.#En()};keydown=e=>{e.context="Floodfill",this.#Rt.onKeydown(e)};activate(e){e&&(this.#Yn.setBaseScale(this.#Rt.getBaseScale()),this.setFeatures({shapeColour:this.#Yn.getLineColour()}))}init(){}getEventNames(){return["drawcreate","drawchange","drawmove","drawdelete"]}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}setFeatures(e){void 0!==e.shapeColour&&this.#Yn.setLineColour(e.shapeColour)}},Livewire:class{#Rt;constructor(e){this.#Rt=e}#An=!1;#bn;#Ut;#Yn=new ui;#Ri=new wi;#Fi=new wi;#wi=[];#Ei=5;#be=new He;#qi(e){const t=e.get(1);for(let e=0;e<t;++e)this.#wi[e]=[]}#Ui(){this.#Ri=new wi,this.#Fi=new wi}#Mi=new xi;#Rn(e,t){const n=this.#Rt.getLayerGroupByDivId(t);let i,r=n.getActiveDrawLayer();i=void 0===r?n.getActiveViewLayer():n.getViewLayerById(r.getReferenceLayerId());const o=i.getViewController().getImageSize();this.#Mi.setDimensions(o.get(0),o.get(1)),this.#Mi.setData(i.getImageData().data);const a=i.displayToPlaneIndex(e);if(this.#An){const e=Math.abs(a.get(0)-this.#bn.getX()),t=Math.abs(a.get(1)-this.#bn.getY());if(e<this.#Ei&&t<this.#Ei)this.#Qi();else{this.#Ri=this.#Fi,this.#qi(o);const e={x:a.get(0),y:a.get(1)};this.#Mi.doTraining(e),this.#Ri.addControlPoint(this.#Fi.getPoint(0))}}else{if(this.#An=!0,this.#bn=new R(a.get(0),a.get(1)),this.#Ui(),this.#qi(o),void 0===r){const e=i.getDataId(),o=this.#Rt.createAnnotationData(e);this.#Rt.addAndRenderAnnotationData(o,t,e),r=n.getActiveDrawLayer(),n.setActiveLayerByDataId(r.getDataId())}this.#Yn.setZoomScale(r.getKonvaLayer().getAbsoluteScale());const e={x:a.get(0),y:a.get(1)};this.#Mi.doTraining(e);const s=new R(a.get(0),a.get(1));this.#Ri.addPoint(s),this.#Ri.addControlPoint(s)}}#Fn(e,t){if(!this.#An)return;const n=this.#Rt.getLayerGroupByDivId(t),i=n.getActiveDrawLayer();if(void 0===i)return void c.warn("No draw layer to update livewire");const r=n.getViewLayerById(i.getReferenceLayerId());if(void 0===r)return void c.warn("No view layer to update livewire");const o=r.displayToPlaneIndex(e);let a={x:o.get(0),y:o.get(1)};this.#Mi.setPoint(a);let s=[],l=!1;for(;!this.#wi[a.y][a.x]&&!l;)if(s=this.#Mi.doWork(),0===s.length)l=!0;else for(let e=0;e<s.length-1;e+=2){const t=s[e],n=s[e+1];this.#wi[t.y][t.x]=n}for(this.#Fi=new wi,l=!1;a&&!l;)this.#Fi.addPoint(new R(a.x,a.y)),this.#wi[a.y]&&this.#wi[a.y][a.x]?a=this.#wi[a.y][a.x]:l=!0;this.#Fi.appenPath(this.#Ri);const u=i.getDrawController(),d=new Ti(this.#Fi.pointArray);let h;if(void 0===this.#Ut){this.#Ut=new Yi,this.#Ut.colour=this.#Yn.getLineColour(),this.#Ut.id=et();const e=r.getViewController();this.#Ut.init(e),this.#Ut.mathShape=d,h=new si(this.#Ut,u)}else{const e=this.#Ut.mathShape;h=new ci(this.#Ut,{mathShape:e},{mathShape:d},u)}this.#Rt.addToUndoStack(h),h.execute()}#Qi(){this.#An=!1}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Rn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup(e){}mouseout=e=>{};dblclick=e=>{this.#Qi()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Rn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchend=e=>{};keydown=e=>{e.context="Livewire",this.#Rt.onKeydown(e)};activate(e){e&&(this.#Yn.setBaseScale(this.#Rt.getBaseScale()),this.setFeatures({shapeColour:this.#Yn.getLineColour()}))}init(){}getEventNames(){return["drawcreate","drawchange","drawmove","drawdelete"]}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}setFeatures(e){void 0!==e.shapeColour&&this.#Yn.setLineColour(e.shapeColour)}}},Wi={draw:{ArrowFactory:class{#Vi="arrow";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof R}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.referencePoints=[t[1]],e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(i);const r=this.#zi(e,t);for(const e of r)n.add(e);const o=this.#Ni.create(e,t);n.add(o);const a=this.#Wi(i);return n.add(this.#Ni.getConnector(a,o,t)),n}#Wi(e){const t=e.points(),n=e.x(),i=e.y(),r=(t[0]+t[2])/2+n,o=(t[1]+t[3])/2+i;return[new R(r,o)]}#Yi(e){const t=e.points(),n=e.x(),i=e.y();return[new R(t[0]+n,t[1]+i),new R(t[2]+n,t[3]+i)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=t.getParent();if(!(n instanceof ai().Group))return;const i=this.#ji(n),r=mi(n,0),o=mi(n,1),a=new R(r.x()-i.x(),r.y()-i.y()),s=new R(o.x()-i.x(),o.y()-i.y());e.mathShape=a,e.referencePoints=[s],e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=e.referencePoints[0],r=new $n(n,i),o=r.getBegin(),a=new R(o.getX()+t.x,o.getY()+t.y),s=r.getEnd(),l=new R(s.getX()+t.x,s.getY()+t.y);e.mathShape=a,e.referencePoints=[l],e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){return e[0]}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape,i=e.referencePoints[0],r=new $n(n,i),o=new(ai().Line)({points:[n.getX(),n.getY(),i.getX(),i.getY()],stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"}),a=ni(r,n,20,t.getZoomScale()),s=ni(r,i,20,t.getZoomScale());return o.hitFunc((function(e){e.beginPath(),e.moveTo(a.getBegin().getX(),a.getBegin().getY()),e.lineTo(a.getEnd().getX(),a.getEnd().getY()),e.lineTo(s.getEnd().getX(),s.getEnd().getY()),e.lineTo(s.getBegin().getX(),s.getBegin().getY()),e.closePath(),e.fillStrokeShape(o)})),o}#ji(e){return pi(e)}#zi(e,t){const n=e.mathShape,i=e.referencePoints[0],r=new $n(n,i),o=ii(r,40,20,t.getZoomScale());return[new(ai().Line)({points:[r.getBegin().getX(),r.getBegin().getY(),o.getBegin().getX(),o.getBegin().getY(),o.getEnd().getX(),o.getEnd().getY()],fill:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,closed:!0,name:"shape-triangle"})]}#Bi(e){return e.mathShape}#Xi(e,t,n){const i=e.mathShape,r=e.referencePoints[0],o=new $n(i,r),a=t.getParent();if(!(a instanceof ai().Group))return;const s=this.#ji(a);s.position({x:0,y:0}),s.points([i.getX(),i.getY(),r.getX(),r.getY()]);const l=a.getChildren((function(e){return"shape-triangle"===e.name()}))[0];if(!(l instanceof ai().Line))return;const u=mi(a,0),d=mi(a,1);switch(t.id()){case"anchor0":u.x(t.x()),u.y(t.y());break;case"anchor1":d.x(t.x()),d.y(t.y());break;default:c.error("Unhandled anchor id: "+t.id())}const h=ii(o,40,20,n.getZoomScale());l.position({x:0,y:0}),l.points([o.getBegin().getX(),o.getBegin().getY(),h.getBegin().getX(),h.getBegin().getY(),h.getEnd().getX(),h.getEnd().getY()]);const S=ni(o,i,20,n.getZoomScale()),g=ni(o,r,20,n.getZoomScale());s.hitFunc((function(e){e.beginPath(),e.moveTo(S.getBegin().getX(),S.getBegin().getY()),e.lineTo(S.getEnd().getX(),S.getEnd().getY()),e.lineTo(g.getEnd().getX(),g.getEnd().getY()),e.lineTo(g.getBegin().getX(),g.getBegin().getY()),e.closePath(),e.fillStrokeShape(s)}))}#Zi(e,t){}#_i(e,t){}},CircleFactory:class{#Vi="circle";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof Fi}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(this.#Hi(e,t));const r=this.#Ni.create(e,t);n.add(this.#Ni.create(e,t));const o=this.#Wi(i);return n.add(this.#Ni.getConnector(o,r,t)),n}#Wi(e){const t=e.x(),n=e.y(),i=e.radius()*Math.sqrt(2)/2;return[new R(t-i,n-i),new R(t+i,n-i),new R(t-i,n+i),new R(t+i,n+i)]}#Yi(e){const t=e.x(),n=e.y(),i=e.radius();return[new R(t-i,n),new R(t+i,n),new R(t,n+i),new R(t,n-i)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){const t=e.getParent();if(!(t instanceof ai().Group))return;const n=mi(t,0),i=mi(t,1),r=mi(t,2),o=mi(t,3);switch(e.id()){case"anchor0":n.y(i.y());break;case"anchor1":i.y(n.y());break;case"anchor2":r.x(o.x());break;case"anchor3":o.x(r.x());break;default:c.error("Unhandled anchor id: "+e.id())}}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=e.mathShape,i=new R(n.getCenter().getX(),n.getCenter().getY()),r=new R(t.x(),t.y()),o=i.getDistance(r);e.mathShape=new Fi(i,o),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=n.getCenter(),r=new R(i.getX()+t.x,i.getY()+t.y);e.mathShape=new Fi(r,n.getRadius()),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){const t=Math.abs(e[0].getX()-e[1].getX()),n=Math.abs(e[0].getY()-e[1].getY()),i=Math.round(Math.sqrt(t*t+n*n));return new Fi(e[0],i)}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape;return new(ai().Circle)({x:n.getCenter().getX(),y:n.getCenter().getY(),radius:n.getRadius(),stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"})}#ji(e){const t=e.getChildren(Si)[0];if(t instanceof ai().Circle)return t}#Bi(e){const t=e.mathShape,n=t.getCenter(),i=t.getRadius();return new R(n.getX()-i,n.getY()+i)}#Xi(e,t,n){const i=e.mathShape,r=i.getCenter(),o=i.getRadius(),a=t.getParent();if(!(a instanceof ai().Group))return;this.#ji(a).radius(o);const s=mi(a,0),l=mi(a,1),u=mi(a,2),d=mi(a,3),h=l.x()<s.x()?-1:1,S=d.y()<u.y()?1:-1;switch(t.id()){case"anchor0":s.x(t.x()),l.x(r.getX()+h*o),u.y(r.getY()+o),d.y(r.getY()-o);break;case"anchor1":l.x(t.x()),s.x(r.getX()-h*o),u.y(r.getY()+o),d.y(r.getY()-o);break;case"anchor2":u.y(t.y()),s.x(r.getX()-o),l.x(r.getX()+o),d.y(r.getY()-S*o);break;case"anchor3":d.y(t.y()),s.x(r.getX()-o),l.x(r.getX()+o),u.y(r.getY()+S*o);break;default:c.error("Unhandled anchor id: "+t.id())}}#Zi(e,t){const n=e.mathShape;let i=0,r=0;void 0!==t&&(i=t.x(),r=t.y());const o=new(ai().Group);o.name("shadow");const a=n.getRound();for(let e=0;e<a.length;++e){const t=a[e],n=t[0][0],s=t[0][1],l=t[1][0],c=new(ai().Rect)({x:n-i,y:s-r,width:l-n,height:1,fill:"grey",strokeWidth:0,strokeScaleEnabled:!1,opacity:.3,name:"shadow-element"});o.add(c)}return o}#_i(e,t){const n=t.getChildren((function(e){return"shadow"===e.name()}))[0];void 0!==n&&(n.destroy(),t.add(this.#Zi(e,t)))}},EllipseFactory:class{#Vi="ellipse";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof Ei}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(this.#Hi(e,t));const r=this.#Ni.create(e,t);n.add(this.#Ni.create(e,t));const o=this.#Wi(i);return n.add(this.#Ni.getConnector(o,r,t)),n}#Wi(e){const t=e.x(),n=e.y(),i=e.radiusX()*Math.sqrt(2)/2,r=e.radiusY()*Math.sqrt(2)/2;return[new R(t-i,n-r),new R(t+i,n-r),new R(t-i,n+r),new R(t+i,n+r)]}#Yi(e){const t=e.x(),n=e.y(),i=e.radius();return[new R(t-i.x,n),new R(t+i.x,n),new R(t,n+i.y),new R(t,n-i.y)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){const t=e.getParent();if(!(t instanceof ai().Group))return;const n=mi(t,0),i=mi(t,1),r=mi(t,2),o=mi(t,3);switch(e.id()){case"anchor0":n.y(i.y());break;case"anchor1":i.y(n.y());break;case"anchor2":r.x(o.x());break;case"anchor3":o.x(r.x());break;default:c.error("Unhandled anchor id: "+e.id())}}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=e.mathShape,i=n.getCenter();let r=n.getA(),o=n.getB();switch(t.id()){case"anchor0":r=i.getX()-t.x();break;case"anchor1":r=t.x()-i.getX();break;case"anchor2":o=t.y()-i.getY();break;case"anchor3":o=i.getY()-t.y();break;default:c.error("Unhandled anchor id: "+t.id())}e.mathShape=new Ei(i,Math.abs(r),Math.abs(o)),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=n.getCenter(),r=new R(i.getX()+t.x,i.getY()+t.y);e.mathShape=new Ei(r,n.getA(),n.getB()),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){const t=Math.abs(e[0].getX()-e[1].getX()),n=Math.abs(e[0].getY()-e[1].getY());return new Ei(e[0],t,n)}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape,i=n.getCenter(),r={x:n.getA(),y:n.getB()};return new(ai().Ellipse)({x:i.getX(),y:i.getY(),radius:r,radiusX:r.x,radiusY:r.y,stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"})}#ji(e){const t=e.getChildren(Si)[0];if(t instanceof ai().Ellipse)return t}#Bi(e){const t=e.mathShape,n=t.getCenter();return new R(n.getX()-t.getA(),n.getY()+t.getB())}#Xi(e,t,n){const i=e.mathShape,r=i.getCenter(),o=i.getA(),a=i.getB(),s=t.getParent();if(!(s instanceof ai().Group))return;this.#ji(s).radius({x:o,y:a});const l=mi(s,0),u=mi(s,1),d=mi(s,2),h=mi(s,3),S=u.x()<l.x()?-1:1,g=h.y()<d.y()?1:-1;switch(t.id()){case"anchor0":l.x(t.x()),u.x(r.getX()+S*o),d.y(r.getY()+a),h.y(r.getY()-a);break;case"anchor1":u.x(t.x()),l.x(r.getX()-S*o),d.y(r.getY()+a),h.y(r.getY()-a);break;case"anchor2":d.y(t.y()),l.x(r.getX()-o),u.x(r.getX()+o),h.y(r.getY()-g*a);break;case"anchor3":h.y(t.y()),l.x(r.getX()-o),u.x(r.getX()+o),d.y(r.getY()+g*a);break;default:c.error("Unhandled anchor id: "+t.id())}}#Zi(e,t){const n=e.mathShape;let i=0,r=0;void 0!==t&&(i=t.x(),r=t.y());const o=new(ai().Group);o.name("shadow");const a=n.getRound();for(let e=0;e<a.length;++e){const t=a[e],n=t[0][0],s=t[0][1],l=t[1][0],c=new(ai().Rect)({x:n-i,y:s-r,width:l-n,height:1,fill:"grey",strokeWidth:0,strokeScaleEnabled:!1,opacity:.3,name:"shadow-element"});o.add(c)}return o}#_i(e,t){const n=t.getChildren((function(e){return"shadow"===e.name()}))[0];void 0!==n&&(n.destroy(),t.add(this.#Zi(e,t)))}},ProtractorFactory:class{#Vi="protractor";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof Ui}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 3}getTimeout(){return 500}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=e.mathShape,i=new(ai().Group);i.name(this.getGroupName()),i.visible(!0),i.id(e.id);const r=this.#Hi(e,t);if(i.add(this.#Hi(e,t)),n.getLength()===this.getNPoints()){const n=this.#zi(e,t);for(const e of n)i.add(e);const o=this.#Ni.create(e,t);i.add(this.#Ni.create(e,t));const a=this.#Wi(r);i.add(this.#Ni.getConnector(a,o,t))}return i}#Wi(e){const t=e.points(),n=e.x(),i=e.y();return[new R(t[2]+n,t[3]+i)]}#Yi(e){const t=e.points(),n=e.x(),i=e.y();return[new R(t[0]+n,t[1]+i),new R(t[2]+n,t[3]+i),new R(t[4]+n,t[5]+i)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=t.getParent();if(!(n instanceof ai().Group))return;const i=this.#ji(n),r=mi(n,0),o=mi(n,1),a=mi(n,2),s=new R(r.x()-i.x(),r.y()-i.y()),l=new R(o.x()-i.x(),o.y()-i.y()),c=new R(a.x()-i.x(),a.y()-i.y());e.mathShape=new Ui([s,l,c]),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=[];for(let e=0;e<3;++e)i.push(new R(n.getPoint(e).getX()+t.x,n.getPoint(e).getY()+t.y));e.mathShape=new Ui(i),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){return new Ui(e)}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape,i=[];for(let e=0;e<n.getLength();++e)i.push(n.getPoint(e).getX()),i.push(n.getPoint(e).getY());const r=new(ai().Line)({points:i,stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"});return n.getLength()===this.getNPoints()&&r.hitFunc((function(e){e.beginPath(),e.moveTo(n.getPoint(0).getX(),n.getPoint(0).getY()),e.lineTo(n.getPoint(1).getX(),n.getPoint(1).getY()),e.lineTo(n.getPoint(2).getX(),n.getPoint(2).getY()),e.closePath(),e.fillStrokeShape(r)})),r}#ji(e){return pi(e)}#zi(e,t){const n=e.mathShape,i=new $n(n.getPoint(0),n.getPoint(1)),r=new $n(n.getPoint(1),n.getPoint(2));let o=ei(i,r),a=i.getInclination();o>180&&(o=360-o,a+=o);const s=33*Math.min(i.getLength(),r.getLength())/100;return[new(ai().Arc)({innerRadius:s,outerRadius:s,stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,angle:o,rotation:-a,x:n.getPoint(1).getX(),y:n.getPoint(1).getY(),name:"shape-arc"})]}#Bi(e){const t=e.mathShape,n=new $n(t.getPoint(0),t.getPoint(1)),i=new $n(t.getPoint(1),t.getPoint(2)),r=(n.getMidpoint().getX()+i.getMidpoint().getX())/2,o=(n.getMidpoint().getY()+i.getMidpoint().getY())/2;return new R(r,o)}#Xi(e,t,n){const i=e.mathShape,r=new $n(i.getPoint(0),i.getPoint(1)),o=new $n(i.getPoint(1),i.getPoint(2)),a=t.getParent();if(!(a instanceof ai().Group))return;const s=this.#ji(a);s.position({x:0,y:0}),s.points([i.getPoint(0).getX(),i.getPoint(0).getY(),i.getPoint(1).getX(),i.getPoint(1).getY(),i.getPoint(2).getX(),i.getPoint(2).getY()]);const l=a.getChildren((function(e){return"shape-arc"===e.name()}))[0];if(!(l instanceof ai().Arc))return;const c=mi(a,0),u=mi(a,1),d=mi(a,2);switch(t.id()){case"anchor0":c.x(t.x()),c.y(t.y());break;case"anchor1":u.x(t.x()),u.y(t.y());break;case"anchor2":d.x(t.x()),d.y(t.y())}let h=ei(r,o),S=r.getInclination();h>180&&(h=360-h,S+=h);const g=33*Math.min(r.getLength(),o.getLength())/100;l.innerRadius(g),l.outerRadius(g),l.angle(h),l.rotation(-S);const p={x:u.x(),y:u.y()};l.position(p),s.hitFunc((function(e){e.beginPath(),e.moveTo(i.getPoint(0).getX(),i.getPoint(0).getY()),e.lineTo(i.getPoint(1).getX(),i.getPoint(1).getY()),e.lineTo(i.getPoint(2).getX(),i.getPoint(2).getY()),e.closePath(),e.fillStrokeShape(s)}))}#Zi(e,t){}#_i(e,t){}},RectangleFactory:class{#Vi="rectangle";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof Mi}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(i);const r=this.#Ni.create(e,t);n.add(r);const o=this.#Wi(i);return n.add(this.#Ni.getConnector(o,r,t)),n}#Wi(e){const t=e.x(),n=e.y(),i=e.width(),r=e.height();return[new R(t+i/2,n),new R(t,n+r/2),new R(t+i/2,n+r),new R(t+i,n+r/2)]}#Yi(e){const t=e.x(),n=e.y(),i=e.width(),r=e.height();return[new R(t,n),new R(t+i,n),new R(t+i,n+r),new R(t,n+r)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=t.getParent();if(!(n instanceof ai().Group))return;const i=mi(n,0),r=mi(n,2),o=new R(i.x(),i.y()),a=new R(r.x(),r.y());e.mathShape=new Mi(o,a),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=n.getBegin(),r=new R(i.getX()+t.x,i.getY()+t.y),o=n.getEnd(),a=new R(o.getX()+t.x,o.getY()+t.y);e.mathShape=new Mi(r,a),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){return new Mi(e[0],e[1])}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape;return new(ai().Rect)({x:n.getBegin().getX(),y:n.getBegin().getY(),width:n.getWidth(),height:n.getHeight(),stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"})}#ji(e){const t=e.getChildren(Si)[0];if(t instanceof ai().Rect)return t}#Bi(e){const t=e.mathShape;return new R(t.getBegin().getX(),t.getEnd().getY())}#Xi(e,t,n){const i=e.mathShape,r=i.getBegin(),o=t.getParent();if(!(o instanceof ai().Group))return;const a=this.#ji(o);a.position({x:r.getX(),y:r.getY()}),a.size({width:i.getWidth(),height:i.getHeight()});const s=mi(o,0),l=mi(o,1),u=mi(o,2),d=mi(o,3);switch(t.id()){case"anchor0":s.x(t.x()),s.y(t.y()),l.y(t.y()),d.x(t.x());break;case"anchor1":l.x(t.x()),l.y(t.y()),s.y(t.y()),u.x(t.x());break;case"anchor2":u.x(t.x()),u.y(t.y()),d.y(t.y()),l.x(t.x());break;case"anchor3":d.x(t.x()),d.y(t.y()),u.y(t.y()),s.x(t.x());break;default:c.error("Unhandled anchor id: "+t.id())}}#Zi(e,t){const n=e.mathShape.getRound(),i=n.max.getX()-n.min.getX(),r=n.max.getY()-n.min.getY();return new(ai().Rect)({x:n.min.getX(),y:n.min.getY(),width:i,height:r,fill:"grey",strokeWidth:0,strokeScaleEnabled:!1,opacity:.3,name:"shadow"})}#_i(e,t){const n=t.getChildren((function(e){return"shadow"===e.name()}))[0];void 0!==n&&(n.destroy(),t.add(this.#Zi(e,t)))}},RoiFactory:class{#Vi="roi";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof Ti}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){}getTimeout(){return 100}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(this.#Hi(e,t));const r=this.#Ni.create(e,t);n.add(this.#Ni.create(e,t));const o=this.#Wi(i);return n.add(this.#Ni.getConnector(o,r,t)),n}#Yi(e){const t=e.points(),n=e.x(),i=e.y(),r=[];for(let e=0;e<t.length;e+=2)r.push(new R(t[e]+n,t[e+1]+i));return r}#Wi(e){const t=e.points(),n=e.x(),i=e.y(),r=[];for(let e=0;e<t.length;e+=2){const o=(e+2)%t.length,a=(t[e]+t[o])/2+n,s=(t[e+1]+t[o+1])/2+i;r.push(new R(a,s))}return r}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=t.getParent();if(!(n instanceof ai().Group))return;const i=this.#ji(n),r=e.mathShape.getPoints().slice(),o=new R(t.x()-i.x(),t.y()-i.y());r[yi(t.id())]=o,e.mathShape=new Ti(r),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=[];for(let e=0;e<n.getLength();++e)i.push(new R(n.getPoint(e).getX()+t.x,n.getPoint(e).getY()+t.y));e.mathShape=new Ti(i),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){return new Ti(e)}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape,i=[];for(let e=0;e<n.getLength();++e)i.push(n.getPoint(e).getX()),i.push(n.getPoint(e).getY());return new(ai().Line)({points:i,stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape",closed:!0})}#ji(e){return pi(e)}#Bi(e){const t=e.mathShape;return new R(t.getPoint(0).getX(),t.getPoint(0).getY())}#Xi(e,t,n){const i=t.getParent();if(!(i instanceof ai().Group))return;const r=this.#ji(i),o=r.points(),a=2*yi(t.id());o[a]=t.x()-r.x(),o[a+1]=t.y()-r.y(),r.points(o);const s=i.getChildren((function(e){return e.id()===t.id()}))[0];s.x(t.x()),s.y(t.y())}#Zi(e,t){}#_i(e,t){}},RulerFactory:class{#Vi="ruler";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof $n}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(this.#Hi(e,t));const r=this.#zi(e,t);for(const e of r)n.add(e);const o=this.#Ni.create(e,t);n.add(this.#Ni.create(e,t));const a=this.#Wi(i);return n.add(this.#Ni.getConnector(a,o,t)),n}#Wi(e){const t=e.points(),n=e.x(),i=e.y(),r=(t[0]+t[2])/2+n,o=(t[1]+t[3])/2+i;return[new R(r,o)]}#Yi(e){const t=e.points(),n=e.x(),i=e.y();return[new R(t[0]+n,t[1]+i),new R(t[2]+n,t[3]+i)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=t.getParent();if(!(n instanceof ai().Group))return;const i=this.#ji(n),r=mi(n,0),o=mi(n,1),a=new R(r.x()-i.x(),r.y()-i.y()),s=new R(o.x()-i.x(),o.y()-i.y());e.mathShape=new $n(a,s),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=n.getBegin(),r=new R(i.getX()+t.x,i.getY()+t.y),o=n.getEnd(),a=new R(o.getX()+t.x,o.getY()+t.y);e.mathShape=new $n(r,a),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){return new $n(e[0],e[1])}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape,i=new(ai().Line)({points:[n.getBegin().getX(),n.getBegin().getY(),n.getEnd().getX(),n.getEnd().getY()],stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"}),r=ni(n,n.getBegin(),20,t.getZoomScale()),o=ni(n,n.getEnd(),20,t.getZoomScale());return i.hitFunc((function(e){e.beginPath(),e.moveTo(r.getBegin().getX(),r.getBegin().getY()),e.lineTo(r.getEnd().getX(),r.getEnd().getY()),e.lineTo(o.getEnd().getX(),o.getEnd().getY()),e.lineTo(o.getBegin().getX(),o.getBegin().getY()),e.closePath(),e.fillStrokeShape(i)})),i}#ji(e){return pi(e)}#zi(e,t){const n=e.mathShape,i=ni(n,n.getBegin(),20,t.getZoomScale()),r=new(ai().Line)({points:[i.getBegin().getX(),i.getBegin().getY(),i.getEnd().getX(),i.getEnd().getY()],stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape-tick0"}),o=ni(n,n.getEnd(),20,t.getZoomScale());return[r,new(ai().Line)({points:[o.getBegin().getX(),o.getBegin().getY(),o.getEnd().getX(),o.getEnd().getY()],stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape-tick1"})]}#Bi(e){const t=e.mathShape,n=t.getBegin(),i=t.getEnd();let r=n;return n.getY()<i.getY()&&(r=i),r}#Xi(e,t,n){const i=e.mathShape,r=t.getParent();if(!(r instanceof ai().Group))return;const o=this.#ji(r);o.position({x:0,y:0}),o.points([i.getBegin().getX(),i.getBegin().getY(),i.getEnd().getX(),i.getEnd().getY()]);const a=r.getChildren((function(e){return"shape-tick0"===e.name()}))[0];if(!(a instanceof ai().Line))return;const s=r.getChildren((function(e){return"shape-tick1"===e.name()}))[0];if(!(s instanceof ai().Line))return;const l=mi(r,0),u=mi(r,1);switch(t.id()){case"anchor0":l.x(t.x()),l.y(t.y());break;case"anchor1":u.x(t.x()),u.y(t.y());break;default:c.error("Unhandled anchor id: "+t.id())}const d=ni(i,i.getBegin(),20,n.getZoomScale());a.position({x:0,y:0}),a.points([d.getBegin().getX(),d.getBegin().getY(),d.getEnd().getX(),d.getEnd().getY()]);const h=ni(i,i.getEnd(),20,n.getZoomScale());s.position({x:0,y:0}),s.points([h.getBegin().getX(),h.getBegin().getY(),h.getEnd().getX(),h.getEnd().getY()]),o.hitFunc((function(e){e.beginPath(),e.moveTo(d.getBegin().getX(),d.getBegin().getY()),e.lineTo(d.getEnd().getX(),d.getEnd().getY()),e.lineTo(h.getEnd().getX(),h.getEnd().getY()),e.lineTo(h.getBegin().getX(),h.getBegin().getY()),e.closePath(),e.fillStrokeShape(o)}))}#Zi(e,t){}#_i(e,t){}}},filter:{Threshold:class{#Rt;constructor(e){this.#Rt=e}#On=new Vi;#Ki=!0;#be=new He;activate(e){e&&(this.#Ki=!0)}init(){}run(e){if(void 0===e.dataId)throw new Error("No dataId to run threshod filter on.");if(this.#On.setMin(e.min),this.#On.setMax(e.max),this.#Ki){const t=this.#Rt.getData(e.dataId).image;this.#On.setOriginalImage(t),this.#Ki=!1}const t=new Gi(this.#On,e.dataId,this.#Rt);t.onExecute=this.#Fe,t.onUndo=this.#Fe,t.execute(),this.#Rt.addToUndoStack(t)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}},Sobel:class{#Rt;constructor(e){this.#Rt=e}#be=new He;activate(e){}init(){}run(e){if(void 0===e.dataId)throw new Error("No dataId to run sobel filter on.");const t=new Bi,n=this.#Rt.getData(e.dataId).image;t.setOriginalImage(n);const i=new Gi(t,e.dataId,this.#Rt);i.onExecute=this.#Fe,i.onUndo=this.#Fe,i.execute(),this.#Rt.addToUndoStack(i)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}},Sharpen:class{#Rt;constructor(e){this.#Rt=e}#be=new He;activate(e){}init(){}run(e){if(void 0===e.dataId)throw new Error("No dataId to run sharpen filter on.");const t=new Ni,n=this.#Rt.getData(e.dataId).image;t.setOriginalImage(n);const i=new Gi(t,e.dataId,this.#Rt);i.onExecute=this.#Fe,i.onUndo=this.#Fe,i.execute(),this.#Rt.addToUndoStack(i)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}}}};class Yi{id;referenceSopUID;mathShape;referencePoints;colour;quantification;textExpr;labelPosition;planeOrigin;planePoints;#nt;getOrientationName(){let e;return void 0!==this.planePoints&&(e=Dt(this.planePoints[1].getValues().concat(this.planePoints[2].getValues()))),e}init(e){void 0===this.referenceSopUID?(this.#nt=e,this.referenceSopUID=e.getCurrentImageUid(),this.planeOrigin=e.getOriginForImageUid(this.referenceSopUID),e.isAquisitionOrientation()||(this.planePoints=e.getPlanePoints(e.getCurrentPosition()))):c.debug("Cannot initialise annotation twice")}isCompatibleView(e){let t=!1;if(void 0===this.planePoints)e.isAquisitionOrientation()&&(t=!0);else{const n=e.getCosines(),i=new F(n[0],n[1],n[2]),r=new F(n[3],n[4],n[5]);i.equals(this.planePoints[1])&&r.equals(this.planePoints[2])&&(t=!0)}return t}setViewController(e){e.includesImageUid(this.referenceSopUID)&&this.isCompatibleView(e.getPlaneHelper())&&(this.#nt=e,this.planeOrigin=e.getOriginForImageUid(this.referenceSopUID))}#Ji(){let e;if(void 0!==this.#nt){let t=this.planeOrigin;void 0!==this.planePoints&&(t=this.planePoints[0]);const n=new E([t.getX(),t.getY(),t.getZ()]);e=this.#nt.getIndexFromPosition(n)}return e}getCentroid(){let e;if(void 0!==this.#nt&&void 0!==this.mathShape.getCentroid){const t=this.#Ji(),n=this.#nt.getScrollDimIndex(),i=t.getValues()[n],r=this.mathShape.getCentroid();e=this.#nt.getPositionFromPlanePoint(r,i)}return e}setTextExpr(e){if(void 0!==this.#nt){const t=this.#nt.getModality();void 0!==e[t]?this.textExpr=e[t]:this.textExpr=e["*"]}else c.warn("Cannot set text expr without a view controller")}getText(){return function(e,t){let n="";if(null==e)return n;if(n=e,null==t)return n;const i=Q(e);for(let e=0;e<i.length;++e){const r=t[i[e]];if(null!=r&&null!==r.value&&void 0!==r.value){let t=r.value.toPrecision(4);null!==r.unit&&void 0!==r.unit&&0!==r.unit.length&&("unit.degree"!==r.unit&&(t+=" "),t+=q.t(r.unit));const o="{"+i[e]+"}";n=n.replace(o,t)}}return n}(this.textExpr,this.quantification)}updateQuantification(){void 0!==this.#nt&&void 0!==this.mathShape.quantify&&(this.quantification=this.mathShape.quantify(this.#nt,this.#Ji(),Q(this.textExpr)))}getFactory(){let e;if(void 0!==Hi.draw)for(const t in Hi.draw){const n=Hi.draw[t];if(n.supports(this.mathShape)){e=new n;break}}if(void 0===e)for(const t in Wi.draw){const n=Wi.draw[t];if(n.supports(this.mathShape)){e=new n;break}}return void 0===e&&c.warn("No shape factory found for math shape"),e}}class Xi{#$i;#Pe={};#be=new He;#er;#tr;constructor(e){this.#$i=void 0!==e?e:[],this.#er=!0}getList(){return this.#$i}getLength(){return this.#$i.length}isEditable(){return this.#er}setEditable(e){this.#er=e,this.#Fe({type:"annotationgroupeditablechange",data:e})}getColour(){return this.#tr}setColour(e){this.#tr=e}add(e){this.#$i.push(e),this.#Fe({type:"annotationadd",data:e})}update(e,t){const n=this.#$i.findIndex((t=>t.id===e.id));-1!==n?((t.includes("mathShape")||t.includes("textExpr"))&&e.updateQuantification(),this.#$i[n]=e,this.#Fe({type:"annotationupdate",data:e,keys:t})):c.warn("Cannot find annotation to update")}remove(e){const t=this.#$i.findIndex((t=>t.id===e));if(-1!==t){const e=this.#$i.splice(t,1)[0];this.#Fe({type:"annotationremove",data:e})}else c.warn("Cannot find annotation to remove")}setViewController(e){for(const t of this.#$i)t.setViewController(e),t.updateQuantification()}find(e){return this.#$i.find((t=>t.id===e))}getMeta(){return this.#Pe}hasMeta(e){return void 0!==this.#Pe[e]}getMetaValue(e){return this.#Pe[e]}setMetaValue(e,t){this.#Pe[e]=t}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}}class ji{#nr;getAnnotation(e){return this.#nr.find(e)}getAnnotationGroup(){return this.#nr}isAnnotationGroupEditable(){return this.#nr.isEditable()}setAnnotationGroupEditable(e){this.#nr.setEditable(e)}addAnnotation(e){this.#nr.add(e)}updateAnnotation(e,t){this.#nr.update(e,t)}removeAnnotation(e){this.#nr.remove(e)}removeAnnotationWithCommand(e,t){const n=this.getAnnotation(e);if(void 0===n)return void c.warn("Cannot create remove command for undefined annotation: "+e);const i=new li(n,this);t(i),i.execute()}updateAnnotationWithCommand(e,t,n,i){const r=this.getAnnotation(e);if(void 0===r)return void c.warn("Cannot create update command for undefined annotation: "+e);const o=new ci(r,t,n,this);i(o),o.execute()}removeAllAnnotationsWithCommand(e){for(const t of this.#nr.getList())this.removeAnnotationWithCommand(t.id,e)}constructor(e){this.#nr=void 0!==e?e:new Xi}hasAnnotationMeta(e){return this.#nr.hasMeta(e)}setAnnotationMeta(e,t){this.#nr.setMetaValue(e,t)}}class Zi{#tt;#ir=null;#lt;#ct;#ht={x:1,y:1};#St={x:1,y:1,z:1};#pt={x:0,y:0};#mt={x:0,y:0};#ft={x:0,y:0};#Dt={x:0,y:0};#Mt;#_e;#Ct;#rr;#or;#ei;#ar=!0;constructor(e){this.#tt=e,this.#tt.className+=" drawLayer"}setShapeHandler(e){this.#ei=e}getDataId(){return this.#Ct}getReferenceLayerId(){return this.#rr}#be=new He;getKonvaStage(){return this.#ir}getKonvaLayer(){return this.#ir.getLayers()[0]}getDrawController(){return this.#Mt}setPlaneHelper(e){this.#_e=e}getId(){return this.#tt.id}removeFromDOM(){this.#tt.remove()}getBaseSize(){return this.#lt}getOpacity(){return this.#ir.opacity()}setOpacity(e){this.#ir.opacity(Math.min(Math.max(e,0),1))}addFlipOffsetX(){const e=this.#ir.scale(),t=this.#ir.size();this.#Dt.x+=t.width/e.x;const n=this.#ir.offset();n.x+=this.#Dt.x,this.#ir.offset(n)}addFlipOffsetY(){const e=this.#ir.scale(),t=this.#ir.size();this.#Dt.y+=t.height/e.y;const n=this.#ir.offset();n.y+=this.#Dt.y,this.#ir.offset(n)}flipScaleX(){this.#St.x*=-1}flipScaleY(){this.#St.y*=-1}flipScaleZ(){this.#St.z*=-1}setScale(e,t){const n=this.#_e.getTargetOrientedPositiveXYZ({x:e.x*this.#St.x,y:e.y*this.#St.y,z:e.z*this.#St.z}),i={x:this.#ht.x*n.x,y:this.#ht.y*n.y},r=this.#ir.offset();if(1===Math.abs(e.x)&&1===Math.abs(e.y)&&1===Math.abs(e.z)){const e={x:r.x-this.#ft.x,y:r.y-this.#ft.y};this.#ft={x:0,y:0},this.#ir.offset(e)}else if(void 0!==t){let e=this.#_e.getPlaneOffsetFromOffset3D({x:t.getX(),y:t.getY(),z:t.getZ()});e={x:e.x+this.#pt.x,y:e.y+this.#pt.y};const n=Ji(r,this.#ir.scale(),i,e),o={x:this.#ft.x+n.x-r.x,y:this.#ft.y+n.y-r.y};this.#ft=o,this.#ir.offset(n)}this.#ir.scale(i),this.#sr(i)}initScale(e,t){const n=this.#_e.getTargetOrientedPositiveXYZ({x:e.x*this.#St.x,y:e.y*this.#St.y,z:e.z*this.#St.z}),i={x:this.#ht.x*n.x,y:this.#ht.y*n.y};this.#ir.scale(i),this.#ft={x:t.x/this.#ht.x,y:t.y/this.#ht.y};const r=this.#ir.offset();this.#ir.offset({x:r.x+this.#ft.x,y:r.y+this.#ft.y})}setOffset(e){const t=this.#_e.getPlaneOffsetFromOffset3D(e);this.#ir.offset({x:t.x+this.#mt.x+this.#pt.x+this.#ft.x+this.#Dt.x,y:t.y+this.#mt.y+this.#pt.y+this.#ft.y+this.#Dt.y})}setBaseOffset(e,t){const n=this.#_e.getNativeScrollDimIndex(),i=this.#_e.getPlaneOffsetFromOffset3D({x:0===n?e.getX():t.getX(),y:1===n?e.getY():t.getY(),z:2===n?e.getZ():t.getZ()}),r=this.#pt.x!==i.x||this.#pt.y!==i.y;if(r){const e=this.#ir.offset();this.#ir.offset({x:e.x-this.#pt.x+i.x,y:e.y-this.#pt.y+i.y}),this.#pt=i}return r}display(e){this.#tt.style.display=e?"":"none"}isVisible(){return""===this.#tt.style.display}draw(){this.#ir.draw()}initialise(e,t,n){this.#lt=e,this.#ct=t,this.#rr=n,this.#ir=new(ai().Stage)({container:this.#tt,width:this.#lt.x,height:this.#lt.y,listening:!1}),this.#ir.getContent().setAttribute("style","");const i=new(ai().Layer)({listening:!1,visible:!0});this.#ir.add(i)}setAnnotationGroup(e,t,n){if(this.#Ct=t,e.addEventListener("annotationadd",(e=>{this.#lr(e.data,!0),this.getKonvaLayer().draw()})),e.addEventListener("annotationupdate",(e=>{this.#cr(e.data),this.getKonvaLayer().draw()})),e.addEventListener("annotationremove",(e=>{this.#ur(e.data),this.getKonvaLayer().draw()})),e.addEventListener("annotationgroupeditablechange",(e=>{this.activateCurrentPositionShapes(e.data)})),this.#Mt=new ji(e),0!==e.getLength())for(const t of e.getList())this.#lr(t,!1),n(new si(t,this.getDrawController()))}activateCurrentPositionShapes(e){const t=this.getKonvaLayer();if(this.#ir.listening(!1),void 0!==this.#ei){this.#ei.disableAndResetEditor();const e=t.getChildren();for(const t of e)t instanceof ai().Group&&t.getChildren().forEach((e=>{e instanceof ai().Group&&this.#ei.removeShapeListeners(e)}))}const n=this.getDrawController();if(e&&n.getAnnotationGroup().isEditable()){this.#ir.listening(!0);const e=this.#dr().getChildren();0!==e.length&&t.listening(!0),void 0!==this.#ei&&e.forEach((e=>{if(e instanceof ai().Group){const t=n.getAnnotation(e.id());this.#ei.addShapeGroupListeners(e,t,this)}}))}t.draw()}#hr(e){let t;return t=void 0!==e.planePoints?e.planePoints:[e.planeOrigin],this.#Sr(t)}#Sr(e){let t="";for(const n of e)0!==t.length&&(t+="-"),t+=G([B(n.getX(),2),B(n.getY(),2),B(n.getZ(),2)]);return t}#gr(e){let t;const n=this.#hr(e),i=this.getKonvaLayer().getChildren(fi(n));if(0!==i.length){const n=i[0];if(!(n instanceof ai().Group))return;const r=n.getChildren(fi(e.id));0!==r.length&&r[0]instanceof ai().Group&&(t=r[0])}return t}#lr(e,t){if(!e.isCompatibleView(this.#_e))return;const n=this.#hr(e);let i=this.getKonvaLayer().getChildren(fi(n))[0];if(void 0===i&&(i=new(ai().Group)({id:n,name:"position-group",visible:t}),this.getKonvaLayer().add(i)),!(i instanceof ai().Group))return;const r=new ui,o=this.getKonvaStage();r.setZoomScale(o.scale());const a=e.getFactory().createShapeGroup(e,r);i.add(a),t&&void 0!==this.#ei&&this.#ei.addShapeGroupListeners(a,e,this),this.setLabelVisibility(a)}#ur(e){const t=this.#gr(e);return t instanceof ai().Group?(t.remove(),!0):(c.debug("No shape group to remove"),!1)}#cr(e){this.#ur(e)&&this.#lr(e,!0)}fitToContainer(e,t,n){this.#ir.width(e.x),this.#ir.height(e.y);const i={x:t*this.#ct.x,y:t*this.#ct.y},r={x:this.#ir.scale().x*i.x/this.#ht.x,y:this.#ir.scale().y*i.y/this.#ht.y};this.#ir.scale().x===r.x&&this.#ir.scale().y===r.y||(this.#ht=i,this.#ir.scale(r));const o={x:n.x/i.x,y:n.y/i.y},a={x:e.x/i.x,y:e.y/i.y},s={x:0!==this.#Dt.x?a.x:0,y:0!==this.#Dt.y?a.y:0};this.#mt.x===o.x&&this.#mt.y===o.y&&this.#Dt.x===s.x&&this.#Dt.y===s.y||(this.#ir.offset({x:this.#ir.offset().x+o.x-this.#mt.x+s.x-this.#Dt.x,y:this.#ir.offset().y+o.y-this.#mt.y+s.y-this.#Dt.y}),this.#Dt=s,this.#mt=o)}isAnnotationVisible(e){const t=this.#pr(e);return void 0!==t&&t.isVisible()}setAnnotationVisibility(e,t){const n=this.#pr(e);return void 0!==n&&(void 0===t&&(t=!n.isVisible()),n.visible(t),this.draw(),!0)}setLabelsVisibility(e){this.#ar=e;const t=this.getKonvaLayer().getChildren();for(const n of t)if(n instanceof ai().Group){const t=n.getChildren();for(const n of t)n instanceof ai().Group&&this.#mr(n,e)}}#mr(e,t){const n=e.getChildren(hi)[0];if(n instanceof ai().Label&&(void 0===t&&(t=!n.isVisible()),void 0!==n.getText()&&0!==n.getText().text().length)){n.visible(t);const i=e.getChildren((e=>"Line"===e.className&&"connector"===e.name()))[0];i&&i.visible(t)}}setLabelVisibility(e){this.#mr(e,this.#ar)}deleteDraw(e,t){}deleteDraws(e){}getNumberOfDraws(){const e=this.getKonvaLayer().getChildren();let t=0;for(const n of e)n instanceof ai().Group&&(t+=n.getChildren().length);return t}bindInteraction(){this.#ir.listening(!0),this.#tt.style.pointerEvents="auto";const e=Wn;for(let t=0;t<e.length;++t)this.#tt.addEventListener(e[t],this.#Fe)}unbindInteraction(){this.#ir.listening(!1),this.#tt.style.pointerEvents="none";const e=Wn;for(let t=0;t<e.length;++t)this.#tt.removeEventListener(e[t],this.#Fe)}setCurrentPosition(e,t){void 0===t&&(t=this.#_e.worldToIndex(e));const n=this.#_e.getPlanePoints(e);let i;i=this.#_e.isAquisitionOrientation()?[n[0]]:n;const r=this.#Sr(i);return this.#fr(r),this.#Fe({type:"positionchange",value:[t.getValues(),e.getValues()],valid:!0}),!0}#fr(e){this.#or=e;const t=this.getKonvaLayer().getChildren(gi);let n;for(let i=0,r=t.length;i<r;++i)n=!1,void 0!==e&&t[i].id()===e&&(n=!0),t[i].visible(n);this.getKonvaLayer().draw()}#dr(){if(void 0===this.#or)return;const e=this.getKonvaLayer().getChildren((e=>e.id()===this.#or));let t;return 1===e.length?e[0]instanceof ai().Group&&(t=e[0]):0===e.length?(t=new(ai().Group),t.name("position-group"),t.id(this.#or),t.visible(!0),this.getKonvaLayer().add(t)):c.warn("Unexpected number of draw position groups"),t}#pr(e){return this.getKonvaLayer().findOne("#"+e)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{e.srclayerid=this.getId(),e.dataid=this.#Ct,this.#be.fireEvent(e)};#sr(e){const t=2/e.x,n=2/e.y,i=this.#ir.find("Label");for(let e=0;e<i.length;++e)i[e].scale({x:t,y:n})}}function _i(e){const t=e.split("-layer-");return 2!==t.length&&c.warn("Not the expected layer div id format..."),{groupDivId:t[0],layerIndex:t[1],layerId:e}}function Ki(e){let t=null;const n=e.target.closest(".layer");return n&&void 0!==n.id&&(t=_i(n.id)),t}function Ji(e,t,n,i){const r=(i.x-e.x)*t.x,o=(i.y-e.y)*t.y;return{x:i.x-r/n.x,y:i.y-o/n.y}}class $i{#tt;#Dr=[];#dt={x:1,y:1,z:1};#Ht={x:1,y:1,z:1};#gt={x:0,y:0,z:0};#yr=void 0;#be=new He;#Cr=!1;#vr=[];#Ir;#Be;#vt=!1;#Ke;#Tr=!1;getPositionHelper(){if(this.#Tr&&(this.#Ke=void 0),void 0===this.#Ke){for(const e of this.#Dr)if(e instanceof _n){const t=e.getViewController().getPositionHelper();void 0===this.#Ke?this.#Ke=t:this.#Ke.merge(t)}this.#Tr=!1}return this.#Ke}constructor(e){this.#tt=e}getShowCrosshair(){return this.#Cr}setShowCrosshair(e){this.#Cr=e,e?(this.addEventListener("offsetchange",this.#Lr),this.addEventListener("zoomchange",this.#Lr),this.#Pr()):(this.removeEventListener("offsetchange",this.#Lr),this.removeEventListener("zoomchange",this.#Lr),this.#wr())}setImageSmoothing(e){this.#vt=e;for(const t of this.#Dr)t instanceof _n&&t.setImageSmoothing(e)}#Lr=e=>{this.#Pr()};getDivId(){let e;return null!==this.#tt&&(e=this.#tt.id),e}getScale(){return this.#dt}getBaseScale(){return this.#Ht}getAddedScale(){return{x:this.#dt.x/this.#Ht.x,y:this.#dt.y/this.#Ht.y,z:this.#dt.z/this.#Ht.z}}getOffset(){return this.#gt}getNumberOfLayers(){let e=0;return this.#Dr.forEach((t=>{void 0!==t&&e++})),e}includes(e){if(void 0===e)return!1;for(const t of this.#Dr)if(void 0!==t&&t.getId()===e)return!0;return!1}getViewLayers(e){void 0===e&&(e=function(){return!0});const t=[];for(const n of this.#Dr)n instanceof _n&&e(n)&&t.push(n);return t}someViewLayer(e){let t=!1;for(const n of this.#Dr)if(n instanceof _n&&e(n)){t=!0;break}return t}getDrawLayers(e){void 0===e&&(e=function(){return!0});const t=[];for(const n of this.#Dr)n instanceof Zi&&e(n)&&t.push(n);return t}getNumberOfViewLayers(){let e=0;return this.#Dr.forEach((t=>{void 0!==t&&t instanceof _n&&e++})),e}getActiveLayer(){let e;return void 0!==this.#yr&&(e=this.#Dr[this.#yr]),e}getActiveViewLayer(){let e;const t=this.getActiveLayer();return void 0!==t&&t instanceof _n&&(e=t),e}getBaseViewLayer(){let e;for(const t of this.#Dr)if(t instanceof _n){e=t;break}if(void 0!==e)return e;c.warn("No layer found")}getViewLayerById(e){const t=this.getViewLayers((function(t){return t.getId()===e}));let n;return 1===t.length&&(n=t[0]),n}getViewLayersByDataId(e){return this.getViewLayers((function(t){return t.getDataId()===e}))}searchViewLayers(e){const t=[];for(const n of this.#Dr)n instanceof _n&&n.getViewController().equalImageMeta(e)&&t.push(n);return t}getViewDataIndices(){const e=[];for(const t of this.#Dr)t instanceof _n&&e.push(t.getDataId());return e}getActiveDrawLayer(){let e;const t=this.getActiveLayer();return void 0!==t&&t instanceof Zi&&(e=t),e}getDrawLayerById(e){const t=this.getDrawLayers((function(t){return t.getId()===e}));let n;return 1===t.length&&(n=t[0]),n}getDrawLayersByDataId(e){return this.getDrawLayers((function(t){return t.getDataId()===e}))}setActiveLayer(e){this.#yr=e,this.#Fe({type:"activelayerchange",value:[this.#Dr[e]]})}setActiveLayerByDataId(e){let t;for(let n=0;n<this.#Dr.length;++n)if(void 0!==this.#Dr[n]&&this.#Dr[n].getDataId()===e){t=n;break}void 0!==t?this.setActiveLayer(t):c.warn("No layer to set as active with dataId: "+e)}addViewLayer(){const e=this.#Dr.length,t=this.#Or();this.#tt.append(t);const n=new _n(t);return n.setImageSmoothing(this.#vt),this.#Dr.push(n),this.setActiveLayer(e),this.#Ar(n),this.#Tr=!0,n}addDrawLayer(){this.#yr=this.#Dr.length;const e=this.#Or();this.#tt.append(e);const t=new Zi(e);return this.#Dr.push(t),this.#br(t),t}#Ar(e){e.addEventListener("positionchange",this.updateLayersToPositionChange);for(const t of Vn)e.addEventListener(t,this.#Fe);e.addEventListener("renderstart",this.#Fe),e.addEventListener("renderend",this.#Fe)}#xr(e){e.removeEventListener("positionchange",this.updateLayersToPositionChange);for(const t of Vn)e.removeEventListener(t,this.#Fe);e.removeEventListener("renderstart",this.#Fe),e.removeEventListener("renderend",this.#Fe),e.unbindImage()}#br(e){e.addEventListener("positionchange",this.updateLayersToPositionChange),e.addEventListener("positionchange",this.#Fe),e.addEventListener("drawcreate",this.#Fe),e.addEventListener("drawdelete",this.#Fe)}#Rr(e){e.removeEventListener("positionchange",this.updateLayersToPositionChange),e.removeEventListener("positionchange",this.#Fe),e.removeEventListener("drawcreate",this.#Fe),e.removeEventListener("drawdelete",this.#Fe)}#Or(){const e=document.createElement("div");return e.id=this.getDivId()+"-layer-"+this.#Dr.length,e.className="layer",e.style.pointerEvents="none",e}empty(){this.#Dr=[],this.#yr=void 0,this.#wr();const e=this.#tt.getElementsByClassName("layer");if(e)for(;e.length>0;)e[0].remove()}removeLayersByDataId(e){for(const t of this.#Dr)void 0!==t&&t.getDataId()===e&&this.removeLayer(t)}removeLayer(e){const t=this.#Dr.findIndex((t=>t===e));if(-1===t)throw new Error("Cannot find layer to remove");this.#yr===t&&(this.#yr=void 0),e instanceof _n?this.#xr(e):this.#Rr(e),this.#Dr[t]=void 0,e.removeFromDOM()}#Pr(e){let t;void 0===e&&(e=this.#Be),this.#wr();for(const e of this.#Dr)if(e instanceof _n){t=e;break}if(void 0===t)return void c.warn("No layer to show crosshair");const n=t.getViewController().getPlanePositionFromPosition(e),i=t.planePosToDisplay(n);if(void 0!==i.getY()){const e=document.createElement("hr");e.id=this.getDivId()+"-scroll-crosshair-horizontal",e.className="horizontal",e.style.width=this.#tt.offsetWidth+"px",e.style.left="0px",e.style.top=i.getY()+"px",this.#vr.push(e),this.#tt.appendChild(e)}if(void 0!==i.getX()){const e=document.createElement("hr");e.id=this.getDivId()+"-scroll-crosshair-vertical",e.className="vertical",e.style.width=this.#tt.offsetHeight+"px",e.style.left=i.getX()+"px",e.style.top="0px",this.#vr.push(e),this.#tt.appendChild(e)}}#wr(){for(const e of this.#vr)e.remove();this.#vr=[]}showTooltip(e){this.removeTooltipDiv();const t=this.getBaseViewLayer(),n=t.getViewController(),i=t.displayToPlanePos(e),r=n.getPositionFromPlanePoint(i),o=n.getRescaledImageValue(r);if(void 0!==o){const t=document.createElement("span");t.id="scroll-tooltip",t.style.left=e.getX()+10+"px",t.style.top=e.getY()+10+"px";let i=B(o,3).toString();void 0!==n.getPixelUnit()&&(i+=" "+n.getPixelUnit()),t.appendChild(document.createTextNode(i)),this.#Ir=t,this.#tt.appendChild(t)}}removeTooltipDiv(){void 0!==this.#Ir&&(this.#Ir.remove(),this.#Ir=void 0)}isPositionInBounds(e){return this.someViewLayer((function(t){return t.getViewController().isPositionInBounds(e)}))}canScroll(){return this.someViewLayer((function(e){return e.getViewController().canScroll()}))}moreThanOne(e){return this.someViewLayer((function(t){return t.getViewController().moreThanOne(e)}))}updateLayersToPositionChange=e=>{for(const e of this.#Dr)void 0!==e&&(e.removeEventListener("positionchange",this.updateLayersToPositionChange),e.removeEventListener("positionchange",this.#Fe));const t=new s(e.value[0]),n=new E(e.value[1]);this.#Be=n,this.#Cr&&this.#Pr(n);const i={};let r,o;for(const a of this.#Dr){if(void 0===a)continue;let s=!1;if(a instanceof _n){const e=a.getViewController(),t=e.getOrigin(),l=e.getOrigin(n);let c,u;if(void 0===o)r=t,o=l,c=new P(0,0,0),u=new P(0,0,0);else if(e.isPositionInBounds(n)&&void 0!==l){const e=r.minus(t);c=new P(e.getX(),e.getY(),e.getZ());const n=o.minus(l);u=new P(n.getX(),n.getY(),n.getZ())}void 0!==c&&void 0!==u&&(s=a.setBaseOffset(c,u,o,r),i[a.getId()]={scroll:c,plane:u})}if(a instanceof Zi){const e=i[a.getReferenceLayerId()];void 0!==e&&(s=a.setBaseOffset(e.scroll,e.plane))}let l=!1;a.getId()!==e.srclayerid&&(l=a.setCurrentPosition(n,t)),!l&&s&&a.draw()}for(const e of this.#Dr)void 0!==e&&(e.addEventListener("positionchange",this.updateLayersToPositionChange),e.addEventListener("positionchange",this.#Fe))};getDivToWorldSizeRatio(){if(0===this.#tt.offsetWidth&&0===this.#tt.offsetHeight)throw new Error("Cannot fit to zero sized container.");const e=this.getMaxWorldSize();if(void 0!==e){if(0===this.#tt.offsetHeight){const t=this.#tt.offsetWidth/e.x,n=e.y*t;this.#tt.style.height=n+"px"}return Math.min(this.#tt.offsetWidth/e.x,this.#tt.offsetHeight/e.y)}}fitToContainer(e){const t=this.getMaxWorldSize();if(void 0===t)return;const n={x:this.#tt.offsetWidth,y:this.#tt.offsetHeight},i={x:-.5*(n.x-Math.floor(t.x*e)),y:-.5*(n.y-Math.floor(t.y*e))};for(const t of this.#Dr)void 0!==t&&t.fitToContainer(n,e,i);this.#Cr&&this.#Pr()}getMaxWorldSize(){let e={x:0,y:0};for(const t of this.#Dr)if(t instanceof _n){const n=t.getImageWorldSize();n.x>e.x&&(e.x=n.x),n.y>e.y&&(e.y=n.y)}return 0===e.x&&0===e.y&&(e=void 0),e}flipScaleZ(){this.#Ht.z*=-1,this.setScale(this.#Ht)}addScale(e,t){const n={x:this.#dt.x*(1+e),y:this.#dt.y*(1+e),z:this.#dt.z*(1+e)};this.setScale(n,t)}setScale(e,t){this.#dt=e;for(const e of this.#Dr)void 0!==e&&e.setScale(this.#dt,t);const n=[e.x,e.y,e.z];void 0!==t&&(n.push(t.getX()),n.push(t.getY()),n.push(t.getZ())),this.#Fe({type:"zoomchange",value:n})}addTranslation(e){this.setOffset({x:this.#gt.x-e.x,y:this.#gt.y-e.y,z:this.#gt.z-e.z})}setOffset(e){this.#gt=e;for(const e of this.#Dr)void 0!==e&&e.setOffset(this.#gt);this.#Fe({type:"offsetchange",value:[this.#gt.x,this.#gt.y,this.#gt.z]})}reset(){this.setScale(this.#Ht),this.setOffset({x:0,y:0,z:0})}draw(){for(const e of this.#Dr)void 0!==e&&e.draw()}display(e){for(const t of this.#Dr)void 0!==t&&t.display(e)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}}const er={WindowLevelBinder:class{getEventType=function(){return"wlchange"};getCallback=function(e){return function(t){const n=e.getViewLayersByDataId(t.dataid);if(0!==n.length){const e=n[0].getViewController();if(2===t.value.length){const n=new u(t.value[0],t.value[1]);e.setWindowLevel(n)}3===t.value.length&&e.setWindowLevelPreset(t.value[2])}}}},PositionBinder:class{getEventType=function(){return"positionchange"};getCallback=function(e){return function(t){const n=t.value[1],i=e.getBaseViewLayer().getViewController(),r=i.getCurrentPosition(),o=r.length(),a=n.length;a!==o&&(a===o-1?n.push(r.get(o-1)):a===o+1&&n.pop()),i.setCurrentPosition(new E(n))}}},ZoomBinder:class{getEventType=function(){return"zoomchange"};getCallback=function(e){return function(t){const n={x:t.value[0],y:t.value[1],z:t.value[2]};let i;6===t.value.length&&(i=new F(t.value[3],t.value[4],t.value[5])),e.setScale(n,i),e.draw()}}},OffsetBinder:class{getEventType=function(){return"offsetchange"};getCallback=function(e){return function(t){e.setOffset({x:t.value[0],y:t.value[1],z:t.value[2]}),e.draw()}}},OpacityBinder:class{getEventType=function(){return"opacitychange"};getCallback=function(e){return function(t){if(void 0===t.dataid)return;const n=e.getViewLayersByDataId(t.dataid),i=e.getBaseViewLayer();0!==n.length&&i!==n[0]&&(n[0].setOpacity(t.value),n[0].draw())}}},ColourMapBinder:class{getEventType=function(){return"colourmapchange"};getCallback=function(e){return function(t){const n=e.getViewLayersByDataId(t.dataid);0!==n.length&&n[0].getViewController().setColourMap(t.value[0])}}}};class tr{#Fr=[];#Er;#vt=!1;#qr=[];#ii=null;getLayerGroup(e){return this.#Fr[e]}getNumberOfLayerGroups(){return this.#Fr.length}getActiveLayerGroup(){return this.getLayerGroup(this.#Er)}setActiveLayerGroup(e){void 0!==this.getLayerGroup(e)?this.#Er=e:c.warn("No layer group to set as active with index: "+e)}getViewLayersByDataId(e){let t=[];for(const n of this.#Fr)t=t.concat(n.getViewLayersByDataId(e));return t}getViewLayers(e){let t=[];for(const n of this.#Fr)t=t.concat(n.getViewLayers(e));return t}getDrawLayersByDataId(e){let t=[];for(const n of this.#Fr)t=t.concat(n.getDrawLayersByDataId(e));return t}getDrawLayers(e){let t=[];for(const n of this.#Fr)t=t.concat(n.getDrawLayers(e));return t}addLayerGroup(e){this.#Er=this.#Fr.length;const t=new $i(e);t.setImageSmoothing(this.#vt);const n=this.#ii&&0!==this.#ii.length;return n&&this.unbindLayerGroups(),this.#Fr.push(t),n&&this.bindLayerGroups(),t}getLayerGroupByDivId(e){return this.#Fr.find((function(t){return t.getDivId()===e}))}setBinders(e){if(null==e)throw new Error("Cannot set null or undefined binders");0!==this.#qr.length&&this.unbindLayerGroups(),this.#qr=e.slice(),this.bindLayerGroups()}empty(){this.unbindLayerGroups();for(const e of this.#Fr)e.empty();this.#Fr=[],this.#Er=void 0}removeLayersByDataId(e){for(const t of this.#Fr)t.removeLayersByDataId(e)}removeLayerGroup(e){const t=this.#Fr.findIndex((t=>t===e));if(-1===t)throw new Error("Cannot find layerGroup to remove");this.unbindLayerGroups(),e.empty(),this.#Fr.splice(t,1),this.#Er===t&&(this.#Er=void 0),this.bindLayerGroups()}reset(){for(const e of this.#Fr)e.reset()}draw(){for(const e of this.#Fr)e.draw()}fitToContainer(){let e;const t=[];for(let n=0;n<this.#Fr.length;++n){const i=this.#Fr[n].getDivToWorldSizeRatio();void 0!==i&&(t.push(n),(void 0===e||i<e)&&(e=i))}if(void 0!==e)for(let n=0;n<this.#Fr.length;++n)t.includes(n)&&this.#Fr[n].fitToContainer(e)}bindLayerGroups(){if(0!==this.#Fr.length&&1!==this.#Fr.length&&0!==this.#qr.length){this.#ii=new Array(this.#Fr.length);for(let e=0;e<this.#Fr.length;++e)for(let t=0;t<this.#qr.length;++t)this.#Ur(e,this.#qr[t])}}unbindLayerGroups(){if(0!==this.#Fr.length&&1!==this.#Fr.length&&0!==this.#qr.length&&this.#ii){for(let e=0;e<this.#Fr.length;++e)for(let t=0;t<this.#qr.length;++t)this.#Mr(e,this.#qr[t]);this.#ii=null}}setImageSmoothing(e){this.#vt=e;for(const t of this.#Fr)t.setImageSmoothing(e)}#Qr(e,t){void 0===this.#ii[t]&&(this.#ii[t]=[]);let n=this.#ii[t].find((function(t){return t.binder===e}));return void 0===n&&(n={binder:e,callback:n=>{this.#Mr(t,e),e.getCallback(this.#Fr[t])(n),this.#Ur(t,e)}},this.#ii[t].push(n)),n.callback}#Ur(e,t){for(let n=0;n<this.#Fr.length;++n)n!==e&&this.#Fr[e].addEventListener(t.getEventType(),this.#Qr(t,n))}#Mr(e,t){for(let n=0;n<this.#Fr.length;++n)n!==e&&this.#Fr[e].removeEventListener(t.getEventType(),this.#Qr(t,n))}}class nr{#Ct;constructor(e){this.#Ct=e}fromJSON(e){const t=JSON.parse(e);let n=null;if("0.1"===t.version)n=this.#Vr(t);else if("0.2"===t.version)n=this.#Nr(t);else if("0.3"===t.version)n=this.#Br(t);else if("0.4"===t.version)n=this.#Gr(t);else{if("0.5"!==t.version)throw new Error("Unknown state file format version: '"+t.version+"'.");n=this.#kr(t)}return n}apply(e,t){const n=e.getActiveLayerGroup().getBaseViewLayer().getViewController(),i=new u(t["window-center"],t["window-width"]);n.setWindowLevel(i),n.setCurrentIndex(new s(t.position));const r=e.getActiveLayerGroup().getBaseScale();let o=null,a=null;if(void 0!==t.scaleCenter){o={x:t.scale*r.x,y:t.scale*r.y,z:1};const e=t.scaleCenter.x-t.scaleCenter.x*t.scale,n=t.scaleCenter.y-t.scaleCenter.y*t.scale,i=e+t.translation.x*o.x,s=n+t.translation.y*o.y;a={x:-i/o.x,y:-s/o.y,z:0}}else o={x:t.scale.x*r.x,y:t.scale.y*r.y,z:r.z},a={x:t.offset.x,y:t.offset.y,z:0};e.getActiveLayerGroup().setScale(o),e.getActiveLayerGroup().setOffset(a),e.setDrawings(t.drawings,t.drawingsDetails,this.#Ct)}#Vr(e){const t=function(e){const t=[],n={};let i,r;for(let o=0,a=e.length;o<a;++o){t[o]=[];for(let a=0,s=e[o].length;a<s;++a){i=e[o][a];const s=[];for(let e=0,t=i.length;e<t;++e){r=ai().Node.create(i[e]),r.visible(!0);let t={x:0,y:0};const o=r.getChildren((function(e){return"shape"===e.name()}))[0];if(o.stroke(T(o.stroke())),"line-group"===r.name()){r.name("ruler-group");const e=new(ai().Line)({points:[o.points()[0],o.points()[1],o.points()[0],o.points()[1]],name:"shape-tick0"});r.add(e);const t=new(ai().Line)({points:[o.points()[2],o.points()[3],o.points()[2],o.points()[3]],name:"shape-tick1"});r.add(t)}const a=r.getChildren((function(e){return"arc"===e.name()}));1===a.length&&a[0].name("shape-arc");const l=r.getChildren((function(e){return"text"===e.name()}));let c=new(ai().Text)({name:"text",text:""});1===l.length?(t.x=l[0].x(),t.y=l[0].y(),l[0].remove(),c=l[0]):0!==o.points().length&&(t={x:o.points()[0],y:o.points()[1]});const u=new(ai().Label)({x:t.x,y:t.y,name:"label"});u.add(c),u.add(new(ai().Tag)),r.add(u),s.push(JSON.stringify(r.toObject()));let d=c.text();const h=d.length;let S=null;"ruler-group"===r.name()?(S={length:{value:parseFloat(d.substring(0,h-2)),unit:d.substring(-2)}},d="{length}"):"ellipse-group"===r.name()||"rectangle-group"===r.name()?(S={surface:{value:parseFloat(d.substring(0,h-3)),unit:d.substring(-3)}},d="{surface}"):"protractor-group"!==r.name()&&"rectangle-group"!==r.name()||(S={angle:{value:parseFloat(d.substring(0,h-1)),unit:d.substring(-1)}},d="{angle}"),n[r.id()]={textExpr:d,longText:"",quant:S}}t[o].push(s)}}return{drawings:t,drawingsDetails:n}}(e.drawings);return e.drawings=ir(t.drawings).toObject(),e.drawingsDetails=rr(t.drawingsDetails),(e=or(e)).drawings=ar(e.drawings),e}#Nr(e){return e.drawings=ir(e.drawings).toObject(),e.drawingsDetails=rr(function(e){const t={},n="string"==typeof e?JSON.parse(e):e;for(let e=0,i=n.length;e<i;++e)for(let i=0,r=n[e].length;i<r;++i)for(let r=0,o=n[e][i].length;r<o;++r){const o=n[e][i][r];t[o.id]={textExpr:o.textExpr,longText:o.longText,quant:o.quant}}return t}(e.drawingsDetails)),(e=or(e)).drawings=ar(e.drawings),e}#Br(e){return e.drawingsDetails=rr(e.drawingsDetails),(e=or(e)).drawings=ar(e.drawings),e}#Gr(e){return(e=or(e)).drawings=ar(e.drawings),e}#kr(e){return e}}function ir(e){let t,n,i;const r=new(ai().Layer)({listening:!1,visible:!0}),o="string"==typeof e?JSON.parse(e):e;for(let e=0,l=o.length;e<l;++e)for(let l=0,c=o[e].length;l<c;++l)if(n=o[e][l],0!==n.length){i=new(ai().Group)({id:(a=new s([1,1,e,l]),"slice-"+a.get(2)+"_frame-"+(4===a.length()?a.get(3):0)),name:"position-group",visible:!1});for(let e=0,r=n.length;e<r;++e)t=ai().Node.create(n[e]),t.draggable(!0),t.getChildren().forEach((function(e){e.draggable(!1)})),i.add(t);r.add(i)}var a;return r}function rr(e){const t={},n=Object.keys(e);for(let i=0,r=n.length;i<r;++i){const r=e[n[i]];t[n[i]]={meta:{textExpr:r.textExpr,longText:r.longText,quantification:r.quant}}}return t}function or(e){const t=e.position;return e.position=[t.i,t.j,t.k],e}function ar(e){const t=e.children;for(let e=0,n=t.length;e<n;++e){const n=t[e],i=n.attrs.id.split("_"),r=parseInt(i[0].substring(6),10),o=parseInt(i[1].substring(6),10);let a="#2-";a+=0===r&&0!==o?o:r,n.attrs.id=a}return e}function sr(e){let t;return"null"!==window.location.origin&&(t=window.location.origin),new URL(e,t)}function lr(e){const t={};let n=null;if(e&&-1!==(n=e.indexOf("?"))){t.base=e.substring(0,n);let i=e.indexOf("#");-1===i&&(i=e.length);const r=e.substring(n+1,i);t.query=function(e){const t={};if(e){const n=e.split("&");for(let e=0;e<n.length;++e){const i=n[e].split("=");t[i[0]]?(t[i[0]]instanceof Array||(t[i[0]]=[t[i[0]]]),t[i[0]].push(i[1])):t[i[0]]=i[1]}}return t}(r)}return t}class cr{#Hr=[];#zr=0;#be=new He;getStackSize(){return this.#Hr.length}getCurrentStackIndex(){return this.#zr}add(e){this.#Hr=this.#Hr.slice(0,this.#zr),this.#Hr.push(e),++this.#zr,this.#Fe({type:"undoadd",command:e.getName()})}remove(e){let t=!1;const n=this.#Hr.findIndex((function(t){return t.getName()===e}));return-1!==n&&(this.#Hr.splice(n,1),--this.#zr,t=!0,this.#Fe({type:"undoremove",command:e})),t}undo(){this.#zr>0&&(--this.#zr,this.#Hr[this.#zr].undo(),this.#Fe({type:"undo",command:this.#Hr[this.#zr].getName()}))}redo(){this.#zr<this.#Hr.length&&(this.#Hr[this.#zr].execute(),this.#Fe({type:"redo",command:this.#Hr[this.#zr].getName()}),++this.#zr)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}}class ur{#Wr;#Yr=null;#ii=[];#Xr={};constructor(e){this.#Wr=e}init(){for(const e in this.#Wr)this.#Wr[e].init();this.enableShortcuts(!0)}enableShortcuts(e){e?window.addEventListener("keydown",this.#jr("window","keydown"),!0):window.removeEventListener("keydown",this.#jr("window","keydown"),!0)}getToolList(){return this.#Wr}hasTool(e){return void 0!==this.getToolList()[e]}getSelectedTool(){return this.#Yr}getSelectedToolEventHandler(e){return this.getSelectedTool()[e]}setSelectedTool(e){if(!this.hasTool(e))throw new Error("Unknown tool: '"+e+"'");this.#Yr&&this.#Yr.activate(!1),this.#Yr=this.#Wr[e],this.#Yr.activate(!0)}setToolFeatures(e){this.getSelectedTool()&&this.getSelectedTool().setFeatures(e)}bindLayerGroup(e,t){const n=e.getDivId();e.addEventListener("activelayerchange",this.#Zr(n)),this.#_r(n,t)}#_r(e,t){void 0!==this.#Xr[e]&&this.#Kr(this.#Xr[e]),this.#Xr[e]=t,this.#Jr(t)}#Zr(e){return t=>{const n=t.value[0];void 0!==n&&this.#_r(e,n)}}#Jr(e){e.bindInteraction();const t=Wn;for(let n=0;n<t.length;++n)e.addEventListener(t[n],this.#jr(e.getId(),t[n]))}#Kr(e){e.unbindInteraction();const t=Wn;for(let n=0;n<t.length;++n)e.removeEventListener(t[n],this.#jr(e.getId(),t[n]))}#jr(e,t){if(void 0===this.#ii[e]&&(this.#ii[e]=[]),void 0===this.#ii[e][t]){const n=e=>{if(this.#Yr){const t=this.#Yr[e.type];t&&t(e)}};this.#ii[e][t]=n}return this.#ii[e][t]}}class dr{#$r=[];#eo=2;#to;constructor(e){this.#to=e}setNumberOfDimensions(e){this.#eo=e}setNToLoad(e){for(let t=0;t<e;++t){this.#$r[t]=[];for(let e=0;e<this.#eo;++e)this.#$r[t][e]=0}}onprogress=e=>{if(!e.lengthComputable)return;if(void 0===e.subindex)return;if(void 0===e.index)return;const t=100*e.loaded/e.total;this.#$r[e.index][e.subindex]=t;let n=null;n=void 0!==e.item?e.item:{loaded:this.#no(e.index),total:100,source:e.source},this.#to({lengthComputable:!0,loaded:this.#io(),total:100,item:n})};#no(e){let t=0;for(let n=0;n<this.#eo;++n)t+=this.#$r[e][n];return t/this.#eo}#io(){let e=0;const t=this.#$r.length;for(let n=0;n<t;++n)e+=this.#no(n);return Math.round(e/t)}getMonoProgressHandler(e,t){return n=>{n.index=e,n.subindex=t,this.onprogress(n)}}getUndefinedMonoProgressHandler(e){return t=>{t.subindex=e,this.onprogress(t)}}}class hr{#ro=null;#oo=[];#ao=null;#so=0;#lo=0;#co;#E;getDefaultCharacterSet(){return this.#E}setDefaultCharacterSet(e){this.#E=e}#uo(e){this.#ro=e,this.#so=0,this.#lo=0,this.#co=!1,this.#do(),this.#ho()}#So(e){this.#oo.push(e)}#do(){this.#oo=[]}#go(e){this.#ao=e}#ho(){this.#ao=null}#po=e=>{this.#so++,this.#so===this.#ro.length&&this.onload({source:this.#ro})};#mo=e=>{this.#lo++,this.#lo===this.#ro.length&&this.onloadend({source:this.#ro})};#fo(e,t){return n=>{n.source=t,e(n)}}load(e,t){this.onloadstart({source:e}),1===e.length&&(M(e[0],"DICOMDIR")||M(e[0],".dcmdir"))?this.#Do(e[0],t):this.#yo(e,t)}#Co(e,t,n){return i=>{const r=i.target.status;200!==r&&0!==r?(this.onerror({source:t,error:"GET "+i.target.responseURL+" "+i.target.status+" ("+i.target.statusText+")",target:i.target}),this.#mo()):e.load(i.target.response,t,n)}}#yo(e,t){if(void 0===e||0===e.length)return;this.#uo(e);const n=new dr(this.onprogress);n.setNToLoad(e.length);const i=[];for(let e=0;e<go.length;++e)i.push(new go[e]);let r=e[0],o=null,a=!1;for(let s=0;s<i.length;++s)if(o=i[s],o.canLoadUrl(r,t)){a=!0,o.setOptions({numberOfFiles:e.length,defaultCharacterSet:this.getDefaultCharacterSet()}),o.onprogress=n.getUndefinedMonoProgressHandler(1),o.onloaditem=this.onloaditem,o.onload=this.#po,o.onloadend=this.#mo,o.onerror=this.onerror,o.onabort=this.onabort,this.#go(o);break}if(!a)throw new Error("No loader found for url: "+r);let s=0;const l=()=>{s<this.#oo.length-1&&!this.#co&&(++s,this.#oo[s].send(null))};for(let i=0;i<e.length;++i){if(r=e[i],!o.canLoadUrl(r,t))throw new Error("Input url of different type: "+r);const a=new XMLHttpRequest;if(a.open("GET",r,!0),void 0!==t){if(void 0!==t.requestHeaders){const e=t.requestHeaders;for(let t=0;t<e.length;++t)void 0!==e[t].name&&void 0!==e[t].value&&a.setRequestHeader(e[t].name,e[t].value)}void 0!==t.withCredentials&&(a.withCredentials=t.withCredentials)}a.onprogress=this.#fo(n.getMonoProgressHandler(i,0),r),a.onload=this.#Co(o,r,i),a.onloadend=l;const s=this.#fo(this.onerror,r);a.onerror=e=>{this.#mo(),s(e)};const c=this.#fo(this.ontimeout,r);a.ontimeout=e=>{this.#mo(),c(e)};const u=this.#fo(this.onabort,r);a.onabort=e=>{this.#mo(),u(e)},1===o.loadUrlAs()&&(a.responseType="arraybuffer"),this.#So(a)}let c=this.#oo.length;void 0!==t&&void 0!==t.batchSize&&0!==c&&(c=Math.min(t.batchSize,this.#oo.length));for(let e=0;e<c;++e)this.#co||(s=e,this.#oo[s].send(null))}#Do(e,t){const n=new XMLHttpRequest;n.open("GET",e,!0),n.responseType="arraybuffer",n.onload=n=>{const i=n.target.status;if(200!==i&&0!==i)this.onerror({source:e,error:"GET "+n.target.responseURL+" "+n.target.status+" ("+n.target.statusText+")",target:n.target}),this.onloadend({});else{const i=function(e){const t=new ke;t.parse(e);const n=t.getDicomElements();if(void 0===n["00041220"]||void 0===n["00041220"].value)return void c.warn("No Directory Record Sequence found in DICOMDIR.");const i=n["00041220"].value;if(0===i.length)return void c.warn("The Directory Record Sequence of the DICOMDIR is empty.");const r=[];let o=null,a=null;for(let e=0;e<i.length;++e){if(void 0===i[e]["00041430"]||void 0===i[e]["00041430"].value)continue;const t=i[e]["00041430"].value[0];if("STUDY"===t)a=[],r.push(a);else if("SERIES"===t)o=[],a.push(o);else if("IMAGE"===t){if(void 0===i[e]["00041500"]||void 0===i[e]["00041500"].value)continue;const t=i[e]["00041500"].value;o.push(t.join("/"))}}return r}(n.target.response)[0][0],r=e.split("/").slice(0,-1).join("/"),o=[];for(let e=0;e<i.length;++e)o.push(r+"/"+i[e]);this.#yo(o,t)}},n.onerror=t=>{this.#fo(this.onerror,e)(t),this.onloadend({})},n.onabort=t=>{this.#fo(this.onabort,e)(t),this.onloadend({})},n.send(null)}abort(){this.#co=!0;for(let e=0;e<this.#oo.length;++e)4!==this.#oo[e].readyState&&this.#oo[e].abort();this.#ao&&this.#ao.isLoading()&&this.#ao.abort()}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}ontimeout(e){}onabort(e){}}class Sr{constructor(e){this.poolSize=e,this.taskQueue=[],this.freeThreads=[];for(let t=0;t<e;++t)this.freeThreads.push(new gr(this));this.runningThreads=[]}addWorkerTask(e){if(this.freeThreads.length===this.poolSize&&this.onworkstart({type:"work-start"}),this.freeThreads.length>0){const t=this.freeThreads.shift();this.runningThreads.push(t),t.run(e)}else this.taskQueue.push(e)}abort(){this.#vo(),this.onabort({type:"work-abort"}),this.onworkend({type:"work-end"})}onTaskEnd(e){if(this.taskQueue.length>0){const t=this.taskQueue.shift();e.run(t)}else{e.stop(),this.freeThreads.push(e);for(let t=0;t<this.runningThreads.length;++t)this.runningThreads[t].getId()===e.getId()&&this.runningThreads.splice(t,1);this.freeThreads.length===this.poolSize&&(this.onwork({type:"work"}),this.onworkend({type:"work-end"}))}}handleWorkerError=e=>{this.#vo(),this.onerror({error:e}),this.onworkend({type:"work-end"})};#vo(){this.taskQueue=[];for(let e=0;e<this.runningThreads.length;++e)this.runningThreads[e].stop();this.runningThreads=[]}onworkstart(e){}onworkitem(e){}onwork(e){}onworkend(e){}onerror(e){}onabort(e){}}class gr{constructor(e){this.parentPool=e,this.id=Math.random().toString(36).substring(2,15),this.runningTask=null,this.worker}getId(){return this.id}run(e){this.runningTask=e,void 0===this.worker&&(this.worker=new Worker(this.runningTask.script),this.worker.onmessage=this.onmessage,this.worker.onerror=this.onerror),this.worker.postMessage(this.runningTask.startMessage)}stop(){void 0!==this.worker&&(this.worker.terminate(),this.worker=void 0)}onmessage=e=>{e.itemNumber=this.runningTask.info.itemNumber,e.numberOfItems=this.runningTask.info.numberOfItems,e.index=this.runningTask.info.index,this.parentPool.onworkitem(e),this.parentPool.onTaskEnd(this)};onerror=e=>{e.itemNumber=this.runningTask.info.itemNumber,e.numberOfItems=this.runningTask.info.numberOfItems,e.index=this.runningTask.info.index,this.parentPool.handleWorkerError(e),this.stop()}}class pr{constructor(e,t,n){this.script=e,this.startMessage=t,this.info=n}}const mr="undefined"!=typeof JpegImage,fr="undefined"!=typeof jpeg&&void 0!==jpeg.lossless,Dr="undefined"!=typeof JpxImage,yr={jpeg2000:"","jpeg-lossless":"","jpeg-baseline":"",rle:""};class Cr{#Io;#To=new Sr(10);#Lo=!1;constructor(e,t){this.#Io=e}decode(e,t,n){this.#Lo||(this.#Lo=!0,this.#To.onworkstart=this.ondecodestart,this.#To.onworkitem=this.ondecodeditem,this.#To.onwork=this.ondecoded,this.#To.onworkend=this.ondecodeend,this.#To.onerror=this.onerror,this.#To.onabort=this.onabort);const i=new pr(this.#Io,{buffer:e,meta:t},n);this.#To.addWorkerTask(i)}abort(){this.#To.abort()}ondecodestart(e){}ondecodeditem(e){}ondecoded(e){}ondecodeend(e){}onerror(e){}onabort(e){}}class vr{#Po;#wo;constructor(e,t){this.#Po=e,this.#wo=t}#Oo=0;decode(e,t,n){++this.#Oo;let i=null,r=null;if("jpeg-lossless"===this.#Po){if(!fr)throw new Error("No JPEG Lossless decoder provided");const n=t.bitsAllocated/8,o=new Uint8Array(e);i=new jpeg.lossless.Decoder;const a=i.decode(o.buffer,0,o.buffer.byteLength,n);8===t.bitsAllocated?r=t.isSigned?new Int8Array(a.buffer):new Uint8Array(a.buffer):16===t.bitsAllocated&&(r=t.isSigned?new Int16Array(a.buffer):new Uint16Array(a.buffer))}else if("jpeg-baseline"===this.#Po){if(!mr)throw new Error("No JPEG Baseline decoder provided");i=new JpegImage,i.parse(e),r=i.getData(i.width,i.height)}else if("jpeg2000"===this.#Po){if(!Dr)throw new Error("No JPEG 2000 decoder provided");i=new JpxImage,i.parse(e),r=i.tiles[0].items}else"rle"===this.#Po&&(i=new dwvdecoder.RleDecoder,r=i.decode(e,t.bitsAllocated,t.isSigned,t.sliceSize,t.samplesPerPixel,t.planarConfiguration));this.ondecodeditem({data:[r],index:n.index,numberOfItems:n.numberOfItems,itemNumber:n.itemNumber}),this.#Oo===this.#wo&&(this.ondecoded({}),this.ondecodeend({}))}abort(){this.onabort({}),this.ondecodeend({})}ondecodestart(e){}ondecodeditem(e){}ondecoded(e){}ondecodeend(e){}onerror(e){}onabort(e){}}class Ir{#Lo=!1;#Ao=null;constructor(e,t){void 0!==yr&&void 0!==yr[e]?this.#Ao=new Cr(yr[e],t):this.#Ao=new vr(e,t)}decode(e,t,n){this.#Lo||(this.#Lo=!0,this.#Ao.ondecodestart=this.ondecodestart,this.#Ao.ondecodeditem=this.ondecodeditem,this.#Ao.ondecoded=this.ondecoded,this.#Ao.ondecodeend=this.ondecodeend,this.#Ao.onerror=this.onerror,this.#Ao.onabort=this.onabort),this.#Ao.decode(e,t,n)}abort(){this.#Ao.abort()}ondecodestart(e){}ondecodeditem(e){}ondecoded(e){}ondecodeend(e){}onerror(e){}onabort(e){}}const Tr={NumericValue:"0040A30A",FloatingPointValue:"0040A161",RationalNumeratorValue:"0040A162",RationalDenominatorValue:"0040A163",MeasurementUnitsCodeSequence:"004008EA"};class Lr{numericValue;floatingPointValue;rationalNumeratorValue;rationalDenominatorValue;measurementUnitsCode;toString(){return this.numericValue+" "+this.measurementUnitsCode.toString()}}function Pr(e){const t={};return void 0!==e.measurementUnitsCode&&(t.MeasurementUnitsCodeSequence={value:[Wt(e.measurementUnitsCode)]}),void 0!==e.floatingPointValue&&(t.FloatingPointValue=e.floatingPointValue),void 0!==e.rationalNumeratorValue&&(t.RationalNumeratorValue=e.rationalNumeratorValue),void 0!==e.rationalDenominatorValue&&(t.RationalDenominatorValue=e.rationalDenominatorValue),void 0!==e.numericValue&&(t.NumericValue=e.numericValue),t}const wr={MeasuredValueSequence:"0040A300",NumericValueQualifierCodeSequence:"0040A301"};class Or{measuredValue;numericValueQualifierCode;toString(){let e=this.measuredValue.toString();return void 0!==this.numericValueQualifierCode&&(e+=" "+this.numericValueQualifierCode.toString()),e}}function Ar(e){const t={};return void 0!==e.measuredValue&&(t.MeasuredValueSequence={value:[Pr(e.measuredValue)]}),void 0!==e.numericValueQualifierCode&&(t.NumericValueQualifierCodeSequence={value:[Wt(e.numericValueQualifierCode)]}),t}const br={ReferencedSOPClassUID:"00081150",ReferencedSOPInstanceUID:"00081155"};class xr{referencedSOPClassUID;referencedSOPInstanceUID;toString(){return this.referencedSOPInstanceUID+" (class: "+this.referencedSOPClassUID+")"}}function Rr(e){const t=new xr;return void 0!==e[br.ReferencedSOPClassUID]&&(t.referencedSOPClassUID=e[br.ReferencedSOPClassUID].value[0]),void 0!==e[br.ReferencedSOPInstanceUID]&&(t.referencedSOPInstanceUID=e[br.ReferencedSOPInstanceUID].value[0]),t}function Fr(e){const t={};return void 0!==e.referencedSOPClassUID&&(t.ReferencedSOPClassUID=e.referencedSOPClassUID),void 0!==e.referencedSOPInstanceUID&&(t.ReferencedSOPInstanceUID=e.referencedSOPInstanceUID),t}const Er={ReferencedFrameNumber:"00081160",ReferencedSOPSequence:"00081199",ReferencedSegmentNumber:"0062000B"};class qr{referencedSOPSequence;referencedFrameNumber;referencedSegmentNumber;fiducialUID;toString(){return this.referencedSOPSequence.toString()}}function Ur(e){const t={};return void 0!==e.referencedFrameNumber&&(t.ReferencedFrameNumber=e.referencedFrameNumber),void 0!==e.referencedSOPSequence&&(t.ReferencedSOPSequence={value:[Fr(e.referencedSOPSequence)]}),void 0!==e.referencedSegmentNumber&&(t.ReferencedSegmentNumber=e.referencedSegmentNumber),t}const Mr={PixelOriginInterpretation:"00480301",GraphicData:"00700022",GraphicType:"00700023",FiducialUID:"0070031A"},Qr="POINT",Vr="MULTIPOINT",Nr="POLYLINE",Br="CIRCLE",Gr="ELLIPSE";class kr{graphicData;graphicType;pixelOriginInterpretation;fiducialUID;toString(){return this.graphicType+" {"+this.graphicData+"}"}}function Hr(e){const t={};return void 0!==e.pixelOriginInterpretation&&(t.PixelOriginInterpretation=e.pixelOriginInterpretation),void 0!==e.graphicData&&(t.GraphicData=e.graphicData),void 0!==e.graphicType&&(t.GraphicType=e.graphicType),void 0!==e.fiducialUID&&(t.FiducialUID=e.fiducialUID),t}const zr={GraphicData:"00700022",GraphicType:"00700023",ReferencedFrameofReferenceUID:"30060024",FiducialUID:"0070031A"};class Wr{graphicData;graphicType;referencedFrameofReferenceUID;fiducialUID;toString(){return this.graphicType+"{"+this.graphicData+"}"}}function Yr(e){const t={};return void 0!==e.graphicData&&(t.GraphicData=e.graphicData),void 0!==e.graphicType&&(t.GraphicType=e.graphicType),void 0!==e.referencedFrameofReferenceUID&&(t.ReferencedFrameofReferenceUID=e.referencedFrameofReferenceUID),void 0!==e.fiducialUID&&(t.FiducialUID=e.fiducialUID),t}const Xr={ReferencedSOPSequence:"00081199",RelationshipType:"0040A010",ValueType:"0040A040",ConceptNameCodeSequence:"0040A043",ConceptCodeSequence:"0040A168",ContentSequence:"0040A730",DateTime:"0040A120",Date:"0040A121",Time:"0040A122",UID:"0040A124",PersonName:"0040A123",TextValue:"0040A160",ContinuityOfContent:"0040A050"},jr="CONTAINS",Zr="HAS PROPERTIES",_r="SELECTED FROM",Kr={text:"TEXT",num:"NUM",code:"CODE",date:"DATE",time:"TIME",datetime:"DATETIME",uidref:"UIDREF",pname:"PNAME",composite:"COMPOSITE",image:"IMAGE",waveform:"WAVEFORM",scoord:"SCOORD",scoord3d:"SCOORD3D",tcoord:"TCOORD",container:"CONTAINER",table:"TABLE"},Jr={TEXT:"TextValue",DATE:"Date",TIME:"Time",DATETIME:"DateTime",UIDREF:"UID",PNAME:"PersonName",CONTAINER:"ContinuityOfContent"};class $r{valueType;conceptNameCode;relationshipType;contentSequence;value;constructor(e){this.valueType=e}toString(e){void 0===e&&(e="");let t="";if(void 0!==this.relationshipType&&(t+="("+this.relationshipType+") "),t+=this.valueType+": ",void 0!==this.conceptNameCode&&(t+=this.conceptNameCode.toString()),t+=" = "+this.value.toString(),void 0!==this.contentSequence)for(const n of this.contentSequence)t+="\n"+e+"- "+n.toString(e+"  ");return t}}function eo(e){let t="";void 0!==e[Xr.ValueType]&&(t=e[Xr.ValueType].value[0]);const n=new $r(t);if(void 0!==e[Xr.RelationshipType]&&(n.relationshipType=e[Xr.RelationshipType].value[0]),void 0!==e[Xr.ConceptNameCodeSequence]&&(n.conceptNameCode=zt(e[Xr.ConceptNameCodeSequence].value[0])),t===Kr.code)n.value=zt(e[Xr.ConceptCodeSequence].value[0]);else if(t===Kr.num)n.value=function(e){const t=new Or;return void 0!==e[wr.MeasuredValueSequence]&&(t.measuredValue=function(e){const t=new Lr;return void 0!==e[Tr.NumericValue]&&(t.numericValue=e[Tr.NumericValue].value[0]),void 0!==e[Tr.FloatingPointValue]&&(t.floatingPointValue=e[Tr.FloatingPointValue].value[0]),void 0!==e[Tr.RationalNumeratorValue]&&(t.rationalNumeratorValue=e[Tr.RationalNumeratorValue].value[0]),void 0!==e[Tr.RationalDenominatorValue]&&(t.rationalDenominatorValue=e[Tr.RationalDenominatorValue].value[0]),void 0!==e[Tr.MeasurementUnitsCodeSequence]&&(t.measurementUnitsCode=zt(e[Tr.MeasurementUnitsCodeSequence].value[0])),t}(e[wr.MeasuredValueSequence].value[0])),void 0!==e[wr.NumericValueQualifierCodeSequence]&&(t.numericValueQualifierCode=zt(e[wr.NumericValueQualifierCodeSequence].value[0])),t}(e);else if(t===Kr.image)n.value=function(e){const t=new qr;return void 0!==e[Er.ReferencedFrameNumber]&&(t.referencedFrameNumber=e[Er.ReferencedFrameNumber].value[0]),void 0!==e[Er.ReferencedSOPSequence]&&(t.referencedSOPSequence=Rr(e[Er.ReferencedSOPSequence].value[0])),void 0!==e[Er.ReferencedSegmentNumber]&&(t.referencedSegmentNumber=e[Er.ReferencedSegmentNumber].value[0]),t}(e);else if(t===Kr.composite)n.value=Rr(e[Xr.ReferencedSOPSequence].value[0]);else if(t===Kr.scoord)n.value=function(e){const t=new kr;return void 0!==e[Mr.GraphicData]&&(t.graphicData=e[Mr.GraphicData].value),void 0!==e[Mr.GraphicType]&&(t.graphicType=e[Mr.GraphicType].value[0]),void 0!==e[Mr.PixelOriginInterpretation]&&(t.pixelOriginInterpretation=e[Mr.PixelOriginInterpretation].value[0]),void 0!==e[Mr.FiducialUID]&&(t.fiducialUID=e[Mr.FiducialUID].value[0]),t}(e);else if(t===Kr.scoord3d)n.value=function(e){const t=new Wr;return void 0!==e[zr.GraphicData]&&(t.graphicData=e[zr.GraphicData].value),void 0!==e[zr.GraphicType]&&(t.graphicType=e[zr.GraphicType].value[0]),void 0!==e[zr.ReferencedFrameofReferenceUID]&&(t.referencedFrameofReferenceUID=e[zr.ReferencedFrameofReferenceUID].value[0]),void 0!==e[zr.FiducialUID]&&(t.fiducialUID=e[zr.FiducialUID].value[0]),t}(e);else{const i=Jr[t];void 0!==i?n.value=e[Xr[i]].value[0]:console.warn("Unsupported input ValueType: "+t)}if(void 0!==e[Xr.ContentSequence]){n.contentSequence=[];for(const t of e[Xr.ContentSequence].value)n.contentSequence.push(eo(t))}return n}function to(e){let t={};if(void 0!==e.relationshipType&&(t.RelationshipType=e.relationshipType),void 0!==e.valueType&&(t.ValueType=e.valueType),void 0!==e.conceptNameCode&&(t.ConceptNameCodeSequence={value:[Wt(e.conceptNameCode)]}),"CODE"===e.valueType)t.ConceptCodeSequence={value:[Wt(e.value)]};else if(e.valueType===Kr.num)t={...t,...Ar(e.value)};else if(e.valueType===Kr.image)t={...t,...Ur(e.value)};else if(e.valueType===Kr.composite)t={...t,...Fr(e.value)};else if(e.valueType===Kr.scoord)t={...t,...Hr(e.value)};else if(e.valueType===Kr.scoord3d)t={...t,...Yr(e.value)};else{const n=Jr[e.valueType];void 0!==n?t[n]=e.value:console.warn("Unsupported output ValueType: "+e.valueType)}if(void 0!==e.contentSequence){t.ContentSequence={value:[]};for(const n of e.contentSequence)t.ContentSequence.value.push(to(n))}return t}function no(e,t,n){const i=function(e){const t=rn[e];let n;return void 0!==t&&(n=Zt(t.key,t.scheme)),n}(e);if(void 0===i)return;const r=new $r(Kr.num);r.relationshipType=jr,r.conceptNameCode=i;const o=new Lr;o.numericValue=t,o.measurementUnitsCode=function(e){const t=an[e];let n;return void 0!==t?n=Zt(t,"UCUM"):void 0===t&&(n=Zt("1","UCUM")),n}(n);const a=new Or;return a.measuredValue=o,r.value=a,r}class io{#ee;getWarning(){return this.#ee}checkElements(e){this.#ee=void 0;const t=eo(e);return void 0!==t.conceptNameCode?t.conceptNameCode.value!==_t().value&&(this.#ee="Not a measurement group"):this.#ee="No root concept name code",this.#ee}#bo(e){const t=new Yi;t.mathShape=function(e){const t=e.graphicData.length;if(t%2!=0)throw new Error("Expecting even number of coordinates in scroord data");const n=[];for(let i=0;i<t;i+=2)n.push(new R(parseFloat(e.graphicData[i]),parseFloat(e.graphicData[i+1])));let i=!1;const r=n.length;if(r>2){const e=n[0],t=n[r-1];i=e.equals(t)}let o;if(e.graphicType===Qr){if(1!==n.length)throw new Error("Expecting 1 point for point");o=n[0]}else if(e.graphicType===Br){if(2!==n.length)throw new Error("Expecting 2 points for circles");const e=n[0],t=n[1].getDistance(e);o=new Fi(e,t)}else if(e.graphicType===Gr){if(4!==n.length)throw new Error("Expecting 4 points for ellipses");const e=n[0].getDistance(n[1])/2,t=n[2].getDistance(n[3])/2,i=new R(n[0].getX()+e,n[0].getY());o=new Ei(i,e,t)}else if(e.graphicType===Nr)if(i)if(5===n.length){const e=new $n(n[0],n[1]),t=new $n(n[1],n[2]),i=new $n(n[2],n[3]),r=new $n(n[3],n[4]);o=ti(e,t)&&ti(t,i)&&ti(i,r)?new Mi(n[0],n[2]):new Ti(n.slice(0,-1))}else o=new Ti(n.slice(0,-1));else 2===n.length?o=new $n(n[0],n[1]):3===n.length&&(o=new Ui([n[0],n[1],n[2]]));return o}(e.value),t.id=et(),t.textExpr="";for(const n of e.contentSequence){if(n.valueType===Kr.image&&n.relationshipType===_r&&Ht(n.conceptNameCode,Jt())&&(t.referenceSopUID=n.value.referencedSOPSequence.referencedSOPInstanceUID),n.valueType===Kr.uidref&&n.relationshipType===Zr&&Ht(n.conceptNameCode,$t())&&(t.id=n.value),n.valueType===Kr.text&&n.relationshipType===Zr&&Ht(n.conceptNameCode,en())&&(t.textExpr=n.value,void 0!==n.contentSequence))for(const e of n.contentSequence)e.valueType===Kr.scoord&&e.relationshipType===Zr&&Ht(e.conceptNameCode,tn())&&(t.labelPosition=new R(e.value.graphicData[0],e.value.graphicData[1]));if(n.valueType===Kr.text&&n.relationshipType===Zr&&Ht(n.conceptNameCode,nn())&&(t.colour=n.value),n.valueType===Kr.scoord&&n.relationshipType===Zr&&Ht(n.conceptNameCode,tn())&&n.value.graphicType===Vr){const e=[];for(let t=0;t<n.value.graphicData.length;t+=2)e.push(new R(n.value.graphicData[t],n.value.graphicData[t+1]));t.referencePoints=e}if(n.valueType===Kr.scoord3d&&n.relationshipType===Zr&&Ht(n.conceptNameCode,Kt())&&n.value.graphicType===Vr){const e=n.value.graphicData,i=[],r=Math.floor(e.length/3);for(let t=0;t<r;++t){const n=3*t;i.push(new F(e[n],e[n+1],e[n+2]))}t.planePoints=i}if(n.valueType===Kr.num&&n.relationshipType===jr){const e=on(n.conceptNameCode);if(void 0===e)continue;const i=n.value.measuredValue,r=sn(i.measurementUnitsCode);void 0===t.quantification&&(t.quantification={}),t.quantification[e]={value:i.numericValue,unit:r}}}return t}create(e){const t=[],n=eo(e);for(const e of n.contentSequence)e.valueType===Kr.scoord&&t.push(this.#bo(e));const i=new Xi(t),r=function(t){return Ie(e,t)};i.setMetaValue("StudyInstanceUID",r("0020000D")),i.setMetaValue("Modality",r("00080060")),i.setMetaValue("PatientName",r("00100010")),i.setMetaValue("PatientID",r("00100020")),i.setMetaValue("PatientBirthDate",r("00100030")),i.setMetaValue("PatientSex",r("00100040"));const o=e["00081115"];if(void 0!==o){const e=o.value[0]["0020000E"];void 0!==e&&i.setMetaValue("ReferencedSeriesSequence",{value:[{SeriesInstanceUID:e.value[0]}]})}return i}#xo(e){const t=new $r(Kr.scoord);t.relationshipType=jr,e.mathShape instanceof $n?t.conceptNameCode=Zt("121055","DCM"):t.conceptNameCode=Zt("111030","DCM"),t.value=function(e){const t=new kr;if(e instanceof R)t.graphicData=[e.getX().toString(),e.getY().toString()],t.graphicType=Qr;else if(e instanceof $n)t.graphicData=[e.getBegin().getX().toString(),e.getBegin().getY().toString(),e.getEnd().getX().toString(),e.getEnd().getY().toString()],t.graphicType=Nr;else if(e instanceof Ui){t.graphicData=[];for(let n=0;n<3;++n)t.graphicData.push(e.getPoint(n).getX().toString()),t.graphicData.push(e.getPoint(n).getY().toString());t.graphicType=Nr}else if(e instanceof Ti){t.graphicData=[];for(let n=0;n<e.getLength();++n)t.graphicData.push(e.getPoint(n).getX().toString()),t.graphicData.push(e.getPoint(n).getY().toString());const n=e.getPoint(0);t.graphicData.push(n.getX().toString()),t.graphicData.push(n.getY().toString()),t.graphicType=Nr}else if(e instanceof Fi){const n=e.getCenter(),i=new R(n.getX()+e.getRadius(),n.getY());t.graphicData=[n.getX().toString(),n.getY().toString(),i.getX().toString(),i.getY().toString()],t.graphicType=Br}else if(e instanceof Ei){const n=e.getCenter(),i=e.getA(),r=e.getB();t.graphicData=[(n.getX()-i).toString(),n.getY().toString(),(n.getX()+i).toString(),n.getY().toString(),n.getX().toString(),(n.getY()-r).toString(),n.getX().toString(),(n.getY()+r).toString()],t.graphicType=Gr}else if(e instanceof Mi){const n=e.getBegin(),i=e.getEnd();t.graphicData=[n.getX().toString(),n.getY().toString(),n.getX().toString(),i.getY().toString(),i.getX().toString(),i.getY().toString(),i.getX().toString(),n.getY().toString(),n.getX().toString(),n.getY().toString()],t.graphicType=Nr}return t}(e.mathShape);const n=[],i=new $r(Kr.image);i.relationshipType=_r,i.conceptNameCode=Jt();const r=new xr;r.referencedSOPClassUID="",r.referencedSOPInstanceUID=e.referenceSopUID;const o=new qr;o.referencedSOPSequence=r,i.value=o,n.push(i);const a=new $r(Kr.uidref);a.relationshipType=Zr,a.conceptNameCode=$t(),a.value=e.id,n.push(a);const s=new $r(Kr.text);if(s.relationshipType=Zr,s.conceptNameCode=en(),s.value=e.textExpr,void 0!==e.labelPosition){const t=new $r(Kr.scoord);t.relationshipType=Zr,t.conceptNameCode=tn();const n=new kr;n.graphicType=Qr;const i=[e.labelPosition.getX().toString(),e.labelPosition.getY().toString()];n.graphicData=i,t.value=n,s.contentSequence=[t]}n.push(s);const l=new $r(Kr.text);if(l.relationshipType=Zr,l.conceptNameCode=nn(),l.value=e.colour,n.push(l),void 0!==e.referencePoints){const t=new $r(Kr.scoord);t.relationshipType=Zr,t.conceptNameCode=tn();const i=new kr;i.graphicType=Vr;const r=[];for(const t of e.referencePoints)r.push(t.getX().toString()),r.push(t.getY().toString());i.graphicData=r,t.value=i,n.push(t)}if(void 0!==e.planePoints){const t=new $r(Kr.scoord3d);t.relationshipType=Zr,t.conceptNameCode=Kt();const i=new Wr;i.graphicType=Vr;const r=[];for(const t of e.planePoints)r.push(t.getX().toString()),r.push(t.getY().toString()),r.push(t.getZ().toString());i.graphicData=r,t.value=i,n.push(t)}if(void 0!==e.quantification)for(const t in e.quantification){const i=no(t,e.quantification[t].value,e.quantification[t].unit);void 0!==i&&n.push(i)}return t.contentSequence=n,t}toDicom(e,t){let n=e.getMeta();n.TransferSyntaxUID="1.2.840.10008.1.2.1",n.SOPClassUID="1.2.840.10008.5.1.4.1.1.88.11",n.MediaStorageSOPClassUID="1.2.840.10008.5.1.4.1.1.88.11",n.CompletionFlag="PARTIAL",n.VerificationFlag="UNVERIFIED";const i=new Date;n.ContentDate=dt(ct(i)),n.ContentTime=ht(ut(i));const r=[];for(const t of e.getList())r.push(this.#xo(t));if(0!==r.length){const e=new $r(Kr.container);e.conceptNameCode=_t(),e.contentSequence=r,n={...n,...to(e)}}return void 0!==t&&function(e,t){const n=Object.keys(t);for(const i of n)void 0!==e[i]&&c.trace("Overwritting tag: "+i),e[i]=t[i]}(n,t),Bt(n)}}class ro{meta;image;annotationGroup;constructor(e){this.meta=e}}class oo{#Ro={};#Fo=-1;#be=new He;getNextDataId(){return++this.#Fo,this.#Fo.toString()}getDataIds(){return Object.keys(this.#Ro)}reset(){this.#Ro={}}get(e){return this.#Ro[e]}getDataIdsFromSopUids(e){const t=[];if(void 0===e||0===e.length)return t;const n=Object.keys(this.#Ro);for(const i of n)void 0!==this.#Ro[i].image&&this.#Ro[i].image.containsImageUids(e)&&t.push(i);return t}setImage(e,t){this.#Ro[e].image=t,this.#Fe({type:"dataimageset",value:[t],dataid:e}),t.addEventListener("imagecontentchange",this.#Eo(e)),t.addEventListener("imagegeometrychange",this.#Eo(e))}add(e,t){if(void 0!==this.#Ro[e])throw new Error("Data id already used in storage: "+e);this.#Ro[e]=t,this.#Fe({type:"dataadd",dataid:e}),void 0!==t.image&&(t.image.addEventListener("imagecontentchange",this.#Eo(e)),t.image.addEventListener("imagegeometrychange",this.#Eo(e))),void 0!==t.annotationGroup&&(t.annotationGroup.addEventListener("annotationadd",this.#Eo(e)),t.annotationGroup.addEventListener("annotationupdate",this.#Eo(e)),t.annotationGroup.addEventListener("annotationremove",this.#Eo(e)))}remove(e){if(void 0!==this.#Ro[e]){const t=this.#Ro[e].image;void 0!==t&&(t.removeEventListener("imagecontentchange",this.#Eo(e)),t.removeEventListener("imagegeometrychange",this.#Eo(e)));const n=this.#Ro[e].annotationGroup;void 0!==n&&(n.removeEventListener("annotationadd",this.#Eo(e)),n.removeEventListener("annotationupdate",this.#Eo(e)),n.removeEventListener("annotationremove",this.#Eo(e))),delete this.#Ro[e],this.#Fe({type:"dataremove",dataid:e})}}update(e,t){if(void 0===this.#Ro[e])throw new Error("Cannot find data to update: "+e);const n=this.#Ro[e];void 0!==n.image&&void 0!==t.image&&n.image.appendSlice(t.image);let i="";i=void 0!==t.meta["00020010"]?"00200013":"imageUid",n.meta=function(e,t,n,i){const r={};if(!n)throw new Error("Cannot merge object with an undefined id key: "+n);if(!Object.prototype.hasOwnProperty.call(e,n))throw new Error("Id key not found in first object while merging: "+n+", obj: "+e);if(!Object.prototype.hasOwnProperty.call(t,n))throw new Error("Id key not found in second object while merging: "+n+", obj: "+t);let o=!1;if(Object.prototype.hasOwnProperty.call(e[n],"merged")&&e[n].merged&&(o=!0),!Object.prototype.hasOwnProperty.call(e[n],i))throw new Error("Id value not found in first object while merging: "+n+", valueKey: "+i+", ojb: "+e);if(!Object.prototype.hasOwnProperty.call(t[n],i))throw new Error("Id value not found in second object while merging: "+n+", valueKey: "+i+", ojb: "+t);let a=e[n][i];const s=t[n][i][0];if(r[n]=e[n],o){for(let e=0;e<a.length;++e)if(a[e]===s)throw new Error("The first object already contains id2: "+s+", id1: "+a);r[n][i].push(s)}else{if(a=a[0],a===s)throw new Error("Cannot merge object with same ids: "+a+", id2: "+s);r[n][i].push(s),r[n].merged=!0}const l=Object.keys(e),c=Object.keys(t).filter((function(e){return l.indexOf(e)<0})),u=l.concat(c);for(let l=0;l<u.length;++l){const c=u[l];if(c!==n){let n,l,u,d,h;if(Object.prototype.hasOwnProperty.call(e,c)&&(n=e[c],Object.prototype.hasOwnProperty.call(n,i)&&(l=n[i])),Object.prototype.hasOwnProperty.call(t,c)&&(u=t[c],Object.prototype.hasOwnProperty.call(u,i)&&(d=u[i])),void 0!==n?h=n:void 0!==u&&(h=u),!H(l,d))if(o){if(Array.isArray(l)){h[i]={};for(let e=0;e<a.length;++e)h[i][a[e]]=l}else h[i]=l;void 0===h[i]&&(h[i]={}),h[i][s]=d}else{const e={};e[a]=l,e[s]=d,h[i]=e}r[c]=h}}return r}(n.meta,t.meta,i,"value"),this.#Fe({type:"dataupdate",dataid:e})}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)};#Eo(e){return t=>{t.dataid=e,this.#Fe(t)}}}class ao{#qo;setOptions(e){this.#qo=e}#Ao=null;#Uo=[];#Mo=[];#Qo=[];#Vo=[];#No(e){let t;const n=e["00080060"];if(void 0!==n){const e=n.value[0];"SEG"===e?t=new Fn:"SR"===e&&(t=new io)}return void 0===t&&void 0!==e["7FE00010"]&&(t=new Pt),t}#Bo(e,t){const n=this.#Uo[e].getDicomElements(),i=this.#Vo[e];if(void 0===i)return!1;try{const r=new ro(n);i instanceof io?r.annotationGroup=i.create(n):r.image=i.create(n,this.#Mo[e],this.#qo.numberOfFiles),this.onloaditem({data:r,source:t,warn:i.getWarning()})}catch(e){return this.onerror({error:e,source:t}),this.onloadend({source:t}),!1}return!0}#Go(e,t){this.#Bo(e,t)&&this.onload({source:t}),this.onloadend({source:t})}#ko(e,t){this.onprogress({lengthComputable:!0,loaded:100,total:100,index:e,source:t}),this.#Go(e,t)}#Ho(e,t,n){const i=this.#Uo[e],r={bitsAllocated:i.getDicomElements()["00280100"].value[0],isSigned:1===i.getDicomElements()["00280103"].value[0]},o=i.getDicomElements()["00280011"],a=i.getDicomElements()["00280010"];void 0!==o&&void 0!==a&&(r.sliceSize=o.value[0]*a.value[0]);const s=i.getDicomElements()["00280002"];void 0!==s&&(r.samplesPerPixel=s.value[0]);const l=i.getDicomElements()["00280006"];void 0!==l&&(r.planarConfiguration=l.value[0]);const c=t.length;null===this.#Ao&&(this.#Ao=new Ir(n,c),this.#Ao.ondecodeditem=e=>{this.#zo(e),e.itemNumber+1===e.numberOfItems&&(this.onload(e),this.onloadend(e))},this.#Ao.onerror=this.onerror,this.#Ao.onabort=this.onabort);for(let n=0;n<c;++n)this.#Ao.decode(t[n],r,{itemNumber:n,numberOfItems:c,index:e})}#zo(e){this.onprogress({lengthComputable:!0,loaded:e.itemNumber+1,total:e.numberOfItems,index:e.index,source:origin});const t=e.index,n=e.data[0];if(1!==e.numberOfItems){if(void 0===this.#Qo[t]){this.#Qo[t]=n.length;const i=e.numberOfItems*this.#Qo[t];try{this.#Mo[t]=new n.constructor(i)}catch(e){if(e instanceof RangeError){const e=Math.floor(Math.log(i)/Math.log(2));c.error("Cannot allocate "+n.constructor.name+" of size: "+i+" (>2^"+e+") for decompressed data.")}return this.#Ao.abort(),this.onerror({error:e,source:origin}),void this.onloadend({source:origin})}}n.length!==this.#Qo[t]&&c.warn("Unsupported varying decompressed data size: "+n.length+" != "+this.#Qo[t]),this.#Mo[t].set(n,this.#Qo[t]*e.itemNumber)}else this.#Mo[t]=n;0===e.itemNumber&&this.#Bo(t,origin)}#Wo(e,t){this.#Go(e,t)}#Yo(e,t){const n=this.#Uo[e],i=n.getDicomElements()["7FE00010"].value;n.getDicomElements()["7FE00010"].value=[],this.#Mo[e]=i[0];const r=function(e){let t;return qe(e)?t="jpeg2000":Fe(e)?t="jpeg-baseline":Ee(e)?t="jpeg-lossless":Ue(e)&&(t="rle"),t}(n.getDicomElements()["00020010"].value[0]);void 0!==r?this.#Ho(e,i,r):this.#ko(e,t)}convert(e,t,n){this.onloadstart({source:t,index:n});const i=new ke;let r;void 0!==this.#qo.defaultCharacterSet&&i.setDefaultCharacterSet(this.#qo.defaultCharacterSet);try{i.parse(e),r=this.#No(i.getDicomElements()),void 0!==r&&r.checkElements(i.getDicomElements())}catch(e){return this.onerror({error:e,source:t}),void this.onloadend({source:t})}this.#Uo[n]=i,this.#Vo[n]=r,r instanceof io?this.#Wo(n,t):this.#Yo(n,t)}abort(){this.#Ao&&this.#Ao.abort()}onloadstart(e){}onloaditem(e){}onprogress(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}}class so{#ro=null;#ao=null;#so=0;#lo=0;#E;getDefaultCharacterSet(){return this.#E}setDefaultCharacterSet(e){this.#E=e}#uo(e){this.#ro=e,this.#so=0,this.#lo=0,this.#ho()}#go(e){this.#ao=e}#ho(){this.#ao=null}#po=e=>{this.#so++,this.#so===this.#ro.length&&this.onload({source:this.#ro})};#mo=e=>{this.#lo++,this.#lo===this.#ro.length&&this.onloadend({source:this.#ro})};load(e){if(void 0===e||0===e.length)return;this.#uo(e),this.onloadstart({source:e});const t=new dr(this.onprogress);t.setNToLoad(e.length),t.setNumberOfDimensions(1);const n=[];for(let e=0;e<go.length;++e)n.push(new go[e]);let i=e[0],r=null,o=!1;for(let a=0;a<n.length;++a)if(r=n[a],r.canLoadMemory(i)){o=!0,r.setOptions({numberOfFiles:e.length,defaultCharacterSet:this.getDefaultCharacterSet()}),r.onprogress=t.getUndefinedMonoProgressHandler(0),r.onloaditem=this.onloaditem,r.onload=this.#po,r.onloadend=this.#mo,r.onerror=this.onerror,r.onabort=this.onabort,this.#go(r);break}if(!o)throw new Error("No loader found for data: "+i.filename);for(let t=0;t<e.length;++t){if(i=e[t],!r.canLoadMemory(i))throw new Error("Input data of different type: "+i.filename);r.load(i.data,i.filename,t)}}abort(){this.#ao&&this.#ao.isLoading()&&this.#ao.abort()}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}}function lo(e){return parseInt(e,36).toString()}function co(e){const t=e.data.length,n=new Uint8Array(t/4*3);let i=0;for(let r=0;r<t;r+=4)n[i]=e.data[r],n[i+1]=e.data[r+1],n[i+2]=e.data[r+2],i+=3;return n}function uo(e,t,n,i,r,o){const a=new Ze([e,t,1]),s=new nt([1,1,1]),l=new F(0,0,n),c=new it([l],a,s),u=new Un(c,i,[o]);u.setPhotometricInterpretation("RGB");const d={BitsStored:8};return void 0!==r&&(d.numberOfFiles=r),u.setMeta(d),u}var ho=o(654),So=o.n(ho);const go=[class{#qo={};#Xo=!1;setOptions(e){this.#qo=e}isLoading(){return this.#Xo}#jo=new ao;load(e,t,n){this.#Xo||(this.#jo.setOptions(this.#qo),this.#jo.onloadstart=this.onloadstart,this.#jo.onprogress=this.onprogress,this.#jo.onloaditem=this.onloaditem,this.#jo.onload=this.onload,this.#jo.onloadend=e=>{this.#Xo=!1,this.onloadend(e)},this.#jo.onerror=e=>{e.source=t,this.onerror(e)},this.#jo.onabort=this.onabort),this.#Xo=!0,this.#jo.convert(e,t,n)}abort(){this.#Xo=!1,this.#jo.abort()}canLoadFile(e){const t=V(e.name);return null===t||"dcm"===t}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"dicom"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n){const e="application/dicom";return U(n.value,e)&&"+"!==n.value[e.length]}}}const n=sr(e),i=V(n.pathname),r=null===i,o="dcm"===i,a=n.searchParams.get("contentType");return null!=a?"application/dicom"===a:r||o}canLoadMemory(e){const t=e["Content-Type"];if(void 0!==t&&t.startsWith("application/dicom"))return!0;if(void 0!==e.filename){const t=new File(["from memory"],e.filename);return this.canLoadFile(t)}return!1}loadFileAs(){return po.ArrayBuffer}loadUrlAs(){return 1}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}},class{#Xo=!1;setOptions(e){}isLoading(){return this.#Xo}load(e,t,n){this.#Xo=!0,this.onloadstart({source:t});try{this.onprogress({lengthComputable:!0,loaded:100,total:100,index:n,source:t});const i={data:e,source:t};this.onloaditem(i),this.onload(i)}catch(e){this.onerror({error:e,source:t})}finally{this.#Xo=!1,this.onloadend({source:t})}}abort(){this.#Xo=!1,this.onabort({}),this.onloadend({})}canLoadFile(e){return"json"===V(e.name)}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"json"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n)return U(n.value,"application/json")||U(n.value,"application/dicom+json")}}return"json"===V(sr(e).pathname)}canLoadMemory(e){const t=e["Content-Type"];if(void 0!==t&&t.startsWith("application/json"))return!0;if(void 0!==e.filename){const t=new File(["from memory"],e.filename);return this.canLoadFile(t)}return!1}loadFileAs(){return po.Text}loadUrlAs(){return 0}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}},class{#Xo=!1;setOptions(e){}isLoading(){return this.#Xo}load(e,t,n){this.onloadstart({source:t}),this.#Xo=!0;const i=new so;i.onprogress=e=>{e.loaded=50+e.loaded/2,e.index=n,this.onprogress(e)},i.onloaditem=this.onloaditem,i.onload=this.onload,i.onloadend=e=>{this.#Xo=!1,this.onloadend(e)},i.onerror=this.onerror,i.onabort=this.onabort,i.load(function(e){const t=new Uint8Array(e),n=[];if(0===t.length)return n;const i=Y(new Uint8Array([13,10,13,10]));let r=W(t,i,0);if(void 0===r)throw new Error("Can't find the end of the first multipart header");const o=z(t.slice(0,r)).split("\r\n");let a;for(let e=0;e<o.length;++e)if("-"===o[e][0]&&"-"===o[e][1]){a=o[e];break}if(void 0===a)throw new Error("Can't find the boundary between multi-parts");const s=Y(N(a)),l=a.length;let c=W(t,s,0);for(;void 0!==r;){const e={},o=z(t.slice(c+l,r)).split("\r\n");for(let t=0;t<o.length;++t){const n=o[t],i=n.indexOf(":");if(-1!==i){const t=n.substring(0,i).trim(),r=n.substring(i+1).trim();e[t]=r}}if(c=W(t,s,r),void 0===c)break;const a=r+4,u=c-2;e.data=a<u?t.slice(a,u).buffer:new Uint8Array,n.push(e),r=W(t,i,c+l)}return n}(e))}abort(){this.#Xo=!1,this.onabort({}),this.onloadend({})}canLoadFile(e){return!1}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"multipart"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n)return U(n.value,"multipart/related")}}return!1}canLoadMemory(e){return!1}loadFileAs(){return po.ArrayBuffer}loadUrlAs(){return 1}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}},class{#Zo=!1;setOptions(e){}isLoading(){return!0}#_o(e,t){let n=t;n&&"jpg"!==n||(n="jpeg");const i=new Blob([e],{type:"image/"+n});return window.URL.createObjectURL(i)}load(e,t,n){this.#Zo=!1;const i=new Image;if(i.onload=()=>{try{if(!this.#Zo){this.onprogress({lengthComputable:!0,loaded:100,total:100,index:n,source:t});const e=function(e,t,n){const i=e.width,r=e.height,o=document.createElement("canvas");o.width=i,o.height=r;const a=o.getContext("2d");a.drawImage(e,0,0);const s=a.getImageData(0,0,i,r),l={};let c;"string"==typeof t?(l.origin={value:t},c=lo(t)):(l.fileName={value:t.name},c=lo(t.name),l.fileType={value:t.type},l.fileLastModifiedDate={value:t.lastModified}),l.imageWidth={value:i},l.imageHeight={value:r};const u=n||0;l.imageUid={value:u},l.seriesUid={value:c};const d=uo(i,r,u,co(s),1,u.toString()),h=d.getMeta();return h.SeriesInstanceUID=c,d.setMeta(h),{data:{image:d,meta:l},source:t}}(i,t,n);this.onloaditem(e),this.onload(e)}}catch(e){this.onerror({error:e,source:t})}finally{this.onloadend({source:t})}},"string"==typeof e)i.src=e;else if("string"==typeof t){const n=t.split(".").pop().toLowerCase();i.src=this.#_o(e,n)}}abort(){this.#Zo=!0,this.onabort({}),this.onloadend({})}canLoadFile(e){return void 0!==e.type&&null!==e.type.match("image.*")}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"rawimage"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n)return U(n.value,"image/")}}const n=sr(e),i=V(n.pathname),r="jpeg"===i||"jpg"===i||"png"===i||"gif"===i,o=n.searchParams.get("contentType");return null!=o?"image/jpeg"===o||"image/png"===o||"image/gif"===o:r}canLoadMemory(e){if(void 0!==e.filename){const t=new File(["from memory"],e.filename);return this.canLoadFile(t)}return!1}loadFileAs(){return po.DataURL}loadUrlAs(){return 1}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}},class{setOptions(e){}isLoading(){return!0}#_o(e,t){const n=new Uint8Array(e);let i="";for(let e=0;e<n.byteLength;++e)i+=String.fromCharCode(n[e]);return"data:video/"+t+";base64,"+window.btoa(i)}load(e,t,n){const i=document.createElement("video");if("string"==typeof t){const n=t.split(".").pop().toLowerCase();i.src=this.#_o(e,n)}else i.src=e;i.onloadedmetadata=e=>{try{!function(e,t,n,i,r,o,a){const s=e.videoWidth,l=e.videoHeight,c=Math.ceil(30*e.duration),u={};let d;"string"==typeof o?(u.origin={value:o},d=lo(o)):(u.fileName={value:o.name},d=lo(o.name),u.fileType={value:o.type},u.fileLastModifiedDate={value:o.lastModified}),u.imageWidth={value:s},u.imageHeight={value:l},u.numberOfFrames={value:c},u.imageUid={value:0},u.seriesUid={value:d};const h=document.createElement("canvas");h.width=s,h.height=l;const S=h.getContext("2d");e.addEventListener("seeked",(function h(f){(function(){i({lengthComputable:!0,loaded:g,total:c,index:a,source:o}),S.drawImage(e,0,0);const n=co(S.getImageData(0,0,s,l));if(0===g){p=uo(s,l,1,n,c,a.toString());const e=p.getMeta();e.SeriesInstanceUID=d,p.setMeta(e),t({data:{image:p,meta:u},source:o})}else p.appendFrameBuffer(n,g);++g})(),m+=1/30,m<=f.target.duration?this.currentTime=m:(n({source:o}),r({source:o}),e.removeEventListener("seeked",h))}),!1);let g=0,p=null,m=0;e.currentTime=m}(e.target,this.onloaditem,this.onload,this.onprogress,this.onloadend,t,n)}catch(e){this.onerror({error:e,source:t}),this.onloadend({source:t})}}}abort(){this.onabort({}),this.onloadend({})}canLoadFile(e){return void 0!==e.type&&null!==e.type.match("video.*")}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"rawvideo"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n)return U(n.value,"video/")}}const n=V(sr(e).pathname);return"mp4"===n||"ogg"===n||"webm"===n}canLoadMemory(e){if(void 0!==e.filename){const t=new File(["from memory"],e.filename);return this.canLoadFile(t)}return!1}loadFileAs(){return po.DataURL}loadUrlAs(){return 1}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}},class{#Xo=!1;setOptions(e){}isLoading(){return this.#Xo}#Ko="";#Jo=[];#$o=null;#ea(e,t,n){this.#Jo.push({filename:this.#Ko,data:e});const i=100*this.#Jo.length/this.#$o.length;if(this.onprogress({lengthComputable:!0,loaded:i/2,total:100,index:n,item:{loaded:i,total:100,source:t}}),this.#Jo.length<this.#$o.length){const e=this.#Jo.length;this.#Ko=this.#$o[e].name,this.#$o[e].async("arrayBuffer").then((e=>{this.#ea(e,t,n)}))}else{const e=new so;e.onprogress=e=>{e.loaded=50+e.loaded/2,e.index=n,this.onprogress(e)},e.onloaditem=this.onloaditem,e.onload=this.onload,e.onloadend=e=>{this.#Xo=!1,this.onloadend(e)},e.onerror=this.onerror,e.onabort=this.onabort,e.load(this.#Jo)}}load(e,t,n){this.onloadstart({source:t}),this.#Xo=!0,So().loadAsync(e).then((e=>{this.#Jo=[],this.#$o=e.file(/.*\.dcm/);const i=this.#Jo.length;this.#Ko=this.#$o[i].name,this.#$o[i].async("arrayBuffer").then((e=>{this.#ea(e,t,n)}))}))}abort(){this.#Xo=!1,this.onabort({}),this.onloadend({})}canLoadFile(e){return"zip"===V(e.name)}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"zip"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n)return U(n.value,"application/zip")}}return"zip"===V(sr(e).pathname)}canLoadMemory(e){const t=e["Content-Type"];if(void 0!==t&&t.startsWith("application/zip"))return!0;if(void 0!==e.filename){const t=new File(["from memory"],e.filename);return this.canLoadFile(t)}return!1}loadFileAs(){return po.ArrayBuffer}loadUrlAs(){return 1}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}}],po={Text:0,ArrayBuffer:1,DataURL:2};class mo{#ro=null;#ta=[];#ao=null;#so=0;#lo=0;#E;getDefaultCharacterSet(){return this.#E}setDefaultCharacterSet(e){this.#E=e}#uo(e){this.#ro=e,this.#so=0,this.#lo=0,this.#na(),this.#ho()}#ia(e){this.#ta.push(e)}#na(){this.#ta=[]}#go(e){this.#ao=e}#ho(){this.#ao=null}#po=e=>{this.#so++,this.#so===this.#ro.length&&this.onload({source:this.#ro})};#mo=e=>{this.#lo++,this.#lo===this.#ro.length&&this.onloadend({source:this.#ro})};#fo(e,t){return n=>{n.source=t,e(n)}}#Co(e,t,n){return i=>{e.load(i.target.result,t,n)}}load(e){if(void 0===e||0===e.length)return;this.#uo(e),this.onloadstart({source:e});const t=new dr(this.onprogress);t.setNToLoad(e.length);const n=[];for(let e=0;e<go.length;++e)n.push(new go[e]);let i=e[0],r=null,o=!1;for(let a=0;a<n.length;++a)if(r=n[a],r.canLoadFile(i)){o=!0,r.setOptions({numberOfFiles:e.length,defaultCharacterSet:this.getDefaultCharacterSet()}),r.onprogress=t.getUndefinedMonoProgressHandler(1),r.onloaditem=this.onloaditem,r.onload=this.#po,r.onloadend=this.#mo,r.onerror=this.onerror,r.onabort=this.onabort,this.#go(r);break}if(!o)throw new Error("No loader found for file: "+i.name);for(let n=0;n<e.length;++n){if(i=e[n],!r.canLoadFile(i))throw new Error("Input file of different type: "+i);const o=new FileReader;this.#ia(o),o.onprogress=this.#fo(t.getMonoProgressHandler(n,0),i),o.onload=this.#Co(r,i,n);const a=this.#fo(this.onerror,i);o.onerror=e=>{this.#mo(),a(e)};const s=this.#fo(this.onabort,i);o.onabort=e=>{this.#mo(),s(e)},r.loadFileAs()===po.Text?o.readAsText(i):r.loadFileAs()===po.DataURL?o.readAsDataURL(i):r.loadFileAs()===po.ArrayBuffer&&o.readAsArrayBuffer(i)}}abort(){for(let e=0;e<this.#ta.length;++e)1===this.#ta[e].readyState&&this.#ta[e].abort();this.#ao&&this.#ao.isLoading()&&this.#ao.abort()}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}}class fo{#E;#ra={};constructor(e){this.#E=e}loadFiles(e,t){"json"===e[0].name.split(".").pop().toLowerCase()?this.#oa(e[0],t):this.#aa(e,t)}loadURLs(e,t,n){"json"===e[0].split(".").pop().toLowerCase()?this.#sa(e[0],t,n):this.#la(e,t,n)}loadImageObject(e,t){const n=new so;this.#ca(e,n,"image",t)}getLoadingDataIds(){return Object.keys(this.#ra)}abort(e){void 0!==this.#ra[e]&&(this.#ra[e].loader.abort(),delete this.#ra[e])}#aa(e,t){const n=new mo;n.setDefaultCharacterSet(this.#E),this.#ca(e,n,"image",t)}#la(e,t,n){const i=new hr;i.setDefaultCharacterSet(this.#E),this.#ca(e,i,"image",t,n)}#oa(e,t){const n=new mo;this.#ca([e],n,"state",t)}#sa(e,t,n){const i=new hr;this.#ca([e],i,"state",t,n)}#ca(e,t,n,i,r){const o={loadtype:n,dataid:i};t.onloadstart=e=>{this.#ra[i]={loader:t,isFirstItem:!0},this.#fo(this.onloadstart,o)(e)},t.onprogress=this.#fo(this.onprogress,o),t.onloaditem=e=>{const t={loadtype:n,dataid:i};void 0!==this.#ra[i]&&(t.isfirstitem=this.#ra[i].isFirstItem),this.#fo(this.onloaditem,t)(e),void 0!==this.#ra[i]&&this.#ra[i].isFirstItem&&(this.#ra[i].isFirstItem=!1)},t.onload=this.#fo(this.onload,o),t.onloadend=e=>{delete this.#ra[i],this.#fo(this.onloadend,o)(e)},t.onerror=this.#fo(this.onerror,o),t.onabort=this.#fo(this.onabort,o),void 0!==t.ontimeout&&(t.ontimeout=this.#fo(this.ontimeout,o));try{t.load(e,r)}catch(e){return this.onerror({error:e,dataid:i}),void this.onloadend({dataid:i})}}#fo(e,t){return function(n){const i=Object.keys(t);for(let e=0;e<i.length;++e){const r=i[e];n[r]=t[r]}e(n)}}onloadstart(e){}onprogress(e){}onload(e){}onloaditem(e){}onloadend(e){}onerror(e){}ontimeout(e){}onabort(e){}}function Do(e){return function(t){return Number(t).toPrecision(e)}}function yo(e){let t="";for(let n=0;n<e;++n)0!==n&&(t+=", "),t+="{v"+n+"}";return t}function Co(e,t){let n=e;for(let e=0;e<t.length;++e)n=n.replace("{v"+e+"}",t[e]);return n}class vo{#Rt;#Ct;#ua;#da=[];#ha;#Sa=[];#ga;#be=new He;constructor(e,t,n){this.#Rt=e,this.#Ct=t,this.#ua=n;const i=Object.keys(this.#ua);for(let e=0;e<i.length;++e){const t=this.#ua[i[e]];for(let e=0;e<t.length;++e){const n=t[e].event;void 0!==n&&(this.#da.includes(n)||this.#da.push(n))}}this.addAppListeners()}reset(){this.#Sa=[],this.#ga=void 0}addItemMeta(e){let t;if(void 0!==e["00020010"])t=void 0!==e["00080018"]?e["00080018"].value[0]:e.length,this.#Sa[t]=function(e,t){const n=[];let i;const r=e["00080060"];if(void 0===r)return n;i=r.value[0];const o=t[i]||t["*"];if(!o)return n;for(let t=0;t<o.length;++t){const i=JSON.parse(JSON.stringify(o[t])),r=i.tags;if(void 0!==r&&0!==r.length){const t=[];for(let n=0;n<r.length;++n)void 0!==e[r[n]]?t.push(e[r[n]].value):t.push("");void 0!==i.format&&null!==i.format||(i.format=yo(t.length)),i.value=Co(i.format,t).trim()}n.push(i)}const a=e["00200020"];if(void 0!==a&&2===a.value.length){const e=a.value[0],t=a.value[1];n.push({pos:"cr",value:e,format:"{v0}"}),n.push({pos:"cl",value:be(e),format:"{v0}"}),n.push({pos:"bc",value:t,format:"{v0}"}),n.push({pos:"tc",value:be(t),format:"{v0}"})}return n}(e,this.#ua);else{const n=Object.keys(e);for(let i=0;i<n.length;++i){const r=e[n[i]];if("imageUid"===n[i]){t=r.value;break}}this.#Sa[t]=function(e,t){const n=[],i=t.DOM;if(!i)return n;const r=Object.keys(e);for(let t=0;t<i.length;++t){const o=JSON.parse(JSON.stringify(i[t])),a=o.tags;if(void 0!==a&&0!==a.length){const t=[];for(let n=0;n<a.length;++n)for(let i=0;i<r.length;++i)a[n]===r[i]&&t.push(e[r[i]].value);void 0!==o.format&&null!==o.format||(o.format=yo(t.length)),o.value=Co(o.format,t).trim()}n.push(o)}return n}(e,this.#ua)}this.#ga=t}#pa=e=>{e.dataid===this.#Ct&&void 0!==e.data&&void 0!==e.data.imageUid&&this.#ga!==e.data.imageUid&&(this.#ga=e.data.imageUid,this.#ma(e))};#ma=e=>{if(e.dataid!==this.#Ct)return;const t=this.#Sa[this.#ga];if(void 0!==t){for(let n=0;n<t.length;++n){let i;if(void 0!==t[n].tags)"positionchange"===e.type&&(i=t[n].value);else if(void 0!==t[n].event&&t[n].event===e.type){const r=t[n].format;let o=e.value;if(void 0!==t[n].precision){let e=null;e="round"===t[n].precision?Math.round:Do(t[n].precision),o=o.map(e)}i=Co(r,o)}void 0!==i&&(t[n].value=i)}this.#Fe({type:"valuechange",data:t})}else console.warn("No slice overlay data for: "+this.#ga)};isListening(){return this.#ha}addAppListeners(){this.#Rt.addEventListener("positionchange",this.#pa);for(let e=0;e<this.#da.length;++e)this.#Rt.addEventListener(this.#da[e],this.#ma);this.#ha=!0}removeAppListeners(){this.#Rt.removeEventListener("positionchange",this.#pa);for(let e=0;e<this.#da.length;++e)this.#Rt.removeEventListener(this.#da[e],this.#ma);this.#ha=!1}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe(e){this.#be.fireEvent(e)}}class Io{divId;orientation;colourMap;opacity;wlPresetName;windowCenter;windowWidth;constructor(e){this.divId=e}}class To{options;constructor(e){this.options=e}}class Lo{dataViewConfigs;tools;binders;viewOnFirstLoadItem;defaultCharacterSet;overlayConfig;rootDocument;constructor(e){this.dataViewConfigs=e}}class Po{#qo=null;#fa=null;#Da=null;#ya=null;#Ca=null;#va=null;#Yn=new ui;#Ia={};#be=new He;getData(e){return this.#fa.get(e)}getImage(e){let t;return void 0!==this.getData(e)&&(t=this.getData(e).image),t}setImage(e,t){this.#fa.setImage(e,t)}addData(e){const t=this.#fa.getNextDataId();return this.#fa.add(t,e),t}getMetaData(e){let t;return void 0!==this.#fa.get(e)&&(t=this.#fa.get(e).meta),t}getDataIds(){return this.#fa.getDataIds()}getDataIdsFromSopUids(e){return this.#fa.getDataIdsFromSopUids(e)}canScroll(){return this.#Ca.getActiveLayerGroup().getActiveViewLayer().getViewController().canScroll()}canWindowLevel(){return this.#Ca.getActiveLayerGroup().getActiveViewLayer().getViewController().canWindowLevel()}getAddedScale(){return this.#Ca.getActiveLayerGroup().getAddedScale()}getBaseScale(){return this.#Ca.getActiveLayerGroup().getBaseScale()}getOffset(){return this.#Ca.getActiveLayerGroup().getOffset()}getToolboxController(){return this.#Da}getActiveLayerGroup(){return this.#Ca.getActiveLayerGroup()}setActiveLayerGroup(e){this.#Ca.setActiveLayerGroup(e)}getViewLayersByDataId(e){return this.#Ca.getViewLayersByDataId(e)}getViewLayers(e){return this.#Ca.getViewLayers(e)}getDrawLayersByDataId(e){return this.#Ca.getDrawLayersByDataId(e)}getDrawLayers(e){return this.#Ca.getDrawLayers(e)}getLayerGroupByDivId(e){return this.#Ca.getLayerGroupByDivId(e)}getNumberOfLayerGroups(){return this.#Ca.getNumberOfLayerGroups()}getStyle(){return this.#Yn}addToUndoStack=e=>{null!==this.#va&&this.#va.add(e)};removeFromUndoStack=e=>{let t=!1;return null!==this.#va&&(t=this.#va.remove(e)),t};init(e){if(this.#qo=e,void 0===this.#qo.viewOnFirstLoadItem&&(this.#qo.viewOnFirstLoadItem=!0),void 0===this.#qo.dataViewConfigs&&(this.#qo.dataViewConfigs={}),void 0===this.#qo.rootDocument&&(this.#qo.rootDocument=document),this.#va=new cr,this.#va.addEventListener("undoadd",this.#Fe),this.#va.addEventListener("undo",this.#Fe),this.#va.addEventListener("redo",this.#Fe),void 0!==this.#qo.tools){const e={},t=Object.keys(this.#qo.tools);for(let n=0;n<t.length;++n){const i=t[n];let r=zi[i];if(void 0===r&&(r=ki[i]),void 0!==r){if(e[i]=new r(this),void 0!==e[i].addEventListener){const t=e[i].getEventNames();for(let n=0;n<t.length;++n)e[i].addEventListener(t[n],this.#Fe)}const t=this.#qo.tools[i];if(void 0!==t.options&&0!==t.options.length){let n,r="raw";if(void 0!==e[i].getOptionsType&&(r=e[i].getOptionsType()),"instance"===r||"factory"===r){n={};for(let e=0;e<t.options.length;++e){const o=t.options[e];let a=o;"factory"===r&&(a+="Factory");const s=i.charAt(0).toLowerCase()+i.slice(1);let l,u=Hi[s];void 0!==u&&(l=u[a]),void 0===l&&(u=Wi[s],void 0!==u&&(l=u[a])),void 0!==l?n[o]=l:c.warn("Could not find option class for: "+o)}}else n=t.options;e[i].setOptions(n)}}else c.warn("Could not initialise unknown tool: "+i)}this.#Da=new ur(e)}this.#ya=new fo(this.#qo.defaultCharacterSet),this.#ya.onloadstart=this.#Ta,this.#ya.onprogress=this.#La,this.#ya.onloaditem=this.#Pa,this.#ya.onload=this.#wa,this.#ya.onloadend=this.#Oa,this.#ya.onerror=this.#Aa,this.#ya.ontimeout=this.#ba,this.#ya.onabort=this.#xa,this.#fa=new oo,this.#fa.addEventListener("dataadd",this.#Fe),this.#fa.addEventListener("dataremove",this.#Fe),this.#fa.addEventListener("dataimageset",this.#Fe),this.#fa.addEventListener("dataupdate",this.#Fe),this.#fa.addEventListener("imagecontentchange",this.#Fe),this.#fa.addEventListener("imagegeometrychange",this.#Fe),this.#fa.addEventListener("annotationadd",this.#Fe),this.#fa.addEventListener("annotationupdate",this.#Fe),this.#fa.addEventListener("annotationremove",this.#Fe),this.#fa.addEventListener("annotationgroupeditablechange",this.#Fe),this.#Ca=new tr,void 0!==this.#qo.binders&&this.#Ca.setBinders(this.#qo.binders)}reset(){this.#Ca.empty(),this.#Ia={},this.#va&&(this.#va=new cr,this.#va.addEventListener("undoadd",this.#Fe),this.#va.addEventListener("undo",this.#Fe),this.#va.addEventListener("redo",this.#Fe))}resetLayout(){this.#Ca.reset(),this.#Ca.draw()}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}loadFiles=e=>{const t=this.#fa.getNextDataId();0!==e.length?this.#ya.loadFiles(e,t):c.warn("Ignoring empty input file list.")};loadURLs=(e,t)=>{const n=this.#fa.getNextDataId();0!==e.length?this.#ya.loadURLs(e,n,t):c.warn("Ignoring empty input url list.")};loadFromUri=(e,t)=>{const n=function(e){const t=lr(e);return 0===Object.keys(t).length?null:t.query}(e),i=()=>{this.removeEventListener("loadend",i),this.loadURLs([n.state])};n&&void 0!==n.input&&(void 0!==n.state&&this.addEventListener("loadend",i),function(e,t,n){e.type&&"manifest"===e.type?function(e,t){let n="";"/"===e.input[0]&&(n=window.location.protocol+"//"+window.location.host),n+=e.input;const i=new XMLHttpRequest;i.open("GET",decodeURIComponent(n),!0),i.responseType="document",i.onload=function(n){t(function(e,t){const n=[],i=e.getElementsByTagName("wado_query")[0].getAttribute("wadoURL")+"?requestType=WADO&contentType=application/dicom&",r=e.getElementsByTagName("Patient");r.length>1&&c.warn("More than one patient, loading first one.");const o=r[0].getElementsByTagName("Study");o.length>1&&c.warn("More than one study, loading first one.");const a=o[0].getAttribute("StudyInstanceUID"),s=o[0].getElementsByTagName("Series");s.length>1&&c.warn("More than one series, loading first one.");const l=s[0].getAttribute("SeriesInstanceUID"),u=s[0].getElementsByTagName("Instance");let d=u.length;t<d&&(d=t);for(let e=0;e<d;++e){const t=i+"&studyUID="+a+"&seriesUID="+l+"&objectUID="+u[e].getAttribute("SOPInstanceUID");n.push(t)}return n}(n.target.responseXML,e.nslices))},i.onerror=function(e){c.warn("RequestError while receiving manifest: "+e.target.status)},i.send(null)}(e,t):t(function(e,t){const n=[];let i="key";t&&(i=t);const r=decodeURIComponent(e),o=lr(r);if(0===Object.keys(o).length)n.push(r);else{const e=Object.keys(o.query);let t=null;for(let n=0;n<e.length;++n)if(o.query[e[n]]instanceof Array){t=e[n];break}if(t){const r=o.query[t];let a=o.base;""!==a&&"file"!==t&&(a+="?");let s,l=!1;for(let n=0;n<e.length;++n)e[n]!==t&&(l&&(a+="&"),a+=e[n]+"="+o.query[e[n]],l=!0);for(let e=0;e<r.length;++e)s=a,l&&(s+="&"),"key"===i&&(s+=t+"="),s+=r[e],n.push(s)}else n.push(r)}return n}(e.input,e.dwvReplaceMode),n)}(n,this.loadURLs,t))};loadImageObject=e=>{const t=this.#fa.getNextDataId();this.#ya.loadImageObject(e,t)};abortAllLoads(){const e=this.#ya.getLoadingDataIds();for(const t of e)this.abortLoad(t)}abortLoad(e){this.#ya.abort(e),this.#fa.remove(e),this.#Ca.removeLayersByDataId(e)}fitToContainer(){this.#Ca.fitToContainer()}initWLDisplay(){this.#Ca.getActiveLayerGroup().getActiveViewLayer().getViewController().initialise()}setImageSmoothing(e){this.#Ca.setImageSmoothing(e),this.#Ca.draw()}getViewConfigs(e,t){if(void 0===t&&(t=!1),null===this.#qo.dataViewConfigs||void 0===this.#qo.dataViewConfigs)throw new Error("No available data view configuration");let n=[];return void 0!==this.#qo.dataViewConfigs[e]?n=this.#qo.dataViewConfigs[e]:t||void 0===this.#qo.dataViewConfigs["*"]||(n=this.#qo.dataViewConfigs["*"]),n}getViewConfig(e,t,n){return this.getViewConfigs(e,n).find((function(e){return e.divId===t}))}getDataViewConfigs(){return this.#qo.dataViewConfigs}setDataViewConfigs(e){this.#Ca.empty(),this.#qo.dataViewConfigs=e,this.#Ra(e)}addDataViewConfig(e,t){const n=this.#qo.dataViewConfigs;if(void 0===n[e]&&(n[e]=[]),-1!==n[e].findIndex((function(e){return e.divId===t.divId})))throw new Error("Duplicate view config for data "+e+" and div "+t.divId);this.#qo.dataViewConfigs[e].push(t),void 0===this.#Ca.getLayerGroupByDivId(t.divId)&&this.#Fa(t),void 0!==this.#fa.get(e)&&this.render(e,[t])}removeDataViewConfig(e,t){const n=this.#qo.dataViewConfigs;if(void 0===n[e])return;const i=n[e].findIndex((function(e){return e.divId===t}));if(-1!==i&&(n[e].splice(i,1),0===n[e].length&&delete n[e],void 0!==this.#fa.get(e))){const n=this.#Ca.getLayerGroupByDivId(t);if(void 0!==n){const t=n.getViewLayersByDataId(e);1===t.length&&n.removeLayer(t[0]);const i=n.getDrawLayersByDataId(e);if(1===i.length&&n.removeLayer(i[0]),0===t.length&&0===i.length)throw new Error("Expected one layer, got none");0===n.getNumberOfLayers()&&this.#Ca.removeLayerGroup(n)}}}updateDataViewConfig(e,t,n){const i=this.#qo.dataViewConfigs;if(void 0===i[e])throw new Error("No config for dataId: "+e);const r=i[e].findIndex((function(e){return e.divId===t}));if(-1===r)throw new Error("No config for dataId: "+e+" and divId: "+t);const o=i[e][r];for(const e in n)o[e]=n[e];const a=this.#Ca.getLayerGroupByDivId(o.divId);if(void 0!==a){const t=a.getViewLayersByDataId(e);1===t.length&&a.removeLayer(t[0]);const n=a.getDrawLayersByDataId(e);if(1===n.length&&a.removeLayer(n[0]),0===t.length&&0===n.length)throw new Error("Expected one layer, got none")}void 0!==this.#fa.get(e)&&this.render(e,[o])}#Ra(e){const t=Object.keys(e),n=[];for(let i=0;i<t.length;++i){const r=e[t[i]];for(let e=0;e<r.length;++e){const t=r[e];n.includes(t.divId)||(this.#Fa(t),n.push(t.divId))}}}#Fa(e){const t=this.#qo.rootDocument.getElementById(e.divId),n=this.#Ca.addLayerGroup(t);this.#Ea(n)}setLayerGroupsBinders(e){const t=[];for(let n=0;n<e.length;++n)void 0!==er[e[n]]&&t.push(new er[e[n]]);this.#Ca.setBinders(t)}render(e,t){if(null==e)throw new Error("Cannot render without data id");const n=void 0!==this.getData(e).image,i=void 0!==this.getData(e).annotationGroup;if(0===this.#Ca.getNumberOfLayerGroups()&&this.#Ra(this.#qo.dataViewConfigs),void 0===t&&(t=this.getViewConfigs(e)),0!==t.length)for(let r=0;r<t.length;++r){const o=t[r],a=this.#Ca.getLayerGroupByDivId(o.divId);if(!a)throw new Error("No layer group for "+o.divId);void 0!==this.#fa.get(e)&&(n&&0===a.getViewLayersByDataId(e).length?this.#qa(e,o):i&&0===a.getDrawLayersByDataId(e).length&&this.addDrawLayer(e,o)),a.draw()}else c.info("Not rendering data: "+e+" (no data view config)")}zoom(e,t,n){const i=this.#Ca.getActiveLayerGroup(),r=i.getBaseViewLayer().getViewController().getCurrentScrollPosition(),o=new F(t,n,r);i.addScale(e,o),i.draw()}translate(e,t){const n=this.#Ca.getActiveLayerGroup();n.addTranslation({x:e,y:t,z:0}),n.draw()}setOpacity(e){const t=this.#Ca.getActiveLayerGroup().getActiveViewLayer();t.setOpacity(e),t.draw()}setDrawings(e,t,n){const i=this.#Ca.getActiveLayerGroup().getBaseViewLayer(),r=i.getDataId(),o=i.getViewController(),a=function(e,t){const n=[],i=ai().Node.create(e).getChildren(gi);for(let e=0,r=i.length;e<r;++e){const r=i[e].getChildren();for(let e=0,i=r.length;e<i;++e){const e=new Yi,i=r[0];e.id=i.id();const o=i.getChildren(Si)[0];if(e.colour=o.stroke(),"line-group"===i.name()){const t=o.points();e.mathShape=new R(t[0],t[1]),e.referencePoints=[new R(t[2],t[3])]}else if("ruler-group"===i.name()){const t=o.points();e.mathShape=new $n(new R(t[0],t[1]),new R(t[2],t[3]))}else if("rectangle-group"===i.name())e.mathShape=new Mi(new R(o.x(),o.y()),new R(o.x()+o.width(),o.y()+o.height()));else if("roi-group"===i.name()){const t=o.points(),n=[];for(let e=0;e<t.length;e+=2)n.push(new R(t[e],t[e+1]));e.mathShape=new Ti(n)}else if("freeHand-group"===i.name()){c.warn("Converting freehand into ROI shape");const t=o.points(),n=[];for(let e=0;e<t.length;e+=2)n.push(new R(t[e],t[e+1]));e.mathShape=new Ti(n)}else if("protractor-group"===i.name()){const t=o.points();e.mathShape=new Ui([new R(t[0],t[1]),new R(t[2],t[3]),new R(t[4],t[5])])}else if("ellipse-group"===i.name()){const t=o.absolutePosition();e.mathShape=new Ei(new R(t.x,t.y),o.radiusX(),o.radiusY())}else if("circle-group"===i.name()){const t=o.absolutePosition();e.mathShape=new Fi(new R(t.x,t.y),o.radius())}if(t){const n=t[i.id()];e.textExpr=n.meta.textExpr,e.quantification=n.meta.quantification}n.push(e)}}return n}(e,t),s=this.createAnnotationData(r);for(const e of a)e.setViewController(o),s.annotationGroup.add(e);this.#fa.add(n,s),this.render(n)}applyJsonState(e,t){const n=new nr(t);n.apply(this,n.fromJSON(e))}onResize=()=>{this.fitToContainer()};onKeydown=e=>{this.#Fe(e)};defaultOnKeydown=e=>{if(e.ctrlKey)if(e.shiftKey){const t=this.#Ca.getActiveLayerGroup(),n=t.getPositionHelper();"ArrowLeft"===e.key?t.moreThanOne(3)&&n.decrementPosition(3):"ArrowUp"===e.key?t.canScroll()&&n.incrementPositionAlongScroll():"ArrowRight"===e.key?t.moreThanOne(3)&&n.incrementPosition(3):"ArrowDown"===e.key&&t.canScroll()&&n.decrementPositionAlongScroll()}else if("y"===e.key)this.#va.redo();else if("z"===e.key)this.#va.undo();else if(" "===e.key)for(let e=0;e<this.#Ca.getNumberOfLayerGroups();++e)this.#Ca.getLayerGroup(e).setShowCrosshair(!this.#Ca.getLayerGroup(e).getShowCrosshair())};resetDisplay(){this.resetLayout(),this.initWLDisplay()}resetZoom(){this.resetLayout()}setColourMap(e){this.#Ca.getActiveLayerGroup().getActiveViewLayer().getViewController().setColourMap(e)}setWindowLevelPreset(e){this.#Ca.getActiveLayerGroup().getActiveViewLayer().getViewController().setWindowLevelPreset(e)}setTool(e){for(let e=0;e<this.#Ca.getNumberOfLayerGroups();++e){const t=this.#Ca.getLayerGroup(e),n=t.getActiveLayer();void 0!==n&&this.#Da.bindLayerGroup(t,n)}this.#Da.setSelectedTool(e)}setToolFeatures(e){this.#Da.setToolFeatures(e)}undo(){this.#va.undo()}redo(){this.#va.redo()}getStackSize(){return this.#va.getStackSize()}getCurrentStackIndex(){return this.#va.getCurrentStackIndex()}getOverlayData(e){let t;return void 0!==this.#Ia&&(t=this.#Ia[e]),t}toggleOverlayListeners(e){const t=this.getOverlayData(e);void 0!==t&&(t.isListening()?t.removeAppListeners():t.addAppListeners())}createAnnotationData(e){const t=this.getData(e).image.getMeta(),n=new ro({});return n.annotationGroup=new Xi,n.annotationGroup.setMetaValue("Modality","SR"),n.annotationGroup.setMetaValue("PatientID",t.PatientID),n.annotationGroup.setMetaValue("StudyInstanceUID",t.StudyInstanceUID),n.annotationGroup.setMetaValue("ReferencedSeriesSequence",{value:[{SeriesInstanceUID:t.SeriesInstanceUID}]}),n}addAndRenderAnnotationData(e,t,n){const i=this.addData(e),r=this.getViewConfigs(n).find((e=>e.divId===t));if(void 0===r)throw new Error("No reference data view config for draw");const o=new Io(t);o.orientation=r.orientation,this.addDataViewConfig(i,o),this.render(i)}#Fe=e=>{this.#be.fireEvent(e)};#Ta=e=>{void 0!==this.#qo.overlayConfig&&(this.#Ia[e.dataid]=new vo(this,e.dataid,this.#qo.overlayConfig)),e.type="loadstart",this.#Fe(e)};#La=e=>{e.type="loadprogress",this.#Fe(e)};#Pa=e=>{void 0===e.data&&c.error("Missing loaditem event data."),void 0===e.loadtype&&c.error("Missing loaditem event load type.");const t=e.isfirstitem;let n=null;"image"===e.loadtype?(t?this.#fa.add(e.dataid,e.data):this.#fa.update(e.dataid,e.data),n=e.data.meta):"state"===e.loadtype&&(this.applyJsonState(e.data,e.dataid),n="state"),this.#Fe({type:"loaditem",data:n,source:e.source,loadtype:e.loadtype,dataid:e.dataid,isfirstitem:e.isfirstitem,warn:e.warn}),void 0!==this.#Ia&&void 0!==this.#Ia[e.dataid]&&this.#Ia[e.dataid].addItemMeta(n),"image"===e.loadtype&&0!==this.getViewConfigs(e.dataid).length&&t&&this.#qo.viewOnFirstLoadItem&&this.render(e.dataid)};#wa=e=>{e.type="load",this.#Fe(e)};#Oa=e=>{e.type="loadend",this.#Fe(e)};#Aa=e=>{void 0===e.type&&(e.type="error"),this.#Fe(e)};#ba=e=>{void 0===e.type&&(e.type="timeout"),this.#Fe(e)};#xa=e=>{void 0===e.type&&(e.type="abort"),this.#Fe(e)};#Ea(e){e.addEventListener("zoomchange",this.#Fe),e.addEventListener("offsetchange",this.#Fe),e.addEventListener("renderstart",this.#Fe),e.addEventListener("renderend",this.#Fe);for(let t=0;t<Vn.length;++t)e.addEventListener(Vn[t],this.#Fe);this.#Da&&this.#Da.hasTool("Draw")&&(e.addEventListener("drawcreate",this.#Fe),e.addEventListener("drawdelete",this.#Fe)),e.addEventListener("wlchange",(e=>{const t=_i(e.srclayerid).groupDivId,n=this.getViewConfig(e.dataid,t,!0);void 0!==n&&(n.windowCenter=void 0,n.windowWidth=void 0,n.wlPresetName=void 0,3===e.value.length&&(n.windowCenter=e.value[0],n.windowWidth=e.value[1],n.wlPresetName=e.value[2]))})),e.addEventListener("opacitychange",(e=>{const t=_i(e.srclayerid).groupDivId,n=this.getViewConfig(e.dataid,t,!0);void 0!==n&&(n.opacity=e.value[0])})),e.addEventListener("colourmapchange",(e=>{const t=_i(e.srclayerid).groupDivId,n=this.getViewConfig(e.dataid,t,!0);void 0!==n&&(n.colourMap=e.value[0])}))}#qa(e,t){const n=this.#fa.get(e);if(!n)throw new Error("Cannot initialise layer with missing data, id: "+e);const i=this.#Ca.getLayerGroupByDivId(t.divId);if(!i)throw new Error("Cannot initialise layer with missing group, id: "+t.divId);const r=n.image.getGeometry();this.#Ca.unbindLayerGroups();const o=(new Qn).create(n.meta,n.image),a=Ct(r.getOrientation(),pt(t.orientation));o.setOrientation(a),"SEG"===n.image.getMeta().Modality&&o.setAlphaFunction((function(e){return 0===e?0:255}));const s=0===i.getNumberOfViewLayers();let l=1;void 0!==t.opacity?l=t.opacity:s||(l=.5);const c=i.addViewLayer();c.setView(o,e);const d=r.getSize(a).get2D(),h=r.getSpacing(a).get2D();c.initialise(d,h,l);const S=c.getViewController();if(void 0!==t.wlPresetName)S.setWindowLevelPreset(t.wlPresetName);else if(void 0!==t.windowCenter&&void 0!==t.windowWidth){const e=new u(t.windowCenter,t.windowWidth);S.setWindowLevel(e)}void 0!==t.colourMap?S.setColourMap(t.colourMap):s||("PT"===n.image.getMeta().Modality?S.setColourMap("hot"):S.setColourMap("rainbow")),this.#fa.addEventListener("dataimageset",c.onimageset);const g=[S.getCurrentIndex().getValues(),S.getCurrentPosition().getValues()];i.updateLayersToPositionChange({value:g,srclayerid:c.getId()}),this.#Ca.fitToContainer(),c.setOffset(i.getOffset());const p=this.#Ua(r.getOrientation(),t.orientation);if(this.#Ma(p,c),s)c.setScale(i.getScale());else{const e=i.getBaseViewLayer();c.initScale(i.getScale(),e.getAbsoluteZoomOffset())}this.#Ca.bindLayerGroups(),this.#Da&&this.#Da.bindLayerGroup(i,c),this.#Fe({type:"viewlayeradd",layerid:c.getId(),layergroupid:i.getDivId(),dataid:e}),s&&this.#Da&&this.#Da.init()}addDrawLayer(e,t){const n=this.#Ca.getLayerGroupByDivId(t.divId);if(!n)throw new Error("Cannot initialise layer with missing group, id: "+t.divId);const i=this.#fa.get(e);if(!i)throw new Error("Cannot initialise layer with missing data, id: "+e);const r=i.annotationGroup.getMetaValue("ReferencedSeriesSequence").value[0].SeriesInstanceUID,o=n.searchViewLayers({SeriesInstanceUID:r});if(0===o.length)return void console.warn("No loaded data that matches the measurement reference series UID");const a=o[0],s=a.getDataId();this.#Ca.unbindLayerGroups();const l=a.getViewController();i.annotationGroup.setViewController(l);const c=this.#fa.get(s);if(!c)throw new Error("Cannot initialise layer without reference data, id: "+s);const u=c.image.getGeometry(),d=Ct(u.getOrientation(),pt(t.orientation)),h=u.getSize(d).get2D(),S=u.getSpacing(d).get2D(),g=n.addDrawLayer();g.initialise(h,S,a.getId());const p=new Gn(u,d);g.setPlaneHelper(p);const m=[l.getCurrentIndex().getValues(),l.getCurrentPosition().getValues()];n.updateLayersToPositionChange({value:m,srclayerid:g.getId()}),this.#Ca.fitToContainer(),g.setOffset(n.getOffset());const f=this.#Ua(u.getOrientation(),t.orientation);this.#Ma(f,g),g.initScale(n.getScale(),a.getAbsoluteZoomOffset()),g.setAnnotationGroup(i.annotationGroup,e,this.addToUndoStack),g.setCurrentPosition(l.getCurrentPosition(),l.getCurrentIndex()),this.#Ca.bindLayerGroups(),this.#Da&&this.#Da.bindLayerGroup(n,g),this.#Fe({type:"drawlayeradd",layerid:g.getId(),layergroupid:n.getDivId(),dataid:e})}#Ua(e,t){const n=mt(e.asOneAndZeros());if(void 0===n)throw new Error("Unsupported undefined orientation code");const i=void 0===t,r=!i&&t===gt.Axial,o=!i&&t===gt.Coronal,a=!i&&t===gt.Sagittal,s={x:!1,y:!1},l={x:!1,y:!1,z:!1};return"LPS"===n?(o||a)&&(l.z=!0,s.y=!0):"LAI"===n?i||r?s.y=!0:o?l.z=!0:a&&(l.z=!0,s.x=!0):"RPI"===n?i||r?s.x=!0:o?(l.z=!0,s.x=!0):a&&(l.z=!0):"RAS"===n?(s.x=!0,s.y=!0,(o||a)&&(l.z=!0)):"LSA"===n?(s.y=!0,i||o?l.z=!0:r?l.y=!0:a&&(s.x=!0,l.y=!0,l.z=!0)):"RSP"===n?i||o?(s.x=!0,s.y=!0,l.x=!0,l.z=!0):r?(s.x=!0,l.x=!0):a&&(s.y=!0,l.z=!0):"RIA"===n?(s.x=!0,i||o?l.x=!0:r?(s.y=!0,l.x=!0,l.y=!0):a&&(l.y=!0)):"PSL"===n?(l.z=!0,(i||a||o)&&(s.y=!0)):"PIR"===n?(l.z=!0,(r||o)&&(s.x=!0)):"ASR"===n?(s.x=!0,s.y=!0,(i||a||o)&&(l.z=!0)):"AIL"===n?i||a?(s.x=!0,l.z=!0):r?s.y=!0:o&&(l.z=!0):c.warn("Unsupported orientation code: "+n+", display could be incorrect"),{scale:l,offset:s}}#Ma(e,t){e.offset.x&&t.addFlipOffsetX(),e.offset.y&&t.addFlipOffsetY(),e.scale.x&&t.flipScaleX(),e.scale.y&&t.flipScaleY(),e.scale.z&&t.flipScaleZ()}}class wo{#vi;#Qa;constructor(e){this.#vi=e;const t=e.getMeta();void 0===t.custom&&(t.custom={}),void 0===t.custom.segments&&(t.custom.segments=[]),this.#Qa=t.custom.segments}#Va(e){return this.#Qa.findIndex((function(t){return t.number===e}))}hasSegment(e){return-1!==this.#Va(e)}getNumberOfSegments(){return this.#Qa.length}maskHasSegments(e){const t=[],n=[];for(let i=0;i<e.length;++i){const r=this.getSegment(e[i]);void 0!==r?void 0!==r.displayValue?t.push(r.displayValue):t.push(r.number):(c.warn("Unknown segment in maskHasSegments: "+e[i]),n.push(i))}const i=this.#vi.hasValues(t);for(let e=0;e<n.length;++e)i.splice(n[e],0,!1);return i}getSegment(e){let t;const n=this.#Va(e);return-1!==n&&(t=this.#Qa[n]),t}addSegment(e){-1===this.#Va(e.number)?(this.#Qa.push(e),void 0!==e.displayRGBValue&&this.#vi.updatePaletteColourMap(e.number,e.displayRGBValue)):c.warn("Not adding segment, it is allready in the segments list: "+e.number)}removeSegment(e){const t=this.#Va(e);-1!==t?this.#Qa.splice(t,1):c.warn("Cannot remove segment, it is not in the segments list: "+e)}updateSegment(e){const t=this.#Va(e.number);-1!==t?this.#Qa[t]=e:c.warn("Cannot update segment, it is not in the segments list: "+e.number)}}class Oo{#vi;#Na;#Ba;#Ga;constructor(e,t,n){this.#vi=e,this.#Na=t,this.#Ba=void 0!==n&&n,void 0!==t.displayRGBValue?this.#Ga=e.getOffsets(t.number):this.#Ga=e.getOffsets(t.displayValue)}getName(){return"Delete-segment"}isValid(){return this.#vi.getMeta().custom.segments.some((e=>e.number===this.#Na.number))}execute(){0!==this.#Ga.length&&this.#vi.setAtOffsets(this.#Ga,0),new wo(this.#vi).removeSegment(this.#Na.number),this.#Ba||this.onExecute({type:"masksegmentdelete",segmentnumber:this.#Na.number})}undo(){0!==this.#Ga.length&&(void 0!==this.#Na.displayRGBValue?this.#vi.setAtOffsets(this.#Ga,this.#Na.number):this.#vi.setAtOffsets(this.#Ga,this.#Na.displayValue)),new wo(this.#vi).addSegment(this.#Na),this.onUndo({type:"masksegmentredraw",segmentnumber:this.#Na.number})}onExecute(e){}onUndo(e){}}class Ao{#vi;#Na;#ka;#Ha;#Ba;#Ga;constructor(e,t,n,i){this.#vi=e,this.#Na=t,this.#ka=n,this.#Ba=void 0!==i&&i,void 0!==t.displayRGBValue?this.#Ha=t.displayRGBValue:(this.#Ha=t.displayValue,this.#Ga=e.getOffsets(this.#Ha))}getName(){return"Change-segment-colour"}isValid(){let e=!0;return void 0!==this.#Ga&&(e=0!==this.#Ga.length),e}execute(){"number"==typeof this.#ka?(this.#vi.setAtOffsets(this.#Ga,this.#ka),this.#Na.displayValue=this.#ka):(this.#vi.updatePaletteColourMap(this.#Na.number,this.#ka),this.#Na.displayRGBValue=this.#ka),this.#Ba||this.onExecute({type:"changemasksegmentcolour",segmentnumber:this.#Na.number,value:[this.#ka]})}undo(){"number"==typeof this.#Ha?(this.#vi.setAtOffsets(this.#Ga,this.#Ha),this.#Na.displayValue=this.#Ha):(this.#vi.updatePaletteColourMap(this.#Na.number,this.#Ha),this.#Na.displayRGBValue=this.#Ha),this.onUndo({type:"changemasksegmentcolour",segmentnumber:this.#Na.number,value:[this.#Ha]})}onExecute(e){}onUndo(e){}}class bo{#za=[];#Wa(e){return this.#za.indexOf(e)}isHidden(e){return-1!==this.#Wa(e)}addToHidden(e){this.isHidden(e)?c.warn("Not hidding segment, it is allready in the hidden list: "+e):this.#za.push(e)}removeFromHidden(e){const t=this.#Wa(e);-1!==t?this.#za.splice(t,1):c.warn("Cannot remove segment, it is not in the hidden list: "+e)}getAlphaFunc(){return e=>Array.isArray(e)||0!==e&&!this.#za.includes(e)?255:0}}class xo{x;y}class Ro{x;y;z}return a}()}));
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("konva"),require("magic-wand-tool"),require("jszip")):"function"==typeof define&&define.amd?define(["konva","konmagic-wand-tool","jszip"],t):"object"==typeof exports?exports.dwv=t(require("konva"),require("magic-wand-tool"),require("jszip")):e.dwv=t(e.Konva,e.MagicWand,e.JSZip)}(this,(function(e,t,n){return function(){"use strict";var i={654:function(e){e.exports=n},944:function(t){t.exports=e},324:function(e){e.exports=t}},r={};function o(e){var t=r[e];if(void 0!==t)return t.exports;var n=r[e]={exports:{}};return i[e](n,n.exports,o),n.exports}o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,{a:t}),t},o.d=function(e,t){for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var a={};o.r(a),o.d(a,{Annotation:function(){return Yi},AnnotationGroup:function(){return Xi},AnnotationGroupFactory:function(){return io},App:function(){return Po},AppOptions:function(){return Lo},ChangeSegmentColourCommand:function(){return Ao},Circle:function(){return Fi},ColourMap:function(){return m},DataElement:function(){return ve},DeleteSegmentCommand:function(){return Oo},DicomCode:function(){return kt},DicomData:function(){return ro},DicomParser:function(){return ke},DicomSRContent:function(){return $r},DicomWriter:function(){return Qt},DrawController:function(){return ji},DrawLayer:function(){return Zi},DrawShapeHandler:function(){return Ii},Ellipse:function(){return Ei},Geometry:function(){return it},Image:function(){return Un},Index:function(){return s},LayerGroup:function(){return $i},MaskFactory:function(){return Fn},MaskSegment:function(){return pn},MaskSegmentHelper:function(){return wo},MaskSegmentViewHelper:function(){return bo},Matrix33:function(){return A},NumberRange:function(){return tt},Orientation:function(){return gt},OverlayData:function(){return vo},PlaneHelper:function(){return Gn},Point:function(){return E},Point2D:function(){return R},Point3D:function(){return F},PositionHelper:function(){return Hn},Protractor:function(){return Ui},RGB:function(){return D},ROI:function(){return Ti},Rectangle:function(){return Mi},RescaleSlopeAndIntercept:function(){return je},Scalar2D:function(){return xo},Scalar3D:function(){return Ro},ScrollWheel:function(){return Jn},Size:function(){return Ze},Spacing:function(){return nt},Tag:function(){return de},ToolConfig:function(){return To},ToolboxController:function(){return ur},Vector3D:function(){return P},View:function(){return Bn},ViewConfig:function(){return Io},ViewController:function(){return zn},ViewLayer:function(){return _n},WindowLevel:function(){return u},WriterRule:function(){return At},addTagsToDictionary:function(){return Z},buildMultipart:function(){return X},createImage:function(){return En},createMaskImage:function(){return qn},createView:function(){return Nn},custom:function(){return L},decoderScripts:function(){return yr},getDefaultDicomSegJson:function(){return Rn},getDicomSRContentItem:function(){return to},getDwvVersion:function(){return Pe},getElementsFromJSONTags:function(){return Bt},getEllipseIndices:function(){return qi},getLayerDetailsFromEvent:function(){return Ki},getMousePoint:function(){return jn},getOrientationName:function(){return Dt},getPixelDataTag:function(){return De},getRectangleIndices:function(){return Qi},getReverseOrientation:function(){return be},getSRContent:function(){return eo},getTagFromKey:function(){return Se},getTouchPoints:function(){return Xn},getTypedArray:function(){return Me},getUID:function(){return xt},hasDicomPrefix:function(){return we},i18n:function(){return q},isEqualRgb:function(){return y},labToUintLab:function(){return C},logger:function(){return c},luts:function(){return f},precisionRound:function(){return B},srgbToCielab:function(){return I},toolList:function(){return ki},toolOptions:function(){return Hi}});class s{#e;constructor(e){if(!e||void 0===e)throw new Error("Cannot create index with no values.");if(0===e.length)throw new Error("Cannot create index with empty values.");if(!e.every((function(e){return!isNaN(e)})))throw new Error("Cannot create index with non number values.");this.#e=e}get(e){return this.#e[e]}length(){return this.#e.length}toString(){return"("+this.#e.toString()+")"}getValues(){return this.#e.slice()}canCompare(e){return!!e&&this.length()===e.length()}equals(e){if(!this.canCompare(e))return!1;for(let t=0,n=this.length();t<n;++t)if(this.get(t)!==e.get(t))return!1;return!0}compare(e){if(!this.canCompare(e))return null;const t=[];for(let n=0,i=this.length();n<i;++n)this.get(n)!==e.get(n)&&t.push(n);return t}add(e){if(!this.canCompare(e))return null;const t=[];for(let n=0,i=this.length();n<i;++n)t.push(this.get(n)+e.get(n));return new s(t)}#t(e,t){const n=this.#e.slice();return e<n.length?n[e]+=t:console.warn("Cannot add to given dimension: ",e,n.length),new s(n)}next(e){return this.#t(e,1)}previous(e){return this.#t(e,-1)}getWithNew2D(e,t){const n=[e,t];for(let e=2,t=this.length();e<t;++e)n.push(this.get(e));return new s(n)}}class l{#n;#i;#r;#o;constructor(e,t){if(this.#n=e,this.#i=e.isID(),this.#r=Math.pow(2,t),!this.#i){this.#o=new Float32Array(this.#r);for(let e=0;e<this.#r;++e)this.#o[e]=this.#n.apply(e)}}getRSI(){return this.#n}getLength(){return this.#r}getValue(e){return this.#i?e:this.#o[e]}}const c={levels:{TRACE:0,DEBUG:1,INFO:2,WARN:3,ERROR:4},level:3,trace:function(e){this.level<=this.levels.TRACE&&console.trace(e)},debug:function(e){this.level<=this.levels.DEBUG&&console.debug(e)},info:function(e){this.level<=this.levels.INFO&&console.info(e)},warn:function(e){this.level<=this.levels.WARN&&console.warn(e)},error:function(e){this.level<=this.levels.ERROR&&console.error(e)}};class u{center;width;constructor(e,t){t<1&&(c.warn("Using minimum window width since input is not valid: "+t),t=1),this.center=e,this.width=t}equals(e){return null!=e&&this.center===e.center&&this.width===e.width}}class d{#a;#s=0;#l=0;#c=255;#u=null;#d=null;#h=null;#S=null;constructor(e){this.#a=e,this.#g()}getWindowLevel(){return this.#a}#g(){const e=this.#a.center,t=this.#a.width,n=e+this.#s;this.#u=n-.5-(t-1)/2,this.#d=n-.5+(t-1)/2,this.#h=(this.#c-this.#l)/(t-1),this.#S=(-(n-.5)/(t-1)+.5)*(this.#c-this.#l)+this.#l}setSignedOffset(e){this.#s=e,this.#g()}apply(e){return e<=this.#u?this.#l:e>this.#d?this.#c:e*this.#h+this.#S}}class h{#p;#m;#o;#f=0;#D=!0;constructor(e,t,n){if(this.#p=e,t){const e=this.#p.getLength();this.#f=e/2}else this.#f=0;this.#D=n}getVoiLut(){return this.#m}getModalityLut(){return this.#p}setVoiLut(e){if(this.#m=e,this.#m.setSignedOffset(this.#p.getRSI().getSlope()*this.#f),this.#D){const e=this.#p.getLength();this.#o=new Uint8ClampedArray(e);for(let t=0;t<e;++t)this.#o[t]=this.#m.apply(this.#p.getValue(t))}}getValue(e){return this.#D?this.#o[e+this.#f]:Math.floor(this.#m.apply(e+this.#f))}}function S(e){const t=[];for(let n=0;n<256;++n)t.push(e(n));return t}function g(e){return e}function p(e){return 255-e}class m{red;green;blue;constructor(e,t,n){this.red=e,this.green=t,this.blue=n}}const f={plain:{red:S(g),green:S(g),blue:S(g)},invPlain:{red:S(p),green:S(p),blue:S(p)},rainbow:{blue:[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,252,255,247,239,231,223,215,207,199,191,183,175,167,159,151,143,135,127,119,111,103,95,87,79,71,63,55,47,39,31,23,15,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],green:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,253,251,249,247,245,243,241,239,237,235,233,231,229,227,225,223,221,219,217,215,213,211,209,207,205,203,201,199,197,195,193,192,189,186,183,180,177,174,171,168,165,162,159,156,153,150,147,144,141,138,135,132,129,126,123,120,117,114,111,108,105,102,99,96,93,90,87,84,81,78,75,72,69,66,63,60,57,54,51,48,45,42,39,36,33,30,27,24,21,18,15,12,9,6,3],red:[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,62,60,58,56,54,52,50,48,46,44,42,40,38,36,34,32,30,28,26,24,22,20,18,16,14,12,10,8,6,4,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255]},hot:{red:S((function(e){const t=3*e;return t>255?255:t})),green:S((function(e){const t=256/3;let n=0;return e>=t&&(n=3*(e-t),n>255)?255:n})),blue:S((function(e){const t=256/3;let n=0;return e>=2*t&&(n=3*(e-2*t),n>255)?255:n}))},hot_iron:{red:[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],green:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,255],blue:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,252,255]},pet:{red:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,65,67,69,71,73,75,77,79,81,83,85,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,171,173,175,177,179,181,183,185,187,189,191,193,195,197,199,201,203,205,207,209,211,213,215,217,219,221,223,225,227,229,231,233,235,237,239,241,243,245,247,249,251,253,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],green:[0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,65,67,69,71,73,75,77,79,81,83,85,87,89,91,93,95,97,99,101,103,105,107,109,111,113,115,117,119,121,123,125,128,126,124,122,120,118,116,114,112,110,108,106,104,102,100,98,96,94,92,90,88,86,84,82,80,78,76,74,72,70,68,66,64,63,61,59,57,55,53,51,49,47,45,43,41,39,37,35,33,31,29,27,25,23,21,19,17,15,13,11,9,7,5,3,1,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,255],blue:[0,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,65,67,69,71,73,75,77,79,81,83,85,87,89,91,93,95,97,99,101,103,105,107,109,111,113,115,117,119,121,123,125,127,129,131,133,135,137,139,141,143,145,147,149,151,153,155,157,159,161,163,165,167,169,171,173,175,177,179,181,183,185,187,189,191,193,195,197,199,201,203,205,207,209,211,213,215,217,219,221,223,225,227,229,231,233,235,237,239,241,243,245,247,249,251,253,255,252,248,244,240,236,232,228,224,220,216,212,208,204,200,196,192,188,184,180,176,172,168,164,160,156,152,148,144,140,136,132,128,124,120,116,112,108,104,100,96,92,88,84,80,76,72,68,64,60,56,52,48,44,40,36,32,28,24,20,16,12,8,4,0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,85,89,93,97,101,105,109,113,117,121,125,129,133,137,141,145,149,153,157,161,165,170,174,178,182,186,190,194,198,202,206,210,214,218,222,226,230,234,238,242,246,250,255]},hot_metal_blue:{red:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,6,9,12,15,18,21,24,26,29,32,35,38,41,44,47,50,52,55,57,59,62,64,66,69,71,74,76,78,81,83,85,88,90,93,96,99,102,105,108,111,114,116,119,122,125,128,131,134,137,140,143,146,149,152,155,158,161,164,166,169,172,175,178,181,184,187,190,194,198,201,205,209,213,217,221,224,228,232,236,240,244,247,251,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],green:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,4,6,8,9,11,13,15,17,19,21,23,24,26,28,30,32,34,36,38,40,41,43,45,47,49,51,53,55,56,58,60,62,64,66,68,70,72,73,75,77,79,81,83,85,87,88,90,92,94,96,98,100,102,104,105,107,109,111,113,115,117,119,120,122,124,126,128,130,132,134,136,137,139,141,143,145,147,149,151,152,154,156,158,160,162,164,166,168,169,171,173,175,177,179,181,183,184,186,188,190,192,194,196,198,200,201,203,205,207,209,211,213,215,216,218,220,222,224,226,228,229,231,233,235,237,239,240,242,244,246,248,250,251,253,255],blue:[0,2,4,6,8,10,12,14,16,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,65,67,69,71,73,75,77,79,81,83,84,86,88,90,92,94,96,98,100,102,104,106,108,110,112,114,116,117,119,121,123,125,127,129,131,133,135,137,139,141,143,145,147,149,151,153,155,157,159,161,163,165,167,169,171,173,175,177,179,181,183,184,186,188,190,192,194,196,198,200,197,194,191,188,185,182,179,176,174,171,168,165,162,159,156,153,150,144,138,132,126,121,115,109,103,97,91,85,79,74,68,62,56,50,47,44,41,38,35,32,29,26,24,21,18,15,12,9,6,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,6,9,12,15,18,21,24,26,29,32,35,38,41,44,47,50,53,56,59,62,65,68,71,74,76,79,82,85,88,91,94,97,100,103,106,109,112,115,118,121,124,126,129,132,135,138,141,144,147,150,153,156,159,162,165,168,171,174,176,179,182,185,188,191,194,197,200,203,206,210,213,216,219,223,226,229,232,236,239,242,245,249,252,255]},pet_20step:{red:[0,0,0,0,0,0,0,0,0,0,0,0,0,96,96,96,96,96,96,96,96,96,96,96,96,96,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,80,80,80,80,80,80,80,80,80,80,80,80,80,96,96,96,96,96,96,96,96,96,96,96,96,96,112,112,112,112,112,112,112,112,112,112,112,112,112,128,128,128,128,128,128,128,128,128,128,128,128,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,80,80,80,80,80,80,80,80,80,80,80,80,80,64,64,64,64,64,64,64,64,64,64,64,64,224,224,224,224,224,224,224,224,224,224,224,224,224,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,192,192,192,192,192,192,192,192,192,192,192,192,192,176,176,176,176,176,176,176,176,176,176,176,176,176,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255],green:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,80,80,80,80,80,80,80,80,80,80,80,80,80,96,96,96,96,96,96,96,96,96,96,96,96,96,112,112,112,112,112,112,112,112,112,112,112,112,112,128,128,128,128,128,128,128,128,128,128,128,128,96,96,96,96,96,96,96,96,96,96,96,96,96,144,144,144,144,144,144,144,144,144,144,144,144,144,192,192,192,192,192,192,192,192,192,192,192,192,192,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,208,208,208,208,208,208,208,208,208,208,208,208,208,176,176,176,176,176,176,176,176,176,176,176,176,176,144,144,144,144,144,144,144,144,144,144,144,144,96,96,96,96,96,96,96,96,96,96,96,96,96,48,48,48,48,48,48,48,48,48,48,48,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255],blue:[0,0,0,0,0,0,0,0,0,0,0,0,0,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,112,112,112,112,112,112,112,112,112,112,112,112,128,128,128,128,128,128,128,128,128,128,128,128,128,176,176,176,176,176,176,176,176,176,176,176,176,176,192,192,192,192,192,192,192,192,192,192,192,192,192,224,224,224,224,224,224,224,224,224,224,224,224,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,80,80,80,80,80,80,80,80,80,80,80,80,80,64,64,64,64,64,64,64,64,64,64,64,64,80,80,80,80,80,80,80,80,80,80,80,80,80,96,96,96,96,96,96,96,96,96,96,96,96,96,64,64,64,64,64,64,64,64,64,64,64,64,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255]}};class D{r;g;b;constructor(e,t,n){this.r=e,this.g=t,this.b=n}}function y(e,t){return null!==e&&null!==t&&void 0!==e&&void 0!==t&&e.r===t.r&&e.g===t.g&&e.b===t.b}function C(e){return{l:655.35*e.l,a:257*e.a+32896,b:257*e.b+32896}}const v={x:95.0489,y:100,z:108.884};function I(e){return function(e){function t(e){let t=null;return t=e>.008856452?Math.pow(e,.333333333):7.787037037*e+.137931034,t}const n=v,i=t(e.y/n.y);return{l:116*i-16,a:500*(t(e.x/n.x)-i),b:200*(i-t(e.z/n.z))}}(function(e){function t(e){let t=null;return t=e<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4),t}const n=t(e.r/255),i=t(e.g/255),r=t(e.b/255);return{x:100*(.4124*n+.3576*i+.1805*r),y:100*(.2126*n+.7152*i+.0722*r),z:100*(.0193*n+.1192*i+.9505*r)}}(e))}function T(e){const t={Yellow:"#ffff00",Red:"#ff0000",White:"#ffffff",Green:"#008000",Blue:"#0000ff",Lime:"#00ff00",Fuchsia:"#ff00ff",Black:"#000000"};let n="#ffff00";return void 0!==t[e]&&(n=t[e]),n}const L={wlPresets:void 0,labelTexts:void 0,openRoiDialog:void 0,getTagTime:void 0,getTagPixelUnit:void 0};class P{#y;#C;#v;constructor(e,t,n){this.#y=e,this.#C=t,this.#v=n}getX(){return this.#y}getY(){return this.#C}getZ(){return this.#v}equals(e){return null!==e&&this.#y===e.getX()&&this.#C===e.getY()&&this.#v===e.getZ()}toString(){return"("+this.#y+", "+this.#C+", "+this.#v+")"}norm(){return Math.sqrt(this.#y*this.#y+this.#C*this.#C+this.#v*this.#v)}crossProduct(e){return new P(this.#C*e.getZ()-e.getY()*this.#v,this.#v*e.getX()-e.getZ()*this.#y,this.#y*e.getY()-e.getX()*this.#C)}dotProduct(e){return this.#y*e.getX()+this.#C*e.getY()+this.#v*e.getZ()}isCodirectional(e){return this.dotProduct(e)>0}}Number.EPSILON;const w=1e-4;function O(e,t,n){return void 0===n&&(n=Number.EPSILON),Math.abs(e-t)<n}class A{#e;#I;constructor(e){this.#e=e}get(e,t){return this.#e[3*e+t]}getInverse(){return void 0===this.#I&&(this.#I=function(e){const t=e.get(0,0),n=e.get(0,1),i=e.get(0,2),r=e.get(1,0),o=e.get(1,1),a=e.get(1,2),s=e.get(2,0),l=e.get(2,1),u=e.get(2,2),d=o*u-a*l,h=a*s-r*u,S=r*l-o*s;let g=t*d+n*h+i*S;if(0!==g)return g=1/g,new A([g*d,g*(i*l-n*u),g*(n*a-i*o),g*h,g*(t*u-i*s),g*(i*r-t*a),g*S,g*(n*s-t*l),g*(t*o-n*r)]);c.warn("Cannot invert 3*3 matrix with zero determinant.")}(this)),this.#I}equals(e,t){for(let n=0;n<3;++n)for(let i=0;i<3;++i)if(!O(this.get(n,i),e.get(n,i),t))return!1;return!0}toString(){let e="[";for(let t=0;t<3;++t){0!==t&&(e+=", \n ");for(let n=0;n<3;++n)0!==n&&(e+=", "),e+=this.get(t,n)}return e+="]",e}multiply(e){const t=[];for(let n=0;n<3;++n)for(let i=0;i<3;++i){let r=0;for(let t=0;t<3;++t)r+=this.get(n,t)*e.get(t,i);t.push(r)}return new A(t)}getAbs(){const e=[];for(let t=0;t<3;++t)for(let n=0;n<3;++n)e.push(Math.abs(this.get(t,n)));return new A(e)}multiplyArray3D(e){if(3!==e.length)throw new Error("Cannot multiply 3x3 matrix with non 3D array: "+e.length);const t=[];for(let n=0;n<3;++n){let i=0;for(let t=0;t<3;++t)i+=this.get(n,t)*e[t];t.push(i)}return t}multiplyVector3D(e){const t=this.multiplyArray3D([e.getX(),e.getY(),e.getZ()]);return new P(t[0],t[1],t[2])}multiplyPoint3D(e){const t=this.multiplyArray3D([e.getX(),e.getY(),e.getZ()]);return new F(t[0],t[1],t[2])}multiplyIndex3D(e){const t=this.multiplyArray3D(e.getValues());return new s(t)}getRowAbsMax(e){const t=[Math.abs(this.get(e,0)),Math.abs(this.get(e,1)),Math.abs(this.get(e,2))],n=Math.max.apply(null,t),i=t.indexOf(n);return{value:this.get(e,i),index:i}}getColAbsMax(e){const t=[Math.abs(this.get(0,e)),Math.abs(this.get(1,e)),Math.abs(this.get(2,e))],n=Math.max.apply(null,t),i=t.indexOf(n);return{value:this.get(i,e),index:i}}asOneAndZeros(){const e=[];for(let t=0;t<3;++t){const n=this.getRowAbsMax(t),i=n.value>0?1:-1;for(let t=0;t<3;++t)t===n.index?e.push(1*i):e.push(0)}return new A(e)}getThirdColMajorDirection(){return this.getColAbsMax(2).index}}function b(){return new A([1,0,0,0,1,0,0,0,1])}function x(e){return e.equals(b())}class R{#y;#C;constructor(e,t){this.#y=e,this.#C=t}getX(){return this.#y}getY(){return this.#C}getValues(){return[this.#y,this.#C]}getCentroid(){return this}equals(e){return null!=e&&this.#y===e.getX()&&this.#C===e.getY()}toString(){return"("+this.#y+", "+this.#C+")"}getDistance(e){const t=this.#y-e.getX(),n=this.#C-e.getY();return Math.sqrt(t*t+n*n)}}class F{#y;#C;#v;constructor(e,t,n){this.#y=e,this.#C=t,this.#v=n}getX(){return this.#y}getY(){return this.#C}getZ(){return this.#v}getValues(){return[this.#y,this.#C,this.#v]}equals(e){return null!==e&&this.#y===e.getX()&&this.#C===e.getY()&&this.#v===e.getZ()}isSimilar(e,t){return null!==e&&O(this.#y,e.getX(),t)&&O(this.#C,e.getY(),t)&&O(this.#v,e.getZ(),t)}toString(){return"("+this.#y+", "+this.#C+", "+this.#v+")"}getDistance(e){return Math.sqrt(this.#T(e))}#T(e){const t=this.#y-e.getX(),n=this.#C-e.getY(),i=this.#v-e.getZ();return t*t+n*n+i*i}getClosest(e){let t=0,n=this.#T(e[t]);for(let i=0;i<e.length;++i){const r=this.#T(e[i]);r<n&&(t=i,n=r)}return t}minus(e){return new P(this.#y-e.getX(),this.#C-e.getY(),this.#v-e.getZ())}}class E{#e;constructor(e){if(!e||void 0===e)throw new Error("Cannot create point with no values.");if(0===e.length)throw new Error("Cannot create point with empty values.");if(!e.every((function(e){return!isNaN(e)})))throw new Error("Cannot create point with non number values.");this.#e=e}get(e){return this.#e[e]}length(){return this.#e.length}toString(){return"("+this.#e.toString()+")"}getValues(){return this.#e.slice()}canCompare(e){return!!e&&this.length()===e.length()}equals(e){if(!this.canCompare(e))return!1;for(let t=0,n=this.length();t<n;++t)if(this.get(t)!==e.get(t))return!1;return!0}compare(e){if(!this.canCompare(e))return null;const t=[];for(let n=0,i=this.length();n<i;++n)this.get(n)!==e.get(n)&&t.push(n);return t}get3D(){return new F(this.get(0),this.get(1),this.get(2))}add(e){if(!this.canCompare(e))return null;const t=[],n=this.getValues(),i=e.getValues();for(let e=0;e<n.length;++e)t.push(n[e]+i[e]);return new E(t)}mergeWith3D(e){const t=this.getValues();return t[0]=e.getX(),t[1]=e.getY(),t[2]=e.getZ(),new E(t)}}const q={t(e){let t=e;const n=e.split(".");return 2===n.length&&"unit"===n[0]&&(t={mm:"mm",cm2:"cm²",degree:"°"}[n[1]]),t}};function U(e,t,n){if(null==e||null==t)return!1;const i=n>0?0|n:0;return e.substring(i,i+t.length)===t}function M(e,t){return null!=e&&null!=t&&e.substring(e.length-t.length)===t}function Q(e){const t=[];if(null==e)return t;const n=/{(\w+)}/g;let i=n.exec(e);for(;i;)t.push(i[1]),i=n.exec(e);return t}function V(e){let t=null;if(null!=e&&"."!==e[0]){const n=e.toLowerCase().split(".");1!==n.length&&(t=n.pop(),/[a-z]/.test(t)&&!t.includes("/")||(t=null))}return t}function N(e){const t=new Uint8Array(e.length);for(let n=0,i=e.length;n<i;n++)t[n]=e.charCodeAt(n);return t}function B(e,t){const n=Math.pow(10,t),i=.01/n;return Math.round(e*n+i)/n}function G(e,t){if(void 0===t){t=[];for(let n=0;n<e.length;++n)t.push(n)}for(let n=0;n<t.length;++n)if(t[n]>=e.length)throw new Error("Non valid dimension for toStringId");let n="";for(let i=0;i<t.length;++i)0!==i&&(n+="_"),n+="#"+t[i]+"-"+e[t[i]];return n}function k(e,t){return null!==e&&null!==t&&void 0!==e&&void 0!==t&&H(e.slice().sort(),t.slice().sort())}function H(e,t){return null!==e&&null!==t&&void 0!==e&&void 0!==t&&e.length===t.length&&e.every((function(e,n){return e===t[n]}))}function z(e){return String.fromCharCode.apply(String,e)}function W(e,t,n,i){(void 0===n||n<0||n>=e.length)&&(n=0),(void 0===i||i<=n||i>e.length)&&(i=e.length);for(let r=n;r<i;++r)if(t(e[r],r,e))return r}function Y(e){return function(t,n,i){for(let t=0;t<e.length;++t)if(i[n+t]!==e[t])return!1;return!0}}function X(e,t){const n="\r\n";let i=0;const r=[];for(let o=0;o<e.length;++o){let a="";0!==o&&(a+=n),a+="--"+t+n;const s=Object.keys(e[o]);for(let t=0;t<s.length;++t){const i=s[t];"data"!==i&&(a+=i+": "+e[o][i]+n)}a+=n;const l=N(a);r.push(l),i+=l.byteLength+e[o].data.byteLength}const o=N("\r\n--"+t+"--"+n),a=new Uint8Array(i+o.byteLength);let s=0;for(let t=0;t<e.length;++t)a.set(r[t],s),s+=r[t].byteLength,a.set(new Uint8Array(e[t].data),s),s+=e[t].data.byteLength;return a.set(o,s),a}const j={"0000":{"0000":["UL","1","CommandGroupLength"],"0001":["UL","1","CommandLengthToEnd"],"0002":["UI","1","AffectedSOPClassUID"],"0003":["UI","1","RequestedSOPClassUID"],"0010":["SH","1","CommandRecognitionCode"],"0100":["US","1","CommandField"],"0110":["US","1","MessageID"],"0120":["US","1","MessageIDBeingRespondedTo"],"0200":["AE","1","Initiator"],"0300":["AE","1","Receiver"],"0400":["AE","1","FindLocation"],"0600":["AE","1","MoveDestination"],"0700":["US","1","Priority"],"0800":["US","1","CommandDataSetType"],"0850":["US","1","NumberOfMatches"],"0860":["US","1","ResponseSequenceNumber"],"0900":["US","1","Status"],"0901":["AT","1-n","OffendingElement"],"0902":["LO","1","ErrorComment"],"0903":["US","1","ErrorID"],1e3:["UI","1","AffectedSOPInstanceUID"],1001:["UI","1","RequestedSOPInstanceUID"],1002:["US","1","EventTypeID"],1005:["AT","1-n","AttributeIdentifierList"],1008:["US","1","ActionTypeID"],1020:["US","1","NumberOfRemainingSuboperations"],1021:["US","1","NumberOfCompletedSuboperations"],1022:["US","1","NumberOfFailedSuboperations"],1023:["US","1","NumberOfWarningSuboperations"],1030:["AE","1","MoveOriginatorApplicationEntityTitle"],1031:["US","1","MoveOriginatorMessageID"],4e3:["LT","1","DialogReceiver"],4010:["LT","1","TerminalType"],5010:["SH","1","MessageSetID"],5020:["SH","1","EndMessageID"],5110:["LT","1","DisplayFormat"],5120:["LT","1","PagePositionID"],5130:["CS","1","TextFormatID"],5140:["CS","1","NormalReverse"],5150:["CS","1","AddGrayScale"],5160:["CS","1","Borders"],5170:["IS","1","Copies"],5180:["CS","1","CommandMagnificationType"],5190:["CS","1","Erase"],"51A0":["CS","1","Print"],"51B0":["US","1-n","Overlays"]},"0002":{"0000":["UL","1","FileMetaInformationGroupLength"],"0001":["OB","1","FileMetaInformationVersion"],"0002":["UI","1","MediaStorageSOPClassUID"],"0003":["UI","1","MediaStorageSOPInstanceUID"],"0010":["UI","1","TransferSyntaxUID"],"0012":["UI","1","ImplementationClassUID"],"0013":["SH","1","ImplementationVersionName"],"0016":["AE","1","SourceApplicationEntityTitle"],"0017":["AE","1","SendingApplicationEntityTitle"],"0018":["AE","1","ReceivingApplicationEntityTitle"],"0026":["UR","1","SourcePresentationAddress"],"0027":["UR","1","SendingPresentationAddress"],"0028":["UR","1","ReceivingPresentationAddress"],"0031":["OB","1","RTVMetaInformationVersion"],"0032":["UI","1","RTVCommunicationSOPClassUID"],"0033":["UI","1","RTVCommunicationSOPInstanceUID"],"0035":["OB","1","RTVSourceIdentifier"],"0036":["OB","1","RTVFlowIdentifier"],"0037":["UL","1","RTVFlowRTPSamplingRate"],"0038":["FD","1","RTVFlowActualFrameDuration"],"0100":["UI","1","PrivateInformationCreatorUID"],"0102":["OB","1","PrivateInformation"]},"0004":{"0000":["UL","1","GenericGroupLength"],1130:["CS","1","FileSetID"],1141:["CS","1-8","FileSetDescriptorFileID"],1142:["CS","1","SpecificCharacterSetOfFileSetDescriptorFile"],1200:["UL","1","OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity"],1202:["UL","1","OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity"],1212:["US","1","FileSetConsistencyFlag"],1220:["SQ","1","DirectoryRecordSequence"],1400:["UL","1","OffsetOfTheNextDirectoryRecord"],1410:["US","1","RecordInUseFlag"],1420:["UL","1","OffsetOfReferencedLowerLevelDirectoryEntity"],1430:["CS","1","DirectoryRecordType"],1432:["UI","1","PrivateRecordUID"],1500:["CS","1-8","ReferencedFileID"],1504:["UL","1","MRDRDirectoryRecordOffset"],1510:["UI","1","ReferencedSOPClassUIDInFile"],1511:["UI","1","ReferencedSOPInstanceUIDInFile"],1512:["UI","1","ReferencedTransferSyntaxUIDInFile"],"151A":["UI","1-n","ReferencedRelatedGeneralSOPClassUIDInFile"],1600:["UL","1","NumberOfReferences"]},"0008":{"0000":["UL","1","GenericGroupLength"],"0001":["UL","1","LengthToEnd"],"0005":["CS","1-n","SpecificCharacterSet"],"0006":["SQ","1","LanguageCodeSequence"],"0008":["CS","2-n","ImageType"],"0010":["SH","1","RecognitionCode"],"0012":["DA","1","InstanceCreationDate"],"0013":["TM","1","InstanceCreationTime"],"0014":["UI","1","InstanceCreatorUID"],"0015":["DT","1","InstanceCoercionDateTime"],"0016":["UI","1","SOPClassUID"],"0018":["UI","1","SOPInstanceUID"],"001A":["UI","1-n","RelatedGeneralSOPClassUID"],"001B":["UI","1","OriginalSpecializedSOPClassUID"],"0020":["DA","1","StudyDate"],"0021":["DA","1","SeriesDate"],"0022":["DA","1","AcquisitionDate"],"0023":["DA","1","ContentDate"],"0024":["DA","1","OverlayDate"],"0025":["DA","1","CurveDate"],"002A":["DT","1","AcquisitionDateTime"],"0030":["TM","1","StudyTime"],"0031":["TM","1","SeriesTime"],"0032":["TM","1","AcquisitionTime"],"0033":["TM","1","ContentTime"],"0034":["TM","1","OverlayTime"],"0035":["TM","1","CurveTime"],"0040":["US","1","DataSetType"],"0041":["LO","1","DataSetSubtype"],"0042":["CS","1","NuclearMedicineSeriesType"],"0050":["SH","1","AccessionNumber"],"0051":["SQ","1","IssuerOfAccessionNumberSequence"],"0052":["CS","1","QueryRetrieveLevel"],"0053":["CS","1","QueryRetrieveView"],"0054":["AE","1-n","RetrieveAETitle"],"0055":["AE","1","StationAETitle"],"0056":["CS","1","InstanceAvailability"],"0058":["UI","1-n","FailedSOPInstanceUIDList"],"0060":["CS","1","Modality"],"0061":["CS","1-n","ModalitiesInStudy"],"0062":["UI","1-n","SOPClassesInStudy"],"0063":["SQ","1","AnatomicRegionsInStudyCodeSequence"],"0064":["CS","1","ConversionType"],"0068":["CS","1","PresentationIntentType"],"0070":["LO","1","Manufacturer"],"0080":["LO","1","InstitutionName"],"0081":["ST","1","InstitutionAddress"],"0082":["SQ","1","InstitutionCodeSequence"],"0090":["PN","1","ReferringPhysicianName"],"0092":["ST","1","ReferringPhysicianAddress"],"0094":["SH","1-n","ReferringPhysicianTelephoneNumbers"],"0096":["SQ","1","ReferringPhysicianIdentificationSequence"],"009C":["PN","1-n","ConsultingPhysicianName"],"009D":["SQ","1","ConsultingPhysicianIdentificationSequence"],"0100":["SH","1","CodeValue"],"0101":["LO","1","ExtendedCodeValue"],"0102":["SH","1","CodingSchemeDesignator"],"0103":["SH","1","CodingSchemeVersion"],"0104":["LO","1","CodeMeaning"],"0105":["CS","1","MappingResource"],"0106":["DT","1","ContextGroupVersion"],"0107":["DT","1","ContextGroupLocalVersion"],"0108":["LT","1","ExtendedCodeMeaning"],"0109":["SQ","1","CodingSchemeResourcesSequence"],"010A":["CS","1","CodingSchemeURLType"],"010B":["CS","1","ContextGroupExtensionFlag"],"010C":["UI","1","CodingSchemeUID"],"010D":["UI","1","ContextGroupExtensionCreatorUID"],"010E":["UR","1","CodingSchemeURL"],"010F":["CS","1","ContextIdentifier"],"0110":["SQ","1","CodingSchemeIdentificationSequence"],"0112":["LO","1","CodingSchemeRegistry"],"0114":["ST","1","CodingSchemeExternalID"],"0115":["ST","1","CodingSchemeName"],"0116":["ST","1","CodingSchemeResponsibleOrganization"],"0117":["UI","1","ContextUID"],"0118":["UI","1","MappingResourceUID"],"0119":["UC","1","LongCodeValue"],"0120":["UR","1","URNCodeValue"],"0121":["SQ","1","EquivalentCodeSequence"],"0122":["LO","1","MappingResourceName"],"0123":["SQ","1","ContextGroupIdentificationSequence"],"0124":["SQ","1","MappingResourceIdentificationSequence"],"0201":["SH","1","TimezoneOffsetFromUTC"],"0202":["","",""],"0220":["SQ","1","ResponsibleGroupCodeSequence"],"0221":["CS","1","EquipmentModality"],"0222":["LO","1","ManufacturerRelatedModelGroup"],"0300":["SQ","1","PrivateDataElementCharacteristicsSequence"],"0301":["US","1","PrivateGroupReference"],"0302":["LO","1","PrivateCreatorReference"],"0303":["CS","1","BlockIdentifyingInformationStatus"],"0304":["US","1-n","NonidentifyingPrivateElements"],"0305":["SQ","1","DeidentificationActionSequence"],"0306":["US","1-n","IdentifyingPrivateElements"],"0307":["CS","1","DeidentificationAction"],"0308":["US","1","PrivateDataElement"],"0309":["UL","1-3","PrivateDataElementValueMultiplicity"],"030A":["CS","1","PrivateDataElementValueRepresentation"],"030B":["UL","1-2","PrivateDataElementNumberOfItems"],"030C":["UC","1","PrivateDataElementName"],"030D":["UC","1","PrivateDataElementKeyword"],"030E":["UT","1","PrivateDataElementDescription"],"030F":["UT","1","PrivateDataElementEncoding"],"0310":["SQ","1","PrivateDataElementDefinitionSequence"],1e3:["AE","1","NetworkID"],1010:["SH","1","StationName"],1030:["LO","1","StudyDescription"],1032:["SQ","1","ProcedureCodeSequence"],"103E":["LO","1","SeriesDescription"],"103F":["SQ","1","SeriesDescriptionCodeSequence"],1040:["LO","1","InstitutionalDepartmentName"],1041:["SQ","1","InstitutionalDepartmentTypeCodeSequence"],1048:["PN","1-n","PhysiciansOfRecord"],1049:["SQ","1","PhysiciansOfRecordIdentificationSequence"],1050:["PN","1-n","PerformingPhysicianName"],1052:["SQ","1","PerformingPhysicianIdentificationSequence"],1060:["PN","1-n","NameOfPhysiciansReadingStudy"],1062:["SQ","1","PhysiciansReadingStudyIdentificationSequence"],1070:["PN","1-n","OperatorsName"],1072:["SQ","1","OperatorIdentificationSequence"],1080:["LO","1-n","AdmittingDiagnosesDescription"],1084:["SQ","1","AdmittingDiagnosesCodeSequence"],1090:["LO","1","ManufacturerModelName"],1100:["SQ","1","ReferencedResultsSequence"],1110:["SQ","1","ReferencedStudySequence"],1111:["SQ","1","ReferencedPerformedProcedureStepSequence"],1115:["SQ","1","ReferencedSeriesSequence"],1120:["SQ","1","ReferencedPatientSequence"],1125:["SQ","1","ReferencedVisitSequence"],1130:["SQ","1","ReferencedOverlaySequence"],1134:["SQ","1","ReferencedStereometricInstanceSequence"],"113A":["SQ","1","ReferencedWaveformSequence"],1140:["SQ","1","ReferencedImageSequence"],1145:["SQ","1","ReferencedCurveSequence"],"114A":["SQ","1","ReferencedInstanceSequence"],"114B":["SQ","1","ReferencedRealWorldValueMappingInstanceSequence"],1150:["UI","1","ReferencedSOPClassUID"],1155:["UI","1","ReferencedSOPInstanceUID"],1156:["SQ","1","DefinitionSourceSequence"],"115A":["UI","1-n","SOPClassesSupported"],1160:["IS","1-n","ReferencedFrameNumber"],1161:["UL","1-n","SimpleFrameList"],1162:["UL","3-3n","CalculatedFrameList"],1163:["FD","2","TimeRange"],1164:["SQ","1","FrameExtractionSequence"],1167:["UI","1","MultiFrameSourceSOPInstanceUID"],1190:["UR","1","RetrieveURL"],1195:["UI","1","TransactionUID"],1196:["US","1","WarningReason"],1197:["US","1","FailureReason"],1198:["SQ","1","FailedSOPSequence"],1199:["SQ","1","ReferencedSOPSequence"],"119A":["SQ","1","OtherFailuresSequence"],1200:["SQ","1","StudiesContainingOtherReferencedInstancesSequence"],1250:["SQ","1","RelatedSeriesSequence"],2110:["CS","1","LossyImageCompressionRetired"],2111:["ST","1","DerivationDescription"],2112:["SQ","1","SourceImageSequence"],2120:["SH","1","StageName"],2122:["IS","1","StageNumber"],2124:["IS","1","NumberOfStages"],2127:["SH","1","ViewName"],2128:["IS","1","ViewNumber"],2129:["IS","1","NumberOfEventTimers"],"212A":["IS","1","NumberOfViewsInStage"],2130:["DS","1-n","EventElapsedTimes"],2132:["LO","1-n","EventTimerNames"],2133:["SQ","1","EventTimerSequence"],2134:["FD","1","EventTimeOffset"],2135:["SQ","1","EventCodeSequence"],2142:["IS","1","StartTrim"],2143:["IS","1","StopTrim"],2144:["IS","1","RecommendedDisplayFrameRate"],2200:["CS","1","TransducerPosition"],2204:["CS","1","TransducerOrientation"],2208:["CS","1","AnatomicStructure"],2218:["SQ","1","AnatomicRegionSequence"],2220:["SQ","1","AnatomicRegionModifierSequence"],2228:["SQ","1","PrimaryAnatomicStructureSequence"],2229:["SQ","1","AnatomicStructureSpaceOrRegionSequence"],2230:["SQ","1","PrimaryAnatomicStructureModifierSequence"],2240:["SQ","1","TransducerPositionSequence"],2242:["SQ","1","TransducerPositionModifierSequence"],2244:["SQ","1","TransducerOrientationSequence"],2246:["SQ","1","TransducerOrientationModifierSequence"],2251:["SQ","1","AnatomicStructureSpaceOrRegionCodeSequenceTrial"],2253:["SQ","1","AnatomicPortalOfEntranceCodeSequenceTrial"],2255:["SQ","1","AnatomicApproachDirectionCodeSequenceTrial"],2256:["ST","1","AnatomicPerspectiveDescriptionTrial"],2257:["SQ","1","AnatomicPerspectiveCodeSequenceTrial"],2258:["ST","1","AnatomicLocationOfExaminingInstrumentDescriptionTrial"],2259:["SQ","1","AnatomicLocationOfExaminingInstrumentCodeSequenceTrial"],"225A":["SQ","1","AnatomicStructureSpaceOrRegionModifierCodeSequenceTrial"],"225C":["SQ","1","OnAxisBackgroundAnatomicStructureCodeSequenceTrial"],3001:["SQ","1","AlternateRepresentationSequence"],3002:["UI","1-n","AvailableTransferSyntaxUID"],3010:["UI","1-n","IrradiationEventUID"],3011:["SQ","1","SourceIrradiationEventSequence"],3012:["UI","1","RadiopharmaceuticalAdministrationEventUID"],4e3:["LT","1","IdentifyingComments"],9007:["CS","4","FrameType"],9092:["SQ","1","ReferencedImageEvidenceSequence"],9121:["SQ","1","ReferencedRawDataSequence"],9123:["UI","1","CreatorVersionUID"],9124:["SQ","1","DerivationImageSequence"],9154:["SQ","1","SourceImageEvidenceSequence"],9205:["CS","1","PixelPresentation"],9206:["CS","1","VolumetricProperties"],9207:["CS","1","VolumeBasedCalculationTechnique"],9208:["CS","1","ComplexImageComponent"],9209:["CS","1","AcquisitionContrast"],9215:["SQ","1","DerivationCodeSequence"],9237:["SQ","1","ReferencedPresentationStateSequence"],9410:["SQ","1","ReferencedOtherPlaneSequence"],9458:["SQ","1","FrameDisplaySequence"],9459:["FL","1","RecommendedDisplayFrameRateInFloat"],9460:["CS","1","SkipFrameRangeFlag"]},"0010":{"0000":["UL","1","GenericGroupLength"],"0010":["PN","1","PatientName"],"0020":["LO","1","PatientID"],"0021":["LO","1","IssuerOfPatientID"],"0022":["CS","1","TypeOfPatientID"],"0024":["SQ","1","IssuerOfPatientIDQualifiersSequence"],"0026":["SQ","1","SourcePatientGroupIdentificationSequence"],"0027":["SQ","1","GroupOfPatientsIdentificationSequence"],"0028":["US","3","SubjectRelativePositionInImage"],"0030":["DA","1","PatientBirthDate"],"0032":["TM","1","PatientBirthTime"],"0033":["LO","1","PatientBirthDateInAlternativeCalendar"],"0034":["LO","1","PatientDeathDateInAlternativeCalendar"],"0035":["CS","1","PatientAlternativeCalendar"],"0040":["CS","1","PatientSex"],"0050":["SQ","1","PatientInsurancePlanCodeSequence"],"0101":["SQ","1","PatientPrimaryLanguageCodeSequence"],"0102":["SQ","1","PatientPrimaryLanguageModifierCodeSequence"],"0200":["CS","1","QualityControlSubject"],"0201":["SQ","1","QualityControlSubjectTypeCodeSequence"],"0212":["UC","1","StrainDescription"],"0213":["LO","1","StrainNomenclature"],"0214":["LO","1","StrainStockNumber"],"0215":["SQ","1","StrainSourceRegistryCodeSequence"],"0216":["SQ","1","StrainStockSequence"],"0217":["LO","1","StrainSource"],"0218":["UT","1","StrainAdditionalInformation"],"0219":["SQ","1","StrainCodeSequence"],"0221":["SQ","1","GeneticModificationsSequence"],"0222":["UC","1","GeneticModificationsDescription"],"0223":["LO","1","GeneticModificationsNomenclature"],"0229":["SQ","1","GeneticModificationsCodeSequence"],1e3:["LO","1-n","OtherPatientIDs"],1001:["PN","1-n","OtherPatientNames"],1002:["SQ","1","OtherPatientIDsSequence"],1005:["PN","1","PatientBirthName"],1010:["AS","1","PatientAge"],1020:["DS","1","PatientSize"],1021:["SQ","1","PatientSizeCodeSequence"],1022:["DS","1","PatientBodyMassIndex"],1023:["DS","1","MeasuredAPDimension"],1024:["DS","1","MeasuredLateralDimension"],1030:["DS","1","PatientWeight"],1040:["LO","1","PatientAddress"],1050:["LO","1-n","InsurancePlanIdentification"],1060:["PN","1","PatientMotherBirthName"],1080:["LO","1","MilitaryRank"],1081:["LO","1","BranchOfService"],1090:["LO","1","MedicalRecordLocator"],1100:["SQ","1","ReferencedPatientPhotoSequence"],2e3:["LO","1-n","MedicalAlerts"],2110:["LO","1-n","Allergies"],2150:["LO","1","CountryOfResidence"],2152:["LO","1","RegionOfResidence"],2154:["SH","1-n","PatientTelephoneNumbers"],2155:["LT","1","PatientTelecomInformation"],2160:["SH","1","EthnicGroup"],2180:["SH","1","Occupation"],"21A0":["CS","1","SmokingStatus"],"21B0":["LT","1","AdditionalPatientHistory"],"21C0":["US","1","PregnancyStatus"],"21D0":["DA","1","LastMenstrualDate"],"21F0":["LO","1","PatientReligiousPreference"],2201:["LO","1","PatientSpeciesDescription"],2202:["SQ","1","PatientSpeciesCodeSequence"],2203:["CS","1","PatientSexNeutered"],2210:["CS","1","AnatomicalOrientationType"],2292:["LO","1","PatientBreedDescription"],2293:["SQ","1","PatientBreedCodeSequence"],2294:["SQ","1","BreedRegistrationSequence"],2295:["LO","1","BreedRegistrationNumber"],2296:["SQ","1","BreedRegistryCodeSequence"],2297:["PN","1","ResponsiblePerson"],2298:["CS","1","ResponsiblePersonRole"],2299:["LO","1","ResponsibleOrganization"],4e3:["LT","1","PatientComments"],9431:["FL","1","ExaminedBodyThickness"]},"0012":{"0000":["UL","1","GenericGroupLength"],"0010":["LO","1","ClinicalTrialSponsorName"],"0020":["LO","1","ClinicalTrialProtocolID"],"0021":["LO","1","ClinicalTrialProtocolName"],"0030":["LO","1","ClinicalTrialSiteID"],"0031":["LO","1","ClinicalTrialSiteName"],"0040":["LO","1","ClinicalTrialSubjectID"],"0042":["LO","1","ClinicalTrialSubjectReadingID"],"0050":["LO","1","ClinicalTrialTimePointID"],"0051":["ST","1","ClinicalTrialTimePointDescription"],"0052":["FD","1","LongitudinalTemporalOffsetFromEvent"],"0053":["CS","1","LongitudinalTemporalEventType"],"0060":["LO","1","ClinicalTrialCoordinatingCenterName"],"0062":["CS","1","PatientIdentityRemoved"],"0063":["LO","1-n","DeidentificationMethod"],"0064":["SQ","1","DeidentificationMethodCodeSequence"],"0071":["LO","1","ClinicalTrialSeriesID"],"0072":["LO","1","ClinicalTrialSeriesDescription"],"0081":["LO","1","ClinicalTrialProtocolEthicsCommitteeName"],"0082":["LO","1","ClinicalTrialProtocolEthicsCommitteeApprovalNumber"],"0083":["SQ","1","ConsentForClinicalTrialUseSequence"],"0084":["CS","1","DistributionType"],"0085":["CS","1","ConsentForDistributionFlag"],"0086":["DA","1","EthicsCommitteeApprovalEffectivenessStartDate"],"0087":["DA","1","EthicsCommitteeApprovalEffectivenessEndDate"]},"0014":{"0000":["UL","1","GenericGroupLength"],"0023":["ST","1","CADFileFormat"],"0024":["ST","1","ComponentReferenceSystem"],"0025":["ST","1","ComponentManufacturingProcedure"],"0028":["ST","1","ComponentManufacturer"],"0030":["DS","1-n","MaterialThickness"],"0032":["DS","1-n","MaterialPipeDiameter"],"0034":["DS","1-n","MaterialIsolationDiameter"],"0042":["ST","1","MaterialGrade"],"0044":["ST","1","MaterialPropertiesDescription"],"0045":["ST","1","MaterialPropertiesFileFormatRetired"],"0046":["LT","1","MaterialNotes"],"0050":["CS","1","ComponentShape"],"0052":["CS","1","CurvatureType"],"0054":["DS","1","OuterDiameter"],"0056":["DS","1","InnerDiameter"],"0100":["LO","1-n","ComponentWelderIDs"],"0101":["CS","1","SecondaryApprovalStatus"],"0102":["DA","1","SecondaryReviewDate"],"0103":["TM","1","SecondaryReviewTime"],"0104":["PN","1","SecondaryReviewerName"],"0105":["ST","1","RepairID"],"0106":["SQ","1","MultipleComponentApprovalSequence"],"0107":["CS","1-n","OtherApprovalStatus"],"0108":["CS","1-n","OtherSecondaryApprovalStatus"],1010:["ST","1","ActualEnvironmentalConditions"],1020:["DA","1","ExpiryDate"],1040:["ST","1","EnvironmentalConditions"],2002:["SQ","1","EvaluatorSequence"],2004:["IS","1","EvaluatorNumber"],2006:["PN","1","EvaluatorName"],2008:["IS","1","EvaluationAttempt"],2012:["SQ","1","IndicationSequence"],2014:["IS","1","IndicationNumber"],2016:["SH","1","IndicationLabel"],2018:["ST","1","IndicationDescription"],"201A":["CS","1-n","IndicationType"],"201C":["CS","1","IndicationDisposition"],"201E":["SQ","1","IndicationROISequence"],2030:["SQ","1","IndicationPhysicalPropertySequence"],2032:["SH","1","PropertyLabel"],2202:["IS","1","CoordinateSystemNumberOfAxes"],2204:["SQ","1","CoordinateSystemAxesSequence"],2206:["ST","1","CoordinateSystemAxisDescription"],2208:["CS","1","CoordinateSystemDataSetMapping"],"220A":["IS","1","CoordinateSystemAxisNumber"],"220C":["CS","1","CoordinateSystemAxisType"],"220E":["CS","1","CoordinateSystemAxisUnits"],2210:["OB","1","CoordinateSystemAxisValues"],2220:["SQ","1","CoordinateSystemTransformSequence"],2222:["ST","1","TransformDescription"],2224:["IS","1","TransformNumberOfAxes"],2226:["IS","1-n","TransformOrderOfAxes"],2228:["CS","1","TransformedAxisUnits"],"222A":["DS","1-n","CoordinateSystemTransformRotationAndScaleMatrix"],"222C":["DS","1-n","CoordinateSystemTransformTranslationMatrix"],3011:["DS","1","InternalDetectorFrameTime"],3012:["DS","1","NumberOfFramesIntegrated"],3020:["SQ","1","DetectorTemperatureSequence"],3022:["ST","1","SensorName"],3024:["DS","1","HorizontalOffsetOfSensor"],3026:["DS","1","VerticalOffsetOfSensor"],3028:["DS","1","SensorTemperature"],3040:["SQ","1","DarkCurrentSequence"],3050:["ox","1","DarkCurrentCounts"],3060:["SQ","1","GainCorrectionReferenceSequence"],3070:["ox","1","AirCounts"],3071:["DS","1","KVUsedInGainCalibration"],3072:["DS","1","MAUsedInGainCalibration"],3073:["DS","1","NumberOfFramesUsedForIntegration"],3074:["LO","1","FilterMaterialUsedInGainCalibration"],3075:["DS","1","FilterThicknessUsedInGainCalibration"],3076:["DA","1","DateOfGainCalibration"],3077:["TM","1","TimeOfGainCalibration"],3080:["OB","1","BadPixelImage"],3099:["LT","1","CalibrationNotes"],3100:["LT","1","LinearityCorrectionTechnique"],3101:["LT","1","BeamHardeningCorrectionTechnique"],4002:["SQ","1","PulserEquipmentSequence"],4004:["CS","1","PulserType"],4006:["LT","1","PulserNotes"],4008:["SQ","1","ReceiverEquipmentSequence"],"400A":["CS","1","AmplifierType"],"400C":["LT","1","ReceiverNotes"],"400E":["SQ","1","PreAmplifierEquipmentSequence"],"400F":["LT","1","PreAmplifierNotes"],4010:["SQ","1","TransmitTransducerSequence"],4011:["SQ","1","ReceiveTransducerSequence"],4012:["US","1","NumberOfElements"],4013:["CS","1","ElementShape"],4014:["DS","1","ElementDimensionA"],4015:["DS","1","ElementDimensionB"],4016:["DS","1","ElementPitchA"],4017:["DS","1","MeasuredBeamDimensionA"],4018:["DS","1","MeasuredBeamDimensionB"],4019:["DS","1","LocationOfMeasuredBeamDiameter"],"401A":["DS","1","NominalFrequency"],"401B":["DS","1","MeasuredCenterFrequency"],"401C":["DS","1","MeasuredBandwidth"],"401D":["DS","1","ElementPitchB"],4020:["SQ","1","PulserSettingsSequence"],4022:["DS","1","PulseWidth"],4024:["DS","1","ExcitationFrequency"],4026:["CS","1","ModulationType"],4028:["DS","1","Damping"],4030:["SQ","1","ReceiverSettingsSequence"],4031:["DS","1","AcquiredSoundpathLength"],4032:["CS","1","AcquisitionCompressionType"],4033:["IS","1","AcquisitionSampleSize"],4034:["DS","1","RectifierSmoothing"],4035:["SQ","1","DACSequence"],4036:["CS","1","DACType"],4038:["DS","1-n","DACGainPoints"],"403A":["DS","1-n","DACTimePoints"],"403C":["DS","1-n","DACAmplitude"],4040:["SQ","1","PreAmplifierSettingsSequence"],4050:["SQ","1","TransmitTransducerSettingsSequence"],4051:["SQ","1","ReceiveTransducerSettingsSequence"],4052:["DS","1","IncidentAngle"],4054:["ST","1","CouplingTechnique"],4056:["ST","1","CouplingMedium"],4057:["DS","1","CouplingVelocity"],4058:["DS","1","ProbeCenterLocationX"],4059:["DS","1","ProbeCenterLocationZ"],"405A":["DS","1","SoundPathLength"],"405C":["ST","1","DelayLawIdentifier"],4060:["SQ","1","GateSettingsSequence"],4062:["DS","1","GateThreshold"],4064:["DS","1","VelocityOfSound"],4070:["SQ","1","CalibrationSettingsSequence"],4072:["ST","1","CalibrationProcedure"],4074:["SH","1","ProcedureVersion"],4076:["DA","1","ProcedureCreationDate"],4078:["DA","1","ProcedureExpirationDate"],"407A":["DA","1","ProcedureLastModifiedDate"],"407C":["TM","1-n","CalibrationTime"],"407E":["DA","1-n","CalibrationDate"],4080:["SQ","1","ProbeDriveEquipmentSequence"],4081:["CS","1","DriveType"],4082:["LT","1","ProbeDriveNotes"],4083:["SQ","1","DriveProbeSequence"],4084:["DS","1","ProbeInductance"],4085:["DS","1","ProbeResistance"],4086:["SQ","1","ReceiveProbeSequence"],4087:["SQ","1","ProbeDriveSettingsSequence"],4088:["DS","1","BridgeResistors"],4089:["DS","1","ProbeOrientationAngle"],"408B":["DS","1","UserSelectedGainY"],"408C":["DS","1","UserSelectedPhase"],"408D":["DS","1","UserSelectedOffsetX"],"408E":["DS","1","UserSelectedOffsetY"],4091:["SQ","1","ChannelSettingsSequence"],4092:["DS","1","ChannelThreshold"],"409A":["SQ","1","ScannerSettingsSequence"],"409B":["ST","1","ScanProcedure"],"409C":["DS","1","TranslationRateX"],"409D":["DS","1","TranslationRateY"],"409F":["DS","1","ChannelOverlap"],"40A0":["LO","1-n","ImageQualityIndicatorType"],"40A1":["LO","1-n","ImageQualityIndicatorMaterial"],"40A2":["LO","1-n","ImageQualityIndicatorSize"],5002:["IS","1","LINACEnergy"],5004:["IS","1","LINACOutput"],5100:["US","1","ActiveAperture"],5101:["DS","1","TotalAperture"],5102:["DS","1","ApertureElevation"],5103:["DS","1","MainLobeAngle"],5104:["DS","1","MainRoofAngle"],5105:["CS","1","ConnectorType"],5106:["SH","1","WedgeModelNumber"],5107:["DS","1","WedgeAngleFloat"],5108:["DS","1","WedgeRoofAngle"],5109:["CS","1","WedgeElement1Position"],"510A":["DS","1","WedgeMaterialVelocity"],"510B":["SH","1","WedgeMaterial"],"510C":["DS","1","WedgeOffsetZ"],"510D":["DS","1","WedgeOriginOffsetX"],"510E":["DS","1","WedgeTimeDelay"],"510F":["SH","1","WedgeName"],5110:["SH","1","WedgeManufacturerName"],5111:["LO","1","WedgeDescription"],5112:["DS","1","NominalBeamAngle"],5113:["DS","1","WedgeOffsetX"],5114:["DS","1","WedgeOffsetY"],5115:["DS","1","WedgeTotalLength"],5116:["DS","1","WedgeInContactLength"],5117:["DS","1","WedgeFrontGap"],5118:["DS","1","WedgeTotalHeight"],5119:["DS","1","WedgeFrontHeight"],"511A":["DS","1","WedgeRearHeight"],"511B":["DS","1","WedgeTotalWidth"],"511C":["DS","1","WedgeInContactWidth"],"511D":["DS","1","WedgeChamferHeight"],"511E":["CS","1","WedgeCurve"],"511F":["DS","1","RadiusAlongWedge"]},"0016":{"0000":["UL","1","GenericGroupLength"],"0001":["DS","1","WhitePoint"],"0002":["DS","3","PrimaryChromaticities"],"0003":["UT","1","BatteryLevel"],"0004":["DS","1","ExposureTimeInSeconds"],"0005":["DS","1","FNumber"],"0006":["IS","1","OECFRows"],"0007":["IS","1","OECFColumns"],"0008":["UC","1-n","OECFColumnNames"],"0009":["DS","1-n","OECFValues"],"000A":["IS","1","SpatialFrequencyResponseRows"],"000B":["IS","1","SpatialFrequencyResponseColumns"],"000C":["UC","1-n","SpatialFrequencyResponseColumnNames"],"000D":["DS","1-n","SpatialFrequencyResponseValues"],"000E":["IS","1","ColorFilterArrayPatternRows"],"000F":["IS","1","ColorFilterArrayPatternColumns"],"0010":["DS","1-n","ColorFilterArrayPatternValues"],"0011":["US","1","FlashFiringStatus"],"0012":["US","1","FlashReturnStatus"],"0013":["US","1","FlashMode"],"0014":["US","1","FlashFunctionPresent"],"0015":["US","1","FlashRedEyeMode"],"0016":["US","1","ExposureProgram"],"0017":["UT","1","SpectralSensitivity"],"0018":["IS","1","PhotographicSensitivity"],"0019":["IS","1","SelfTimerMode"],"001A":["US","1","SensitivityType"],"001B":["IS","1","StandardOutputSensitivity"],"001C":["IS","1","RecommendedExposureIndex"],"001D":["IS","1","ISOSpeed"],"001E":["IS","1","ISOSpeedLatitudeyyy"],"001F":["IS","1","ISOSpeedLatitudezzz"],"0020":["UT","1","EXIFVersion"],"0021":["DS","1","ShutterSpeedValue"],"0022":["DS","1","ApertureValue"],"0023":["DS","1","BrightnessValue"],"0024":["DS","1","ExposureBiasValue"],"0025":["DS","1","MaxApertureValue"],"0026":["DS","1","SubjectDistance"],"0027":["US","1","MeteringMode"],"0028":["US","1","LightSource"],"0029":["DS","1","FocalLength"],"002A":["IS","2-4","SubjectArea"],"002B":["OB","1","MakerNote"],"0030":["DS","1","Temperature"],"0031":["DS","1","Humidity"],"0032":["DS","1","Pressure"],"0033":["DS","1","WaterDepth"],"0034":["DS","1","Acceleration"],"0035":["DS","1","CameraElevationAngle"],"0036":["DS","1-2","FlashEnergy"],"0037":["IS","2","SubjectLocation"],"0038":["DS","1","PhotographicExposureIndex"],"0039":["US","1","SensingMethod"],"003A":["US","1","FileSource"],"003B":["US","1","SceneType"],"0041":["US","1","CustomRendered"],"0042":["US","1","ExposureMode"],"0043":["US","1","WhiteBalance"],"0044":["DS","1","DigitalZoomRatio"],"0045":["IS","1","FocalLengthIn35mmFilm"],"0046":["US","1","SceneCaptureType"],"0047":["US","1","GainControl"],"0048":["US","1","Contrast"],"0049":["US","1","Saturation"],"004A":["US","1","Sharpness"],"004B":["OB","1","DeviceSettingDescription"],"004C":["US","1","SubjectDistanceRange"],"004D":["UT","1","CameraOwnerName"],"004E":["DS","4","LensSpecification"],"004F":["UT","1","LensMake"],"0050":["UT","1","LensModel"],"0051":["UT","1","LensSerialNumber"],"0061":["CS","1","InteroperabilityIndex"],"0062":["OB","1","InteroperabilityVersion"],"0070":["OB","1","GPSVersionID"],"0071":["CS","1","GPSLatitudeRef"],"0072":["DS","3","GPSLatitude"],"0073":["CS","1","GPSLongitudeRef"],"0074":["DS","3","GPSLongitude"],"0075":["US","1","GPSAltitudeRef"],"0076":["DS","1","GPSAltitude"],"0077":["DT","1","GPSTimeStamp"],"0078":["UT","1","GPSSatellites"],"0079":["CS","1","GPSStatus"],"007A":["CS","1","GPSMeasureMode"],"007B":["DS","1","GPSDOP"],"007C":["CS","1","GPSSpeedRef"],"007D":["DS","1","GPSSpeed"],"007E":["CS","1","GPSTrackRef"],"007F":["DS","1","GPSTrack"],"0080":["CS","1","GPSImgDirectionRef"],"0081":["DS","1","GPSImgDirection"],"0082":["UT","1","GPSMapDatum"],"0083":["CS","1","GPSDestLatitudeRef"],"0084":["DS","3","GPSDestLatitude"],"0085":["CS","1","GPSDestLongitudeRef"],"0086":["DS","3","GPSDestLongitude"],"0087":["CS","1","GPSDestBearingRef"],"0088":["DS","1","GPSDestBearing"],"0089":["CS","1","GPSDestDistanceRef"],"008A":["DS","1","GPSDestDistance"],"008B":["OB","1","GPSProcessingMethod"],"008C":["OB","1","GPSAreaInformation"],"008D":["DT","1","GPSDateStamp"],"008E":["IS","1","GPSDifferential"],1001:["CS","1","LightSourcePolarization"],1002:["DS","1","EmitterColorTemperature"],1003:["CS","1","ContactMethod"],1004:["CS","1-n","ImmersionMedia"],1005:["DS","1","OpticalMagnificationFactor"]},"0018":{"0000":["UL","1","GenericGroupLength"],"0010":["LO","1","ContrastBolusAgent"],"0012":["SQ","1","ContrastBolusAgentSequence"],"0013":["FL","1","ContrastBolusT1Relaxivity"],"0014":["SQ","1","ContrastBolusAdministrationRouteSequence"],"0015":["CS","1","BodyPartExamined"],"0020":["CS","1-n","ScanningSequence"],"0021":["CS","1-n","SequenceVariant"],"0022":["CS","1-n","ScanOptions"],"0023":["CS","1","MRAcquisitionType"],"0024":["SH","1","SequenceName"],"0025":["CS","1","AngioFlag"],"0026":["SQ","1","InterventionDrugInformationSequence"],"0027":["TM","1","InterventionDrugStopTime"],"0028":["DS","1","InterventionDrugDose"],"0029":["SQ","1","InterventionDrugCodeSequence"],"002A":["SQ","1","AdditionalDrugSequence"],"0030":["LO","1-n","Radionuclide"],"0031":["LO","1","Radiopharmaceutical"],"0032":["DS","1","EnergyWindowCenterline"],"0033":["DS","1-n","EnergyWindowTotalWidth"],"0034":["LO","1","InterventionDrugName"],"0035":["TM","1","InterventionDrugStartTime"],"0036":["SQ","1","InterventionSequence"],"0037":["CS","1","TherapyType"],"0038":["CS","1","InterventionStatus"],"0039":["CS","1","TherapyDescription"],"003A":["ST","1","InterventionDescription"],"0040":["IS","1","CineRate"],"0042":["CS","1","InitialCineRunState"],"0050":["DS","1","SliceThickness"],"0060":["DS","1","KVP"],"0061":["DS","1",""],"0070":["IS","1","CountsAccumulated"],"0071":["CS","1","AcquisitionTerminationCondition"],"0072":["DS","1","EffectiveDuration"],"0073":["CS","1","AcquisitionStartCondition"],"0074":["IS","1","AcquisitionStartConditionData"],"0075":["IS","1","AcquisitionTerminationConditionData"],"0080":["DS","1","RepetitionTime"],"0081":["DS","1","EchoTime"],"0082":["DS","1","InversionTime"],"0083":["DS","1","NumberOfAverages"],"0084":["DS","1","ImagingFrequency"],"0085":["SH","1","ImagedNucleus"],"0086":["IS","1-n","EchoNumbers"],"0087":["DS","1","MagneticFieldStrength"],"0088":["DS","1","SpacingBetweenSlices"],"0089":["IS","1","NumberOfPhaseEncodingSteps"],"0090":["DS","1","DataCollectionDiameter"],"0091":["IS","1","EchoTrainLength"],"0093":["DS","1","PercentSampling"],"0094":["DS","1","PercentPhaseFieldOfView"],"0095":["DS","1","PixelBandwidth"],1e3:["LO","1","DeviceSerialNumber"],1002:["UI","1","DeviceUID"],1003:["LO","1","DeviceID"],1004:["LO","1","PlateID"],1005:["LO","1","GeneratorID"],1006:["LO","1","GridID"],1007:["LO","1","CassetteID"],1008:["LO","1","GantryID"],1009:["UT","1","UniqueDeviceIdentifier"],"100A":["SQ","1","UDISequence"],"100B":["UI","1-n","ManufacturerDeviceClassUID"],1010:["LO","1","SecondaryCaptureDeviceID"],1011:["LO","1","HardcopyCreationDeviceID"],1012:["DA","1","DateOfSecondaryCapture"],1014:["TM","1","TimeOfSecondaryCapture"],1016:["LO","1","SecondaryCaptureDeviceManufacturer"],1017:["LO","1","HardcopyDeviceManufacturer"],1018:["LO","1","SecondaryCaptureDeviceManufacturerModelName"],1019:["LO","1-n","SecondaryCaptureDeviceSoftwareVersions"],"101A":["LO","1-n","HardcopyDeviceSoftwareVersion"],"101B":["LO","1","HardcopyDeviceManufacturerModelName"],1020:["LO","1-n","SoftwareVersions"],1022:["SH","1","VideoImageFormatAcquired"],1023:["LO","1","DigitalImageFormatAcquired"],1030:["LO","1","ProtocolName"],1040:["LO","1","ContrastBolusRoute"],1041:["DS","1","ContrastBolusVolume"],1042:["TM","1","ContrastBolusStartTime"],1043:["TM","1","ContrastBolusStopTime"],1044:["DS","1","ContrastBolusTotalDose"],1045:["IS","1","SyringeCounts"],1046:["DS","1-n","ContrastFlowRate"],1047:["DS","1-n","ContrastFlowDuration"],1048:["CS","1","ContrastBolusIngredient"],1049:["DS","1","ContrastBolusIngredientConcentration"],1050:["DS","1","SpatialResolution"],1060:["DS","1","TriggerTime"],1061:["LO","1","TriggerSourceOrType"],1062:["IS","1","NominalInterval"],1063:["DS","1","FrameTime"],1064:["LO","1","CardiacFramingType"],1065:["DS","1-n","FrameTimeVector"],1066:["DS","1","FrameDelay"],1067:["DS","1","ImageTriggerDelay"],1068:["DS","1","MultiplexGroupTimeOffset"],1069:["DS","1","TriggerTimeOffset"],"106A":["CS","1","SynchronizationTrigger"],"106C":["US","2","SynchronizationChannel"],"106E":["UL","1","TriggerSamplePosition"],1070:["LO","1","RadiopharmaceuticalRoute"],1071:["DS","1","RadiopharmaceuticalVolume"],1072:["TM","1","RadiopharmaceuticalStartTime"],1073:["TM","1","RadiopharmaceuticalStopTime"],1074:["DS","1","RadionuclideTotalDose"],1075:["DS","1","RadionuclideHalfLife"],1076:["DS","1","RadionuclidePositronFraction"],1077:["DS","1","RadiopharmaceuticalSpecificActivity"],1078:["DT","1","RadiopharmaceuticalStartDateTime"],1079:["DT","1","RadiopharmaceuticalStopDateTime"],1080:["CS","1","BeatRejectionFlag"],1081:["IS","1","LowRRValue"],1082:["IS","1","HighRRValue"],1083:["IS","1","IntervalsAcquired"],1084:["IS","1","IntervalsRejected"],1085:["LO","1","PVCRejection"],1086:["IS","1","SkipBeats"],1088:["IS","1","HeartRate"],1090:["IS","1","CardiacNumberOfImages"],1094:["IS","1","TriggerWindow"],1100:["DS","1","ReconstructionDiameter"],1110:["DS","1","DistanceSourceToDetector"],1111:["DS","1","DistanceSourceToPatient"],1114:["DS","1","EstimatedRadiographicMagnificationFactor"],1120:["DS","1","GantryDetectorTilt"],1121:["DS","1","GantryDetectorSlew"],1130:["DS","1","TableHeight"],1131:["DS","1","TableTraverse"],1134:["CS","1","TableMotion"],1135:["DS","1-n","TableVerticalIncrement"],1136:["DS","1-n","TableLateralIncrement"],1137:["DS","1-n","TableLongitudinalIncrement"],1138:["DS","1","TableAngle"],"113A":["CS","1","TableType"],1140:["CS","1","RotationDirection"],1141:["DS","1","AngularPosition"],1142:["DS","1-n","RadialPosition"],1143:["DS","1","ScanArc"],1144:["DS","1","AngularStep"],1145:["DS","1","CenterOfRotationOffset"],1146:["DS","1-n","RotationOffset"],1147:["CS","1","FieldOfViewShape"],1149:["IS","1-2","FieldOfViewDimensions"],1150:["IS","1","ExposureTime"],1151:["IS","1","XRayTubeCurrent"],1152:["IS","1","Exposure"],1153:["IS","1","ExposureInuAs"],1154:["DS","1","AveragePulseWidth"],1155:["CS","1","RadiationSetting"],1156:["CS","1","RectificationType"],"115A":["CS","1","RadiationMode"],"115E":["DS","1","ImageAndFluoroscopyAreaDoseProduct"],1160:["SH","1","FilterType"],1161:["LO","1-n","TypeOfFilters"],1162:["DS","1","IntensifierSize"],1164:["DS","2","ImagerPixelSpacing"],1166:["CS","1-n","Grid"],1170:["IS","1","GeneratorPower"],1180:["SH","1","CollimatorGridName"],1181:["CS","1","CollimatorType"],1182:["IS","1-2","FocalDistance"],1183:["DS","1-2","XFocusCenter"],1184:["DS","1-2","YFocusCenter"],1190:["DS","1-n","FocalSpots"],1191:["CS","1","AnodeTargetMaterial"],"11A0":["DS","1","BodyPartThickness"],"11A2":["DS","1","CompressionForce"],"11A3":["DS","1","CompressionPressure"],"11A4":["LO","1","PaddleDescription"],"11A5":["DS","1","CompressionContactArea"],"11B0":["LO","1","AcquisitionMode"],"11B1":["LO","1","DoseModeName"],"11B2":["CS","1","AcquiredSubtractionMaskFlag"],"11B3":["CS","1","FluoroscopyPersistenceFlag"],"11B4":["CS","1","FluoroscopyLastImageHoldPersistenceFlag"],"11B5":["IS","1","UpperLimitNumberOfPersistentFluoroscopyFrames"],"11B6":["CS","1","ContrastBolusAutoInjectionTriggerFlag"],"11B7":["FD","1","ContrastBolusInjectionDelay"],"11B8":["SQ","1","XAAcquisitionPhaseDetailsSequence"],"11B9":["FD","1","XAAcquisitionFrameRate"],"11BA":["SQ","1","XAPlaneDetailsSequence"],"11BB":["LO","1","AcquisitionFieldOfViewLabel"],"11BC":["SQ","1","XRayFilterDetailsSequence"],"11BD":["FD","1","XAAcquisitionDuration"],"11BE":["CS","1","ReconstructionPipelineType"],"11BF":["SQ","1","ImageFilterDetailsSequence"],"11C0":["CS","1","AppliedMaskSubtractionFlag"],"11C1":["SQ","1","RequestedSeriesDescriptionCodeSequence"],1200:["DA","1-n","DateOfLastCalibration"],1201:["TM","1-n","TimeOfLastCalibration"],1202:["DT","1","DateTimeOfLastCalibration"],1203:["DT","1","CalibrationDateTime"],1210:["SH","1-n","ConvolutionKernel"],1240:["IS","1-n","UpperLowerPixelValues"],1242:["IS","1","ActualFrameDuration"],1243:["IS","1","CountRate"],1244:["US","1","PreferredPlaybackSequencing"],1250:["SH","1","ReceiveCoilName"],1251:["SH","1","TransmitCoilName"],1260:["SH","1","PlateType"],1261:["LO","1","PhosphorType"],1271:["FD","1","WaterEquivalentDiameter"],1272:["SQ","1","WaterEquivalentDiameterCalculationMethodCodeSequence"],1300:["DS","1","ScanVelocity"],1301:["CS","1-n","WholeBodyTechnique"],1302:["IS","1","ScanLength"],1310:["US","4","AcquisitionMatrix"],1312:["CS","1","InPlanePhaseEncodingDirection"],1314:["DS","1","FlipAngle"],1315:["CS","1","VariableFlipAngleFlag"],1316:["DS","1","SAR"],1318:["DS","1","dBdt"],1320:["FL","1","B1rms"],1400:["LO","1","AcquisitionDeviceProcessingDescription"],1401:["LO","1","AcquisitionDeviceProcessingCode"],1402:["CS","1","CassetteOrientation"],1403:["CS","1","CassetteSize"],1404:["US","1","ExposuresOnPlate"],1405:["IS","1","RelativeXRayExposure"],1411:["DS","1","ExposureIndex"],1412:["DS","1","TargetExposureIndex"],1413:["DS","1","DeviationIndex"],1450:["DS","1","ColumnAngulation"],1460:["DS","1","TomoLayerHeight"],1470:["DS","1","TomoAngle"],1480:["DS","1","TomoTime"],1490:["CS","1","TomoType"],1491:["CS","1","TomoClass"],1495:["IS","1","NumberOfTomosynthesisSourceImages"],1500:["CS","1","PositionerMotion"],1508:["CS","1","PositionerType"],1510:["DS","1","PositionerPrimaryAngle"],1511:["DS","1","PositionerSecondaryAngle"],1520:["DS","1-n","PositionerPrimaryAngleIncrement"],1521:["DS","1-n","PositionerSecondaryAngleIncrement"],1530:["DS","1","DetectorPrimaryAngle"],1531:["DS","1","DetectorSecondaryAngle"],1600:["CS","1-3","ShutterShape"],1602:["IS","1","ShutterLeftVerticalEdge"],1604:["IS","1","ShutterRightVerticalEdge"],1606:["IS","1","ShutterUpperHorizontalEdge"],1608:["IS","1","ShutterLowerHorizontalEdge"],1610:["IS","2","CenterOfCircularShutter"],1612:["IS","1","RadiusOfCircularShutter"],1620:["IS","2-2n","VerticesOfThePolygonalShutter"],1622:["US","1","ShutterPresentationValue"],1623:["US","1","ShutterOverlayGroup"],1624:["US","3","ShutterPresentationColorCIELabValue"],1630:["CS","1","OutlineShapeType"],1631:["FD","1","OutlineLeftVerticalEdge"],1632:["FD","1","OutlineRightVerticalEdge"],1633:["FD","1","OutlineUpperHorizontalEdge"],1634:["FD","1","OutlineLowerHorizontalEdge"],1635:["FD","2","CenterOfCircularOutline"],1636:["FD","1","DiameterOfCircularOutline"],1637:["UL","1","NumberOfPolygonalVertices"],1638:["OF","1","VerticesOfThePolygonalOutline"],1700:["CS","1-3","CollimatorShape"],1702:["IS","1","CollimatorLeftVerticalEdge"],1704:["IS","1","CollimatorRightVerticalEdge"],1706:["IS","1","CollimatorUpperHorizontalEdge"],1708:["IS","1","CollimatorLowerHorizontalEdge"],1710:["IS","2","CenterOfCircularCollimator"],1712:["IS","1","RadiusOfCircularCollimator"],1720:["IS","2-2n","VerticesOfThePolygonalCollimator"],1800:["CS","1","AcquisitionTimeSynchronized"],1801:["SH","1","TimeSource"],1802:["CS","1","TimeDistributionProtocol"],1803:["LO","1","NTPSourceAddress"],2001:["IS","1-n","PageNumberVector"],2002:["SH","1-n","FrameLabelVector"],2003:["DS","1-n","FramePrimaryAngleVector"],2004:["DS","1-n","FrameSecondaryAngleVector"],2005:["DS","1-n","SliceLocationVector"],2006:["SH","1-n","DisplayWindowLabelVector"],2010:["DS","2","NominalScannedPixelSpacing"],2020:["CS","1","DigitizingDeviceTransportDirection"],2030:["DS","1","RotationOfScannedFilm"],2041:["SQ","1","BiopsyTargetSequence"],2042:["UI","1","TargetUID"],2043:["FL","2","LocalizingCursorPosition"],2044:["FL","3","CalculatedTargetPosition"],2045:["SH","1","TargetLabel"],2046:["FL","1","DisplayedZValue"],3100:["CS","1","IVUSAcquisition"],3101:["DS","1","IVUSPullbackRate"],3102:["DS","1","IVUSGatedRate"],3103:["IS","1","IVUSPullbackStartFrameNumber"],3104:["IS","1","IVUSPullbackStopFrameNumber"],3105:["IS","1-n","LesionNumber"],4e3:["LT","1","AcquisitionComments"],5e3:["SH","1-n","OutputPower"],5010:["LO","1-n","TransducerData"],5011:["SQ","1","TransducerIdentificationSequence"],5012:["DS","1","FocusDepth"],5020:["LO","1","ProcessingFunction"],5021:["LO","1","PostprocessingFunction"],5022:["DS","1","MechanicalIndex"],5024:["DS","1","BoneThermalIndex"],5026:["DS","1","CranialThermalIndex"],5027:["DS","1","SoftTissueThermalIndex"],5028:["DS","1","SoftTissueFocusThermalIndex"],5029:["DS","1","SoftTissueSurfaceThermalIndex"],5030:["DS","1","DynamicRange"],5040:["DS","1","TotalGain"],5050:["IS","1","DepthOfScanField"],5100:["CS","1","PatientPosition"],5101:["CS","1","ViewPosition"],5104:["SQ","1","ProjectionEponymousNameCodeSequence"],5210:["DS","6","ImageTransformationMatrix"],5212:["DS","3","ImageTranslationVector"],6e3:["DS","1","Sensitivity"],6011:["SQ","1","SequenceOfUltrasoundRegions"],6012:["US","1","RegionSpatialFormat"],6014:["US","1","RegionDataType"],6016:["UL","1","RegionFlags"],6018:["UL","1","RegionLocationMinX0"],"601A":["UL","1","RegionLocationMinY0"],"601C":["UL","1","RegionLocationMaxX1"],"601E":["UL","1","RegionLocationMaxY1"],6020:["SL","1","ReferencePixelX0"],6022:["SL","1","ReferencePixelY0"],6024:["US","1","PhysicalUnitsXDirection"],6026:["US","1","PhysicalUnitsYDirection"],6028:["FD","1","ReferencePixelPhysicalValueX"],"602A":["FD","1","ReferencePixelPhysicalValueY"],"602C":["FD","1","PhysicalDeltaX"],"602E":["FD","1","PhysicalDeltaY"],6030:["UL","1","TransducerFrequency"],6031:["CS","1","TransducerType"],6032:["UL","1","PulseRepetitionFrequency"],6034:["FD","1","DopplerCorrectionAngle"],6036:["FD","1","SteeringAngle"],6038:["UL","1","DopplerSampleVolumeXPositionRetired"],6039:["SL","1","DopplerSampleVolumeXPosition"],"603A":["UL","1","DopplerSampleVolumeYPositionRetired"],"603B":["SL","1","DopplerSampleVolumeYPosition"],"603C":["UL","1","TMLinePositionX0Retired"],"603D":["SL","1","TMLinePositionX0"],"603E":["UL","1","TMLinePositionY0Retired"],"603F":["SL","1","TMLinePositionY0"],6040:["UL","1","TMLinePositionX1Retired"],6041:["SL","1","TMLinePositionX1"],6042:["UL","1","TMLinePositionY1Retired"],6043:["SL","1","TMLinePositionY1"],6044:["US","1","PixelComponentOrganization"],6046:["UL","1","PixelComponentMask"],6048:["UL","1","PixelComponentRangeStart"],"604A":["UL","1","PixelComponentRangeStop"],"604C":["US","1","PixelComponentPhysicalUnits"],"604E":["US","1","PixelComponentDataType"],6050:["UL","1","NumberOfTableBreakPoints"],6052:["UL","1-n","TableOfXBreakPoints"],6054:["FD","1-n","TableOfYBreakPoints"],6056:["UL","1","NumberOfTableEntries"],6058:["UL","1-n","TableOfPixelValues"],"605A":["FL","1-n","TableOfParameterValues"],6060:["FL","1-n","RWaveTimeVector"],6070:["US","1","ActiveImageAreaOverlayGroup"],7e3:["CS","1","DetectorConditionsNominalFlag"],7001:["DS","1","DetectorTemperature"],7004:["CS","1","DetectorType"],7005:["CS","1","DetectorConfiguration"],7006:["LT","1","DetectorDescription"],7008:["LT","1","DetectorMode"],"700A":["SH","1","DetectorID"],"700C":["DA","1","DateOfLastDetectorCalibration"],"700E":["TM","1","TimeOfLastDetectorCalibration"],7010:["IS","1","ExposuresOnDetectorSinceLastCalibration"],7011:["IS","1","ExposuresOnDetectorSinceManufactured"],7012:["DS","1","DetectorTimeSinceLastExposure"],7014:["DS","1","DetectorActiveTime"],7016:["DS","1","DetectorActivationOffsetFromExposure"],"701A":["DS","2","DetectorBinning"],7020:["DS","2","DetectorElementPhysicalSize"],7022:["DS","2","DetectorElementSpacing"],7024:["CS","1","DetectorActiveShape"],7026:["DS","1-2","DetectorActiveDimensions"],7028:["DS","2","DetectorActiveOrigin"],"702A":["LO","1","DetectorManufacturerName"],"702B":["LO","1","DetectorManufacturerModelName"],7030:["DS","2","FieldOfViewOrigin"],7032:["DS","1","FieldOfViewRotation"],7034:["CS","1","FieldOfViewHorizontalFlip"],7036:["FL","2","PixelDataAreaOriginRelativeToFOV"],7038:["FL","1","PixelDataAreaRotationAngleRelativeToFOV"],7040:["LT","1","GridAbsorbingMaterial"],7041:["LT","1","GridSpacingMaterial"],7042:["DS","1","GridThickness"],7044:["DS","1","GridPitch"],7046:["IS","2","GridAspectRatio"],7048:["DS","1","GridPeriod"],"704C":["DS","1","GridFocalDistance"],7050:["CS","1-n","FilterMaterial"],7052:["DS","1-n","FilterThicknessMinimum"],7054:["DS","1-n","FilterThicknessMaximum"],7056:["FL","1-n","FilterBeamPathLengthMinimum"],7058:["FL","1-n","FilterBeamPathLengthMaximum"],7060:["CS","1","ExposureControlMode"],7062:["LT","1","ExposureControlModeDescription"],7064:["CS","1","ExposureStatus"],7065:["DS","1","PhototimerSetting"],8150:["DS","1","ExposureTimeInuS"],8151:["DS","1","XRayTubeCurrentInuA"],9004:["CS","1","ContentQualification"],9005:["SH","1","PulseSequenceName"],9006:["SQ","1","MRImagingModifierSequence"],9008:["CS","1","EchoPulseSequence"],9009:["CS","1","InversionRecovery"],9010:["CS","1","FlowCompensation"],9011:["CS","1","MultipleSpinEcho"],9012:["CS","1","MultiPlanarExcitation"],9014:["CS","1","PhaseContrast"],9015:["CS","1","TimeOfFlightContrast"],9016:["CS","1","Spoiling"],9017:["CS","1","SteadyStatePulseSequence"],9018:["CS","1","EchoPlanarPulseSequence"],9019:["FD","1","TagAngleFirstAxis"],9020:["CS","1","MagnetizationTransfer"],9021:["CS","1","T2Preparation"],9022:["CS","1","BloodSignalNulling"],9024:["CS","1","SaturationRecovery"],9025:["CS","1","SpectrallySelectedSuppression"],9026:["CS","1","SpectrallySelectedExcitation"],9027:["CS","1","SpatialPresaturation"],9028:["CS","1","Tagging"],9029:["CS","1","OversamplingPhase"],9030:["FD","1","TagSpacingFirstDimension"],9032:["CS","1","GeometryOfKSpaceTraversal"],9033:["CS","1","SegmentedKSpaceTraversal"],9034:["CS","1","RectilinearPhaseEncodeReordering"],9035:["FD","1","TagThickness"],9036:["CS","1","PartialFourierDirection"],9037:["CS","1","CardiacSynchronizationTechnique"],9041:["LO","1","ReceiveCoilManufacturerName"],9042:["SQ","1","MRReceiveCoilSequence"],9043:["CS","1","ReceiveCoilType"],9044:["CS","1","QuadratureReceiveCoil"],9045:["SQ","1","MultiCoilDefinitionSequence"],9046:["LO","1","MultiCoilConfiguration"],9047:["SH","1","MultiCoilElementName"],9048:["CS","1","MultiCoilElementUsed"],9049:["SQ","1","MRTransmitCoilSequence"],9050:["LO","1","TransmitCoilManufacturerName"],9051:["CS","1","TransmitCoilType"],9052:["FD","1-2","SpectralWidth"],9053:["FD","1-2","ChemicalShiftReference"],9054:["CS","1","VolumeLocalizationTechnique"],9058:["US","1","MRAcquisitionFrequencyEncodingSteps"],9059:["CS","1","Decoupling"],9060:["CS","1-2","DecoupledNucleus"],9061:["FD","1-2","DecouplingFrequency"],9062:["CS","1","DecouplingMethod"],9063:["FD","1-2","DecouplingChemicalShiftReference"],9064:["CS","1","KSpaceFiltering"],9065:["CS","1-2","TimeDomainFiltering"],9066:["US","1-2","NumberOfZeroFills"],9067:["CS","1","BaselineCorrection"],9069:["FD","1","ParallelReductionFactorInPlane"],9070:["FD","1","CardiacRRIntervalSpecified"],9073:["FD","1","AcquisitionDuration"],9074:["DT","1","FrameAcquisitionDateTime"],9075:["CS","1","DiffusionDirectionality"],9076:["SQ","1","DiffusionGradientDirectionSequence"],9077:["CS","1","ParallelAcquisition"],9078:["CS","1","ParallelAcquisitionTechnique"],9079:["FD","1-n","InversionTimes"],9080:["ST","1","MetaboliteMapDescription"],9081:["CS","1","PartialFourier"],9082:["FD","1","EffectiveEchoTime"],9083:["SQ","1","MetaboliteMapCodeSequence"],9084:["SQ","1","ChemicalShiftSequence"],9085:["CS","1","CardiacSignalSource"],9087:["FD","1","DiffusionBValue"],9089:["FD","3","DiffusionGradientOrientation"],9090:["FD","3","VelocityEncodingDirection"],9091:["FD","1","VelocityEncodingMinimumValue"],9092:["SQ","1","VelocityEncodingAcquisitionSequence"],9093:["US","1","NumberOfKSpaceTrajectories"],9094:["CS","1","CoverageOfKSpace"],9095:["UL","1","SpectroscopyAcquisitionPhaseRows"],9096:["FD","1","ParallelReductionFactorInPlaneRetired"],9098:["FD","1-2","TransmitterFrequency"],9100:["CS","1-2","ResonantNucleus"],9101:["CS","1","FrequencyCorrection"],9103:["SQ","1","MRSpectroscopyFOVGeometrySequence"],9104:["FD","1","SlabThickness"],9105:["FD","3","SlabOrientation"],9106:["FD","3","MidSlabPosition"],9107:["SQ","1","MRSpatialSaturationSequence"],9112:["SQ","1","MRTimingAndRelatedParametersSequence"],9114:["SQ","1","MREchoSequence"],9115:["SQ","1","MRModifierSequence"],9117:["SQ","1","MRDiffusionSequence"],9118:["SQ","1","CardiacSynchronizationSequence"],9119:["SQ","1","MRAveragesSequence"],9125:["SQ","1","MRFOVGeometrySequence"],9126:["SQ","1","VolumeLocalizationSequence"],9127:["UL","1","SpectroscopyAcquisitionDataColumns"],9147:["CS","1","DiffusionAnisotropyType"],9151:["DT","1","FrameReferenceDateTime"],9152:["SQ","1","MRMetaboliteMapSequence"],9155:["FD","1","ParallelReductionFactorOutOfPlane"],9159:["UL","1","SpectroscopyAcquisitionOutOfPlanePhaseSteps"],9166:["CS","1","BulkMotionStatus"],9168:["FD","1","ParallelReductionFactorSecondInPlane"],9169:["CS","1","CardiacBeatRejectionTechnique"],9170:["CS","1","RespiratoryMotionCompensationTechnique"],9171:["CS","1","RespiratorySignalSource"],9172:["CS","1","BulkMotionCompensationTechnique"],9173:["CS","1","BulkMotionSignalSource"],9174:["CS","1","ApplicableSafetyStandardAgency"],9175:["LO","1","ApplicableSafetyStandardDescription"],9176:["SQ","1","OperatingModeSequence"],9177:["CS","1","OperatingModeType"],9178:["CS","1","OperatingMode"],9179:["CS","1","SpecificAbsorptionRateDefinition"],9180:["CS","1","GradientOutputType"],9181:["FD","1","SpecificAbsorptionRateValue"],9182:["FD","1","GradientOutput"],9183:["CS","1","FlowCompensationDirection"],9184:["FD","1","TaggingDelay"],9185:["ST","1","RespiratoryMotionCompensationTechniqueDescription"],9186:["SH","1","RespiratorySignalSourceID"],9195:["FD","1","ChemicalShiftMinimumIntegrationLimitInHz"],9196:["FD","1","ChemicalShiftMaximumIntegrationLimitInHz"],9197:["SQ","1","MRVelocityEncodingSequence"],9198:["CS","1","FirstOrderPhaseCorrection"],9199:["CS","1","WaterReferencedPhaseCorrection"],9200:["CS","1","MRSpectroscopyAcquisitionType"],9214:["CS","1","RespiratoryCyclePosition"],9217:["FD","1","VelocityEncodingMaximumValue"],9218:["FD","1","TagSpacingSecondDimension"],9219:["SS","1","TagAngleSecondAxis"],9220:["FD","1","FrameAcquisitionDuration"],9226:["SQ","1","MRImageFrameTypeSequence"],9227:["SQ","1","MRSpectroscopyFrameTypeSequence"],9231:["US","1","MRAcquisitionPhaseEncodingStepsInPlane"],9232:["US","1","MRAcquisitionPhaseEncodingStepsOutOfPlane"],9234:["UL","1","SpectroscopyAcquisitionPhaseColumns"],9236:["CS","1","CardiacCyclePosition"],9239:["SQ","1","SpecificAbsorptionRateSequence"],9240:["US","1","RFEchoTrainLength"],9241:["US","1","GradientEchoTrainLength"],9250:["CS","1","ArterialSpinLabelingContrast"],9251:["SQ","1","MRArterialSpinLabelingSequence"],9252:["LO","1","ASLTechniqueDescription"],9253:["US","1","ASLSlabNumber"],9254:["FD","1","ASLSlabThickness"],9255:["FD","3","ASLSlabOrientation"],9256:["FD","3","ASLMidSlabPosition"],9257:["CS","1","ASLContext"],9258:["UL","1","ASLPulseTrainDuration"],9259:["CS","1","ASLCrusherFlag"],"925A":["FD","1","ASLCrusherFlowLimit"],"925B":["LO","1","ASLCrusherDescription"],"925C":["CS","1","ASLBolusCutoffFlag"],"925D":["SQ","1","ASLBolusCutoffTimingSequence"],"925E":["LO","1","ASLBolusCutoffTechnique"],"925F":["UL","1","ASLBolusCutoffDelayTime"],9260:["SQ","1","ASLSlabSequence"],9295:["FD","1","ChemicalShiftMinimumIntegrationLimitInppm"],9296:["FD","1","ChemicalShiftMaximumIntegrationLimitInppm"],9297:["CS","1","WaterReferenceAcquisition"],9298:["IS","1","EchoPeakPosition"],9301:["SQ","1","CTAcquisitionTypeSequence"],9302:["CS","1","AcquisitionType"],9303:["FD","1","TubeAngle"],9304:["SQ","1","CTAcquisitionDetailsSequence"],9305:["FD","1","RevolutionTime"],9306:["FD","1","SingleCollimationWidth"],9307:["FD","1","TotalCollimationWidth"],9308:["SQ","1","CTTableDynamicsSequence"],9309:["FD","1","TableSpeed"],9310:["FD","1","TableFeedPerRotation"],9311:["FD","1","SpiralPitchFactor"],9312:["SQ","1","CTGeometrySequence"],9313:["FD","3","DataCollectionCenterPatient"],9314:["SQ","1","CTReconstructionSequence"],9315:["CS","1","ReconstructionAlgorithm"],9316:["CS","1","ConvolutionKernelGroup"],9317:["FD","2","ReconstructionFieldOfView"],9318:["FD","3","ReconstructionTargetCenterPatient"],9319:["FD","1","ReconstructionAngle"],9320:["SH","1","ImageFilter"],9321:["SQ","1","CTExposureSequence"],9322:["FD","2","ReconstructionPixelSpacing"],9323:["CS","1-n","ExposureModulationType"],9324:["FD","1","EstimatedDoseSaving"],9325:["SQ","1","CTXRayDetailsSequence"],9326:["SQ","1","CTPositionSequence"],9327:["FD","1","TablePosition"],9328:["FD","1","ExposureTimeInms"],9329:["SQ","1","CTImageFrameTypeSequence"],9330:["FD","1","XRayTubeCurrentInmA"],9332:["FD","1","ExposureInmAs"],9333:["CS","1","ConstantVolumeFlag"],9334:["CS","1","FluoroscopyFlag"],9335:["FD","1","DistanceSourceToDataCollectionCenter"],9337:["US","1","ContrastBolusAgentNumber"],9338:["SQ","1","ContrastBolusIngredientCodeSequence"],9340:["SQ","1","ContrastAdministrationProfileSequence"],9341:["SQ","1","ContrastBolusUsageSequence"],9342:["CS","1","ContrastBolusAgentAdministered"],9343:["CS","1","ContrastBolusAgentDetected"],9344:["CS","1","ContrastBolusAgentPhase"],9345:["FD","1","CTDIvol"],9346:["SQ","1","CTDIPhantomTypeCodeSequence"],9351:["FL","1","CalciumScoringMassFactorPatient"],9352:["FL","3","CalciumScoringMassFactorDevice"],9353:["FL","1","EnergyWeightingFactor"],9360:["SQ","1","CTAdditionalXRaySourceSequence"],9361:["CS","1","MultienergyCTAcquisition"],9362:["SQ","1","MultienergyCTAcquisitionSequence"],9363:["SQ","1","MultienergyCTProcessingSequence"],9364:["SQ","1","MultienergyCTCharacteristicsSequence"],9365:["SQ","1","MultienergyCTXRaySourceSequence"],9366:["US","1","XRaySourceIndex"],9367:["UC","1","XRaySourceID"],9368:["CS","1","MultienergySourceTechnique"],9369:["DT","1","SourceStartDateTime"],"936A":["DT","1","SourceEndDateTime"],"936B":["US","1","SwitchingPhaseNumber"],"936C":["DS","1","SwitchingPhaseNominalDuration"],"936D":["DS","1","SwitchingPhaseTransitionDuration"],"936E":["DS","1","EffectiveBinEnergy"],"936F":["SQ","1","MultienergyCTXRayDetectorSequence"],9370:["US","1","XRayDetectorIndex"],9371:["UC","1","XRayDetectorID"],9372:["CS","1","MultienergyDetectorType"],9373:["ST","1","XRayDetectorLabel"],9374:["DS","1","NominalMaxEnergy"],9375:["DS","1","NominalMinEnergy"],9376:["US","1-n","ReferencedXRayDetectorIndex"],9377:["US","1-n","ReferencedXRaySourceIndex"],9378:["US","1-n","ReferencedPathIndex"],9379:["SQ","1","MultienergyCTPathSequence"],"937A":["US","1","MultienergyCTPathIndex"],"937B":["UT","1","MultienergyAcquisitionDescription"],"937C":["FD","1","MonoenergeticEnergyEquivalent"],"937D":["SQ","1","MaterialCodeSequence"],"937E":["CS","1","DecompositionMethod"],"937F":["UT","1","DecompositionDescription"],9380:["SQ","1","DecompositionAlgorithmIdentificationSequence"],9381:["SQ","1","DecompositionMaterialSequence"],9382:["SQ","1","MaterialAttenuationSequence"],9383:["DS","1","PhotonEnergy"],9384:["DS","1","XRayMassAttenuationCoefficient"],9401:["SQ","1","ProjectionPixelCalibrationSequence"],9402:["FL","1","DistanceSourceToIsocenter"],9403:["FL","1","DistanceObjectToTableTop"],9404:["FL","2","ObjectPixelSpacingInCenterOfBeam"],9405:["SQ","1","PositionerPositionSequence"],9406:["SQ","1","TablePositionSequence"],9407:["SQ","1","CollimatorShapeSequence"],9410:["CS","1","PlanesInAcquisition"],9412:["SQ","1","XAXRFFrameCharacteristicsSequence"],9417:["SQ","1","FrameAcquisitionSequence"],9420:["CS","1","XRayReceptorType"],9423:["LO","1","AcquisitionProtocolName"],9424:["LT","1","AcquisitionProtocolDescription"],9425:["CS","1","ContrastBolusIngredientOpaque"],9426:["FL","1","DistanceReceptorPlaneToDetectorHousing"],9427:["CS","1","IntensifierActiveShape"],9428:["FL","1-2","IntensifierActiveDimensions"],9429:["FL","2","PhysicalDetectorSize"],9430:["FL","2","PositionOfIsocenterProjection"],9432:["SQ","1","FieldOfViewSequence"],9433:["LO","1","FieldOfViewDescription"],9434:["SQ","1","ExposureControlSensingRegionsSequence"],9435:["CS","1","ExposureControlSensingRegionShape"],9436:["SS","1","ExposureControlSensingRegionLeftVerticalEdge"],9437:["SS","1","ExposureControlSensingRegionRightVerticalEdge"],9438:["SS","1","ExposureControlSensingRegionUpperHorizontalEdge"],9439:["SS","1","ExposureControlSensingRegionLowerHorizontalEdge"],9440:["SS","2","CenterOfCircularExposureControlSensingRegion"],9441:["US","1","RadiusOfCircularExposureControlSensingRegion"],9442:["SS","2-n","VerticesOfThePolygonalExposureControlSensingRegion"],9445:["","",""],9447:["FL","1","ColumnAngulationPatient"],9449:["FL","1","BeamAngle"],9451:["SQ","1","FrameDetectorParametersSequence"],9452:["FL","1","CalculatedAnatomyThickness"],9455:["SQ","1","CalibrationSequence"],9456:["SQ","1","ObjectThicknessSequence"],9457:["CS","1","PlaneIdentification"],9461:["FL","1-2","FieldOfViewDimensionsInFloat"],9462:["SQ","1","IsocenterReferenceSystemSequence"],9463:["FL","1","PositionerIsocenterPrimaryAngle"],9464:["FL","1","PositionerIsocenterSecondaryAngle"],9465:["FL","1","PositionerIsocenterDetectorRotationAngle"],9466:["FL","1","TableXPositionToIsocenter"],9467:["FL","1","TableYPositionToIsocenter"],9468:["FL","1","TableZPositionToIsocenter"],9469:["FL","1","TableHorizontalRotationAngle"],9470:["FL","1","TableHeadTiltAngle"],9471:["FL","1","TableCradleTiltAngle"],9472:["SQ","1","FrameDisplayShutterSequence"],9473:["FL","1","AcquiredImageAreaDoseProduct"],9474:["CS","1","CArmPositionerTabletopRelationship"],9476:["SQ","1","XRayGeometrySequence"],9477:["SQ","1","IrradiationEventIdentificationSequence"],9504:["SQ","1","XRay3DFrameTypeSequence"],9506:["SQ","1","ContributingSourcesSequence"],9507:["SQ","1","XRay3DAcquisitionSequence"],9508:["FL","1","PrimaryPositionerScanArc"],9509:["FL","1","SecondaryPositionerScanArc"],9510:["FL","1","PrimaryPositionerScanStartAngle"],9511:["FL","1","SecondaryPositionerScanStartAngle"],9514:["FL","1","PrimaryPositionerIncrement"],9515:["FL","1","SecondaryPositionerIncrement"],9516:["DT","1","StartAcquisitionDateTime"],9517:["DT","1","EndAcquisitionDateTime"],9518:["SS","1","PrimaryPositionerIncrementSign"],9519:["SS","1","SecondaryPositionerIncrementSign"],9524:["LO","1","ApplicationName"],9525:["LO","1","ApplicationVersion"],9526:["LO","1","ApplicationManufacturer"],9527:["CS","1","AlgorithmType"],9528:["LO","1","AlgorithmDescription"],9530:["SQ","1","XRay3DReconstructionSequence"],9531:["LO","1","ReconstructionDescription"],9538:["SQ","1","PerProjectionAcquisitionSequence"],9541:["SQ","1","DetectorPositionSequence"],9542:["SQ","1","XRayAcquisitionDoseSequence"],9543:["FD","1","XRaySourceIsocenterPrimaryAngle"],9544:["FD","1","XRaySourceIsocenterSecondaryAngle"],9545:["FD","1","BreastSupportIsocenterPrimaryAngle"],9546:["FD","1","BreastSupportIsocenterSecondaryAngle"],9547:["FD","1","BreastSupportXPositionToIsocenter"],9548:["FD","1","BreastSupportYPositionToIsocenter"],9549:["FD","1","BreastSupportZPositionToIsocenter"],9550:["FD","1","DetectorIsocenterPrimaryAngle"],9551:["FD","1","DetectorIsocenterSecondaryAngle"],9552:["FD","1","DetectorXPositionToIsocenter"],9553:["FD","1","DetectorYPositionToIsocenter"],9554:["FD","1","DetectorZPositionToIsocenter"],9555:["SQ","1","XRayGridSequence"],9556:["SQ","1","XRayFilterSequence"],9557:["FD","3","DetectorActiveAreaTLHCPosition"],9558:["FD","6","DetectorActiveAreaOrientation"],9559:["CS","1","PositionerPrimaryAngleDirection"],9601:["SQ","1","DiffusionBMatrixSequence"],9602:["FD","1","DiffusionBValueXX"],9603:["FD","1","DiffusionBValueXY"],9604:["FD","1","DiffusionBValueXZ"],9605:["FD","1","DiffusionBValueYY"],9606:["FD","1","DiffusionBValueYZ"],9607:["FD","1","DiffusionBValueZZ"],9621:["SQ","1","FunctionalMRSequence"],9622:["CS","1","FunctionalSettlingPhaseFramesPresent"],9623:["DT","1","FunctionalSyncPulse"],9624:["CS","1","SettlingPhaseFrame"],9701:["DT","1","DecayCorrectionDateTime"],9715:["FD","1","StartDensityThreshold"],9716:["FD","1","StartRelativeDensityDifferenceThreshold"],9717:["FD","1","StartCardiacTriggerCountThreshold"],9718:["FD","1","StartRespiratoryTriggerCountThreshold"],9719:["FD","1","TerminationCountsThreshold"],9720:["FD","1","TerminationDensityThreshold"],9721:["FD","1","TerminationRelativeDensityThreshold"],9722:["FD","1","TerminationTimeThreshold"],9723:["FD","1","TerminationCardiacTriggerCountThreshold"],9724:["FD","1","TerminationRespiratoryTriggerCountThreshold"],9725:["CS","1","DetectorGeometry"],9726:["FD","1","TransverseDetectorSeparation"],9727:["FD","1","AxialDetectorDimension"],9729:["US","1","RadiopharmaceuticalAgentNumber"],9732:["SQ","1","PETFrameAcquisitionSequence"],9733:["SQ","1","PETDetectorMotionDetailsSequence"],9734:["SQ","1","PETTableDynamicsSequence"],9735:["SQ","1","PETPositionSequence"],9736:["SQ","1","PETFrameCorrectionFactorsSequence"],9737:["SQ","1","RadiopharmaceuticalUsageSequence"],9738:["CS","1","AttenuationCorrectionSource"],9739:["US","1","NumberOfIterations"],9740:["US","1","NumberOfSubsets"],9749:["SQ","1","PETReconstructionSequence"],9751:["SQ","1","PETFrameTypeSequence"],9755:["CS","1","TimeOfFlightInformationUsed"],9756:["CS","1","ReconstructionType"],9758:["CS","1","DecayCorrected"],9759:["CS","1","AttenuationCorrected"],9760:["CS","1","ScatterCorrected"],9761:["CS","1","DeadTimeCorrected"],9762:["CS","1","GantryMotionCorrected"],9763:["CS","1","PatientMotionCorrected"],9764:["CS","1","CountLossNormalizationCorrected"],9765:["CS","1","RandomsCorrected"],9766:["CS","1","NonUniformRadialSamplingCorrected"],9767:["CS","1","SensitivityCalibrated"],9768:["CS","1","DetectorNormalizationCorrection"],9769:["CS","1","IterativeReconstructionMethod"],9770:["CS","1","AttenuationCorrectionTemporalRelationship"],9771:["SQ","1","PatientPhysiologicalStateSequence"],9772:["SQ","1","PatientPhysiologicalStateCodeSequence"],9801:["FD","1-n","DepthsOfFocus"],9803:["SQ","1","ExcludedIntervalsSequence"],9804:["DT","1","ExclusionStartDateTime"],9805:["FD","1","ExclusionDuration"],9806:["SQ","1","USImageDescriptionSequence"],9807:["SQ","1","ImageDataTypeSequence"],9808:["CS","1","DataType"],9809:["SQ","1","TransducerScanPatternCodeSequence"],"980B":["CS","1","AliasedDataType"],"980C":["CS","1","PositionMeasuringDeviceUsed"],"980D":["SQ","1","TransducerGeometryCodeSequence"],"980E":["SQ","1","TransducerBeamSteeringCodeSequence"],"980F":["SQ","1","TransducerApplicationCodeSequence"],9810:["xs","1","ZeroVelocityPixelValue"],9900:["LO","1","ReferenceLocationLabel"],9901:["UT","1","ReferenceLocationDescription"],9902:["SQ","1","ReferenceBasisCodeSequence"],9903:["SQ","1","ReferenceGeometryCodeSequence"],9904:["DS","1","OffsetDistance"],9905:["CS","1","OffsetDirection"],9906:["SQ","1","PotentialScheduledProtocolCodeSequence"],9907:["SQ","1","PotentialRequestedProcedureCodeSequence"],9908:["UC","1-n","PotentialReasonsForProcedure"],9909:["SQ","1","PotentialReasonsForProcedureCodeSequence"],"990A":["UC","1-n","PotentialDiagnosticTasks"],"990B":["SQ","1","ContraindicationsCodeSequence"],"990C":["SQ","1","ReferencedDefinedProtocolSequence"],"990D":["SQ","1","ReferencedPerformedProtocolSequence"],"990E":["SQ","1","PredecessorProtocolSequence"],"990F":["UT","1","ProtocolPlanningInformation"],9910:["UT","1","ProtocolDesignRationale"],9911:["SQ","1","PatientSpecificationSequence"],9912:["SQ","1","ModelSpecificationSequence"],9913:["SQ","1","ParametersSpecificationSequence"],9914:["SQ","1","InstructionSequence"],9915:["US","1","InstructionIndex"],9916:["LO","1","InstructionText"],9917:["UT","1","InstructionDescription"],9918:["CS","1","InstructionPerformedFlag"],9919:["DT","1","InstructionPerformedDateTime"],"991A":["UT","1","InstructionPerformanceComment"],"991B":["SQ","1","PatientPositioningInstructionSequence"],"991C":["SQ","1","PositioningMethodCodeSequence"],"991D":["SQ","1","PositioningLandmarkSequence"],"991E":["UI","1","TargetFrameOfReferenceUID"],"991F":["SQ","1","AcquisitionProtocolElementSpecificationSequence"],9920:["SQ","1","AcquisitionProtocolElementSequence"],9921:["US","1","ProtocolElementNumber"],9922:["LO","1","ProtocolElementName"],9923:["UT","1","ProtocolElementCharacteristicsSummary"],9924:["UT","1","ProtocolElementPurpose"],9930:["CS","1","AcquisitionMotion"],9931:["SQ","1","AcquisitionStartLocationSequence"],9932:["SQ","1","AcquisitionEndLocationSequence"],9933:["SQ","1","ReconstructionProtocolElementSpecificationSequence"],9934:["SQ","1","ReconstructionProtocolElementSequence"],9935:["SQ","1","StorageProtocolElementSpecificationSequence"],9936:["SQ","1","StorageProtocolElementSequence"],9937:["LO","1","RequestedSeriesDescription"],9938:["US","1-n","SourceAcquisitionProtocolElementNumber"],9939:["US","1-n","SourceAcquisitionBeamNumber"],"993A":["US","1-n","SourceReconstructionProtocolElementNumber"],"993B":["SQ","1","ReconstructionStartLocationSequence"],"993C":["SQ","1","ReconstructionEndLocationSequence"],"993D":["SQ","1","ReconstructionAlgorithmSequence"],"993E":["SQ","1","ReconstructionTargetCenterLocationSequence"],9941:["UT","1","ImageFilterDescription"],9942:["FD","1","CTDIvolNotificationTrigger"],9943:["FD","1","DLPNotificationTrigger"],9944:["CS","1","AutoKVPSelectionType"],9945:["FD","1","AutoKVPUpperBound"],9946:["FD","1","AutoKVPLowerBound"],9947:["CS","1","ProtocolDefinedPatientPosition"],A001:["SQ","1","ContributingEquipmentSequence"],A002:["DT","1","ContributionDateTime"],A003:["ST","1","ContributionDescription"]},"0020":{"0000":["UL","1","GenericGroupLength"],"000D":["UI","1","StudyInstanceUID"],"000E":["UI","1","SeriesInstanceUID"],"0010":["SH","1","StudyID"],"0011":["IS","1","SeriesNumber"],"0012":["IS","1","AcquisitionNumber"],"0013":["IS","1","InstanceNumber"],"0014":["IS","1","IsotopeNumber"],"0015":["IS","1","PhaseNumber"],"0016":["IS","1","IntervalNumber"],"0017":["IS","1","TimeSlotNumber"],"0018":["IS","1","AngleNumber"],"0019":["IS","1","ItemNumber"],"0020":["CS","2","PatientOrientation"],"0022":["IS","1","OverlayNumber"],"0024":["IS","1","CurveNumber"],"0026":["IS","1","LUTNumber"],"0030":["DS","3","ImagePosition"],"0032":["DS","3","ImagePositionPatient"],"0035":["DS","6","ImageOrientation"],"0037":["DS","6","ImageOrientationPatient"],"0050":["DS","1","Location"],"0052":["UI","1","FrameOfReferenceUID"],"0060":["CS","1","Laterality"],"0062":["CS","1","ImageLaterality"],"0070":["LO","1","ImageGeometryType"],"0080":["CS","1-n","MaskingImage"],"00AA":["IS","1","ReportNumber"],"0100":["IS","1","TemporalPositionIdentifier"],"0105":["IS","1","NumberOfTemporalPositions"],"0110":["DS","1","TemporalResolution"],"0200":["UI","1","SynchronizationFrameOfReferenceUID"],"0242":["UI","1","SOPInstanceUIDOfConcatenationSource"],1e3:["IS","1","SeriesInStudy"],1001:["IS","1","AcquisitionsInSeries"],1002:["IS","1","ImagesInAcquisition"],1003:["IS","1","ImagesInSeries"],1004:["IS","1","AcquisitionsInStudy"],1005:["IS","1","ImagesInStudy"],1020:["LO","1-n","Reference"],"103F":["LO","1","TargetPositionReferenceIndicator"],1040:["LO","1","PositionReferenceIndicator"],1041:["DS","1","SliceLocation"],1070:["IS","1-n","OtherStudyNumbers"],1200:["IS","1","NumberOfPatientRelatedStudies"],1202:["IS","1","NumberOfPatientRelatedSeries"],1204:["IS","1","NumberOfPatientRelatedInstances"],1206:["IS","1","NumberOfStudyRelatedSeries"],1208:["IS","1","NumberOfStudyRelatedInstances"],1209:["IS","1","NumberOfSeriesRelatedInstances"],3100:["CS","1-n","SourceImageIDs"],3401:["CS","1","ModifyingDeviceID"],3402:["CS","1","ModifiedImageID"],3403:["DA","1","ModifiedImageDate"],3404:["LO","1","ModifyingDeviceManufacturer"],3405:["TM","1","ModifiedImageTime"],3406:["LO","1","ModifiedImageDescription"],4e3:["LT","1","ImageComments"],5e3:["AT","1-n","OriginalImageIdentification"],5002:["LO","1-n","OriginalImageIdentificationNomenclature"],9056:["SH","1","StackID"],9057:["UL","1","InStackPositionNumber"],9071:["SQ","1","FrameAnatomySequence"],9072:["CS","1","FrameLaterality"],9111:["SQ","1","FrameContentSequence"],9113:["SQ","1","PlanePositionSequence"],9116:["SQ","1","PlaneOrientationSequence"],9128:["UL","1","TemporalPositionIndex"],9153:["FD","1","NominalCardiacTriggerDelayTime"],9154:["FL","1","NominalCardiacTriggerTimePriorToRPeak"],9155:["FL","1","ActualCardiacTriggerTimePriorToRPeak"],9156:["US","1","FrameAcquisitionNumber"],9157:["UL","1-n","DimensionIndexValues"],9158:["LT","1","FrameComments"],9161:["UI","1","ConcatenationUID"],9162:["US","1","InConcatenationNumber"],9163:["US","1","InConcatenationTotalNumber"],9164:["UI","1","DimensionOrganizationUID"],9165:["AT","1","DimensionIndexPointer"],9167:["AT","1","FunctionalGroupPointer"],9170:["SQ","1","UnassignedSharedConvertedAttributesSequence"],9171:["SQ","1","UnassignedPerFrameConvertedAttributesSequence"],9172:["SQ","1","ConversionSourceAttributesSequence"],9213:["LO","1","DimensionIndexPrivateCreator"],9221:["SQ","1","DimensionOrganizationSequence"],9222:["SQ","1","DimensionIndexSequence"],9228:["UL","1","ConcatenationFrameOffsetNumber"],9238:["LO","1","FunctionalGroupPrivateCreator"],9241:["FL","1","NominalPercentageOfCardiacPhase"],9245:["FL","1","NominalPercentageOfRespiratoryPhase"],9246:["FL","1","StartingRespiratoryAmplitude"],9247:["CS","1","StartingRespiratoryPhase"],9248:["FL","1","EndingRespiratoryAmplitude"],9249:["CS","1","EndingRespiratoryPhase"],9250:["CS","1","RespiratoryTriggerType"],9251:["FD","1","RRIntervalTimeNominal"],9252:["FD","1","ActualCardiacTriggerDelayTime"],9253:["SQ","1","RespiratorySynchronizationSequence"],9254:["FD","1","RespiratoryIntervalTime"],9255:["FD","1","NominalRespiratoryTriggerDelayTime"],9256:["FD","1","RespiratoryTriggerDelayThreshold"],9257:["FD","1","ActualRespiratoryTriggerDelayTime"],9301:["FD","3","ImagePositionVolume"],9302:["FD","6","ImageOrientationVolume"],9307:["CS","1","UltrasoundAcquisitionGeometry"],9308:["FD","3","ApexPosition"],9309:["FD","16","VolumeToTransducerMappingMatrix"],"930A":["FD","16","VolumeToTableMappingMatrix"],"930B":["CS","1","VolumeToTransducerRelationship"],"930C":["CS","1","PatientFrameOfReferenceSource"],"930D":["FD","1","TemporalPositionTimeOffset"],"930E":["SQ","1","PlanePositionVolumeSequence"],"930F":["SQ","1","PlaneOrientationVolumeSequence"],9310:["SQ","1","TemporalPositionSequence"],9311:["CS","1","DimensionOrganizationType"],9312:["UI","1","VolumeFrameOfReferenceUID"],9313:["UI","1","TableFrameOfReferenceUID"],9421:["LO","1","DimensionDescriptionLabel"],9450:["SQ","1","PatientOrientationInFrameSequence"],9453:["LO","1","FrameLabel"],9518:["US","1-n","AcquisitionIndex"],9529:["SQ","1","ContributingSOPInstancesReferenceSequence"],9536:["US","1","ReconstructionIndex"]},"0022":{"0000":["UL","1","GenericGroupLength"],"0001":["US","1","LightPathFilterPassThroughWavelength"],"0002":["US","2","LightPathFilterPassBand"],"0003":["US","1","ImagePathFilterPassThroughWavelength"],"0004":["US","2","ImagePathFilterPassBand"],"0005":["CS","1","PatientEyeMovementCommanded"],"0006":["SQ","1","PatientEyeMovementCommandCodeSequence"],"0007":["FL","1","SphericalLensPower"],"0008":["FL","1","CylinderLensPower"],"0009":["FL","1","CylinderAxis"],"000A":["FL","1","EmmetropicMagnification"],"000B":["FL","1","IntraOcularPressure"],"000C":["FL","1","HorizontalFieldOfView"],"000D":["CS","1","PupilDilated"],"000E":["FL","1","DegreeOfDilation"],"0010":["FL","1","StereoBaselineAngle"],"0011":["FL","1","StereoBaselineDisplacement"],"0012":["FL","1","StereoHorizontalPixelOffset"],"0013":["FL","1","StereoVerticalPixelOffset"],"0014":["FL","1","StereoRotation"],"0015":["SQ","1","AcquisitionDeviceTypeCodeSequence"],"0016":["SQ","1","IlluminationTypeCodeSequence"],"0017":["SQ","1","LightPathFilterTypeStackCodeSequence"],"0018":["SQ","1","ImagePathFilterTypeStackCodeSequence"],"0019":["SQ","1","LensesCodeSequence"],"001A":["SQ","1","ChannelDescriptionCodeSequence"],"001B":["SQ","1","RefractiveStateSequence"],"001C":["SQ","1","MydriaticAgentCodeSequence"],"001D":["SQ","1","RelativeImagePositionCodeSequence"],"001E":["FL","1","CameraAngleOfView"],"0020":["SQ","1","StereoPairsSequence"],"0021":["SQ","1","LeftImageSequence"],"0022":["SQ","1","RightImageSequence"],"0028":["CS","1","StereoPairsPresent"],"0030":["FL","1","AxialLengthOfTheEye"],"0031":["SQ","1","OphthalmicFrameLocationSequence"],"0032":["FL","2-2n","ReferenceCoordinates"],"0035":["FL","1","DepthSpatialResolution"],"0036":["FL","1","MaximumDepthDistortion"],"0037":["FL","1","AlongScanSpatialResolution"],"0038":["FL","1","MaximumAlongScanDistortion"],"0039":["CS","1","OphthalmicImageOrientation"],"0041":["FL","1","DepthOfTransverseImage"],"0042":["SQ","1","MydriaticAgentConcentrationUnitsSequence"],"0048":["FL","1","AcrossScanSpatialResolution"],"0049":["FL","1","MaximumAcrossScanDistortion"],"004E":["DS","1","MydriaticAgentConcentration"],"0055":["FL","1","IlluminationWaveLength"],"0056":["FL","1","IlluminationPower"],"0057":["FL","1","IlluminationBandwidth"],"0058":["SQ","1","MydriaticAgentSequence"],1007:["SQ","1","OphthalmicAxialMeasurementsRightEyeSequence"],1008:["SQ","1","OphthalmicAxialMeasurementsLeftEyeSequence"],1009:["CS","1","OphthalmicAxialMeasurementsDeviceType"],1010:["CS","1","OphthalmicAxialLengthMeasurementsType"],1012:["SQ","1","OphthalmicAxialLengthSequence"],1019:["FL","1","OphthalmicAxialLength"],1024:["SQ","1","LensStatusCodeSequence"],1025:["SQ","1","VitreousStatusCodeSequence"],1028:["SQ","1","IOLFormulaCodeSequence"],1029:["LO","1","IOLFormulaDetail"],1033:["FL","1","KeratometerIndex"],1035:["SQ","1","SourceOfOphthalmicAxialLengthCodeSequence"],1036:["SQ","1","SourceOfCornealSizeDataCodeSequence"],1037:["FL","1","TargetRefraction"],1039:["CS","1","RefractiveProcedureOccurred"],1040:["SQ","1","RefractiveSurgeryTypeCodeSequence"],1044:["SQ","1","OphthalmicUltrasoundMethodCodeSequence"],1045:["SQ","1","SurgicallyInducedAstigmatismSequence"],1046:["CS","1","TypeOfOpticalCorrection"],1047:["SQ","1","ToricIOLPowerSequence"],1048:["SQ","1","PredictedToricErrorSequence"],1049:["CS","1","PreSelectedForImplantation"],"104A":["SQ","1","ToricIOLPowerForExactEmmetropiaSequence"],"104B":["SQ","1","ToricIOLPowerForExactTargetRefractionSequence"],1050:["SQ","1","OphthalmicAxialLengthMeasurementsSequence"],1053:["FL","1","IOLPower"],1054:["FL","1","PredictedRefractiveError"],1059:["FL","1","OphthalmicAxialLengthVelocity"],1065:["LO","1","LensStatusDescription"],1066:["LO","1","VitreousStatusDescription"],1090:["SQ","1","IOLPowerSequence"],1092:["SQ","1","LensConstantSequence"],1093:["LO","1","IOLManufacturer"],1094:["LO","1","LensConstantDescription"],1095:["LO","1","ImplantName"],1096:["SQ","1","KeratometryMeasurementTypeCodeSequence"],1097:["LO","1","ImplantPartNumber"],1100:["SQ","1","ReferencedOphthalmicAxialMeasurementsSequence"],1101:["SQ","1","OphthalmicAxialLengthMeasurementsSegmentNameCodeSequence"],1103:["SQ","1","RefractiveErrorBeforeRefractiveSurgeryCodeSequence"],1121:["FL","1","IOLPowerForExactEmmetropia"],1122:["FL","1","IOLPowerForExactTargetRefraction"],1125:["SQ","1","AnteriorChamberDepthDefinitionCodeSequence"],1127:["SQ","1","LensThicknessSequence"],1128:["SQ","1","AnteriorChamberDepthSequence"],"112A":["SQ","1","CalculationCommentSequence"],"112B":["CS","1","CalculationCommentType"],"112C":["LT","1","CalculationComment"],1130:["FL","1","LensThickness"],1131:["FL","1","AnteriorChamberDepth"],1132:["SQ","1","SourceOfLensThicknessDataCodeSequence"],1133:["SQ","1","SourceOfAnteriorChamberDepthDataCodeSequence"],1134:["SQ","1","SourceOfRefractiveMeasurementsSequence"],1135:["SQ","1","SourceOfRefractiveMeasurementsCodeSequence"],1140:["CS","1","OphthalmicAxialLengthMeasurementModified"],1150:["SQ","1","OphthalmicAxialLengthDataSourceCodeSequence"],1153:["SQ","1","OphthalmicAxialLengthAcquisitionMethodCodeSequence"],1155:["FL","1","SignalToNoiseRatio"],1159:["LO","1","OphthalmicAxialLengthDataSourceDescription"],1210:["SQ","1","OphthalmicAxialLengthMeasurementsTotalLengthSequence"],1211:["SQ","1","OphthalmicAxialLengthMeasurementsSegmentalLengthSequence"],1212:["SQ","1","OphthalmicAxialLengthMeasurementsLengthSummationSequence"],1220:["SQ","1","UltrasoundOphthalmicAxialLengthMeasurementsSequence"],1225:["SQ","1","OpticalOphthalmicAxialLengthMeasurementsSequence"],1230:["SQ","1","UltrasoundSelectedOphthalmicAxialLengthSequence"],1250:["SQ","1","OphthalmicAxialLengthSelectionMethodCodeSequence"],1255:["SQ","1","OpticalSelectedOphthalmicAxialLengthSequence"],1257:["SQ","1","SelectedSegmentalOphthalmicAxialLengthSequence"],1260:["SQ","1","SelectedTotalOphthalmicAxialLengthSequence"],1262:["SQ","1","OphthalmicAxialLengthQualityMetricSequence"],1265:["SQ","1","OphthalmicAxialLengthQualityMetricTypeCodeSequence"],1273:["LO","1","OphthalmicAxialLengthQualityMetricTypeDescription"],1300:["SQ","1","IntraocularLensCalculationsRightEyeSequence"],1310:["SQ","1","IntraocularLensCalculationsLeftEyeSequence"],1330:["SQ","1","ReferencedOphthalmicAxialLengthMeasurementQCImageSequence"],1415:["CS","1","OphthalmicMappingDeviceType"],1420:["SQ","1","AcquisitionMethodCodeSequence"],1423:["SQ","1","AcquisitionMethodAlgorithmSequence"],1436:["SQ","1","OphthalmicThicknessMapTypeCodeSequence"],1443:["SQ","1","OphthalmicThicknessMappingNormalsSequence"],1445:["SQ","1","RetinalThicknessDefinitionCodeSequence"],1450:["SQ","1","PixelValueMappingToCodedConceptSequence"],1452:["xs","1","MappedPixelValue"],1454:["LO","1","PixelValueMappingExplanation"],1458:["SQ","1","OphthalmicThicknessMapQualityThresholdSequence"],1460:["FL","1","OphthalmicThicknessMapThresholdQualityRating"],1463:["FL","2","AnatomicStructureReferencePoint"],1465:["SQ","1","RegistrationToLocalizerSequence"],1466:["CS","1","RegisteredLocalizerUnits"],1467:["FL","2","RegisteredLocalizerTopLeftHandCorner"],1468:["FL","2","RegisteredLocalizerBottomRightHandCorner"],1470:["SQ","1","OphthalmicThicknessMapQualityRatingSequence"],1472:["SQ","1","RelevantOPTAttributesSequence"],1512:["SQ","1","TransformationMethodCodeSequence"],1513:["SQ","1","TransformationAlgorithmSequence"],1515:["CS","1","OphthalmicAxialLengthMethod"],1517:["FL","1","OphthalmicFOV"],1518:["SQ","1","TwoDimensionalToThreeDimensionalMapSequence"],1525:["SQ","1","WideFieldOphthalmicPhotographyQualityRatingSequence"],1526:["SQ","1","WideFieldOphthalmicPhotographyQualityThresholdSequence"],1527:["FL","1","WideFieldOphthalmicPhotographyThresholdQualityRating"],1528:["FL","1","XCoordinatesCenterPixelViewAngle"],1529:["FL","1","YCoordinatesCenterPixelViewAngle"],1530:["UL","1","NumberOfMapPoints"],1531:["OF","1","TwoDimensionalToThreeDimensionalMapData"],1612:["SQ","1","DerivationAlgorithmSequence"],1615:["SQ","1","OphthalmicImageTypeCodeSequence"],1616:["LO","1","OphthalmicImageTypeDescription"],1618:["SQ","1","ScanPatternTypeCodeSequence"],1620:["SQ","1","ReferencedSurfaceMeshIdentificationSequence"],1622:["CS","1","OphthalmicVolumetricPropertiesFlag"],1624:["FL","1","OphthalmicAnatomicReferencePointXCoordinate"],1626:["FL","1","OphthalmicAnatomicReferencePointYCoordinate"],1628:["SQ","1","OphthalmicEnFaceImageQualityRatingSequence"],1630:["DS","1","QualityThreshold"],1640:["SQ","1","OCTBscanAnalysisAcquisitionParametersSequence"],1642:["UL","1","NumberOfBscansPerFrame"],1643:["FL","1","BscanSlabThickness"],1644:["FL","1","DistanceBetweenBscanSlabs"],1645:["FL","1","BscanCycleTime"],1646:["FL","1-n","BscanCycleTimeVector"],1649:["FL","1","AscanRate"],1650:["FL","1","BscanRate"],1658:["UL","1","SurfaceMeshZPixelOffset"]},"0024":{"0000":["UL","1","GenericGroupLength"],"0010":["FL","1","VisualFieldHorizontalExtent"],"0011":["FL","1","VisualFieldVerticalExtent"],"0012":["CS","1","VisualFieldShape"],"0016":["SQ","1","ScreeningTestModeCodeSequence"],"0018":["FL","1","MaximumStimulusLuminance"],"0020":["FL","1","BackgroundLuminance"],"0021":["SQ","1","StimulusColorCodeSequence"],"0024":["SQ","1","BackgroundIlluminationColorCodeSequence"],"0025":["FL","1","StimulusArea"],"0028":["FL","1","StimulusPresentationTime"],"0032":["SQ","1","FixationSequence"],"0033":["SQ","1","FixationMonitoringCodeSequence"],"0034":["SQ","1","VisualFieldCatchTrialSequence"],"0035":["US","1","FixationCheckedQuantity"],"0036":["US","1","PatientNotProperlyFixatedQuantity"],"0037":["CS","1","PresentedVisualStimuliDataFlag"],"0038":["US","1","NumberOfVisualStimuli"],"0039":["CS","1","ExcessiveFixationLossesDataFlag"],"0040":["CS","1","ExcessiveFixationLosses"],"0042":["US","1","StimuliRetestingQuantity"],"0044":["LT","1","CommentsOnPatientPerformanceOfVisualField"],"0045":["CS","1","FalseNegativesEstimateFlag"],"0046":["FL","1","FalseNegativesEstimate"],"0048":["US","1","NegativeCatchTrialsQuantity"],"0050":["US","1","FalseNegativesQuantity"],"0051":["CS","1","ExcessiveFalseNegativesDataFlag"],"0052":["CS","1","ExcessiveFalseNegatives"],"0053":["CS","1","FalsePositivesEstimateFlag"],"0054":["FL","1","FalsePositivesEstimate"],"0055":["CS","1","CatchTrialsDataFlag"],"0056":["US","1","PositiveCatchTrialsQuantity"],"0057":["CS","1","TestPointNormalsDataFlag"],"0058":["SQ","1","TestPointNormalsSequence"],"0059":["CS","1","GlobalDeviationProbabilityNormalsFlag"],"0060":["US","1","FalsePositivesQuantity"],"0061":["CS","1","ExcessiveFalsePositivesDataFlag"],"0062":["CS","1","ExcessiveFalsePositives"],"0063":["CS","1","VisualFieldTestNormalsFlag"],"0064":["SQ","1","ResultsNormalsSequence"],"0065":["SQ","1","AgeCorrectedSensitivityDeviationAlgorithmSequence"],"0066":["FL","1","GlobalDeviationFromNormal"],"0067":["SQ","1","GeneralizedDefectSensitivityDeviationAlgorithmSequence"],"0068":["FL","1","LocalizedDeviationFromNormal"],"0069":["LO","1","PatientReliabilityIndicator"],"0070":["FL","1","VisualFieldMeanSensitivity"],"0071":["FL","1","GlobalDeviationProbability"],"0072":["CS","1","LocalDeviationProbabilityNormalsFlag"],"0073":["FL","1","LocalizedDeviationProbability"],"0074":["CS","1","ShortTermFluctuationCalculated"],"0075":["FL","1","ShortTermFluctuation"],"0076":["CS","1","ShortTermFluctuationProbabilityCalculated"],"0077":["FL","1","ShortTermFluctuationProbability"],"0078":["CS","1","CorrectedLocalizedDeviationFromNormalCalculated"],"0079":["FL","1","CorrectedLocalizedDeviationFromNormal"],"0080":["CS","1","CorrectedLocalizedDeviationFromNormalProbabilityCalculated"],"0081":["FL","1","CorrectedLocalizedDeviationFromNormalProbability"],"0083":["SQ","1","GlobalDeviationProbabilitySequence"],"0085":["SQ","1","LocalizedDeviationProbabilitySequence"],"0086":["CS","1","FovealSensitivityMeasured"],"0087":["FL","1","FovealSensitivity"],"0088":["FL","1","VisualFieldTestDuration"],"0089":["SQ","1","VisualFieldTestPointSequence"],"0090":["FL","1","VisualFieldTestPointXCoordinate"],"0091":["FL","1","VisualFieldTestPointYCoordinate"],"0092":["FL","1","AgeCorrectedSensitivityDeviationValue"],"0093":["CS","1","StimulusResults"],"0094":["FL","1","SensitivityValue"],"0095":["CS","1","RetestStimulusSeen"],"0096":["FL","1","RetestSensitivityValue"],"0097":["SQ","1","VisualFieldTestPointNormalsSequence"],"0098":["FL","1","QuantifiedDefect"],"0100":["FL","1","AgeCorrectedSensitivityDeviationProbabilityValue"],"0102":["CS","1","GeneralizedDefectCorrectedSensitivityDeviationFlag"],"0103":["FL","1","GeneralizedDefectCorrectedSensitivityDeviationValue"],"0104":["FL","1","GeneralizedDefectCorrectedSensitivityDeviationProbabilityValue"],"0105":["FL","1","MinimumSensitivityValue"],"0106":["CS","1","BlindSpotLocalized"],"0107":["FL","1","BlindSpotXCoordinate"],"0108":["FL","1","BlindSpotYCoordinate"],"0110":["SQ","1","VisualAcuityMeasurementSequence"],"0112":["SQ","1","RefractiveParametersUsedOnPatientSequence"],"0113":["CS","1","MeasurementLaterality"],"0114":["SQ","1","OphthalmicPatientClinicalInformationLeftEyeSequence"],"0115":["SQ","1","OphthalmicPatientClinicalInformationRightEyeSequence"],"0117":["CS","1","FovealPointNormativeDataFlag"],"0118":["FL","1","FovealPointProbabilityValue"],"0120":["CS","1","ScreeningBaselineMeasured"],"0122":["SQ","1","ScreeningBaselineMeasuredSequence"],"0124":["CS","1","ScreeningBaselineType"],"0126":["FL","1","ScreeningBaselineValue"],"0202":["LO","1","AlgorithmSource"],"0306":["LO","1","DataSetName"],"0307":["LO","1","DataSetVersion"],"0308":["LO","1","DataSetSource"],"0309":["LO","1","DataSetDescription"],"0317":["SQ","1","VisualFieldTestReliabilityGlobalIndexSequence"],"0320":["SQ","1","VisualFieldGlobalResultsIndexSequence"],"0325":["SQ","1","DataObservationSequence"],"0338":["CS","1","IndexNormalsFlag"],"0341":["FL","1","IndexProbability"],"0344":["SQ","1","IndexProbabilitySequence"]},"0028":{"0000":["UL","1","GenericGroupLength"],"0002":["US","1","SamplesPerPixel"],"0003":["US","1","SamplesPerPixelUsed"],"0004":["CS","1","PhotometricInterpretation"],"0005":["US","1","ImageDimensions"],"0006":["US","1","PlanarConfiguration"],"0008":["IS","1","NumberOfFrames"],"0009":["AT","1-n","FrameIncrementPointer"],"000A":["AT","1-n","FrameDimensionPointer"],"0010":["US","1","Rows"],"0011":["US","1","Columns"],"0012":["US","1","Planes"],"0014":["US","1","UltrasoundColorDataPresent"],"0020":["","",""],"0030":["DS","2","PixelSpacing"],"0031":["DS","2","ZoomFactor"],"0032":["DS","2","ZoomCenter"],"0034":["IS","2","PixelAspectRatio"],"0040":["CS","1","ImageFormat"],"0050":["LO","1-n","ManipulatedImage"],"0051":["CS","1-n","CorrectedImage"],"005F":["LO","1","CompressionRecognitionCode"],"0060":["CS","1","CompressionCode"],"0061":["SH","1","CompressionOriginator"],"0062":["LO","1","CompressionLabel"],"0063":["SH","1","CompressionDescription"],"0065":["CS","1-n","CompressionSequence"],"0066":["AT","1-n","CompressionStepPointers"],"0068":["US","1","RepeatInterval"],"0069":["US","1","BitsGrouped"],"0070":["US","1-n","PerimeterTable"],"0071":["xs","1","PerimeterValue"],"0080":["US","1","PredictorRows"],"0081":["US","1","PredictorColumns"],"0082":["US","1-n","PredictorConstants"],"0090":["CS","1","BlockedPixels"],"0091":["US","1","BlockRows"],"0092":["US","1","BlockColumns"],"0093":["US","1","RowOverlap"],"0094":["US","1","ColumnOverlap"],"0100":["US","1","BitsAllocated"],"0101":["US","1","BitsStored"],"0102":["US","1","HighBit"],"0103":["US","1","PixelRepresentation"],"0104":["xs","1","SmallestValidPixelValue"],"0105":["xs","1","LargestValidPixelValue"],"0106":["xs","1","SmallestImagePixelValue"],"0107":["xs","1","LargestImagePixelValue"],"0108":["xs","1","SmallestPixelValueInSeries"],"0109":["xs","1","LargestPixelValueInSeries"],"0110":["xs","1","SmallestImagePixelValueInPlane"],"0111":["xs","1","LargestImagePixelValueInPlane"],"0120":["xs","1","PixelPaddingValue"],"0121":["xs","1","PixelPaddingRangeLimit"],"0122":["FL","1","FloatPixelPaddingValue"],"0123":["FD","1","DoubleFloatPixelPaddingValue"],"0124":["FL","1","FloatPixelPaddingRangeLimit"],"0125":["FD","1","DoubleFloatPixelPaddingRangeLimit"],"0200":["US","1","ImageLocation"],"0300":["CS","1","QualityControlImage"],"0301":["CS","1","BurnedInAnnotation"],"0302":["CS","1","RecognizableVisualFeatures"],"0303":["CS","1","LongitudinalTemporalInformationModified"],"0304":["UI","1","ReferencedColorPaletteInstanceUID"],"0400":["LO","1","TransformLabel"],"0401":["LO","1","TransformVersionNumber"],"0402":["US","1","NumberOfTransformSteps"],"0403":["LO","1-n","SequenceOfCompressedData"],"0404":["AT","1-n","DetailsOfCoefficients"],"04x0":["US","1","RowsForNthOrderCoefficients"],"04x1":["US","1","ColumnsForNthOrderCoefficients"],"04x2":["LO","1-n","CoefficientCoding"],"04x3":["AT","1-n","CoefficientCodingPointers"],"0700":["LO","1","DCTLabel"],"0701":["CS","1-n","DataBlockDescription"],"0702":["AT","1-n","DataBlock"],"0710":["US","1","NormalizationFactorFormat"],"0720":["US","1","ZonalMapNumberFormat"],"0721":["AT","1-n","ZonalMapLocation"],"0722":["US","1","ZonalMapFormat"],"0730":["US","1","AdaptiveMapFormat"],"0740":["US","1","CodeNumberFormat"],"08x0":["CS","1-n","CodeLabel"],"08x2":["US","1","NumberOfTables"],"08x3":["AT","1-n","CodeTableLocation"],"08x4":["US","1","BitsForCodeWord"],"08x8":["AT","1-n","ImageDataLocation"],"0A02":["CS","1","PixelSpacingCalibrationType"],"0A04":["LO","1","PixelSpacingCalibrationDescription"],1040:["CS","1","PixelIntensityRelationship"],1041:["SS","1","PixelIntensityRelationshipSign"],1050:["DS","1-n","WindowCenter"],1051:["DS","1-n","WindowWidth"],1052:["DS","1","RescaleIntercept"],1053:["DS","1","RescaleSlope"],1054:["LO","1","RescaleType"],1055:["LO","1-n","WindowCenterWidthExplanation"],1056:["CS","1","VOILUTFunction"],1080:["CS","1","GrayScale"],1090:["CS","1","RecommendedViewingMode"],1100:["xs","3","GrayLookupTableDescriptor"],1101:["xs","3","RedPaletteColorLookupTableDescriptor"],1102:["xs","3","GreenPaletteColorLookupTableDescriptor"],1103:["xs","3","BluePaletteColorLookupTableDescriptor"],1104:["US","3","AlphaPaletteColorLookupTableDescriptor"],1111:["xs","4","LargeRedPaletteColorLookupTableDescriptor"],1112:["xs","4","LargeGreenPaletteColorLookupTableDescriptor"],1113:["xs","4","LargeBluePaletteColorLookupTableDescriptor"],1199:["UI","1","PaletteColorLookupTableUID"],1200:["xs","1-n or 1","GrayLookupTableData"],1201:["OW","1","RedPaletteColorLookupTableData"],1202:["OW","1","GreenPaletteColorLookupTableData"],1203:["OW","1","BluePaletteColorLookupTableData"],1204:["OW","1","AlphaPaletteColorLookupTableData"],1211:["OW","1","LargeRedPaletteColorLookupTableData"],1212:["OW","1","LargeGreenPaletteColorLookupTableData"],1213:["OW","1","LargeBluePaletteColorLookupTableData"],1214:["UI","1","LargePaletteColorLookupTableUID"],1221:["OW","1","SegmentedRedPaletteColorLookupTableData"],1222:["OW","1","SegmentedGreenPaletteColorLookupTableData"],1223:["OW","1","SegmentedBluePaletteColorLookupTableData"],1224:["OW","1","SegmentedAlphaPaletteColorLookupTableData"],1230:["SQ","1","StoredValueColorRangeSequence"],1231:["FD","1","MinimumStoredValueMapped"],1232:["FD","1","MaximumStoredValueMapped"],1300:["CS","1","BreastImplantPresent"],1350:["CS","1","PartialView"],1351:["ST","1","PartialViewDescription"],1352:["SQ","1","PartialViewCodeSequence"],"135A":["CS","1","SpatialLocationsPreserved"],1401:["SQ","1","DataFrameAssignmentSequence"],1402:["CS","1","DataPathAssignment"],1403:["US","1","BitsMappedToColorLookupTable"],1404:["SQ","1","BlendingLUT1Sequence"],1405:["CS","1","BlendingLUT1TransferFunction"],1406:["FD","1","BlendingWeightConstant"],1407:["US","3","BlendingLookupTableDescriptor"],1408:["OW","1","BlendingLookupTableData"],"140B":["SQ","1","EnhancedPaletteColorLookupTableSequence"],"140C":["SQ","1","BlendingLUT2Sequence"],"140D":["CS","1","BlendingLUT2TransferFunction"],"140E":["CS","1","DataPathID"],"140F":["CS","1","RGBLUTTransferFunction"],1410:["CS","1","AlphaLUTTransferFunction"],2e3:["OB","1","ICCProfile"],2002:["CS","1","ColorSpace"],2110:["CS","1","LossyImageCompression"],2112:["DS","1-n","LossyImageCompressionRatio"],2114:["CS","1-n","LossyImageCompressionMethod"],3e3:["SQ","1","ModalityLUTSequence"],3002:["xs","3","LUTDescriptor"],3003:["LO","1","LUTExplanation"],3004:["LO","1","ModalityLUTType"],3006:["xx","1-n or 1","LUTData"],3010:["SQ","1","VOILUTSequence"],3110:["SQ","1","SoftcopyVOILUTSequence"],4e3:["LT","1","ImagePresentationComments"],5e3:["SQ","1","BiPlaneAcquisitionSequence"],6010:["US","1","RepresentativeFrameNumber"],6020:["US","1-n","FrameNumbersOfInterest"],6022:["LO","1-n","FrameOfInterestDescription"],6023:["CS","1-n","FrameOfInterestType"],6030:["US","1-n","MaskPointers"],6040:["US","1-n","RWavePointer"],6100:["SQ","1","MaskSubtractionSequence"],6101:["CS","1","MaskOperation"],6102:["US","2-2n","ApplicableFrameRange"],6110:["US","1-n","MaskFrameNumbers"],6112:["US","1","ContrastFrameAveraging"],6114:["FL","2","MaskSubPixelShift"],6120:["SS","1","TIDOffset"],6190:["ST","1","MaskOperationExplanation"],7e3:["SQ","1","EquipmentAdministratorSequence"],7001:["US","1","NumberOfDisplaySubsystems"],7002:["US","1","CurrentConfigurationID"],7003:["US","1","DisplaySubsystemID"],7004:["SH","1","DisplaySubsystemName"],7005:["LO","1","DisplaySubsystemDescription"],7006:["CS","1","SystemStatus"],7007:["LO","1","SystemStatusComment"],7008:["SQ","1","TargetLuminanceCharacteristicsSequence"],7009:["US","1","LuminanceCharacteristicsID"],"700A":["SQ","1","DisplaySubsystemConfigurationSequence"],"700B":["US","1","ConfigurationID"],"700C":["SH","1","ConfigurationName"],"700D":["LO","1","ConfigurationDescription"],"700E":["US","1","ReferencedTargetLuminanceCharacteristicsID"],"700F":["SQ","1","QAResultsSequence"],7010:["SQ","1","DisplaySubsystemQAResultsSequence"],7011:["SQ","1","ConfigurationQAResultsSequence"],7012:["SQ","1","MeasurementEquipmentSequence"],7013:["CS","1-n","MeasurementFunctions"],7014:["CS","1","MeasurementEquipmentType"],7015:["SQ","1","VisualEvaluationResultSequence"],7016:["SQ","1","DisplayCalibrationResultSequence"],7017:["US","1","DDLValue"],7018:["FL","2","CIExyWhitePoint"],7019:["CS","1","DisplayFunctionType"],"701A":["FL","1","GammaValue"],"701B":["US","1","NumberOfLuminancePoints"],"701C":["SQ","1","LuminanceResponseSequence"],"701D":["FL","1","TargetMinimumLuminance"],"701E":["FL","1","TargetMaximumLuminance"],"701F":["FL","1","LuminanceValue"],7020:["LO","1","LuminanceResponseDescription"],7021:["CS","1","WhitePointFlag"],7022:["SQ","1","DisplayDeviceTypeCodeSequence"],7023:["SQ","1","DisplaySubsystemSequence"],7024:["SQ","1","LuminanceResultSequence"],7025:["CS","1","AmbientLightValueSource"],7026:["CS","1-n","MeasuredCharacteristics"],7027:["SQ","1","LuminanceUniformityResultSequence"],7028:["SQ","1","VisualEvaluationTestSequence"],7029:["CS","1","TestResult"],"702A":["LO","1","TestResultComment"],"702B":["CS","1","TestImageValidation"],"702C":["SQ","1","TestPatternCodeSequence"],"702D":["SQ","1","MeasurementPatternCodeSequence"],"702E":["SQ","1","VisualEvaluationMethodCodeSequence"],"7FE0":["UR","1","PixelDataProviderURL"],9001:["UL","1","DataPointRows"],9002:["UL","1","DataPointColumns"],9003:["CS","1","SignalDomainColumns"],9099:["US","1","LargestMonochromePixelValue"],9108:["CS","1","DataRepresentation"],9110:["SQ","1","PixelMeasuresSequence"],9132:["SQ","1","FrameVOILUTSequence"],9145:["SQ","1","PixelValueTransformationSequence"],9235:["CS","1","SignalDomainRows"],9411:["FL","1","DisplayFilterPercentage"],9415:["SQ","1","FramePixelShiftSequence"],9416:["US","1","SubtractionItemID"],9422:["SQ","1","PixelIntensityRelationshipLUTSequence"],9443:["SQ","1","FramePixelDataPropertiesSequence"],9444:["CS","1","GeometricalProperties"],9445:["FL","1","GeometricMaximumDistortion"],9446:["CS","1-n","ImageProcessingApplied"],9454:["CS","1","MaskSelectionMode"],9474:["CS","1","LUTFunction"],9478:["FL","1","MaskVisibilityPercentage"],9501:["SQ","1","PixelShiftSequence"],9502:["SQ","1","RegionPixelShiftSequence"],9503:["SS","2-2n","VerticesOfTheRegion"],9505:["SQ","1","MultiFramePresentationSequence"],9506:["US","2-2n","PixelShiftFrameRange"],9507:["US","2-2n","LUTFrameRange"],9520:["DS","16","ImageToEquipmentMappingMatrix"],9537:["CS","1","EquipmentCoordinateSystemIdentification"]},"0032":{"0000":["UL","1","GenericGroupLength"],"000A":["CS","1","StudyStatusID"],"000C":["CS","1","StudyPriorityID"],"0012":["LO","1","StudyIDIssuer"],"0032":["DA","1","StudyVerifiedDate"],"0033":["TM","1","StudyVerifiedTime"],"0034":["DA","1","StudyReadDate"],"0035":["TM","1","StudyReadTime"],1e3:["DA","1","ScheduledStudyStartDate"],1001:["TM","1","ScheduledStudyStartTime"],1010:["DA","1","ScheduledStudyStopDate"],1011:["TM","1","ScheduledStudyStopTime"],1020:["LO","1","ScheduledStudyLocation"],1021:["AE","1-n","ScheduledStudyLocationAETitle"],1030:["LO","1","ReasonForStudy"],1031:["SQ","1","RequestingPhysicianIdentificationSequence"],1032:["PN","1","RequestingPhysician"],1033:["LO","1","RequestingService"],1034:["SQ","1","RequestingServiceCodeSequence"],1040:["DA","1","StudyArrivalDate"],1041:["TM","1","StudyArrivalTime"],1050:["DA","1","StudyCompletionDate"],1051:["TM","1","StudyCompletionTime"],1055:["CS","1","StudyComponentStatusID"],1060:["LO","1","RequestedProcedureDescription"],1064:["SQ","1","RequestedProcedureCodeSequence"],1065:["SQ","1","RequestedLateralityCodeSequence"],1066:["UT","1","ReasonForVisit"],1067:["SQ","1","ReasonForVisitCodeSequence"],1070:["LO","1","RequestedContrastAgent"],4e3:["LT","1","StudyComments"]},"0034":{"0000":["UL","1","GenericGroupLength"],"0001":["SQ","1","FlowIdentifierSequence"],"0002":["OB","1","FlowIdentifier"],"0003":["UI","1","FlowTransferSyntaxUID"],"0004":["UL","1","FlowRTPSamplingRate"],"0005":["OB","1","SourceIdentifier"],"0007":["OB","1","FrameOriginTimestamp"],"0008":["CS","1","IncludesImagingSubject"],"0009":["SQ","1","FrameUsefulnessGroupSequence"],"000A":["SQ","1","RealTimeBulkDataFlowSequence"],"000B":["SQ","1","CameraPositionGroupSequence"],"000C":["CS","1","IncludesInformation"],"000D":["SQ","1","TimeOfFrameGroupSequence"]},"0038":{"0000":["UL","1","GenericGroupLength"],"0004":["SQ","1","ReferencedPatientAliasSequence"],"0008":["CS","1","VisitStatusID"],"0010":["LO","1","AdmissionID"],"0011":["LO","1","IssuerOfAdmissionID"],"0014":["SQ","1","IssuerOfAdmissionIDSequence"],"0016":["LO","1","RouteOfAdmissions"],"001A":["DA","1","ScheduledAdmissionDate"],"001B":["TM","1","ScheduledAdmissionTime"],"001C":["DA","1","ScheduledDischargeDate"],"001D":["TM","1","ScheduledDischargeTime"],"001E":["LO","1","ScheduledPatientInstitutionResidence"],"0020":["DA","1","AdmittingDate"],"0021":["TM","1","AdmittingTime"],"0030":["DA","1","DischargeDate"],"0032":["TM","1","DischargeTime"],"0040":["LO","1","DischargeDiagnosisDescription"],"0044":["SQ","1","DischargeDiagnosisCodeSequence"],"0050":["LO","1","SpecialNeeds"],"0060":["LO","1","ServiceEpisodeID"],"0061":["LO","1","IssuerOfServiceEpisodeID"],"0062":["LO","1","ServiceEpisodeDescription"],"0064":["SQ","1","IssuerOfServiceEpisodeIDSequence"],"0100":["SQ","1","PertinentDocumentsSequence"],"0101":["SQ","1","PertinentResourcesSequence"],"0102":["LO","1","ResourceDescription"],"0300":["LO","1","CurrentPatientLocation"],"0400":["LO","1","PatientInstitutionResidence"],"0500":["LO","1","PatientState"],"0502":["SQ","1","PatientClinicalTrialParticipationSequence"],4e3:["LT","1","VisitComments"]},"003A":{"0000":["UL","1","GenericGroupLength"],"0004":["CS","1","WaveformOriginality"],"0005":["US","1","NumberOfWaveformChannels"],"0010":["UL","1","NumberOfWaveformSamples"],"001A":["DS","1","SamplingFrequency"],"0020":["SH","1","MultiplexGroupLabel"],"0200":["SQ","1","ChannelDefinitionSequence"],"0202":["IS","1","WaveformChannelNumber"],"0203":["SH","1","ChannelLabel"],"0205":["CS","1-n","ChannelStatus"],"0208":["SQ","1","ChannelSourceSequence"],"0209":["SQ","1","ChannelSourceModifiersSequence"],"020A":["SQ","1","SourceWaveformSequence"],"020C":["LO","1","ChannelDerivationDescription"],"0210":["DS","1","ChannelSensitivity"],"0211":["SQ","1","ChannelSensitivityUnitsSequence"],"0212":["DS","1","ChannelSensitivityCorrectionFactor"],"0213":["DS","1","ChannelBaseline"],"0214":["DS","1","ChannelTimeSkew"],"0215":["DS","1","ChannelSampleSkew"],"0218":["DS","1","ChannelOffset"],"021A":["US","1","WaveformBitsStored"],"0220":["DS","1","FilterLowFrequency"],"0221":["DS","1","FilterHighFrequency"],"0222":["DS","1","NotchFilterFrequency"],"0223":["DS","1","NotchFilterBandwidth"],"0230":["FL","1","WaveformDataDisplayScale"],"0231":["US","3","WaveformDisplayBackgroundCIELabValue"],"0240":["SQ","1","WaveformPresentationGroupSequence"],"0241":["US","1","PresentationGroupNumber"],"0242":["SQ","1","ChannelDisplaySequence"],"0244":["US","3","ChannelRecommendedDisplayCIELabValue"],"0245":["FL","1","ChannelPosition"],"0246":["CS","1","DisplayShadingFlag"],"0247":["FL","1","FractionalChannelDisplayScale"],"0248":["FL","1","AbsoluteChannelDisplayScale"],"0300":["SQ","1","MultiplexedAudioChannelsDescriptionCodeSequence"],"0301":["IS","1","ChannelIdentificationCode"],"0302":["CS","1","ChannelMode"],"0310":["UI","1","MultiplexGroupUID"],"0311":["DS","1","PowerlineFrequency"],"0312":["SQ","1","ChannelImpedanceSequence"],"0313":["DS","1","ImpedanceValue"],"0314":["DT","1","ImpedanceMeasurementDateTime"],"0315":["DS","1","ImpedanceMeasurementFrequency"],"0316":["CS","1","ImpedanceMeasurementCurrentType"]},"0040":{"0000":["UL","1","GenericGroupLength"],"0001":["AE","1-n","ScheduledStationAETitle"],"0002":["DA","1","ScheduledProcedureStepStartDate"],"0003":["TM","1","ScheduledProcedureStepStartTime"],"0004":["DA","1","ScheduledProcedureStepEndDate"],"0005":["TM","1","ScheduledProcedureStepEndTime"],"0006":["PN","1","ScheduledPerformingPhysicianName"],"0007":["LO","1","ScheduledProcedureStepDescription"],"0008":["SQ","1","ScheduledProtocolCodeSequence"],"0009":["SH","1","ScheduledProcedureStepID"],"000A":["SQ","1","StageCodeSequence"],"000B":["SQ","1","ScheduledPerformingPhysicianIdentificationSequence"],"0010":["SH","1-n","ScheduledStationName"],"0011":["SH","1","ScheduledProcedureStepLocation"],"0012":["LO","1","PreMedication"],"0020":["CS","1","ScheduledProcedureStepStatus"],"0026":["SQ","1","OrderPlacerIdentifierSequence"],"0027":["SQ","1","OrderFillerIdentifierSequence"],"0031":["UT","1","LocalNamespaceEntityID"],"0032":["UT","1","UniversalEntityID"],"0033":["CS","1","UniversalEntityIDType"],"0035":["CS","1","IdentifierTypeCode"],"0036":["SQ","1","AssigningFacilitySequence"],"0039":["SQ","1","AssigningJurisdictionCodeSequence"],"003A":["SQ","1","AssigningAgencyOrDepartmentCodeSequence"],"0100":["SQ","1","ScheduledProcedureStepSequence"],"0220":["SQ","1","ReferencedNonImageCompositeSOPInstanceSequence"],"0241":["AE","1","PerformedStationAETitle"],"0242":["SH","1","PerformedStationName"],"0243":["SH","1","PerformedLocation"],"0244":["DA","1","PerformedProcedureStepStartDate"],"0245":["TM","1","PerformedProcedureStepStartTime"],"0250":["DA","1","PerformedProcedureStepEndDate"],"0251":["TM","1","PerformedProcedureStepEndTime"],"0252":["CS","1","PerformedProcedureStepStatus"],"0253":["SH","1","PerformedProcedureStepID"],"0254":["LO","1","PerformedProcedureStepDescription"],"0255":["LO","1","PerformedProcedureTypeDescription"],"0260":["SQ","1","PerformedProtocolCodeSequence"],"0261":["CS","1","PerformedProtocolType"],"0270":["SQ","1","ScheduledStepAttributesSequence"],"0275":["SQ","1","RequestAttributesSequence"],"0280":["ST","1","CommentsOnThePerformedProcedureStep"],"0281":["SQ","1","PerformedProcedureStepDiscontinuationReasonCodeSequence"],"0293":["SQ","1","QuantitySequence"],"0294":["DS","1","Quantity"],"0295":["SQ","1","MeasuringUnitsSequence"],"0296":["SQ","1","BillingItemSequence"],"0300":["US","1","TotalTimeOfFluoroscopy"],"0301":["US","1","TotalNumberOfExposures"],"0302":["US","1","EntranceDose"],"0303":["US","1-2","ExposedArea"],"0306":["DS","1","DistanceSourceToEntrance"],"0307":["DS","1","DistanceSourceToSupport"],"030E":["SQ","1","ExposureDoseSequence"],"0310":["ST","1","CommentsOnRadiationDose"],"0312":["DS","1","XRayOutput"],"0314":["DS","1","HalfValueLayer"],"0316":["DS","1","OrganDose"],"0318":["CS","1","OrganExposed"],"0320":["SQ","1","BillingProcedureStepSequence"],"0321":["SQ","1","FilmConsumptionSequence"],"0324":["SQ","1","BillingSuppliesAndDevicesSequence"],"0330":["SQ","1","ReferencedProcedureStepSequence"],"0340":["SQ","1","PerformedSeriesSequence"],"0400":["LT","1","CommentsOnTheScheduledProcedureStep"],"0440":["SQ","1","ProtocolContextSequence"],"0441":["SQ","1","ContentItemModifierSequence"],"0500":["SQ","1","ScheduledSpecimenSequence"],"050A":["LO","1","SpecimenAccessionNumber"],"0512":["LO","1","ContainerIdentifier"],"0513":["SQ","1","IssuerOfTheContainerIdentifierSequence"],"0515":["SQ","1","AlternateContainerIdentifierSequence"],"0518":["SQ","1","ContainerTypeCodeSequence"],"051A":["LO","1","ContainerDescription"],"0520":["SQ","1","ContainerComponentSequence"],"0550":["SQ","1","SpecimenSequence"],"0551":["LO","1","SpecimenIdentifier"],"0552":["SQ","1","SpecimenDescriptionSequenceTrial"],"0553":["ST","1","SpecimenDescriptionTrial"],"0554":["UI","1","SpecimenUID"],"0555":["SQ","1","AcquisitionContextSequence"],"0556":["ST","1","AcquisitionContextDescription"],"0560":["SQ","1","SpecimenDescriptionSequence"],"0562":["SQ","1","IssuerOfTheSpecimenIdentifierSequence"],"059A":["SQ","1","SpecimenTypeCodeSequence"],"0600":["LO","1","SpecimenShortDescription"],"0602":["UT","1","SpecimenDetailedDescription"],"0610":["SQ","1","SpecimenPreparationSequence"],"0612":["SQ","1","SpecimenPreparationStepContentItemSequence"],"0620":["SQ","1","SpecimenLocalizationContentItemSequence"],"06FA":["LO","1","SlideIdentifier"],"0710":["SQ","1","WholeSlideMicroscopyImageFrameTypeSequence"],"071A":["SQ","1","ImageCenterPointCoordinatesSequence"],"072A":["DS","1","XOffsetInSlideCoordinateSystem"],"073A":["DS","1","YOffsetInSlideCoordinateSystem"],"074A":["DS","1","ZOffsetInSlideCoordinateSystem"],"08D8":["SQ","1","PixelSpacingSequence"],"08DA":["SQ","1","CoordinateSystemAxisCodeSequence"],"08EA":["SQ","1","MeasurementUnitsCodeSequence"],"09F8":["SQ","1","VitalStainCodeSequenceTrial"],1001:["SH","1","RequestedProcedureID"],1002:["LO","1","ReasonForTheRequestedProcedure"],1003:["SH","1","RequestedProcedurePriority"],1004:["LO","1","PatientTransportArrangements"],1005:["LO","1","RequestedProcedureLocation"],1006:["SH","1","PlacerOrderNumberProcedure"],1007:["SH","1","FillerOrderNumberProcedure"],1008:["LO","1","ConfidentialityCode"],1009:["SH","1","ReportingPriority"],"100A":["SQ","1","ReasonForRequestedProcedureCodeSequence"],1010:["PN","1-n","NamesOfIntendedRecipientsOfResults"],1011:["SQ","1","IntendedRecipientsOfResultsIdentificationSequence"],1012:["SQ","1","ReasonForPerformedProcedureCodeSequence"],1060:["LO","1","RequestedProcedureDescriptionTrial"],1101:["SQ","1","PersonIdentificationCodeSequence"],1102:["ST","1","PersonAddress"],1103:["LO","1-n","PersonTelephoneNumbers"],1104:["LT","1","PersonTelecomInformation"],1400:["LT","1","RequestedProcedureComments"],2001:["LO","1","ReasonForTheImagingServiceRequest"],2004:["DA","1","IssueDateOfImagingServiceRequest"],2005:["TM","1","IssueTimeOfImagingServiceRequest"],2006:["SH","1","PlacerOrderNumberImagingServiceRequestRetired"],2007:["SH","1","FillerOrderNumberImagingServiceRequestRetired"],2008:["PN","1","OrderEnteredBy"],2009:["SH","1","OrderEntererLocation"],2010:["SH","1","OrderCallbackPhoneNumber"],2011:["LT","1","OrderCallbackTelecomInformation"],2016:["LO","1","PlacerOrderNumberImagingServiceRequest"],2017:["LO","1","FillerOrderNumberImagingServiceRequest"],2400:["LT","1","ImagingServiceRequestComments"],3001:["LO","1","ConfidentialityConstraintOnPatientDataDescription"],4001:["CS","1","GeneralPurposeScheduledProcedureStepStatus"],4002:["CS","1","GeneralPurposePerformedProcedureStepStatus"],4003:["CS","1","GeneralPurposeScheduledProcedureStepPriority"],4004:["SQ","1","ScheduledProcessingApplicationsCodeSequence"],4005:["DT","1","ScheduledProcedureStepStartDateTime"],4006:["CS","1","MultipleCopiesFlag"],4007:["SQ","1","PerformedProcessingApplicationsCodeSequence"],4008:["DT","1","ScheduledProcedureStepExpirationDateTime"],4009:["SQ","1","HumanPerformerCodeSequence"],4010:["DT","1","ScheduledProcedureStepModificationDateTime"],4011:["DT","1","ExpectedCompletionDateTime"],4015:["SQ","1","ResultingGeneralPurposePerformedProcedureStepsSequence"],4016:["SQ","1","ReferencedGeneralPurposeScheduledProcedureStepSequence"],4018:["SQ","1","ScheduledWorkitemCodeSequence"],4019:["SQ","1","PerformedWorkitemCodeSequence"],4020:["CS","1","InputAvailabilityFlag"],4021:["SQ","1","InputInformationSequence"],4022:["SQ","1","RelevantInformationSequence"],4023:["UI","1","ReferencedGeneralPurposeScheduledProcedureStepTransactionUID"],4025:["SQ","1","ScheduledStationNameCodeSequence"],4026:["SQ","1","ScheduledStationClassCodeSequence"],4027:["SQ","1","ScheduledStationGeographicLocationCodeSequence"],4028:["SQ","1","PerformedStationNameCodeSequence"],4029:["SQ","1","PerformedStationClassCodeSequence"],4030:["SQ","1","PerformedStationGeographicLocationCodeSequence"],4031:["SQ","1","RequestedSubsequentWorkitemCodeSequence"],4032:["SQ","1","NonDICOMOutputCodeSequence"],4033:["SQ","1","OutputInformationSequence"],4034:["SQ","1","ScheduledHumanPerformersSequence"],4035:["SQ","1","ActualHumanPerformersSequence"],4036:["LO","1","HumanPerformerOrganization"],4037:["PN","1","HumanPerformerName"],4040:["CS","1","RawDataHandling"],4041:["CS","1","InputReadinessState"],4050:["DT","1","PerformedProcedureStepStartDateTime"],4051:["DT","1","PerformedProcedureStepEndDateTime"],4052:["DT","1","ProcedureStepCancellationDateTime"],4070:["SQ","1","OutputDestinationSequence"],4071:["SQ","1","DICOMStorageSequence"],4072:["SQ","1","STOWRSStorageSequence"],4073:["UR","1","StorageURL"],4074:["SQ","1","XDSStorageSequence"],8302:["DS","1","EntranceDoseInmGy"],8303:["CS","1","EntranceDoseDerivation"],9092:["SQ","1","ParametricMapFrameTypeSequence"],9094:["SQ","1","ReferencedImageRealWorldValueMappingSequence"],9096:["SQ","1","RealWorldValueMappingSequence"],9098:["SQ","1","PixelValueMappingCodeSequence"],9210:["SH","1","LUTLabel"],9211:["xs","1","RealWorldValueLastValueMapped"],9212:["FD","1-n","RealWorldValueLUTData"],9213:["FD","1","DoubleFloatRealWorldValueLastValueMapped"],9214:["FD","1","DoubleFloatRealWorldValueFirstValueMapped"],9216:["xs","1","RealWorldValueFirstValueMapped"],9220:["SQ","1","QuantityDefinitionSequence"],9224:["FD","1","RealWorldValueIntercept"],9225:["FD","1","RealWorldValueSlope"],A007:["CS","1","FindingsFlagTrial"],A010:["CS","1","RelationshipType"],A020:["SQ","1","FindingsSequenceTrial"],A021:["UI","1","FindingsGroupUIDTrial"],A022:["UI","1","ReferencedFindingsGroupUIDTrial"],A023:["DA","1","FindingsGroupRecordingDateTrial"],A024:["TM","1","FindingsGroupRecordingTimeTrial"],A026:["SQ","1","FindingsSourceCategoryCodeSequenceTrial"],A027:["LO","1","VerifyingOrganization"],A028:["SQ","1","DocumentingOrganizationIdentifierCodeSequenceTrial"],A030:["DT","1","VerificationDateTime"],A032:["DT","1","ObservationDateTime"],A033:["DT","1","ObservationStartDateTime"],A040:["CS","1","ValueType"],A043:["SQ","1","ConceptNameCodeSequence"],A047:["LO","1","MeasurementPrecisionDescriptionTrial"],A050:["CS","1","ContinuityOfContent"],A057:["CS","1-n","UrgencyOrPriorityAlertsTrial"],A060:["LO","1","SequencingIndicatorTrial"],A066:["SQ","1","DocumentIdentifierCodeSequenceTrial"],A067:["PN","1","DocumentAuthorTrial"],A068:["SQ","1","DocumentAuthorIdentifierCodeSequenceTrial"],A070:["SQ","1","IdentifierCodeSequenceTrial"],A073:["SQ","1","VerifyingObserverSequence"],A074:["OB","1","ObjectBinaryIdentifierTrial"],A075:["PN","1","VerifyingObserverName"],A076:["SQ","1","DocumentingObserverIdentifierCodeSequenceTrial"],A078:["SQ","1","AuthorObserverSequence"],A07A:["SQ","1","ParticipantSequence"],A07C:["SQ","1","CustodialOrganizationSequence"],A080:["CS","1","ParticipationType"],A082:["DT","1","ParticipationDateTime"],A084:["CS","1","ObserverType"],A085:["SQ","1","ProcedureIdentifierCodeSequenceTrial"],A088:["SQ","1","VerifyingObserverIdentificationCodeSequence"],A089:["OB","1","ObjectDirectoryBinaryIdentifierTrial"],A090:["SQ","1","EquivalentCDADocumentSequence"],A0B0:["US","2-2n","ReferencedWaveformChannels"],A110:["DA","1","DateOfDocumentOrVerbalTransactionTrial"],A112:["TM","1","TimeOfDocumentCreationOrVerbalTransactionTrial"],A120:["DT","1","DateTime"],A121:["DA","1","Date"],A122:["TM","1","Time"],A123:["PN","1","PersonName"],A124:["UI","1","UID"],A125:["CS","2","ReportStatusIDTrial"],A130:["CS","1","TemporalRangeType"],A132:["UL","1-n","ReferencedSamplePositions"],A136:["US","1-n","ReferencedFrameNumbers"],A138:["DS","1-n","ReferencedTimeOffsets"],A13A:["DT","1-n","ReferencedDateTime"],A160:["UT","1","TextValue"],A161:["FD","1-n","FloatingPointValue"],A162:["SL","1-n","RationalNumeratorValue"],A163:["UL","1-n","RationalDenominatorValue"],A167:["SQ","1","ObservationCategoryCodeSequenceTrial"],A168:["SQ","1","ConceptCodeSequence"],A16A:["ST","1","BibliographicCitationTrial"],A170:["SQ","1","PurposeOfReferenceCodeSequence"],A171:["UI","1","ObservationUID"],A172:["UI","1","ReferencedObservationUIDTrial"],A173:["CS","1","ReferencedObservationClassTrial"],A174:["CS","1","ReferencedObjectObservationClassTrial"],A180:["US","1","AnnotationGroupNumber"],A192:["DA","1","ObservationDateTrial"],A193:["TM","1","ObservationTimeTrial"],A194:["CS","1","MeasurementAutomationTrial"],A195:["SQ","1","ModifierCodeSequence"],A224:["ST","1","IdentificationDescriptionTrial"],A290:["CS","1","CoordinatesSetGeometricTypeTrial"],A296:["SQ","1","AlgorithmCodeSequenceTrial"],A297:["ST","1","AlgorithmDescriptionTrial"],A29A:["SL","2-2n","PixelCoordinatesSetTrial"],A300:["SQ","1","MeasuredValueSequence"],A301:["SQ","1","NumericValueQualifierCodeSequence"],A307:["PN","1","CurrentObserverTrial"],A30A:["DS","1-n","NumericValue"],A313:["SQ","1","ReferencedAccessionSequenceTrial"],A33A:["ST","1","ReportStatusCommentTrial"],A340:["SQ","1","ProcedureContextSequenceTrial"],A352:["PN","1","VerbalSourceTrial"],A353:["ST","1","AddressTrial"],A354:["LO","1","TelephoneNumberTrial"],A358:["SQ","1","VerbalSourceIdentifierCodeSequenceTrial"],A360:["SQ","1","PredecessorDocumentsSequence"],A370:["SQ","1","ReferencedRequestSequence"],A372:["SQ","1","PerformedProcedureCodeSequence"],A375:["SQ","1","CurrentRequestedProcedureEvidenceSequence"],A380:["SQ","1","ReportDetailSequenceTrial"],A385:["SQ","1","PertinentOtherEvidenceSequence"],A390:["SQ","1","HL7StructuredDocumentReferenceSequence"],A402:["UI","1","ObservationSubjectUIDTrial"],A403:["CS","1","ObservationSubjectClassTrial"],A404:["SQ","1","ObservationSubjectTypeCodeSequenceTrial"],A491:["CS","1","CompletionFlag"],A492:["LO","1","CompletionFlagDescription"],A493:["CS","1","VerificationFlag"],A494:["CS","1","ArchiveRequested"],A496:["CS","1","PreliminaryFlag"],A504:["SQ","1","ContentTemplateSequence"],A525:["SQ","1","IdenticalDocumentsSequence"],A600:["CS","1","ObservationSubjectContextFlagTrial"],A601:["CS","1","ObserverContextFlagTrial"],A603:["CS","1","ProcedureContextFlagTrial"],A730:["SQ","1","ContentSequence"],A731:["SQ","1","RelationshipSequenceTrial"],A732:["SQ","1","RelationshipTypeCodeSequenceTrial"],A744:["SQ","1","LanguageCodeSequenceTrial"],A801:["SQ","1","TabulatedValuesSequence"],A802:["UL","1","NumberOfTableRows"],A803:["UL","1","NumberOfTableColumns"],A804:["UL","1","TableRowNumber"],A805:["UL","1","TableColumnNumber"],A806:["SQ","1","TableRowDefinitionSequence"],A807:["SQ","1","TableColumnDefinitionSequence"],A808:["SQ","1","CellValuesSequence"],A992:["ST","1","UniformResourceLocatorTrial"],B020:["SQ","1","WaveformAnnotationSequence"],DB00:["CS","1","TemplateIdentifier"],DB06:["DT","1","TemplateVersion"],DB07:["DT","1","TemplateLocalVersion"],DB0B:["CS","1","TemplateExtensionFlag"],DB0C:["UI","1","TemplateExtensionOrganizationUID"],DB0D:["UI","1","TemplateExtensionCreatorUID"],DB73:["UL","1-n","ReferencedContentItemIdentifier"],E001:["ST","1","HL7InstanceIdentifier"],E004:["DT","1","HL7DocumentEffectiveTime"],E006:["SQ","1","HL7DocumentTypeCodeSequence"],E008:["SQ","1","DocumentClassCodeSequence"],E010:["UR","1","RetrieveURI"],E011:["UI","1","RetrieveLocationUID"],E020:["CS","1","TypeOfInstances"],E021:["SQ","1","DICOMRetrievalSequence"],E022:["SQ","1","DICOMMediaRetrievalSequence"],E023:["SQ","1","WADORetrievalSequence"],E024:["SQ","1","XDSRetrievalSequence"],E025:["SQ","1","WADORSRetrievalSequence"],E030:["UI","1","RepositoryUniqueID"],E031:["UI","1","HomeCommunityID"]},"0042":{"0000":["UL","1","GenericGroupLength"],"0010":["ST","1","DocumentTitle"],"0011":["OB","1","EncapsulatedDocument"],"0012":["LO","1","MIMETypeOfEncapsulatedDocument"],"0013":["SQ","1","SourceInstanceSequence"],"0014":["LO","1-n","ListOfMIMETypes"],"0015":["UL","1","EncapsulatedDocumentLength"]},"0044":{"0000":["UL","1","GenericGroupLength"],"0001":["ST","1","ProductPackageIdentifier"],"0002":["CS","1","SubstanceAdministrationApproval"],"0003":["LT","1","ApprovalStatusFurtherDescription"],"0004":["DT","1","ApprovalStatusDateTime"],"0007":["SQ","1","ProductTypeCodeSequence"],"0008":["LO","1-n","ProductName"],"0009":["LT","1","ProductDescription"],"000A":["LO","1","ProductLotIdentifier"],"000B":["DT","1","ProductExpirationDateTime"],"0010":["DT","1","SubstanceAdministrationDateTime"],"0011":["LO","1","SubstanceAdministrationNotes"],"0012":["LO","1","SubstanceAdministrationDeviceID"],"0013":["SQ","1","ProductParameterSequence"],"0019":["SQ","1","SubstanceAdministrationParameterSequence"],"0100":["SQ","1","ApprovalSequence"],"0101":["SQ","1","AssertionCodeSequence"],"0102":["UI","1","AssertionUID"],"0103":["SQ","1","AsserterIdentificationSequence"],"0104":["DT","1","AssertionDateTime"],"0105":["DT","1","AssertionExpirationDateTime"],"0106":["UT","1","AssertionComments"],"0107":["SQ","1","RelatedAssertionSequence"],"0108":["UI","1","ReferencedAssertionUID"],"0109":["SQ","1","ApprovalSubjectSequence"],"010A":["SQ","1","OrganizationalRoleCodeSequence"]},"0046":{"0000":["UL","1","GenericGroupLength"],"0012":["LO","1","LensDescription"],"0014":["SQ","1","RightLensSequence"],"0015":["SQ","1","LeftLensSequence"],"0016":["SQ","1","UnspecifiedLateralityLensSequence"],"0018":["SQ","1","CylinderSequence"],"0028":["SQ","1","PrismSequence"],"0030":["FD","1","HorizontalPrismPower"],"0032":["CS","1","HorizontalPrismBase"],"0034":["FD","1","VerticalPrismPower"],"0036":["CS","1","VerticalPrismBase"],"0038":["CS","1","LensSegmentType"],"0040":["FD","1","OpticalTransmittance"],"0042":["FD","1","ChannelWidth"],"0044":["FD","1","PupilSize"],"0046":["FD","1","CornealSize"],"0047":["SQ","1","CornealSizeSequence"],"0050":["SQ","1","AutorefractionRightEyeSequence"],"0052":["SQ","1","AutorefractionLeftEyeSequence"],"0060":["FD","1","DistancePupillaryDistance"],"0062":["FD","1","NearPupillaryDistance"],"0063":["FD","1","IntermediatePupillaryDistance"],"0064":["FD","1","OtherPupillaryDistance"],"0070":["SQ","1","KeratometryRightEyeSequence"],"0071":["SQ","1","KeratometryLeftEyeSequence"],"0074":["SQ","1","SteepKeratometricAxisSequence"],"0075":["FD","1","RadiusOfCurvature"],"0076":["FD","1","KeratometricPower"],"0077":["FD","1","KeratometricAxis"],"0080":["SQ","1","FlatKeratometricAxisSequence"],"0092":["CS","1","BackgroundColor"],"0094":["CS","1","Optotype"],"0095":["CS","1","OptotypePresentation"],"0097":["SQ","1","SubjectiveRefractionRightEyeSequence"],"0098":["SQ","1","SubjectiveRefractionLeftEyeSequence"],"0100":["SQ","1","AddNearSequence"],"0101":["SQ","1","AddIntermediateSequence"],"0102":["SQ","1","AddOtherSequence"],"0104":["FD","1","AddPower"],"0106":["FD","1","ViewingDistance"],"0110":["SQ","1","CorneaMeasurementsSequence"],"0111":["SQ","1","SourceOfCorneaMeasurementDataCodeSequence"],"0112":["SQ","1","SteepCornealAxisSequence"],"0113":["SQ","1","FlatCornealAxisSequence"],"0114":["FD","1","CornealPower"],"0115":["FD","1","CornealAxis"],"0116":["SQ","1","CorneaMeasurementMethodCodeSequence"],"0117":["FL","1","RefractiveIndexOfCornea"],"0118":["FL","1","RefractiveIndexOfAqueousHumor"],"0121":["SQ","1","VisualAcuityTypeCodeSequence"],"0122":["SQ","1","VisualAcuityRightEyeSequence"],"0123":["SQ","1","VisualAcuityLeftEyeSequence"],"0124":["SQ","1","VisualAcuityBothEyesOpenSequence"],"0125":["CS","1","ViewingDistanceType"],"0135":["SS","2","VisualAcuityModifiers"],"0137":["FD","1","DecimalVisualAcuity"],"0139":["LO","1","OptotypeDetailedDefinition"],"0145":["SQ","1","ReferencedRefractiveMeasurementsSequence"],"0146":["FD","1","SpherePower"],"0147":["FD","1","CylinderPower"],"0201":["CS","1","CornealTopographySurface"],"0202":["FL","2","CornealVertexLocation"],"0203":["FL","1","PupilCentroidXCoordinate"],"0204":["FL","1","PupilCentroidYCoordinate"],"0205":["FL","1","EquivalentPupilRadius"],"0207":["SQ","1","CornealTopographyMapTypeCodeSequence"],"0208":["IS","2-2n","VerticesOfTheOutlineOfPupil"],"0210":["SQ","1","CornealTopographyMappingNormalsSequence"],"0211":["SQ","1","MaximumCornealCurvatureSequence"],"0212":["FL","1","MaximumCornealCurvature"],"0213":["FL","2","MaximumCornealCurvatureLocation"],"0215":["SQ","1","MinimumKeratometricSequence"],"0218":["SQ","1","SimulatedKeratometricCylinderSequence"],"0220":["FL","1","AverageCornealPower"],"0224":["FL","1","CornealISValue"],"0227":["FL","1","AnalyzedArea"],"0230":["FL","1","SurfaceRegularityIndex"],"0232":["FL","1","SurfaceAsymmetryIndex"],"0234":["FL","1","CornealEccentricityIndex"],"0236":["FL","1","KeratoconusPredictionIndex"],"0238":["FL","1","DecimalPotentialVisualAcuity"],"0242":["CS","1","CornealTopographyMapQualityEvaluation"],"0244":["SQ","1","SourceImageCornealProcessedDataSequence"],"0247":["FL","3","CornealPointLocation"],"0248":["CS","1","CornealPointEstimated"],"0249":["FL","1","AxialPower"],"0250":["FL","1","TangentialPower"],"0251":["FL","1","RefractivePower"],"0252":["FL","1","RelativeElevation"],"0253":["FL","1","CornealWavefront"]},"0048":{"0000":["UL","1","GenericGroupLength"],"0001":["FL","1","ImagedVolumeWidth"],"0002":["FL","1","ImagedVolumeHeight"],"0003":["FL","1","ImagedVolumeDepth"],"0006":["UL","1","TotalPixelMatrixColumns"],"0007":["UL","1","TotalPixelMatrixRows"],"0008":["SQ","1","TotalPixelMatrixOriginSequence"],"0010":["CS","1","SpecimenLabelInImage"],"0011":["CS","1","FocusMethod"],"0012":["CS","1","ExtendedDepthOfField"],"0013":["US","1","NumberOfFocalPlanes"],"0014":["FL","1","DistanceBetweenFocalPlanes"],"0015":["US","3","RecommendedAbsentPixelCIELabValue"],"0100":["SQ","1","IlluminatorTypeCodeSequence"],"0102":["DS","6","ImageOrientationSlide"],"0105":["SQ","1","OpticalPathSequence"],"0106":["SH","1","OpticalPathIdentifier"],"0107":["ST","1","OpticalPathDescription"],"0108":["SQ","1","IlluminationColorCodeSequence"],"0110":["SQ","1","SpecimenReferenceSequence"],"0111":["DS","1","CondenserLensPower"],"0112":["DS","1","ObjectiveLensPower"],"0113":["DS","1","ObjectiveLensNumericalAperture"],"0120":["SQ","1","PaletteColorLookupTableSequence"],"0200":["SQ","1","ReferencedImageNavigationSequence"],"0201":["US","2","TopLeftHandCornerOfLocalizerArea"],"0202":["US","2","BottomRightHandCornerOfLocalizerArea"],"0207":["SQ","1","OpticalPathIdentificationSequence"],"021A":["SQ","1","PlanePositionSlideSequence"],"021E":["SL","1","ColumnPositionInTotalImagePixelMatrix"],"021F":["SL","1","RowPositionInTotalImagePixelMatrix"],"0301":["CS","1","PixelOriginInterpretation"],"0302":["UL","1","NumberOfOpticalPaths"],"0303":["UL","1","TotalPixelMatrixFocalPlanes"]},"0050":{"0000":["UL","1","GenericGroupLength"],"0004":["CS","1","CalibrationImage"],"0010":["SQ","1","DeviceSequence"],"0012":["SQ","1","ContainerComponentTypeCodeSequence"],"0013":["FD","1","ContainerComponentThickness"],"0014":["DS","1","DeviceLength"],"0015":["FD","1","ContainerComponentWidth"],"0016":["DS","1","DeviceDiameter"],"0017":["CS","1","DeviceDiameterUnits"],"0018":["DS","1","DeviceVolume"],"0019":["DS","1","InterMarkerDistance"],"001A":["CS","1","ContainerComponentMaterial"],"001B":["LO","1","ContainerComponentID"],"001C":["FD","1","ContainerComponentLength"],"001D":["FD","1","ContainerComponentDiameter"],"001E":["LO","1","ContainerComponentDescription"],"0020":["LO","1","DeviceDescription"],"0021":["ST","1","LongDeviceDescription"]},"0052":{"0000":["UL","1","GenericGroupLength"],"0001":["FL","1","ContrastBolusIngredientPercentByVolume"],"0002":["FD","1","OCTFocalDistance"],"0003":["FD","1","BeamSpotSize"],"0004":["FD","1","EffectiveRefractiveIndex"],"0006":["CS","1","OCTAcquisitionDomain"],"0007":["FD","1","OCTOpticalCenterWavelength"],"0008":["FD","1","AxialResolution"],"0009":["FD","1","RangingDepth"],"0011":["FD","1","ALineRate"],"0012":["US","1","ALinesPerFrame"],"0013":["FD","1","CatheterRotationalRate"],"0014":["FD","1","ALinePixelSpacing"],"0016":["SQ","1","ModeOfPercutaneousAccessSequence"],"0025":["SQ","1","IntravascularOCTFrameTypeSequence"],"0026":["CS","1","OCTZOffsetApplied"],"0027":["SQ","1","IntravascularFrameContentSequence"],"0028":["FD","1","IntravascularLongitudinalDistance"],"0029":["SQ","1","IntravascularOCTFrameContentSequence"],"0030":["SS","1","OCTZOffsetCorrection"],"0031":["CS","1","CatheterDirectionOfRotation"],"0033":["FD","1","SeamLineLocation"],"0034":["FD","1","FirstALineLocation"],"0036":["US","1","SeamLineIndex"],"0038":["US","1","NumberOfPaddedALines"],"0039":["CS","1","InterpolationType"],"003A":["CS","1","RefractiveIndexApplied"]},"0054":{"0000":["UL","1","GenericGroupLength"],"0010":["US","1-n","EnergyWindowVector"],"0011":["US","1","NumberOfEnergyWindows"],"0012":["SQ","1","EnergyWindowInformationSequence"],"0013":["SQ","1","EnergyWindowRangeSequence"],"0014":["DS","1","EnergyWindowLowerLimit"],"0015":["DS","1","EnergyWindowUpperLimit"],"0016":["SQ","1","RadiopharmaceuticalInformationSequence"],"0017":["IS","1","ResidualSyringeCounts"],"0018":["SH","1","EnergyWindowName"],"0020":["US","1-n","DetectorVector"],"0021":["US","1","NumberOfDetectors"],"0022":["SQ","1","DetectorInformationSequence"],"0030":["US","1-n","PhaseVector"],"0031":["US","1","NumberOfPhases"],"0032":["SQ","1","PhaseInformationSequence"],"0033":["US","1","NumberOfFramesInPhase"],"0036":["IS","1","PhaseDelay"],"0038":["IS","1","PauseBetweenFrames"],"0039":["CS","1","PhaseDescription"],"0050":["US","1-n","RotationVector"],"0051":["US","1","NumberOfRotations"],"0052":["SQ","1","RotationInformationSequence"],"0053":["US","1","NumberOfFramesInRotation"],"0060":["US","1-n","RRIntervalVector"],"0061":["US","1","NumberOfRRIntervals"],"0062":["SQ","1","GatedInformationSequence"],"0063":["SQ","1","DataInformationSequence"],"0070":["US","1-n","TimeSlotVector"],"0071":["US","1","NumberOfTimeSlots"],"0072":["SQ","1","TimeSlotInformationSequence"],"0073":["DS","1","TimeSlotTime"],"0080":["US","1-n","SliceVector"],"0081":["US","1","NumberOfSlices"],"0090":["US","1-n","AngularViewVector"],"0100":["US","1-n","TimeSliceVector"],"0101":["US","1","NumberOfTimeSlices"],"0200":["DS","1","StartAngle"],"0202":["CS","1","TypeOfDetectorMotion"],"0210":["IS","1-n","TriggerVector"],"0211":["US","1","NumberOfTriggersInPhase"],"0220":["SQ","1","ViewCodeSequence"],"0222":["SQ","1","ViewModifierCodeSequence"],"0300":["SQ","1","RadionuclideCodeSequence"],"0302":["SQ","1","AdministrationRouteCodeSequence"],"0304":["SQ","1","RadiopharmaceuticalCodeSequence"],"0306":["SQ","1","CalibrationDataSequence"],"0308":["US","1","EnergyWindowNumber"],"0400":["SH","1","ImageID"],"0410":["SQ","1","PatientOrientationCodeSequence"],"0412":["SQ","1","PatientOrientationModifierCodeSequence"],"0414":["SQ","1","PatientGantryRelationshipCodeSequence"],"0500":["CS","1","SliceProgressionDirection"],"0501":["CS","1","ScanProgressionDirection"],1e3:["CS","2","SeriesType"],1001:["CS","1","Units"],1002:["CS","1","CountsSource"],1004:["CS","1","ReprojectionMethod"],1006:["CS","1","SUVType"],1100:["CS","1","RandomsCorrectionMethod"],1101:["LO","1","AttenuationCorrectionMethod"],1102:["CS","1","DecayCorrection"],1103:["LO","1","ReconstructionMethod"],1104:["LO","1","DetectorLinesOfResponseUsed"],1105:["LO","1","ScatterCorrectionMethod"],1200:["DS","1","AxialAcceptance"],1201:["IS","2","AxialMash"],1202:["IS","1","TransverseMash"],1203:["DS","2","DetectorElementSize"],1210:["DS","1","CoincidenceWindowWidth"],1220:["CS","1-n","SecondaryCountsType"],1300:["DS","1","FrameReferenceTime"],1310:["IS","1","PrimaryPromptsCountsAccumulated"],1311:["IS","1-n","SecondaryCountsAccumulated"],1320:["DS","1","SliceSensitivityFactor"],1321:["DS","1","DecayFactor"],1322:["DS","1","DoseCalibrationFactor"],1323:["DS","1","ScatterFractionFactor"],1324:["DS","1","DeadTimeFactor"],1330:["US","1","ImageIndex"],1400:["CS","1-n","CountsIncluded"],1401:["CS","1","DeadTimeCorrectionFlag"]},"0060":{"0000":["UL","1","GenericGroupLength"],3e3:["SQ","1","HistogramSequence"],3002:["US","1","HistogramNumberOfBins"],3004:["xs","1","HistogramFirstBinValue"],3006:["xs","1","HistogramLastBinValue"],3008:["US","1","HistogramBinWidth"],3010:["LO","1","HistogramExplanation"],3020:["UL","1-n","HistogramData"]},"0062":{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","SegmentationType"],"0002":["SQ","1","SegmentSequence"],"0003":["SQ","1","SegmentedPropertyCategoryCodeSequence"],"0004":["US","1","SegmentNumber"],"0005":["LO","1","SegmentLabel"],"0006":["ST","1","SegmentDescription"],"0007":["SQ","1","SegmentationAlgorithmIdentificationSequence"],"0008":["CS","1","SegmentAlgorithmType"],"0009":["LO","1-n","SegmentAlgorithmName"],"000A":["SQ","1","SegmentIdentificationSequence"],"000B":["US","1-n","ReferencedSegmentNumber"],"000C":["US","1","RecommendedDisplayGrayscaleValue"],"000D":["US","3","RecommendedDisplayCIELabValue"],"000E":["US","1","MaximumFractionalValue"],"000F":["SQ","1","SegmentedPropertyTypeCodeSequence"],"0010":["CS","1","SegmentationFractionalType"],"0011":["SQ","1","SegmentedPropertyTypeModifierCodeSequence"],"0012":["SQ","1","UsedSegmentsSequence"],"0013":["CS","1","SegmentsOverlap"],"0020":["UT","1","TrackingID"],"0021":["UI","1","TrackingUID"]},"0064":{"0000":["UL","1","GenericGroupLength"],"0002":["SQ","1","DeformableRegistrationSequence"],"0003":["UI","1","SourceFrameOfReferenceUID"],"0005":["SQ","1","DeformableRegistrationGridSequence"],"0007":["UL","3","GridDimensions"],"0008":["FD","3","GridResolution"],"0009":["OF","1","VectorGridData"],"000F":["SQ","1","PreDeformationMatrixRegistrationSequence"],"0010":["SQ","1","PostDeformationMatrixRegistrationSequence"]},"0066":{"0000":["UL","1","GenericGroupLength"],"0001":["UL","1","NumberOfSurfaces"],"0002":["SQ","1","SurfaceSequence"],"0003":["UL","1","SurfaceNumber"],"0004":["LT","1","SurfaceComments"],"0009":["CS","1","SurfaceProcessing"],"000A":["FL","1","SurfaceProcessingRatio"],"000B":["LO","1","SurfaceProcessingDescription"],"000C":["FL","1","RecommendedPresentationOpacity"],"000D":["CS","1","RecommendedPresentationType"],"000E":["CS","1","FiniteVolume"],"0010":["CS","1","Manifold"],"0011":["SQ","1","SurfacePointsSequence"],"0012":["SQ","1","SurfacePointsNormalsSequence"],"0013":["SQ","1","SurfaceMeshPrimitivesSequence"],"0015":["UL","1","NumberOfSurfacePoints"],"0016":["OF","1","PointCoordinatesData"],"0017":["FL","3","PointPositionAccuracy"],"0018":["FL","1","MeanPointDistance"],"0019":["FL","1","MaximumPointDistance"],"001A":["FL","6","PointsBoundingBoxCoordinates"],"001B":["FL","3","AxisOfRotation"],"001C":["FL","3","CenterOfRotation"],"001E":["UL","1","NumberOfVectors"],"001F":["US","1","VectorDimensionality"],"0020":["FL","1-n","VectorAccuracy"],"0021":["OF","1","VectorCoordinateData"],"0022":["OD","1","DoublePointCoordinatesData"],"0023":["OW","1","TrianglePointIndexList"],"0024":["OW","1","EdgePointIndexList"],"0025":["OW","1","VertexPointIndexList"],"0026":["SQ","1","TriangleStripSequence"],"0027":["SQ","1","TriangleFanSequence"],"0028":["SQ","1","LineSequence"],"0029":["OW","1","PrimitivePointIndexList"],"002A":["UL","1","SurfaceCount"],"002B":["SQ","1","ReferencedSurfaceSequence"],"002C":["UL","1","ReferencedSurfaceNumber"],"002D":["SQ","1","SegmentSurfaceGenerationAlgorithmIdentificationSequence"],"002E":["SQ","1","SegmentSurfaceSourceInstanceSequence"],"002F":["SQ","1","AlgorithmFamilyCodeSequence"],"0030":["SQ","1","AlgorithmNameCodeSequence"],"0031":["LO","1","AlgorithmVersion"],"0032":["LT","1","AlgorithmParameters"],"0034":["SQ","1","FacetSequence"],"0035":["SQ","1","SurfaceProcessingAlgorithmIdentificationSequence"],"0036":["LO","1","AlgorithmName"],"0037":["FL","1","RecommendedPointRadius"],"0038":["FL","1","RecommendedLineThickness"],"0040":["OL","1","LongPrimitivePointIndexList"],"0041":["OL","1","LongTrianglePointIndexList"],"0042":["OL","1","LongEdgePointIndexList"],"0043":["OL","1","LongVertexPointIndexList"],"0101":["SQ","1","TrackSetSequence"],"0102":["SQ","1","TrackSequence"],"0103":["OW","1","RecommendedDisplayCIELabValueList"],"0104":["SQ","1","TrackingAlgorithmIdentificationSequence"],"0105":["UL","1","TrackSetNumber"],"0106":["LO","1","TrackSetLabel"],"0107":["UT","1","TrackSetDescription"],"0108":["SQ","1","TrackSetAnatomicalTypeCodeSequence"],"0121":["SQ","1","MeasurementsSequence"],"0124":["SQ","1","TrackSetStatisticsSequence"],"0125":["OF","1","FloatingPointValues"],"0129":["OL","1","TrackPointIndexList"],"0130":["SQ","1","TrackStatisticsSequence"],"0132":["SQ","1","MeasurementValuesSequence"],"0133":["SQ","1","DiffusionAcquisitionCodeSequence"],"0134":["SQ","1","DiffusionModelCodeSequence"]},"0068":{"0000":["UL","1","GenericGroupLength"],6210:["LO","1","ImplantSize"],6221:["LO","1","ImplantTemplateVersion"],6222:["SQ","1","ReplacedImplantTemplateSequence"],6223:["CS","1","ImplantType"],6224:["SQ","1","DerivationImplantTemplateSequence"],6225:["SQ","1","OriginalImplantTemplateSequence"],6226:["DT","1","EffectiveDateTime"],6230:["SQ","1","ImplantTargetAnatomySequence"],6260:["SQ","1","InformationFromManufacturerSequence"],6265:["SQ","1","NotificationFromManufacturerSequence"],6270:["DT","1","InformationIssueDateTime"],6280:["ST","1","InformationSummary"],"62A0":["SQ","1","ImplantRegulatoryDisapprovalCodeSequence"],"62A5":["FD","1","OverallTemplateSpatialTolerance"],"62C0":["SQ","1","HPGLDocumentSequence"],"62D0":["US","1","HPGLDocumentID"],"62D5":["LO","1","HPGLDocumentLabel"],"62E0":["SQ","1","ViewOrientationCodeSequence"],"62F0":["SQ","1","ViewOrientationModifierCodeSequence"],"62F2":["FD","1","HPGLDocumentScaling"],6300:["OB","1","HPGLDocument"],6310:["US","1","HPGLContourPenNumber"],6320:["SQ","1","HPGLPenSequence"],6330:["US","1","HPGLPenNumber"],6340:["LO","1","HPGLPenLabel"],6345:["ST","1","HPGLPenDescription"],6346:["FD","2","RecommendedRotationPoint"],6347:["FD","4","BoundingRectangle"],6350:["US","1-n","ImplantTemplate3DModelSurfaceNumber"],6360:["SQ","1","SurfaceModelDescriptionSequence"],6380:["LO","1","SurfaceModelLabel"],6390:["FD","1","SurfaceModelScalingFactor"],"63A0":["SQ","1","MaterialsCodeSequence"],"63A4":["SQ","1","CoatingMaterialsCodeSequence"],"63A8":["SQ","1","ImplantTypeCodeSequence"],"63AC":["SQ","1","FixationMethodCodeSequence"],"63B0":["SQ","1","MatingFeatureSetsSequence"],"63C0":["US","1","MatingFeatureSetID"],"63D0":["LO","1","MatingFeatureSetLabel"],"63E0":["SQ","1","MatingFeatureSequence"],"63F0":["US","1","MatingFeatureID"],6400:["SQ","1","MatingFeatureDegreeOfFreedomSequence"],6410:["US","1","DegreeOfFreedomID"],6420:["CS","1","DegreeOfFreedomType"],6430:["SQ","1","TwoDMatingFeatureCoordinatesSequence"],6440:["US","1","ReferencedHPGLDocumentID"],6450:["FD","2","TwoDMatingPoint"],6460:["FD","4","TwoDMatingAxes"],6470:["SQ","1","TwoDDegreeOfFreedomSequence"],6490:["FD","3","ThreeDDegreeOfFreedomAxis"],"64A0":["FD","2","RangeOfFreedom"],"64C0":["FD","3","ThreeDMatingPoint"],"64D0":["FD","9","ThreeDMatingAxes"],"64F0":["FD","3","TwoDDegreeOfFreedomAxis"],6500:["SQ","1","PlanningLandmarkPointSequence"],6510:["SQ","1","PlanningLandmarkLineSequence"],6520:["SQ","1","PlanningLandmarkPlaneSequence"],6530:["US","1","PlanningLandmarkID"],6540:["LO","1","PlanningLandmarkDescription"],6545:["SQ","1","PlanningLandmarkIdentificationCodeSequence"],6550:["SQ","1","TwoDPointCoordinatesSequence"],6560:["FD","2","TwoDPointCoordinates"],6590:["FD","3","ThreeDPointCoordinates"],"65A0":["SQ","1","TwoDLineCoordinatesSequence"],"65B0":["FD","4","TwoDLineCoordinates"],"65D0":["FD","6","ThreeDLineCoordinates"],"65E0":["SQ","1","TwoDPlaneCoordinatesSequence"],"65F0":["FD","4","TwoDPlaneIntersection"],6610:["FD","3","ThreeDPlaneOrigin"],6620:["FD","3","ThreeDPlaneNormal"],7001:["CS","1","ModelModification"],7002:["CS","1","ModelMirroring"],7003:["SQ","1","ModelUsageCodeSequence"],7004:["UI","1","ModelGroupUID"],7005:["UR","1","RelativeURIReferenceWithinEncapsulatedDocument"]},"006A":{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","AnnotationCoordinateType"],"0002":["SQ","1","AnnotationGroupSequence"],"0003":["UI","1","AnnotationGroupUID"],"0005":["LO","1","AnnotationGroupLabel"],"0006":["UT","1","AnnotationGroupDescription"],"0007":["CS","1","AnnotationGroupGenerationType"],"0008":["SQ","1","AnnotationGroupAlgorithmIdentificationSequence"],"0009":["SQ","1","AnnotationPropertyCategoryCodeSequence"],"000A":["SQ","1","AnnotationPropertyTypeCodeSequence"],"000B":["SQ","1","AnnotationPropertyTypeModifierCodeSequence"],"000C":["UL","1","NumberOfAnnotations"],"000D":["CS","1","AnnotationAppliesToAllOpticalPaths"],"000E":["SH","1-n","ReferencedOpticalPathIdentifier"],"000F":["CS","1","AnnotationAppliesToAllZPlanes"],"0010":["FD","1-n","CommonZCoordinateValue"],"0011":["OL","1","AnnotationIndexList"]},"0070":{"0000":["UL","1","GenericGroupLength"],"0001":["SQ","1","GraphicAnnotationSequence"],"0002":["CS","1","GraphicLayer"],"0003":["CS","1","BoundingBoxAnnotationUnits"],"0004":["CS","1","AnchorPointAnnotationUnits"],"0005":["CS","1","GraphicAnnotationUnits"],"0006":["ST","1","UnformattedTextValue"],"0008":["SQ","1","TextObjectSequence"],"0009":["SQ","1","GraphicObjectSequence"],"0010":["FL","2","BoundingBoxTopLeftHandCorner"],"0011":["FL","2","BoundingBoxBottomRightHandCorner"],"0012":["CS","1","BoundingBoxTextHorizontalJustification"],"0014":["FL","2","AnchorPoint"],"0015":["CS","1","AnchorPointVisibility"],"0020":["US","1","GraphicDimensions"],"0021":["US","1","NumberOfGraphicPoints"],"0022":["FL","2-n","GraphicData"],"0023":["CS","1","GraphicType"],"0024":["CS","1","GraphicFilled"],"0040":["IS","1","ImageRotationRetired"],"0041":["CS","1","ImageHorizontalFlip"],"0042":["US","1","ImageRotation"],"0050":["US","2","DisplayedAreaTopLeftHandCornerTrial"],"0051":["US","2","DisplayedAreaBottomRightHandCornerTrial"],"0052":["SL","2","DisplayedAreaTopLeftHandCorner"],"0053":["SL","2","DisplayedAreaBottomRightHandCorner"],"005A":["SQ","1","DisplayedAreaSelectionSequence"],"0060":["SQ","1","GraphicLayerSequence"],"0062":["IS","1","GraphicLayerOrder"],"0066":["US","1","GraphicLayerRecommendedDisplayGrayscaleValue"],"0067":["US","3","GraphicLayerRecommendedDisplayRGBValue"],"0068":["LO","1","GraphicLayerDescription"],"0080":["CS","1","ContentLabel"],"0081":["LO","1","ContentDescription"],"0082":["DA","1","PresentationCreationDate"],"0083":["TM","1","PresentationCreationTime"],"0084":["PN","1","ContentCreatorName"],"0086":["SQ","1","ContentCreatorIdentificationCodeSequence"],"0087":["SQ","1","AlternateContentDescriptionSequence"],"0100":["CS","1","PresentationSizeMode"],"0101":["DS","2","PresentationPixelSpacing"],"0102":["IS","2","PresentationPixelAspectRatio"],"0103":["FL","1","PresentationPixelMagnificationRatio"],"0207":["LO","1","GraphicGroupLabel"],"0208":["ST","1","GraphicGroupDescription"],"0209":["SQ","1","CompoundGraphicSequence"],"0226":["UL","1","CompoundGraphicInstanceID"],"0227":["LO","1","FontName"],"0228":["CS","1","FontNameType"],"0229":["LO","1","CSSFontName"],"0230":["FD","1","RotationAngle"],"0231":["SQ","1","TextStyleSequence"],"0232":["SQ","1","LineStyleSequence"],"0233":["SQ","1","FillStyleSequence"],"0234":["SQ","1","GraphicGroupSequence"],"0241":["US","3","TextColorCIELabValue"],"0242":["CS","1","HorizontalAlignment"],"0243":["CS","1","VerticalAlignment"],"0244":["CS","1","ShadowStyle"],"0245":["FL","1","ShadowOffsetX"],"0246":["FL","1","ShadowOffsetY"],"0247":["US","3","ShadowColorCIELabValue"],"0248":["CS","1","Underlined"],"0249":["CS","1","Bold"],"0250":["CS","1","Italic"],"0251":["US","3","PatternOnColorCIELabValue"],"0252":["US","3","PatternOffColorCIELabValue"],"0253":["FL","1","LineThickness"],"0254":["CS","1","LineDashingStyle"],"0255":["UL","1","LinePattern"],"0256":["OB","1","FillPattern"],"0257":["CS","1","FillMode"],"0258":["FL","1","ShadowOpacity"],"0261":["FL","1","GapLength"],"0262":["FL","1","DiameterOfVisibility"],"0273":["FL","2","RotationPoint"],"0274":["CS","1","TickAlignment"],"0278":["CS","1","ShowTickLabel"],"0279":["CS","1","TickLabelAlignment"],"0282":["CS","1","CompoundGraphicUnits"],"0284":["FL","1","PatternOnOpacity"],"0285":["FL","1","PatternOffOpacity"],"0287":["SQ","1","MajorTicksSequence"],"0288":["FL","1","TickPosition"],"0289":["SH","1","TickLabel"],"0294":["CS","1","CompoundGraphicType"],"0295":["UL","1","GraphicGroupID"],"0306":["CS","1","ShapeType"],"0308":["SQ","1","RegistrationSequence"],"0309":["SQ","1","MatrixRegistrationSequence"],"030A":["SQ","1","MatrixSequence"],"030B":["FD","16","FrameOfReferenceToDisplayedCoordinateSystemTransformationMatrix"],"030C":["CS","1","FrameOfReferenceTransformationMatrixType"],"030D":["SQ","1","RegistrationTypeCodeSequence"],"030F":["ST","1","FiducialDescription"],"0310":["SH","1","FiducialIdentifier"],"0311":["SQ","1","FiducialIdentifierCodeSequence"],"0312":["FD","1","ContourUncertaintyRadius"],"0314":["SQ","1","UsedFiducialsSequence"],"0318":["SQ","1","GraphicCoordinatesDataSequence"],"031A":["UI","1","FiducialUID"],"031B":["UI","1","ReferencedFiducialUID"],"031C":["SQ","1","FiducialSetSequence"],"031E":["SQ","1","FiducialSequence"],"031F":["SQ","1","FiducialsPropertyCategoryCodeSequence"],"0401":["US","3","GraphicLayerRecommendedDisplayCIELabValue"],"0402":["SQ","1","BlendingSequence"],"0403":["FL","1","RelativeOpacity"],"0404":["SQ","1","ReferencedSpatialRegistrationSequence"],"0405":["CS","1","BlendingPosition"],1101:["UI","1","PresentationDisplayCollectionUID"],1102:["UI","1","PresentationSequenceCollectionUID"],1103:["US","1","PresentationSequencePositionIndex"],1104:["SQ","1","RenderedImageReferenceSequence"],1201:["SQ","1","VolumetricPresentationStateInputSequence"],1202:["CS","1","PresentationInputType"],1203:["US","1","InputSequencePositionIndex"],1204:["CS","1","Crop"],1205:["US","1-n","CroppingSpecificationIndex"],1206:["CS","1","CompositingMethod"],1207:["US","1","VolumetricPresentationInputNumber"],1208:["CS","1","ImageVolumeGeometry"],1209:["UI","1","VolumetricPresentationInputSetUID"],"120A":["SQ","1","VolumetricPresentationInputSetSequence"],"120B":["CS","1","GlobalCrop"],"120C":["US","1-n","GlobalCroppingSpecificationIndex"],"120D":["CS","1","RenderingMethod"],1301:["SQ","1","VolumeCroppingSequence"],1302:["CS","1","VolumeCroppingMethod"],1303:["FD","6","BoundingBoxCrop"],1304:["SQ","1","ObliqueCroppingPlaneSequence"],1305:["FD","4","Plane"],1306:["FD","3","PlaneNormal"],1309:["US","1","CroppingSpecificationNumber"],1501:["CS","1","MultiPlanarReconstructionStyle"],1502:["CS","1","MPRThicknessType"],1503:["FD","1","MPRSlabThickness"],1505:["FD","3","MPRTopLeftHandCorner"],1507:["FD","3","MPRViewWidthDirection"],1508:["FD","1","MPRViewWidth"],"150C":["UL","1","NumberOfVolumetricCurvePoints"],"150D":["OD","1","VolumetricCurvePoints"],1511:["FD","3","MPRViewHeightDirection"],1512:["FD","1","MPRViewHeight"],1602:["CS","1","RenderProjection"],1603:["FD","3","ViewpointPosition"],1604:["FD","3","ViewpointLookAtPoint"],1605:["FD","3","ViewpointUpDirection"],1606:["FD","6","RenderFieldOfView"],1607:["FD","1","SamplingStepSize"],1701:["CS","1","ShadingStyle"],1702:["FD","1","AmbientReflectionIntensity"],1703:["FD","3","LightDirection"],1704:["FD","1","DiffuseReflectionIntensity"],1705:["FD","1","SpecularReflectionIntensity"],1706:["FD","1","Shininess"],1801:["SQ","1","PresentationStateClassificationComponentSequence"],1802:["CS","1","ComponentType"],1803:["SQ","1","ComponentInputSequence"],1804:["US","1","VolumetricPresentationInputIndex"],1805:["SQ","1","PresentationStateCompositorComponentSequence"],1806:["SQ","1","WeightingTransferFunctionSequence"],1807:["US","3","WeightingLookupTableDescriptor"],1808:["OB","1","WeightingLookupTableData"],1901:["SQ","1","VolumetricAnnotationSequence"],1903:["SQ","1","ReferencedStructuredContextSequence"],1904:["UI","1","ReferencedContentItem"],1905:["SQ","1","VolumetricPresentationInputAnnotationSequence"],1907:["CS","1","AnnotationClipping"],"1A01":["CS","1","PresentationAnimationStyle"],"1A03":["FD","1","RecommendedAnimationRate"],"1A04":["SQ","1","AnimationCurveSequence"],"1A05":["FD","1","AnimationStepSize"],"1A06":["FD","1","SwivelRange"],"1A07":["OD","1","VolumetricCurveUpDirections"],"1A08":["SQ","1","VolumeStreamSequence"],"1A09":["LO","1","RGBATransferFunctionDescription"],"1B01":["SQ","1","AdvancedBlendingSequence"],"1B02":["US","1","BlendingInputNumber"],"1B03":["SQ","1","BlendingDisplayInputSequence"],"1B04":["SQ","1","BlendingDisplaySequence"],"1B06":["CS","1","BlendingMode"],"1B07":["CS","1","TimeSeriesBlending"],"1B08":["CS","1","GeometryForDisplay"],"1B11":["SQ","1","ThresholdSequence"],"1B12":["SQ","1","ThresholdValueSequence"],"1B13":["CS","1","ThresholdType"],"1B14":["FD","1","ThresholdValue"]},"0072":{"0000":["UL","1","GenericGroupLength"],"0002":["SH","1","HangingProtocolName"],"0004":["LO","1","HangingProtocolDescription"],"0006":["CS","1","HangingProtocolLevel"],"0008":["LO","1","HangingProtocolCreator"],"000A":["DT","1","HangingProtocolCreationDateTime"],"000C":["SQ","1","HangingProtocolDefinitionSequence"],"000E":["SQ","1","HangingProtocolUserIdentificationCodeSequence"],"0010":["LO","1","HangingProtocolUserGroupName"],"0012":["SQ","1","SourceHangingProtocolSequence"],"0014":["US","1","NumberOfPriorsReferenced"],"0020":["SQ","1","ImageSetsSequence"],"0022":["SQ","1","ImageSetSelectorSequence"],"0024":["CS","1","ImageSetSelectorUsageFlag"],"0026":["AT","1","SelectorAttribute"],"0028":["US","1","SelectorValueNumber"],"0030":["SQ","1","TimeBasedImageSetsSequence"],"0032":["US","1","ImageSetNumber"],"0034":["CS","1","ImageSetSelectorCategory"],"0038":["US","2","RelativeTime"],"003A":["CS","1","RelativeTimeUnits"],"003C":["SS","2","AbstractPriorValue"],"003E":["SQ","1","AbstractPriorCodeSequence"],"0040":["LO","1","ImageSetLabel"],"0050":["CS","1","SelectorAttributeVR"],"0052":["AT","1-n","SelectorSequencePointer"],"0054":["LO","1-n","SelectorSequencePointerPrivateCreator"],"0056":["LO","1","SelectorAttributePrivateCreator"],"005E":["AE","1-n","SelectorAEValue"],"005F":["AS","1-n","SelectorASValue"],"0060":["AT","1-n","SelectorATValue"],"0061":["DA","1-n","SelectorDAValue"],"0062":["CS","1-n","SelectorCSValue"],"0063":["DT","1-n","SelectorDTValue"],"0064":["IS","1-n","SelectorISValue"],"0065":["OB","1","SelectorOBValue"],"0066":["LO","1-n","SelectorLOValue"],"0067":["OF","1","SelectorOFValue"],"0068":["LT","1","SelectorLTValue"],"0069":["OW","1","SelectorOWValue"],"006A":["PN","1-n","SelectorPNValue"],"006B":["TM","1-n","SelectorTMValue"],"006C":["SH","1-n","SelectorSHValue"],"006D":["UN","1","SelectorUNValue"],"006E":["ST","1","SelectorSTValue"],"006F":["UC","1-n","SelectorUCValue"],"0070":["UT","1","SelectorUTValue"],"0071":["UR","1","SelectorURValue"],"0072":["DS","1-n","SelectorDSValue"],"0073":["OD","1","SelectorODValue"],"0074":["FD","1-n","SelectorFDValue"],"0075":["OL","1","SelectorOLValue"],"0076":["FL","1-n","SelectorFLValue"],"0078":["UL","1-n","SelectorULValue"],"007A":["US","1-n","SelectorUSValue"],"007C":["SL","1-n","SelectorSLValue"],"007E":["SS","1-n","SelectorSSValue"],"007F":["UI","1-n","SelectorUIValue"],"0080":["SQ","1","SelectorCodeSequenceValue"],"0081":["OV","1","SelectorOVValue"],"0082":["SV","1-n","SelectorSVValue"],"0083":["UV","1-n","SelectorUVValue"],"0100":["US","1","NumberOfScreens"],"0102":["SQ","1","NominalScreenDefinitionSequence"],"0104":["US","1","NumberOfVerticalPixels"],"0106":["US","1","NumberOfHorizontalPixels"],"0108":["FD","4","DisplayEnvironmentSpatialPosition"],"010A":["US","1","ScreenMinimumGrayscaleBitDepth"],"010C":["US","1","ScreenMinimumColorBitDepth"],"010E":["US","1","ApplicationMaximumRepaintTime"],"0200":["SQ","1","DisplaySetsSequence"],"0202":["US","1","DisplaySetNumber"],"0203":["LO","1","DisplaySetLabel"],"0204":["US","1","DisplaySetPresentationGroup"],"0206":["LO","1","DisplaySetPresentationGroupDescription"],"0208":["CS","1","PartialDataDisplayHandling"],"0210":["SQ","1","SynchronizedScrollingSequence"],"0212":["US","2-n","DisplaySetScrollingGroup"],"0214":["SQ","1","NavigationIndicatorSequence"],"0216":["US","1","NavigationDisplaySet"],"0218":["US","1-n","ReferenceDisplaySets"],"0300":["SQ","1","ImageBoxesSequence"],"0302":["US","1","ImageBoxNumber"],"0304":["CS","1","ImageBoxLayoutType"],"0306":["US","1","ImageBoxTileHorizontalDimension"],"0308":["US","1","ImageBoxTileVerticalDimension"],"0310":["CS","1","ImageBoxScrollDirection"],"0312":["CS","1","ImageBoxSmallScrollType"],"0314":["US","1","ImageBoxSmallScrollAmount"],"0316":["CS","1","ImageBoxLargeScrollType"],"0318":["US","1","ImageBoxLargeScrollAmount"],"0320":["US","1","ImageBoxOverlapPriority"],"0330":["FD","1","CineRelativeToRealTime"],"0400":["SQ","1","FilterOperationsSequence"],"0402":["CS","1","FilterByCategory"],"0404":["CS","1","FilterByAttributePresence"],"0406":["CS","1","FilterByOperator"],"0420":["US","3","StructuredDisplayBackgroundCIELabValue"],"0421":["US","3","EmptyImageBoxCIELabValue"],"0422":["SQ","1","StructuredDisplayImageBoxSequence"],"0424":["SQ","1","StructuredDisplayTextBoxSequence"],"0427":["SQ","1","ReferencedFirstFrameSequence"],"0430":["SQ","1","ImageBoxSynchronizationSequence"],"0432":["US","2-n","SynchronizedImageBoxList"],"0434":["CS","1","TypeOfSynchronization"],"0500":["CS","1","BlendingOperationType"],"0510":["CS","1","ReformattingOperationType"],"0512":["FD","1","ReformattingThickness"],"0514":["FD","1","ReformattingInterval"],"0516":["CS","1","ReformattingOperationInitialViewDirection"],"0520":["CS","1-n","ThreeDRenderingType"],"0600":["SQ","1","SortingOperationsSequence"],"0602":["CS","1","SortByCategory"],"0604":["CS","1","SortingDirection"],"0700":["CS","2","DisplaySetPatientOrientation"],"0702":["CS","1","VOIType"],"0704":["CS","1","PseudoColorType"],"0705":["SQ","1","PseudoColorPaletteInstanceReferenceSequence"],"0706":["CS","1","ShowGrayscaleInverted"],"0710":["CS","1","ShowImageTrueSizeFlag"],"0712":["CS","1","ShowGraphicAnnotationFlag"],"0714":["CS","1","ShowPatientDemographicsFlag"],"0716":["CS","1","ShowAcquisitionTechniquesFlag"],"0717":["CS","1","DisplaySetHorizontalJustification"],"0718":["CS","1","DisplaySetVerticalJustification"]},"0074":{"0000":["UL","1","GenericGroupLength"],"0120":["FD","1","ContinuationStartMeterset"],"0121":["FD","1","ContinuationEndMeterset"],1e3:["CS","1","ProcedureStepState"],1002:["SQ","1","ProcedureStepProgressInformationSequence"],1004:["DS","1","ProcedureStepProgress"],1006:["ST","1","ProcedureStepProgressDescription"],1007:["SQ","1","ProcedureStepProgressParametersSequence"],1008:["SQ","1","ProcedureStepCommunicationsURISequence"],"100A":["UR","1","ContactURI"],"100C":["LO","1","ContactDisplayName"],"100E":["SQ","1","ProcedureStepDiscontinuationReasonCodeSequence"],1020:["SQ","1","BeamTaskSequence"],1022:["CS","1","BeamTaskType"],1024:["IS","1","BeamOrderIndexTrial"],1025:["CS","1","AutosequenceFlag"],1026:["FD","1","TableTopVerticalAdjustedPosition"],1027:["FD","1","TableTopLongitudinalAdjustedPosition"],1028:["FD","1","TableTopLateralAdjustedPosition"],"102A":["FD","1","PatientSupportAdjustedAngle"],"102B":["FD","1","TableTopEccentricAdjustedAngle"],"102C":["FD","1","TableTopPitchAdjustedAngle"],"102D":["FD","1","TableTopRollAdjustedAngle"],1030:["SQ","1","DeliveryVerificationImageSequence"],1032:["CS","1","VerificationImageTiming"],1034:["CS","1","DoubleExposureFlag"],1036:["CS","1","DoubleExposureOrdering"],1038:["DS","1","DoubleExposureMetersetTrial"],"103A":["DS","4","DoubleExposureFieldDeltaTrial"],1040:["SQ","1","RelatedReferenceRTImageSequence"],1042:["SQ","1","GeneralMachineVerificationSequence"],1044:["SQ","1","ConventionalMachineVerificationSequence"],1046:["SQ","1","IonMachineVerificationSequence"],1048:["SQ","1","FailedAttributesSequence"],"104A":["SQ","1","OverriddenAttributesSequence"],"104C":["SQ","1","ConventionalControlPointVerificationSequence"],"104E":["SQ","1","IonControlPointVerificationSequence"],1050:["SQ","1","AttributeOccurrenceSequence"],1052:["AT","1","AttributeOccurrencePointer"],1054:["UL","1","AttributeItemSelector"],1056:["LO","1","AttributeOccurrencePrivateCreator"],1057:["IS","1-n","SelectorSequencePointerItems"],1200:["CS","1","ScheduledProcedureStepPriority"],1202:["LO","1","WorklistLabel"],1204:["LO","1","ProcedureStepLabel"],1210:["SQ","1","ScheduledProcessingParametersSequence"],1212:["SQ","1","PerformedProcessingParametersSequence"],1216:["SQ","1","UnifiedProcedureStepPerformedProcedureSequence"],1220:["SQ","1","RelatedProcedureStepSequence"],1222:["LO","1","ProcedureStepRelationshipType"],1224:["SQ","1","ReplacedProcedureStepSequence"],1230:["LO","1","DeletionLock"],1234:["AE","1","ReceivingAE"],1236:["AE","1","RequestingAE"],1238:["LT","1","ReasonForCancellation"],1242:["CS","1","SCPStatus"],1244:["CS","1","SubscriptionListStatus"],1246:["CS","1","UnifiedProcedureStepListStatus"],1324:["UL","1","BeamOrderIndex"],1338:["FD","1","DoubleExposureMeterset"],"133A":["FD","4","DoubleExposureFieldDelta"],1401:["SQ","1","BrachyTaskSequence"],1402:["DS","1","ContinuationStartTotalReferenceAirKerma"],1403:["DS","1","ContinuationEndTotalReferenceAirKerma"],1404:["IS","1","ContinuationPulseNumber"],1405:["SQ","1","ChannelDeliveryOrderSequence"],1406:["IS","1","ReferencedChannelNumber"],1407:["DS","1","StartCumulativeTimeWeight"],1408:["DS","1","EndCumulativeTimeWeight"],1409:["SQ","1","OmittedChannelSequence"],"140A":["CS","1","ReasonForChannelOmission"],"140B":["LO","1","ReasonForChannelOmissionDescription"],"140C":["IS","1","ChannelDeliveryOrderIndex"],"140D":["SQ","1","ChannelDeliveryContinuationSequence"],"140E":["SQ","1","OmittedApplicationSetupSequence"]},"0076":{"0000":["UL","1","GenericGroupLength"],"0001":["LO","1","ImplantAssemblyTemplateName"],"0003":["LO","1","ImplantAssemblyTemplateIssuer"],"0006":["LO","1","ImplantAssemblyTemplateVersion"],"0008":["SQ","1","ReplacedImplantAssemblyTemplateSequence"],"000A":["CS","1","ImplantAssemblyTemplateType"],"000C":["SQ","1","OriginalImplantAssemblyTemplateSequence"],"000E":["SQ","1","DerivationImplantAssemblyTemplateSequence"],"0010":["SQ","1","ImplantAssemblyTemplateTargetAnatomySequence"],"0020":["SQ","1","ProcedureTypeCodeSequence"],"0030":["LO","1","SurgicalTechnique"],"0032":["SQ","1","ComponentTypesSequence"],"0034":["SQ","1","ComponentTypeCodeSequence"],"0036":["CS","1","ExclusiveComponentType"],"0038":["CS","1","MandatoryComponentType"],"0040":["SQ","1","ComponentSequence"],"0055":["US","1","ComponentID"],"0060":["SQ","1","ComponentAssemblySequence"],"0070":["US","1","Component1ReferencedID"],"0080":["US","1","Component1ReferencedMatingFeatureSetID"],"0090":["US","1","Component1ReferencedMatingFeatureID"],"00A0":["US","1","Component2ReferencedID"],"00B0":["US","1","Component2ReferencedMatingFeatureSetID"],"00C0":["US","1","Component2ReferencedMatingFeatureID"]},"0078":{"0000":["UL","1","GenericGroupLength"],"0001":["LO","1","ImplantTemplateGroupName"],"0010":["ST","1","ImplantTemplateGroupDescription"],"0020":["LO","1","ImplantTemplateGroupIssuer"],"0024":["LO","1","ImplantTemplateGroupVersion"],"0026":["SQ","1","ReplacedImplantTemplateGroupSequence"],"0028":["SQ","1","ImplantTemplateGroupTargetAnatomySequence"],"002A":["SQ","1","ImplantTemplateGroupMembersSequence"],"002E":["US","1","ImplantTemplateGroupMemberID"],"0050":["FD","3","ThreeDImplantTemplateGroupMemberMatchingPoint"],"0060":["FD","9","ThreeDImplantTemplateGroupMemberMatchingAxes"],"0070":["SQ","1","ImplantTemplateGroupMemberMatching2DCoordinatesSequence"],"0090":["FD","2","TwoDImplantTemplateGroupMemberMatchingPoint"],"00A0":["FD","4","TwoDImplantTemplateGroupMemberMatchingAxes"],"00B0":["SQ","1","ImplantTemplateGroupVariationDimensionSequence"],"00B2":["LO","1","ImplantTemplateGroupVariationDimensionName"],"00B4":["SQ","1","ImplantTemplateGroupVariationDimensionRankSequence"],"00B6":["US","1","ReferencedImplantTemplateGroupMemberID"],"00B8":["US","1","ImplantTemplateGroupVariationDimensionRank"]},"0080":{"0000":["UL","1","GenericGroupLength"],"0001":["SQ","1","SurfaceScanAcquisitionTypeCodeSequence"],"0002":["SQ","1","SurfaceScanModeCodeSequence"],"0003":["SQ","1","RegistrationMethodCodeSequence"],"0004":["FD","1","ShotDurationTime"],"0005":["FD","1","ShotOffsetTime"],"0006":["US","1-n","SurfacePointPresentationValueData"],"0007":["US","3-3n","SurfacePointColorCIELabValueData"],"0008":["SQ","1","UVMappingSequence"],"0009":["SH","1","TextureLabel"],"0010":["OF","1","UValueData"],"0011":["OF","1","VValueData"],"0012":["SQ","1","ReferencedTextureSequence"],"0013":["SQ","1","ReferencedSurfaceDataSequence"]},"0082":{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","AssessmentSummary"],"0003":["UT","1","AssessmentSummaryDescription"],"0004":["SQ","1","AssessedSOPInstanceSequence"],"0005":["SQ","1","ReferencedComparisonSOPInstanceSequence"],"0006":["UL","1","NumberOfAssessmentObservations"],"0007":["SQ","1","AssessmentObservationsSequence"],"0008":["CS","1","ObservationSignificance"],"000A":["UT","1","ObservationDescription"],"000C":["SQ","1","StructuredConstraintObservationSequence"],"0010":["SQ","1","AssessedAttributeValueSequence"],"0016":["LO","1","AssessmentSetID"],"0017":["SQ","1","AssessmentRequesterSequence"],"0018":["LO","1","SelectorAttributeName"],"0019":["LO","1","SelectorAttributeKeyword"],"0021":["SQ","1","AssessmentTypeCodeSequence"],"0022":["SQ","1","ObservationBasisCodeSequence"],"0023":["LO","1","AssessmentLabel"],"0032":["CS","1","ConstraintType"],"0033":["UT","1","SpecificationSelectionGuidance"],"0034":["SQ","1","ConstraintValueSequence"],"0035":["SQ","1","RecommendedDefaultValueSequence"],"0036":["CS","1","ConstraintViolationSignificance"],"0037":["UT","1","ConstraintViolationCondition"],"0038":["CS","1","ModifiableConstraintFlag"]},"0088":{"0000":["UL","1","GenericGroupLength"],"0130":["SH","1","StorageMediaFileSetID"],"0140":["UI","1","StorageMediaFileSetUID"],"0200":["SQ","1","IconImageSequence"],"0904":["LO","1","TopicTitle"],"0906":["ST","1","TopicSubject"],"0910":["LO","1","TopicAuthor"],"0912":["LO","1-32","TopicKeywords"]},"0100":{"0000":["UL","1","GenericGroupLength"],"0410":["CS","1","SOPInstanceStatus"],"0420":["DT","1","SOPAuthorizationDateTime"],"0424":["LT","1","SOPAuthorizationComment"],"0426":["LO","1","AuthorizationEquipmentCertificationNumber"]},"0400":{"0000":["UL","1","GenericGroupLength"],"0005":["US","1","MACIDNumber"],"0010":["UI","1","MACCalculationTransferSyntaxUID"],"0015":["CS","1","MACAlgorithm"],"0020":["AT","1-n","DataElementsSigned"],"0100":["UI","1","DigitalSignatureUID"],"0105":["DT","1","DigitalSignatureDateTime"],"0110":["CS","1","CertificateType"],"0115":["OB","1","CertificateOfSigner"],"0120":["OB","1","Signature"],"0305":["CS","1","CertifiedTimestampType"],"0310":["OB","1","CertifiedTimestamp"],"0315":["FL","1",""],"0401":["SQ","1","DigitalSignaturePurposeCodeSequence"],"0402":["SQ","1","ReferencedDigitalSignatureSequence"],"0403":["SQ","1","ReferencedSOPInstanceMACSequence"],"0404":["OB","1","MAC"],"0500":["SQ","1","EncryptedAttributesSequence"],"0510":["UI","1","EncryptedContentTransferSyntaxUID"],"0520":["OB","1","EncryptedContent"],"0550":["SQ","1","ModifiedAttributesSequence"],"0551":["SQ","1","NonconformingModifiedAttributesSequence"],"0552":["OB","1","NonconformingDataElementValue"],"0561":["SQ","1","OriginalAttributesSequence"],"0562":["DT","1","AttributeModificationDateTime"],"0563":["LO","1","ModifyingSystem"],"0564":["LO","1","SourceOfPreviousValues"],"0565":["CS","1","ReasonForTheAttributeModification"],"0600":["CS","1","InstanceOriginStatus"]},1e3:{"0000":["UL","1","GenericGroupLength"],"0010":["US","3","EscapeTriplet"],"0011":["US","3","RunLengthTriplet"],"0012":["US","1","HuffmanTableSize"],"0013":["US","3","HuffmanTableTriplet"],"0014":["US","1","ShiftTableSize"],"0015":["US","3","ShiftTableTriplet"]},1010:{"0000":["UL","1","GenericGroupLength"],"0004":["US","1-n","ZonalMap"]},2e3:{"0000":["UL","1","GenericGroupLength"],"0010":["IS","1","NumberOfCopies"],"001E":["SQ","1","PrinterConfigurationSequence"],"0020":["CS","1","PrintPriority"],"0030":["CS","1","MediumType"],"0040":["CS","1","FilmDestination"],"0050":["LO","1","FilmSessionLabel"],"0060":["IS","1","MemoryAllocation"],"0061":["IS","1","MaximumMemoryAllocation"],"0062":["CS","1","ColorImagePrintingFlag"],"0063":["CS","1","CollationFlag"],"0065":["CS","1","AnnotationFlag"],"0067":["CS","1","ImageOverlayFlag"],"0069":["CS","1","PresentationLUTFlag"],"006A":["CS","1","ImageBoxPresentationLUTFlag"],"00A0":["US","1","MemoryBitDepth"],"00A1":["US","1","PrintingBitDepth"],"00A2":["SQ","1","MediaInstalledSequence"],"00A4":["SQ","1","OtherMediaAvailableSequence"],"00A8":["SQ","1","SupportedImageDisplayFormatsSequence"],"0500":["SQ","1","ReferencedFilmBoxSequence"],"0510":["SQ","1","ReferencedStoredPrintSequence"]},2010:{"0000":["UL","1","GenericGroupLength"],"0010":["ST","1","ImageDisplayFormat"],"0030":["CS","1","AnnotationDisplayFormatID"],"0040":["CS","1","FilmOrientation"],"0050":["CS","1","FilmSizeID"],"0052":["CS","1","PrinterResolutionID"],"0054":["CS","1","DefaultPrinterResolutionID"],"0060":["CS","1","MagnificationType"],"0080":["CS","1","SmoothingType"],"00A6":["CS","1","DefaultMagnificationType"],"00A7":["CS","1-n","OtherMagnificationTypesAvailable"],"00A8":["CS","1","DefaultSmoothingType"],"00A9":["CS","1-n","OtherSmoothingTypesAvailable"],"0100":["CS","1","BorderDensity"],"0110":["CS","1","EmptyImageDensity"],"0120":["US","1","MinDensity"],"0130":["US","1","MaxDensity"],"0140":["CS","1","Trim"],"0150":["ST","1","ConfigurationInformation"],"0152":["LT","1","ConfigurationInformationDescription"],"0154":["IS","1","MaximumCollatedFilms"],"015E":["US","1","Illumination"],"0160":["US","1","ReflectedAmbientLight"],"0376":["DS","2","PrinterPixelSpacing"],"0500":["SQ","1","ReferencedFilmSessionSequence"],"0510":["SQ","1","ReferencedImageBoxSequence"],"0520":["SQ","1","ReferencedBasicAnnotationBoxSequence"]},2020:{"0000":["UL","1","GenericGroupLength"],"0010":["US","1","ImageBoxPosition"],"0020":["CS","1","Polarity"],"0030":["DS","1","RequestedImageSize"],"0040":["CS","1","RequestedDecimateCropBehavior"],"0050":["CS","1","RequestedResolutionID"],"00A0":["CS","1","RequestedImageSizeFlag"],"00A2":["CS","1","DecimateCropResult"],"0110":["SQ","1","BasicGrayscaleImageSequence"],"0111":["SQ","1","BasicColorImageSequence"],"0130":["SQ","1","ReferencedImageOverlayBoxSequence"],"0140":["SQ","1","ReferencedVOILUTBoxSequence"]},2030:{"0000":["UL","1","GenericGroupLength"],"0010":["US","1","AnnotationPosition"],"0020":["LO","1","TextString"]},2040:{"0000":["UL","1","GenericGroupLength"],"0010":["SQ","1","ReferencedOverlayPlaneSequence"],"0011":["US","1-99","ReferencedOverlayPlaneGroups"],"0020":["SQ","1","OverlayPixelDataSequence"],"0060":["CS","1","OverlayMagnificationType"],"0070":["CS","1","OverlaySmoothingType"],"0072":["CS","1","OverlayOrImageMagnification"],"0074":["US","1","MagnifyToNumberOfColumns"],"0080":["CS","1","OverlayForegroundDensity"],"0082":["CS","1","OverlayBackgroundDensity"],"0090":["CS","1","OverlayMode"],"0100":["CS","1","ThresholdDensity"],"0500":["SQ","1","ReferencedImageBoxSequenceRetired"]},2050:{"0000":["UL","1","GenericGroupLength"],"0010":["SQ","1","PresentationLUTSequence"],"0020":["CS","1","PresentationLUTShape"],"0500":["SQ","1","ReferencedPresentationLUTSequence"]},2100:{"0000":["UL","1","GenericGroupLength"],"0010":["SH","1","PrintJobID"],"0020":["CS","1","ExecutionStatus"],"0030":["CS","1","ExecutionStatusInfo"],"0040":["DA","1","CreationDate"],"0050":["TM","1","CreationTime"],"0070":["AE","1","Originator"],"0140":["AE","1","DestinationAE"],"0160":["SH","1","OwnerID"],"0170":["IS","1","NumberOfFilms"],"0500":["SQ","1","ReferencedPrintJobSequencePullStoredPrint"]},2110:{"0000":["UL","1","GenericGroupLength"],"0010":["CS","1","PrinterStatus"],"0020":["CS","1","PrinterStatusInfo"],"0030":["LO","1","PrinterName"],"0099":["SH","1","PrintQueueID"]},2120:{"0000":["UL","1","GenericGroupLength"],"0010":["CS","1","QueueStatus"],"0050":["SQ","1","PrintJobDescriptionSequence"],"0070":["SQ","1","ReferencedPrintJobSequence"]},2130:{"0000":["UL","1","GenericGroupLength"],"0010":["SQ","1","PrintManagementCapabilitiesSequence"],"0015":["SQ","1","PrinterCharacteristicsSequence"],"0030":["SQ","1","FilmBoxContentSequence"],"0040":["SQ","1","ImageBoxContentSequence"],"0050":["SQ","1","AnnotationContentSequence"],"0060":["SQ","1","ImageOverlayBoxContentSequence"],"0080":["SQ","1","PresentationLUTContentSequence"],"00A0":["SQ","1","ProposedStudySequence"],"00C0":["SQ","1","OriginalImageSequence"]},2200:{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","LabelUsingInformationExtractedFromInstances"],"0002":["UT","1","LabelText"],"0003":["CS","1","LabelStyleSelection"],"0004":["LT","1","MediaDisposition"],"0005":["LT","1","BarcodeValue"],"0006":["CS","1","BarcodeSymbology"],"0007":["CS","1","AllowMediaSplitting"],"0008":["CS","1","IncludeNonDICOMObjects"],"0009":["CS","1","IncludeDisplayApplication"],"000A":["CS","1","PreserveCompositeInstancesAfterMediaCreation"],"000B":["US","1","TotalNumberOfPiecesOfMediaCreated"],"000C":["LO","1","RequestedMediaApplicationProfile"],"000D":["SQ","1","ReferencedStorageMediaSequence"],"000E":["AT","1-n","FailureAttributes"],"000F":["CS","1","AllowLossyCompression"],"0020":["CS","1","RequestPriority"]},3002:{"0000":["UL","1","GenericGroupLength"],"0002":["SH","1","RTImageLabel"],"0003":["LO","1","RTImageName"],"0004":["ST","1","RTImageDescription"],"000A":["CS","1","ReportedValuesOrigin"],"000C":["CS","1","RTImagePlane"],"000D":["DS","3","XRayImageReceptorTranslation"],"000E":["DS","1","XRayImageReceptorAngle"],"0010":["DS","6","RTImageOrientation"],"0011":["DS","2","ImagePlanePixelSpacing"],"0012":["DS","2","RTImagePosition"],"0020":["SH","1","RadiationMachineName"],"0022":["DS","1","RadiationMachineSAD"],"0024":["DS","1","RadiationMachineSSD"],"0026":["DS","1","RTImageSID"],"0028":["DS","1","SourceToReferenceObjectDistance"],"0029":["IS","1","FractionNumber"],"0030":["SQ","1","ExposureSequence"],"0032":["DS","1","MetersetExposure"],"0034":["DS","4","DiaphragmPosition"],"0040":["SQ","1","FluenceMapSequence"],"0041":["CS","1","FluenceDataSource"],"0042":["DS","1","FluenceDataScale"],"0050":["SQ","1","PrimaryFluenceModeSequence"],"0051":["CS","1","FluenceMode"],"0052":["SH","1","FluenceModeID"]},3004:{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","DVHType"],"0002":["CS","1","DoseUnits"],"0004":["CS","1","DoseType"],"0005":["CS","1","SpatialTransformOfDose"],"0006":["LO","1","DoseComment"],"0008":["DS","3","NormalizationPoint"],"000A":["CS","1","DoseSummationType"],"000C":["DS","2-n","GridFrameOffsetVector"],"000E":["DS","1","DoseGridScaling"],"0010":["SQ","1","RTDoseROISequence"],"0012":["DS","1","DoseValue"],"0014":["CS","1-3","TissueHeterogeneityCorrection"],"0040":["DS","3","DVHNormalizationPoint"],"0042":["DS","1","DVHNormalizationDoseValue"],"0050":["SQ","1","DVHSequence"],"0052":["DS","1","DVHDoseScaling"],"0054":["CS","1","DVHVolumeUnits"],"0056":["IS","1","DVHNumberOfBins"],"0058":["DS","2-2n","DVHData"],"0060":["SQ","1","DVHReferencedROISequence"],"0062":["CS","1","DVHROIContributionType"],"0070":["DS","1","DVHMinimumDose"],"0072":["DS","1","DVHMaximumDose"],"0074":["DS","1","DVHMeanDose"]},3006:{"0000":["UL","1","GenericGroupLength"],"0002":["SH","1","StructureSetLabel"],"0004":["LO","1","StructureSetName"],"0006":["ST","1","StructureSetDescription"],"0008":["DA","1","StructureSetDate"],"0009":["TM","1","StructureSetTime"],"0010":["SQ","1","ReferencedFrameOfReferenceSequence"],"0012":["SQ","1","RTReferencedStudySequence"],"0014":["SQ","1","RTReferencedSeriesSequence"],"0016":["SQ","1","ContourImageSequence"],"0018":["SQ","1","PredecessorStructureSetSequence"],"0020":["SQ","1","StructureSetROISequence"],"0022":["IS","1","ROINumber"],"0024":["UI","1","ReferencedFrameOfReferenceUID"],"0026":["LO","1","ROIName"],"0028":["ST","1","ROIDescription"],"002A":["IS","3","ROIDisplayColor"],"002C":["DS","1","ROIVolume"],"0030":["SQ","1","RTRelatedROISequence"],"0033":["CS","1","RTROIRelationship"],"0036":["CS","1","ROIGenerationAlgorithm"],"0037":["SQ","1","ROIDerivationAlgorithmIdentificationSequence"],"0038":["LO","1","ROIGenerationDescription"],"0039":["SQ","1","ROIContourSequence"],"0040":["SQ","1","ContourSequence"],"0042":["CS","1","ContourGeometricType"],"0044":["DS","1","ContourSlabThickness"],"0045":["DS","3","ContourOffsetVector"],"0046":["IS","1","NumberOfContourPoints"],"0048":["IS","1","ContourNumber"],"0049":["IS","1-n","AttachedContours"],"004A":["SQ","1","SourcePixelPlanesCharacteristicsSequence"],"0050":["DS","3-3n","ContourData"],"0080":["SQ","1","RTROIObservationsSequence"],"0082":["IS","1","ObservationNumber"],"0084":["IS","1","ReferencedROINumber"],"0085":["SH","1","ROIObservationLabel"],"0086":["SQ","1","RTROIIdentificationCodeSequence"],"0088":["ST","1","ROIObservationDescription"],"00A0":["SQ","1","RelatedRTROIObservationsSequence"],"00A4":["CS","1","RTROIInterpretedType"],"00A6":["PN","1","ROIInterpreter"],"00B0":["SQ","1","ROIPhysicalPropertiesSequence"],"00B2":["CS","1","ROIPhysicalProperty"],"00B4":["DS","1","ROIPhysicalPropertyValue"],"00B6":["SQ","1","ROIElementalCompositionSequence"],"00B7":["US","1","ROIElementalCompositionAtomicNumber"],"00B8":["FL","1","ROIElementalCompositionAtomicMassFraction"],"00B9":["SQ","1","AdditionalRTROIIdentificationCodeSequence"],"00C0":["SQ","1","FrameOfReferenceRelationshipSequence"],"00C2":["UI","1","RelatedFrameOfReferenceUID"],"00C4":["CS","1","FrameOfReferenceTransformationType"],"00C6":["DS","16","FrameOfReferenceTransformationMatrix"],"00C8":["LO","1","FrameOfReferenceTransformationComment"],"00C9":["SQ","1","PatientLocationCoordinatesSequence"],"00CA":["SQ","1","PatientLocationCoordinatesCodeSequence"],"00CB":["SQ","1","PatientSupportPositionSequence"]},3008:{"0000":["UL","1","GenericGroupLength"],"0010":["SQ","1","MeasuredDoseReferenceSequence"],"0012":["ST","1","MeasuredDoseDescription"],"0014":["CS","1","MeasuredDoseType"],"0016":["DS","1","MeasuredDoseValue"],"0020":["SQ","1","TreatmentSessionBeamSequence"],"0021":["SQ","1","TreatmentSessionIonBeamSequence"],"0022":["IS","1","CurrentFractionNumber"],"0024":["DA","1","TreatmentControlPointDate"],"0025":["TM","1","TreatmentControlPointTime"],"002A":["CS","1","TreatmentTerminationStatus"],"002B":["SH","1","TreatmentTerminationCode"],"002C":["CS","1","TreatmentVerificationStatus"],"0030":["SQ","1","ReferencedTreatmentRecordSequence"],"0032":["DS","1","SpecifiedPrimaryMeterset"],"0033":["DS","1","SpecifiedSecondaryMeterset"],"0036":["DS","1","DeliveredPrimaryMeterset"],"0037":["DS","1","DeliveredSecondaryMeterset"],"003A":["DS","1","SpecifiedTreatmentTime"],"003B":["DS","1","DeliveredTreatmentTime"],"0040":["SQ","1","ControlPointDeliverySequence"],"0041":["SQ","1","IonControlPointDeliverySequence"],"0042":["DS","1","SpecifiedMeterset"],"0044":["DS","1","DeliveredMeterset"],"0045":["FL","1","MetersetRateSet"],"0046":["FL","1","MetersetRateDelivered"],"0047":["FL","1-n","ScanSpotMetersetsDelivered"],"0048":["DS","1","DoseRateDelivered"],"0050":["SQ","1","TreatmentSummaryCalculatedDoseReferenceSequence"],"0052":["DS","1","CumulativeDoseToDoseReference"],"0054":["DA","1","FirstTreatmentDate"],"0056":["DA","1","MostRecentTreatmentDate"],"005A":["IS","1","NumberOfFractionsDelivered"],"0060":["SQ","1","OverrideSequence"],"0061":["AT","1","ParameterSequencePointer"],"0062":["AT","1","OverrideParameterPointer"],"0063":["IS","1","ParameterItemIndex"],"0064":["IS","1","MeasuredDoseReferenceNumber"],"0065":["AT","1","ParameterPointer"],"0066":["ST","1","OverrideReason"],"0067":["US","1","ParameterValueNumber"],"0068":["SQ","1","CorrectedParameterSequence"],"006A":["FL","1","CorrectionValue"],"0070":["SQ","1","CalculatedDoseReferenceSequence"],"0072":["IS","1","CalculatedDoseReferenceNumber"],"0074":["ST","1","CalculatedDoseReferenceDescription"],"0076":["DS","1","CalculatedDoseReferenceDoseValue"],"0078":["DS","1","StartMeterset"],"007A":["DS","1","EndMeterset"],"0080":["SQ","1","ReferencedMeasuredDoseReferenceSequence"],"0082":["IS","1","ReferencedMeasuredDoseReferenceNumber"],"0090":["SQ","1","ReferencedCalculatedDoseReferenceSequence"],"0092":["IS","1","ReferencedCalculatedDoseReferenceNumber"],"00A0":["SQ","1","BeamLimitingDeviceLeafPairsSequence"],"00B0":["SQ","1","RecordedWedgeSequence"],"00C0":["SQ","1","RecordedCompensatorSequence"],"00D0":["SQ","1","RecordedBlockSequence"],"00D1":["SQ","1","RecordedBlockSlabSequence"],"00E0":["SQ","1","TreatmentSummaryMeasuredDoseReferenceSequence"],"00F0":["SQ","1","RecordedSnoutSequence"],"00F2":["SQ","1","RecordedRangeShifterSequence"],"00F4":["SQ","1","RecordedLateralSpreadingDeviceSequence"],"00F6":["SQ","1","RecordedRangeModulatorSequence"],"0100":["SQ","1","RecordedSourceSequence"],"0105":["LO","1","SourceSerialNumber"],"0110":["SQ","1","TreatmentSessionApplicationSetupSequence"],"0116":["CS","1","ApplicationSetupCheck"],"0120":["SQ","1","RecordedBrachyAccessoryDeviceSequence"],"0122":["IS","1","ReferencedBrachyAccessoryDeviceNumber"],"0130":["SQ","1","RecordedChannelSequence"],"0132":["DS","1","SpecifiedChannelTotalTime"],"0134":["DS","1","DeliveredChannelTotalTime"],"0136":["IS","1","SpecifiedNumberOfPulses"],"0138":["IS","1","DeliveredNumberOfPulses"],"013A":["DS","1","SpecifiedPulseRepetitionInterval"],"013C":["DS","1","DeliveredPulseRepetitionInterval"],"0140":["SQ","1","RecordedSourceApplicatorSequence"],"0142":["IS","1","ReferencedSourceApplicatorNumber"],"0150":["SQ","1","RecordedChannelShieldSequence"],"0152":["IS","1","ReferencedChannelShieldNumber"],"0160":["SQ","1","BrachyControlPointDeliveredSequence"],"0162":["DA","1","SafePositionExitDate"],"0164":["TM","1","SafePositionExitTime"],"0166":["DA","1","SafePositionReturnDate"],"0168":["TM","1","SafePositionReturnTime"],"0171":["SQ","1","PulseSpecificBrachyControlPointDeliveredSequence"],"0172":["US","1","PulseNumber"],"0173":["SQ","1","BrachyPulseControlPointDeliveredSequence"],"0200":["CS","1","CurrentTreatmentStatus"],"0202":["ST","1","TreatmentStatusComment"],"0220":["SQ","1","FractionGroupSummarySequence"],"0223":["IS","1","ReferencedFractionNumber"],"0224":["CS","1","FractionGroupType"],"0230":["CS","1","BeamStopperPosition"],"0240":["SQ","1","FractionStatusSummarySequence"],"0250":["DA","1","TreatmentDate"],"0251":["TM","1","TreatmentTime"]},"300A":{"0000":["UL","1","GenericGroupLength"],"0002":["SH","1","RTPlanLabel"],"0003":["LO","1","RTPlanName"],"0004":["ST","1","RTPlanDescription"],"0006":["DA","1","RTPlanDate"],"0007":["TM","1","RTPlanTime"],"0009":["LO","1-n","TreatmentProtocols"],"000A":["CS","1","PlanIntent"],"000B":["LO","1-n","TreatmentSites"],"000C":["CS","1","RTPlanGeometry"],"000E":["ST","1","PrescriptionDescription"],"0010":["SQ","1","DoseReferenceSequence"],"0012":["IS","1","DoseReferenceNumber"],"0013":["UI","1","DoseReferenceUID"],"0014":["CS","1","DoseReferenceStructureType"],"0015":["CS","1","NominalBeamEnergyUnit"],"0016":["LO","1","DoseReferenceDescription"],"0018":["DS","3","DoseReferencePointCoordinates"],"001A":["DS","1","NominalPriorDose"],"0020":["CS","1","DoseReferenceType"],"0021":["DS","1","ConstraintWeight"],"0022":["DS","1","DeliveryWarningDose"],"0023":["DS","1","DeliveryMaximumDose"],"0025":["DS","1","TargetMinimumDose"],"0026":["DS","1","TargetPrescriptionDose"],"0027":["DS","1","TargetMaximumDose"],"0028":["DS","1","TargetUnderdoseVolumeFraction"],"002A":["DS","1","OrganAtRiskFullVolumeDose"],"002B":["DS","1","OrganAtRiskLimitDose"],"002C":["DS","1","OrganAtRiskMaximumDose"],"002D":["DS","1","OrganAtRiskOverdoseVolumeFraction"],"0040":["SQ","1","ToleranceTableSequence"],"0042":["IS","1","ToleranceTableNumber"],"0043":["SH","1","ToleranceTableLabel"],"0044":["DS","1","GantryAngleTolerance"],"0046":["DS","1","BeamLimitingDeviceAngleTolerance"],"0048":["SQ","1","BeamLimitingDeviceToleranceSequence"],"004A":["DS","1","BeamLimitingDevicePositionTolerance"],"004B":["FL","1","SnoutPositionTolerance"],"004C":["DS","1","PatientSupportAngleTolerance"],"004E":["DS","1","TableTopEccentricAngleTolerance"],"004F":["FL","1","TableTopPitchAngleTolerance"],"0050":["FL","1","TableTopRollAngleTolerance"],"0051":["DS","1","TableTopVerticalPositionTolerance"],"0052":["DS","1","TableTopLongitudinalPositionTolerance"],"0053":["DS","1","TableTopLateralPositionTolerance"],"0055":["CS","1","RTPlanRelationship"],"0070":["SQ","1","FractionGroupSequence"],"0071":["IS","1","FractionGroupNumber"],"0072":["LO","1","FractionGroupDescription"],"0078":["IS","1","NumberOfFractionsPlanned"],"0079":["IS","1","NumberOfFractionPatternDigitsPerDay"],"007A":["IS","1","RepeatFractionCycleLength"],"007B":["LT","1","FractionPattern"],"0080":["IS","1","NumberOfBeams"],"0082":["DS","3","BeamDoseSpecificationPoint"],"0083":["UI","1","ReferencedDoseReferenceUID"],"0084":["DS","1","BeamDose"],"0086":["DS","1","BeamMeterset"],"0088":["FL","1","BeamDosePointDepth"],"0089":["FL","1","BeamDosePointEquivalentDepth"],"008A":["FL","1","BeamDosePointSSD"],"008B":["CS","1","BeamDoseMeaning"],"008C":["SQ","1","BeamDoseVerificationControlPointSequence"],"008D":["FL","1","AverageBeamDosePointDepth"],"008E":["FL","1","AverageBeamDosePointEquivalentDepth"],"008F":["FL","1","AverageBeamDosePointSSD"],"0090":["CS","1","BeamDoseType"],"0091":["DS","1","AlternateBeamDose"],"0092":["CS","1","AlternateBeamDoseType"],"0093":["CS","1","DepthValueAveragingFlag"],"0094":["DS","1","BeamDosePointSourceToExternalContourDistance"],"00A0":["IS","1","NumberOfBrachyApplicationSetups"],"00A2":["DS","3","BrachyApplicationSetupDoseSpecificationPoint"],"00A4":["DS","1","BrachyApplicationSetupDose"],"00B0":["SQ","1","BeamSequence"],"00B2":["SH","1","TreatmentMachineName"],"00B3":["CS","1","PrimaryDosimeterUnit"],"00B4":["DS","1","SourceAxisDistance"],"00B6":["SQ","1","BeamLimitingDeviceSequence"],"00B8":["CS","1","RTBeamLimitingDeviceType"],"00BA":["DS","1","SourceToBeamLimitingDeviceDistance"],"00BB":["FL","1","IsocenterToBeamLimitingDeviceDistance"],"00BC":["IS","1","NumberOfLeafJawPairs"],"00BE":["DS","3-n","LeafPositionBoundaries"],"00C0":["IS","1","BeamNumber"],"00C2":["LO","1","BeamName"],"00C3":["ST","1","BeamDescription"],"00C4":["CS","1","BeamType"],"00C5":["FD","1","BeamDeliveryDurationLimit"],"00C6":["CS","1","RadiationType"],"00C7":["CS","1","HighDoseTechniqueType"],"00C8":["IS","1","ReferenceImageNumber"],"00CA":["SQ","1","PlannedVerificationImageSequence"],"00CC":["LO","1-n","ImagingDeviceSpecificAcquisitionParameters"],"00CE":["CS","1","TreatmentDeliveryType"],"00D0":["IS","1","NumberOfWedges"],"00D1":["SQ","1","WedgeSequence"],"00D2":["IS","1","WedgeNumber"],"00D3":["CS","1","WedgeType"],"00D4":["SH","1","WedgeID"],"00D5":["IS","1","WedgeAngle"],"00D6":["DS","1","WedgeFactor"],"00D7":["FL","1","TotalWedgeTrayWaterEquivalentThickness"],"00D8":["DS","1","WedgeOrientation"],"00D9":["FL","1","IsocenterToWedgeTrayDistance"],"00DA":["DS","1","SourceToWedgeTrayDistance"],"00DB":["FL","1","WedgeThinEdgePosition"],"00DC":["SH","1","BolusID"],"00DD":["ST","1","BolusDescription"],"00DE":["DS","1","EffectiveWedgeAngle"],"00E0":["IS","1","NumberOfCompensators"],"00E1":["SH","1","MaterialID"],"00E2":["DS","1","TotalCompensatorTrayFactor"],"00E3":["SQ","1","CompensatorSequence"],"00E4":["IS","1","CompensatorNumber"],"00E5":["SH","1","CompensatorID"],"00E6":["DS","1","SourceToCompensatorTrayDistance"],"00E7":["IS","1","CompensatorRows"],"00E8":["IS","1","CompensatorColumns"],"00E9":["DS","2","CompensatorPixelSpacing"],"00EA":["DS","2","CompensatorPosition"],"00EB":["DS","1-n","CompensatorTransmissionData"],"00EC":["DS","1-n","CompensatorThicknessData"],"00ED":["IS","1","NumberOfBoli"],"00EE":["CS","1","CompensatorType"],"00EF":["SH","1","CompensatorTrayID"],"00F0":["IS","1","NumberOfBlocks"],"00F2":["DS","1","TotalBlockTrayFactor"],"00F3":["FL","1","TotalBlockTrayWaterEquivalentThickness"],"00F4":["SQ","1","BlockSequence"],"00F5":["SH","1","BlockTrayID"],"00F6":["DS","1","SourceToBlockTrayDistance"],"00F7":["FL","1","IsocenterToBlockTrayDistance"],"00F8":["CS","1","BlockType"],"00F9":["LO","1","AccessoryCode"],"00FA":["CS","1","BlockDivergence"],"00FB":["CS","1","BlockMountingPosition"],"00FC":["IS","1","BlockNumber"],"00FE":["LO","1","BlockName"],"0100":["DS","1","BlockThickness"],"0102":["DS","1","BlockTransmission"],"0104":["IS","1","BlockNumberOfPoints"],"0106":["DS","2-2n","BlockData"],"0107":["SQ","1","ApplicatorSequence"],"0108":["SH","1","ApplicatorID"],"0109":["CS","1","ApplicatorType"],"010A":["LO","1","ApplicatorDescription"],"010C":["DS","1","CumulativeDoseReferenceCoefficient"],"010E":["DS","1","FinalCumulativeMetersetWeight"],"0110":["IS","1","NumberOfControlPoints"],"0111":["SQ","1","ControlPointSequence"],"0112":["IS","1","ControlPointIndex"],"0114":["DS","1","NominalBeamEnergy"],"0115":["DS","1","DoseRateSet"],"0116":["SQ","1","WedgePositionSequence"],"0118":["CS","1","WedgePosition"],"011A":["SQ","1","BeamLimitingDevicePositionSequence"],"011C":["DS","2-2n","LeafJawPositions"],"011E":["DS","1","GantryAngle"],"011F":["CS","1","GantryRotationDirection"],"0120":["DS","1","BeamLimitingDeviceAngle"],"0121":["CS","1","BeamLimitingDeviceRotationDirection"],"0122":["DS","1","PatientSupportAngle"],"0123":["CS","1","PatientSupportRotationDirection"],"0124":["DS","1","TableTopEccentricAxisDistance"],"0125":["DS","1","TableTopEccentricAngle"],"0126":["CS","1","TableTopEccentricRotationDirection"],"0128":["DS","1","TableTopVerticalPosition"],"0129":["DS","1","TableTopLongitudinalPosition"],"012A":["DS","1","TableTopLateralPosition"],"012C":["DS","3","IsocenterPosition"],"012E":["DS","3","SurfaceEntryPoint"],"0130":["DS","1","SourceToSurfaceDistance"],"0131":["FL","1","AverageBeamDosePointSourceToExternalContourDistance"],"0132":["FL","1","SourceToExternalContourDistance"],"0133":["FL","3","ExternalContourEntryPoint"],"0134":["DS","1","CumulativeMetersetWeight"],"0140":["FL","1","TableTopPitchAngle"],"0142":["CS","1","TableTopPitchRotationDirection"],"0144":["FL","1","TableTopRollAngle"],"0146":["CS","1","TableTopRollRotationDirection"],"0148":["FL","1","HeadFixationAngle"],"014A":["FL","1","GantryPitchAngle"],"014C":["CS","1","GantryPitchRotationDirection"],"014E":["FL","1","GantryPitchAngleTolerance"],"0150":["CS","1","FixationEye"],"0151":["DS","1","ChairHeadFramePosition"],"0152":["DS","1","HeadFixationAngleTolerance"],"0153":["DS","1","ChairHeadFramePositionTolerance"],"0154":["DS","1","FixationLightAzimuthalAngleTolerance"],"0155":["DS","1","FixationLightPolarAngleTolerance"],"0180":["SQ","1","PatientSetupSequence"],"0182":["IS","1","PatientSetupNumber"],"0183":["LO","1","PatientSetupLabel"],"0184":["LO","1","PatientAdditionalPosition"],"0190":["SQ","1","FixationDeviceSequence"],"0192":["CS","1","FixationDeviceType"],"0194":["SH","1","FixationDeviceLabel"],"0196":["ST","1","FixationDeviceDescription"],"0198":["SH","1","FixationDevicePosition"],"0199":["FL","1","FixationDevicePitchAngle"],"019A":["FL","1","FixationDeviceRollAngle"],"01A0":["SQ","1","ShieldingDeviceSequence"],"01A2":["CS","1","ShieldingDeviceType"],"01A4":["SH","1","ShieldingDeviceLabel"],"01A6":["ST","1","ShieldingDeviceDescription"],"01A8":["SH","1","ShieldingDevicePosition"],"01B0":["CS","1","SetupTechnique"],"01B2":["ST","1","SetupTechniqueDescription"],"01B4":["SQ","1","SetupDeviceSequence"],"01B6":["CS","1","SetupDeviceType"],"01B8":["SH","1","SetupDeviceLabel"],"01BA":["ST","1","SetupDeviceDescription"],"01BC":["DS","1","SetupDeviceParameter"],"01D0":["ST","1","SetupReferenceDescription"],"01D2":["DS","1","TableTopVerticalSetupDisplacement"],"01D4":["DS","1","TableTopLongitudinalSetupDisplacement"],"01D6":["DS","1","TableTopLateralSetupDisplacement"],"0200":["CS","1","BrachyTreatmentTechnique"],"0202":["CS","1","BrachyTreatmentType"],"0206":["SQ","1","TreatmentMachineSequence"],"0210":["SQ","1","SourceSequence"],"0212":["IS","1","SourceNumber"],"0214":["CS","1","SourceType"],"0216":["LO","1","SourceManufacturer"],"0218":["DS","1","ActiveSourceDiameter"],"021A":["DS","1","ActiveSourceLength"],"021B":["SH","1","SourceModelID"],"021C":["LO","1","SourceDescription"],"0222":["DS","1","SourceEncapsulationNominalThickness"],"0224":["DS","1","SourceEncapsulationNominalTransmission"],"0226":["LO","1","SourceIsotopeName"],"0228":["DS","1","SourceIsotopeHalfLife"],"0229":["CS","1","SourceStrengthUnits"],"022A":["DS","1","ReferenceAirKermaRate"],"022B":["DS","1","SourceStrength"],"022C":["DA","1","SourceStrengthReferenceDate"],"022E":["TM","1","SourceStrengthReferenceTime"],"0230":["SQ","1","ApplicationSetupSequence"],"0232":["CS","1","ApplicationSetupType"],"0234":["IS","1","ApplicationSetupNumber"],"0236":["LO","1","ApplicationSetupName"],"0238":["LO","1","ApplicationSetupManufacturer"],"0240":["IS","1","TemplateNumber"],"0242":["SH","1","TemplateType"],"0244":["LO","1","TemplateName"],"0250":["DS","1","TotalReferenceAirKerma"],"0260":["SQ","1","BrachyAccessoryDeviceSequence"],"0262":["IS","1","BrachyAccessoryDeviceNumber"],"0263":["SH","1","BrachyAccessoryDeviceID"],"0264":["CS","1","BrachyAccessoryDeviceType"],"0266":["LO","1","BrachyAccessoryDeviceName"],"026A":["DS","1","BrachyAccessoryDeviceNominalThickness"],"026C":["DS","1","BrachyAccessoryDeviceNominalTransmission"],"0271":["DS","1","ChannelEffectiveLength"],"0272":["DS","1","ChannelInnerLength"],"0273":["SH","1","AfterloaderChannelID"],"0274":["DS","1","SourceApplicatorTipLength"],"0280":["SQ","1","ChannelSequence"],"0282":["IS","1","ChannelNumber"],"0284":["DS","1","ChannelLength"],"0286":["DS","1","ChannelTotalTime"],"0288":["CS","1","SourceMovementType"],"028A":["IS","1","NumberOfPulses"],"028C":["DS","1","PulseRepetitionInterval"],"0290":["IS","1","SourceApplicatorNumber"],"0291":["SH","1","SourceApplicatorID"],"0292":["CS","1","SourceApplicatorType"],"0294":["LO","1","SourceApplicatorName"],"0296":["DS","1","SourceApplicatorLength"],"0298":["LO","1","SourceApplicatorManufacturer"],"029C":["DS","1","SourceApplicatorWallNominalThickness"],"029E":["DS","1","SourceApplicatorWallNominalTransmission"],"02A0":["DS","1","SourceApplicatorStepSize"],"02A1":["IS","1","ApplicatorShapeReferencedROINumber"],"02A2":["IS","1","TransferTubeNumber"],"02A4":["DS","1","TransferTubeLength"],"02B0":["SQ","1","ChannelShieldSequence"],"02B2":["IS","1","ChannelShieldNumber"],"02B3":["SH","1","ChannelShieldID"],"02B4":["LO","1","ChannelShieldName"],"02B8":["DS","1","ChannelShieldNominalThickness"],"02BA":["DS","1","ChannelShieldNominalTransmission"],"02C8":["DS","1","FinalCumulativeTimeWeight"],"02D0":["SQ","1","BrachyControlPointSequence"],"02D2":["DS","1","ControlPointRelativePosition"],"02D4":["DS","3","ControlPoint3DPosition"],"02D6":["DS","1","CumulativeTimeWeight"],"02E0":["CS","1","CompensatorDivergence"],"02E1":["CS","1","CompensatorMountingPosition"],"02E2":["DS","1-n","SourceToCompensatorDistance"],"02E3":["FL","1","TotalCompensatorTrayWaterEquivalentThickness"],"02E4":["FL","1","IsocenterToCompensatorTrayDistance"],"02E5":["FL","1","CompensatorColumnOffset"],"02E6":["FL","1-n","IsocenterToCompensatorDistances"],"02E7":["FL","1","CompensatorRelativeStoppingPowerRatio"],"02E8":["FL","1","CompensatorMillingToolDiameter"],"02EA":["SQ","1","IonRangeCompensatorSequence"],"02EB":["LT","1","CompensatorDescription"],"0302":["IS","1","RadiationMassNumber"],"0304":["IS","1","RadiationAtomicNumber"],"0306":["SS","1","RadiationChargeState"],"0308":["CS","1","ScanMode"],"0309":["CS","1","ModulatedScanModeType"],"030A":["FL","2","VirtualSourceAxisDistances"],"030C":["SQ","1","SnoutSequence"],"030D":["FL","1","SnoutPosition"],"030F":["SH","1","SnoutID"],"0312":["IS","1","NumberOfRangeShifters"],"0314":["SQ","1","RangeShifterSequence"],"0316":["IS","1","RangeShifterNumber"],"0318":["SH","1","RangeShifterID"],"0320":["CS","1","RangeShifterType"],"0322":["LO","1","RangeShifterDescription"],"0330":["IS","1","NumberOfLateralSpreadingDevices"],"0332":["SQ","1","LateralSpreadingDeviceSequence"],"0334":["IS","1","LateralSpreadingDeviceNumber"],"0336":["SH","1","LateralSpreadingDeviceID"],"0338":["CS","1","LateralSpreadingDeviceType"],"033A":["LO","1","LateralSpreadingDeviceDescription"],"033C":["FL","1","LateralSpreadingDeviceWaterEquivalentThickness"],"0340":["IS","1","NumberOfRangeModulators"],"0342":["SQ","1","RangeModulatorSequence"],"0344":["IS","1","RangeModulatorNumber"],"0346":["SH","1","RangeModulatorID"],"0348":["CS","1","RangeModulatorType"],"034A":["LO","1","RangeModulatorDescription"],"034C":["SH","1","BeamCurrentModulationID"],"0350":["CS","1","PatientSupportType"],"0352":["SH","1","PatientSupportID"],"0354":["LO","1","PatientSupportAccessoryCode"],"0355":["LO","1","TrayAccessoryCode"],"0356":["FL","1","FixationLightAzimuthalAngle"],"0358":["FL","1","FixationLightPolarAngle"],"035A":["FL","1","MetersetRate"],"0360":["SQ","1","RangeShifterSettingsSequence"],"0362":["LO","1","RangeShifterSetting"],"0364":["FL","1","IsocenterToRangeShifterDistance"],"0366":["FL","1","RangeShifterWaterEquivalentThickness"],"0370":["SQ","1","LateralSpreadingDeviceSettingsSequence"],"0372":["LO","1","LateralSpreadingDeviceSetting"],"0374":["FL","1","IsocenterToLateralSpreadingDeviceDistance"],"0380":["SQ","1","RangeModulatorSettingsSequence"],"0382":["FL","1","RangeModulatorGatingStartValue"],"0384":["FL","1","RangeModulatorGatingStopValue"],"0386":["FL","1","RangeModulatorGatingStartWaterEquivalentThickness"],"0388":["FL","1","RangeModulatorGatingStopWaterEquivalentThickness"],"038A":["FL","1","IsocenterToRangeModulatorDistance"],"038F":["FL","1-n","ScanSpotTimeOffset"],"0390":["SH","1","ScanSpotTuneID"],"0391":["IS","1-n","ScanSpotPrescribedIndices"],"0392":["IS","1","NumberOfScanSpotPositions"],"0393":["CS","1","ScanSpotReordered"],"0394":["FL","1-n","ScanSpotPositionMap"],"0395":["CS","1","ScanSpotReorderingAllowed"],"0396":["FL","1-n","ScanSpotMetersetWeights"],"0398":["FL","2","ScanningSpotSize"],"0399":["FL","2-2n","ScanSpotSizesDelivered"],"039A":["IS","1","NumberOfPaintings"],"03A0":["SQ","1","IonToleranceTableSequence"],"03A2":["SQ","1","IonBeamSequence"],"03A4":["SQ","1","IonBeamLimitingDeviceSequence"],"03A6":["SQ","1","IonBlockSequence"],"03A8":["SQ","1","IonControlPointSequence"],"03AA":["SQ","1","IonWedgeSequence"],"03AC":["SQ","1","IonWedgePositionSequence"],"0401":["SQ","1","ReferencedSetupImageSequence"],"0402":["ST","1","SetupImageComment"],"0410":["SQ","1","MotionSynchronizationSequence"],"0412":["FL","3","ControlPointOrientation"],"0420":["SQ","1","GeneralAccessorySequence"],"0421":["SH","1","GeneralAccessoryID"],"0422":["ST","1","GeneralAccessoryDescription"],"0423":["CS","1","GeneralAccessoryType"],"0424":["IS","1","GeneralAccessoryNumber"],"0425":["FL","1","SourceToGeneralAccessoryDistance"],"0426":["DS","1","IsocenterToGeneralAccessoryDistance"],"0431":["SQ","1","ApplicatorGeometrySequence"],"0432":["CS","1","ApplicatorApertureShape"],"0433":["FL","1","ApplicatorOpening"],"0434":["FL","1","ApplicatorOpeningX"],"0435":["FL","1","ApplicatorOpeningY"],"0436":["FL","1","SourceToApplicatorMountingPositionDistance"],"0440":["IS","1","NumberOfBlockSlabItems"],"0441":["SQ","1","BlockSlabSequence"],"0442":["DS","1","BlockSlabThickness"],"0443":["US","1","BlockSlabNumber"],"0450":["SQ","1","DeviceMotionControlSequence"],"0451":["CS","1","DeviceMotionExecutionMode"],"0452":["CS","1","DeviceMotionObservationMode"],"0453":["SQ","1","DeviceMotionParameterCodeSequence"],"0501":["FL","1","DistalDepthFraction"],"0502":["FL","1","DistalDepth"],"0503":["FL","2","NominalRangeModulationFractions"],"0504":["FL","2","NominalRangeModulatedRegionDepths"],"0505":["SQ","1","DepthDoseParametersSequence"],"0506":["SQ","1","DeliveredDepthDoseParametersSequence"],"0507":["FL","1","DeliveredDistalDepthFraction"],"0508":["FL","1","DeliveredDistalDepth"],"0509":["FL","2","DeliveredNominalRangeModulationFractions"],"0510":["FL","2","DeliveredNominalRangeModulatedRegionDepths"],"0511":["CS","1","DeliveredReferenceDoseDefinition"],"0512":["CS","1","ReferenceDoseDefinition"],"0600":["US","1","RTControlPointIndex"],"0601":["US","1","RadiationGenerationModeIndex"],"0602":["US","1","ReferencedDefinedDeviceIndex"],"0603":["US","1","RadiationDoseIdentificationIndex"],"0604":["US","1","NumberOfRTControlPoints"],"0605":["US","1","ReferencedRadiationGenerationModeIndex"],"0606":["US","1","TreatmentPositionIndex"],"0607":["US","1","ReferencedDeviceIndex"],"0608":["LO","1","TreatmentPositionGroupLabel"],"0609":["UI","1","TreatmentPositionGroupUID"],"060A":["SQ","1","TreatmentPositionGroupSequence"],"060B":["US","1","ReferencedTreatmentPositionIndex"],"060C":["US","1","ReferencedRadiationDoseIdentificationIndex"],"060D":["FD","1","RTAccessoryHolderWaterEquivalentThickness"],"060E":["US","1","ReferencedRTAccessoryHolderDeviceIndex"],"060F":["CS","1","RTAccessoryHolderSlotExistenceFlag"],"0610":["SQ","1","RTAccessoryHolderSlotSequence"],"0611":["LO","1","RTAccessoryHolderSlotID"],"0612":["FD","1","RTAccessoryHolderSlotDistance"],"0613":["FD","1","RTAccessorySlotDistance"],"0614":["SQ","1","RTAccessoryHolderDefinitionSequence"],"0615":["LO","1","RTAccessoryDeviceSlotID"],"0616":["SQ","1","RTRadiationSequence"],"0617":["SQ","1","RadiationDoseSequence"],"0618":["SQ","1","RadiationDoseIdentificationSequence"],"0619":["LO","1","RadiationDoseIdentificationLabel"],"061A":["CS","1","ReferenceDoseType"],"061B":["CS","1","PrimaryDoseValueIndicator"],"061C":["SQ","1","DoseValuesSequence"],"061D":["CS","1-n","DoseValuePurpose"],"061E":["FD","3","ReferenceDosePointCoordinates"],"061F":["SQ","1","RadiationDoseValuesParametersSequence"],"0620":["SQ","1","MetersetToDoseMappingSequence"],"0621":["SQ","1","ExpectedInVivoMeasurementValuesSequence"],"0622":["US","1","ExpectedInVivoMeasurementValueIndex"],"0623":["LO","1","RadiationDoseInVivoMeasurementLabel"],"0624":["FD","2","RadiationDoseCentralAxisDisplacement"],"0625":["FD","1","RadiationDoseValue"],"0626":["FD","1","RadiationDoseSourceToSkinDistance"],"0627":["FD","3","RadiationDoseMeasurementPointCoordinates"],"0628":["FD","1","RadiationDoseSourceToExternalContourDistance"],"0629":["SQ","1","RTToleranceSetSequence"],"062A":["LO","1","RTToleranceSetLabel"],"062B":["SQ","1","AttributeToleranceValuesSequence"],"062C":["FD","1","ToleranceValue"],"062D":["SQ","1","PatientSupportPositionToleranceSequence"],"062E":["FD","1","TreatmentTimeLimit"],"062F":["SQ","1","CArmPhotonElectronControlPointSequence"],"0630":["SQ","1","ReferencedRTRadiationSequence"],"0631":["SQ","1","ReferencedRTInstanceSequence"],"0632":["SQ","1","ReferencedRTPatientSetupSequence"],"0634":["FD","1","SourceToPatientSurfaceDistance"],"0635":["SQ","1","TreatmentMachineSpecialModeCodeSequence"],"0636":["US","1","IntendedNumberOfFractions"],"0637":["CS","1","RTRadiationSetIntent"],"0638":["CS","1","RTRadiationPhysicalAndGeometricContentDetailFlag"],"0639":["CS","1","RTRecordFlag"],"063A":["SQ","1","TreatmentDeviceIdentificationSequence"],"063B":["SQ","1","ReferencedRTPhysicianIntentSequence"],"063C":["FD","1","CumulativeMeterset"],"063D":["FD","1","DeliveryRate"],"063E":["SQ","1","DeliveryRateUnitSequence"],"063F":["SQ","1","TreatmentPositionSequence"],"0640":["FD","1","RadiationSourceAxisDistance"],"0641":["US","1","NumberOfRTBeamLimitingDevices"],"0642":["FD","1","RTBeamLimitingDeviceProximalDistance"],"0643":["FD","1","RTBeamLimitingDeviceDistalDistance"],"0644":["SQ","1","ParallelRTBeamDelimiterDeviceOrientationLabelCodeSequence"],"0645":["FD","1","BeamModifierOrientationAngle"],"0646":["SQ","1","FixedRTBeamDelimiterDeviceSequence"],"0647":["SQ","1","ParallelRTBeamDelimiterDeviceSequence"],"0648":["US","1","NumberOfParallelRTBeamDelimiters"],"0649":["FD","2-n","ParallelRTBeamDelimiterBoundaries"],"064A":["FD","2-n","ParallelRTBeamDelimiterPositions"],"064B":["FD","2","RTBeamLimitingDeviceOffset"],"064C":["SQ","1","RTBeamDelimiterGeometrySequence"],"064D":["SQ","1","RTBeamLimitingDeviceDefinitionSequence"],"064E":["CS","1","ParallelRTBeamDelimiterOpeningMode"],"064F":["CS","1-n","ParallelRTBeamDelimiterLeafMountingSide"],"0650":["UI","1","PatientSetupUID"],"0651":["SQ","1","WedgeDefinitionSequence"],"0652":["FD","1","RadiationBeamWedgeAngle"],"0653":["FD","1","RadiationBeamWedgeThinEdgeDistance"],"0654":["FD","1","RadiationBeamEffectiveWedgeAngle"],"0655":["US","1","NumberOfWedgePositions"],"0656":["SQ","1","RTBeamLimitingDeviceOpeningSequence"],"0657":["US","1","NumberOfRTBeamLimitingDeviceOpenings"],"0658":["SQ","1","RadiationDosimeterUnitSequence"],"0659":["SQ","1","RTDeviceDistanceReferenceLocationCodeSequence"],"065A":["SQ","1","RadiationDeviceConfigurationAndCommissioningKeySequence"],"065B":["SQ","1","PatientSupportPositionParameterSequence"],"065C":["CS","1","PatientSupportPositionSpecificationMethod"],"065D":["SQ","1","PatientSupportPositionDeviceParameterSequence"],"065E":["US","1","DeviceOrderIndex"],"065F":["US","1","PatientSupportPositionParameterOrderIndex"],"0660":["SQ","1","PatientSupportPositionDeviceToleranceSequence"],"0661":["US","1","PatientSupportPositionToleranceOrderIndex"],"0662":["SQ","1","CompensatorDefinitionSequence"],"0663":["CS","1","CompensatorMapOrientation"],"0664":["OF","1","CompensatorProximalThicknessMap"],"0665":["OF","1","CompensatorDistalThicknessMap"],"0666":["FD","1","CompensatorBasePlaneOffset"],"0667":["SQ","1","CompensatorShapeFabricationCodeSequence"],"0668":["SQ","1","CompensatorShapeSequence"],"0669":["FD","1","RadiationBeamCompensatorMillingToolDiameter"],"066A":["SQ","1","BlockDefinitionSequence"],"066B":["OF","1","BlockEdgeData"],"066C":["CS","1","BlockOrientation"],"066D":["FD","1","RadiationBeamBlockThickness"],"066E":["FD","1","RadiationBeamBlockSlabThickness"],"066F":["SQ","1","BlockEdgeDataSequence"],"0670":["US","1","NumberOfRTAccessoryHolders"],"0671":["SQ","1","GeneralAccessoryDefinitionSequence"],"0672":["US","1","NumberOfGeneralAccessories"],"0673":["SQ","1","BolusDefinitionSequence"],"0674":["US","1","NumberOfBoluses"],"0675":["UI","1","EquipmentFrameOfReferenceUID"],"0676":["ST","1","EquipmentFrameOfReferenceDescription"],"0677":["SQ","1","EquipmentReferencePointCoordinatesSequence"],"0678":["SQ","1","EquipmentReferencePointCodeSequence"],"0679":["FD","1","RTBeamLimitingDeviceAngle"],"067A":["FD","1","SourceRollAngle"],"067B":["SQ","1","RadiationGenerationModeSequence"],"067C":["SH","1","RadiationGenerationModeLabel"],"067D":["ST","1","RadiationGenerationModeDescription"],"067E":["SQ","1","RadiationGenerationModeMachineCodeSequence"],"067F":["SQ","1","RadiationTypeCodeSequence"],"0680":["DS","1","NominalEnergy"],"0681":["DS","1","MinimumNominalEnergy"],"0682":["DS","1","MaximumNominalEnergy"],"0683":["SQ","1","RadiationFluenceModifierCodeSequence"],"0684":["SQ","1","EnergyUnitCodeSequence"],"0685":["US","1","NumberOfRadiationGenerationModes"],"0686":["SQ","1","PatientSupportDevicesSequence"],"0687":["US","1","NumberOfPatientSupportDevices"],"0688":["FD","1","RTBeamModifierDefinitionDistance"],"0689":["SQ","1","BeamAreaLimitSequence"],"068A":["SQ","1","ReferencedRTPrescriptionSequence"],"0700":["UI","1","TreatmentSessionUID"],"0701":["CS","1","RTRadiationUsage"],"0702":["SQ","1","ReferencedRTRadiationSetSequence"],"0703":["SQ","1","ReferencedRTRadiationRecordSequence"],"0704":["US","1","RTRadiationSetDeliveryNumber"],"0705":["US","1","ClinicalFractionNumber"],"0706":["CS","1","RTTreatmentFractionCompletionStatus"],"0707":["CS","1","RTRadiationSetUsage"],"0708":["CS","1","TreatmentDeliveryContinuationFlag"],"0709":["CS","1","TreatmentRecordContentOrigin"],"0714":["CS","1","RTTreatmentTerminationStatus"],"0715":["SQ","1","RTTreatmentTerminationReasonCodeSequence"],"0716":["SQ","1","MachineSpecificTreatmentTerminationCodeSequence"],"0722":["SQ","1","RTRadiationSalvageRecordControlPointSequence"],"0723":["CS","1","StartingMetersetValueKnownFlag"],"0730":["ST","1","TreatmentTerminationDescription"],"0731":["SQ","1","TreatmentToleranceViolationSequence"],"0732":["CS","1","TreatmentToleranceViolationCategory"],"0733":["SQ","1","TreatmentToleranceViolationAttributeSequence"],"0734":["ST","1","TreatmentToleranceViolationDescription"],"0735":["ST","1","TreatmentToleranceViolationIdentification"],"0736":["DT","1","TreatmentToleranceViolationDateTime"],"073A":["DT","1","RecordedRTControlPointDateTime"],"073B":["US","1","ReferencedRadiationRTControlPointIndex"],"073E":["SQ","1","AlternateValueSequence"],"073F":["SQ","1","ConfirmationSequence"],"0740":["SQ","1","InterlockSequence"],"0741":["DT","1","InterlockDateTime"],"0742":["ST","1","InterlockDescription"],"0743":["SQ","1","InterlockOriginatingDeviceSequence"],"0744":["SQ","1","InterlockCodeSequence"],"0745":["SQ","1","InterlockResolutionCodeSequence"],"0746":["SQ","1","InterlockResolutionUserSequence"],"0760":["DT","1","OverrideDateTime"],"0761":["SQ","1","TreatmentToleranceViolationTypeCodeSequence"],"0762":["SQ","1","TreatmentToleranceViolationCauseCodeSequence"],"0772":["SQ","1","MeasuredMetersetToDoseMappingSequence"],"0773":["US","1","ReferencedExpectedInVivoMeasurementValueIndex"],"0774":["SQ","1","DoseMeasurementDeviceCodeSequence"],"0780":["SQ","1","AdditionalParameterRecordingInstanceSequence"],"0782":["US","1",""],"0783":["ST","1","InterlockOriginDescription"],"0784":["SQ","1","RTPatientPositionScopeSequence"],"0785":["UI","1","ReferencedTreatmentPositionGroupUID"],"0786":["US","1","RadiationOrderIndex"],"0787":["SQ","1","OmittedRadiationSequence"],"0788":["SQ","1","ReasonForOmissionCodeSequence"],"0789":["SQ","1","RTDeliveryStartPatientPositionSequence"],"078A":["SQ","1","RTTreatmentPreparationPatientPositionSequence"],"078B":["SQ","1","ReferencedRTTreatmentPreparationSequence"],"078C":["SQ","1","ReferencedPatientSetupPhotoSequence"],"078D":["SQ","1","PatientTreatmentPreparationMethodCodeSequence"],"078E":["LT","1","PatientTreatmentPreparationProcedureParameterDescription"],"078F":["SQ","1","PatientTreatmentPreparationDeviceSequence"],"0790":["SQ","1","PatientTreatmentPreparationProcedureSequence"],"0791":["SQ","1","PatientTreatmentPreparationProcedureCodeSequence"],"0792":["LT","1","PatientTreatmentPreparationMethodDescription"],"0793":["SQ","1","PatientTreatmentPreparationProcedureParameterSequence"],"0794":["LT","1","PatientSetupPhotoDescription"],"0795":["US","1","PatientTreatmentPreparationProcedureIndex"],"0796":["US","1","ReferencedPatientSetupProcedureIndex"],"0797":["SQ","1","RTRadiationTaskSequence"],"0798":["SQ","1","RTPatientPositionDisplacementSequence"],"0799":["SQ","1","RTPatientPositionSequence"],"079A":["LO","1","DisplacementReferenceLabel"],"079B":["FD","16","DisplacementMatrix"],"079C":["SQ","1","PatientSupportDisplacementSequence"],"079D":["SQ","1","DisplacementReferenceLocationCodeSequence"],"079E":["CS","1","RTRadiationSetDeliveryUsage"]},"300C":{"0000":["UL","1","GenericGroupLength"],"0002":["SQ","1","ReferencedRTPlanSequence"],"0004":["SQ","1","ReferencedBeamSequence"],"0006":["IS","1","ReferencedBeamNumber"],"0007":["IS","1","ReferencedReferenceImageNumber"],"0008":["DS","1","StartCumulativeMetersetWeight"],"0009":["DS","1","EndCumulativeMetersetWeight"],"000A":["SQ","1","ReferencedBrachyApplicationSetupSequence"],"000C":["IS","1","ReferencedBrachyApplicationSetupNumber"],"000E":["IS","1","ReferencedSourceNumber"],"0020":["SQ","1","ReferencedFractionGroupSequence"],"0022":["IS","1","ReferencedFractionGroupNumber"],"0040":["SQ","1","ReferencedVerificationImageSequence"],"0042":["SQ","1","ReferencedReferenceImageSequence"],"0050":["SQ","1","ReferencedDoseReferenceSequence"],"0051":["IS","1","ReferencedDoseReferenceNumber"],"0055":["SQ","1","BrachyReferencedDoseReferenceSequence"],"0060":["SQ","1","ReferencedStructureSetSequence"],"006A":["IS","1","ReferencedPatientSetupNumber"],"0080":["SQ","1","ReferencedDoseSequence"],"00A0":["IS","1","ReferencedToleranceTableNumber"],"00B0":["SQ","1","ReferencedBolusSequence"],"00C0":["IS","1","ReferencedWedgeNumber"],"00D0":["IS","1","ReferencedCompensatorNumber"],"00E0":["IS","1","ReferencedBlockNumber"],"00F0":["IS","1","ReferencedControlPointIndex"],"00F2":["SQ","1","ReferencedControlPointSequence"],"00F4":["IS","1","ReferencedStartControlPointIndex"],"00F6":["IS","1","ReferencedStopControlPointIndex"],"0100":["IS","1","ReferencedRangeShifterNumber"],"0102":["IS","1","ReferencedLateralSpreadingDeviceNumber"],"0104":["IS","1","ReferencedRangeModulatorNumber"],"0111":["SQ","1","OmittedBeamTaskSequence"],"0112":["CS","1","ReasonForOmission"],"0113":["LO","1","ReasonForOmissionDescription"],"0114":["SQ","1","PrescriptionOverviewSequence"],"0115":["FL","1","TotalPrescriptionDose"],"0116":["SQ","1","PlanOverviewSequence"],"0117":["US","1","PlanOverviewIndex"],"0118":["US","1","ReferencedPlanOverviewIndex"],"0119":["US","1","NumberOfFractionsIncluded"],"0120":["SQ","1","DoseCalibrationConditionsSequence"],"0121":["FD","1","AbsorbedDoseToMetersetRatio"],"0122":["FD","2","DelineatedRadiationFieldSize"],"0123":["CS","1","DoseCalibrationConditionsVerifiedFlag"],"0124":["FD","1","CalibrationReferencePointDepth"],"0125":["SQ","1","GatingBeamHoldTransitionSequence"],"0126":["CS","1","BeamHoldTransition"],"0127":["DT","1","BeamHoldTransitionDateTime"],"0128":["SQ","1","BeamHoldOriginatingDeviceSequence"]},"300E":{"0000":["UL","1","GenericGroupLength"],"0002":["CS","1","ApprovalStatus"],"0004":["DA","1","ReviewDate"],"0005":["TM","1","ReviewTime"],"0008":["PN","1","ReviewerName"]},3010:{"0000":["UL","1","GenericGroupLength"],"0001":["SQ","1","RadiobiologicalDoseEffectSequence"],"0002":["CS","1","RadiobiologicalDoseEffectFlag"],"0003":["SQ","1","EffectiveDoseCalculationMethodCategoryCodeSequence"],"0004":["SQ","1","EffectiveDoseCalculationMethodCodeSequence"],"0005":["LO","1","EffectiveDoseCalculationMethodDescription"],"0006":["UI","1","ConceptualVolumeUID"],"0007":["SQ","1","OriginatingSOPInstanceReferenceSequence"],"0008":["SQ","1","ConceptualVolumeConstituentSequence"],"0009":["SQ","1","EquivalentConceptualVolumeInstanceReferenceSequence"],"000A":["SQ","1","EquivalentConceptualVolumesSequence"],"000B":["UI","1","ReferencedConceptualVolumeUID"],"000C":["UT","1","ConceptualVolumeCombinationExpression"],"000D":["US","1","ConceptualVolumeConstituentIndex"],"000E":["CS","1","ConceptualVolumeCombinationFlag"],"000F":["ST","1","ConceptualVolumeCombinationDescription"],"0010":["CS","1","ConceptualVolumeSegmentationDefinedFlag"],"0011":["SQ","1","ConceptualVolumeSegmentationReferenceSequence"],"0012":["SQ","1","ConceptualVolumeConstituentSegmentationReferenceSequence"],"0013":["UI","1","ConstituentConceptualVolumeUID"],"0014":["SQ","1","DerivationConceptualVolumeSequence"],"0015":["UI","1","SourceConceptualVolumeUID"],"0016":["SQ","1","ConceptualVolumeDerivationAlgorithmSequence"],"0017":["ST","1","ConceptualVolumeDescription"],"0018":["SQ","1","SourceConceptualVolumeSequence"],"0019":["SQ","1","AuthorIdentificationSequence"],"001A":["LO","1","ManufacturerModelVersion"],"001B":["UC","1","DeviceAlternateIdentifier"],"001C":["CS","1","DeviceAlternateIdentifierType"],"001D":["LT","1","DeviceAlternateIdentifierFormat"],"001E":["LO","1","SegmentationCreationTemplateLabel"],"001F":["UI","1","SegmentationTemplateUID"],"0020":["US","1","ReferencedSegmentReferenceIndex"],"0021":["SQ","1","SegmentReferenceSequence"],"0022":["US","1","SegmentReferenceIndex"],"0023":["SQ","1","DirectSegmentReferenceSequence"],"0024":["SQ","1","CombinationSegmentReferenceSequence"],"0025":["SQ","1","ConceptualVolumeSequence"],"0026":["SQ","1","SegmentedRTAccessoryDeviceSequence"],"0027":["SQ","1","SegmentCharacteristicsSequence"],"0028":["SQ","1","RelatedSegmentCharacteristicsSequence"],"0029":["US","1","SegmentCharacteristicsPrecedence"],"002A":["SQ","1","RTSegmentAnnotationSequence"],"002B":["SQ","1","SegmentAnnotationCategoryCodeSequence"],"002C":["SQ","1","SegmentAnnotationTypeCodeSequence"],"002D":["LO","1","DeviceLabel"],"002E":["SQ","1","DeviceTypeCodeSequence"],"002F":["SQ","1","SegmentAnnotationTypeModifierCodeSequence"],"0030":["SQ","1","PatientEquipmentRelationshipCodeSequence"],"0031":["UI","1","ReferencedFiducialsUID"],"0032":["SQ","1","PatientTreatmentOrientationSequence"],"0033":["SH","1","UserContentLabel"],"0034":["LO","1","UserContentLongLabel"],"0035":["SH","1","EntityLabel"],"0036":["LO","1","EntityName"],"0037":["ST","1","EntityDescription"],"0038":["LO","1","EntityLongLabel"],"0039":["US","1","DeviceIndex"],"003A":["US","1","RTTreatmentPhaseIndex"],"003B":["UI","1","RTTreatmentPhaseUID"],"003C":["US","1","RTPrescriptionIndex"],"003D":["US","1","RTSegmentAnnotationIndex"],"003E":["US","1","BasisRTTreatmentPhaseIndex"],"003F":["US","1","RelatedRTTreatmentPhaseIndex"],"0040":["US","1","ReferencedRTTreatmentPhaseIndex"],"0041":["US","1","ReferencedRTPrescriptionIndex"],"0042":["US","1","ReferencedParentRTPrescriptionIndex"],"0043":["ST","1","ManufacturerDeviceIdentifier"],"0044":["SQ","1","InstanceLevelReferencedPerformedProcedureStepSequence"],"0045":["CS","1","RTTreatmentPhaseIntentPresenceFlag"],"0046":["CS","1","RadiotherapyTreatmentType"],"0047":["CS","1-n","TeletherapyRadiationType"],"0048":["CS","1-n","BrachytherapySourceType"],"0049":["SQ","1","ReferencedRTTreatmentPhaseSequence"],"004A":["SQ","1","ReferencedDirectSegmentInstanceSequence"],"004B":["SQ","1","IntendedRTTreatmentPhaseSequence"],"004C":["DA","1","IntendedPhaseStartDate"],"004D":["DA","1","IntendedPhaseEndDate"],"004E":["SQ","1","RTTreatmentPhaseIntervalSequence"],"004F":["CS","1","TemporalRelationshipIntervalAnchor"],"0050":["FD","1","MinimumNumberOfIntervalDays"],"0051":["FD","1","MaximumNumberOfIntervalDays"],"0052":["UI","1-n","PertinentSOPClassesInStudy"],"0053":["UI","1-n","PertinentSOPClassesInSeries"],"0054":["LO","1","RTPrescriptionLabel"],"0055":["SQ","1","RTPhysicianIntentPredecessorSequence"],"0056":["LO","1","RTTreatmentApproachLabel"],"0057":["SQ","1","RTPhysicianIntentSequence"],"0058":["US","1","RTPhysicianIntentIndex"],"0059":["CS","1","RTTreatmentIntentType"],"005A":["UT","1","RTPhysicianIntentNarrative"],"005B":["SQ","1","RTProtocolCodeSequence"],"005C":["ST","1","ReasonForSuperseding"],"005D":["SQ","1","RTDiagnosisCodeSequence"],"005E":["US","1","ReferencedRTPhysicianIntentIndex"],"005F":["SQ","1","RTPhysicianIntentInputInstanceSequence"],"0060":["SQ","1","RTAnatomicPrescriptionSequence"],"0061":["UT","1","PriorTreatmentDoseDescription"],"0062":["SQ","1","PriorTreatmentReferenceSequence"],"0063":["CS","1","DosimetricObjectiveEvaluationScope"],"0064":["SQ","1","TherapeuticRoleCategoryCodeSequence"],"0065":["SQ","1","TherapeuticRoleTypeCodeSequence"],"0066":["US","1","ConceptualVolumeOptimizationPrecedence"],"0067":["SQ","1","ConceptualVolumeCategoryCodeSequence"],"0068":["CS","1","ConceptualVolumeBlockingConstraint"],"0069":["SQ","1","ConceptualVolumeTypeCodeSequence"],"006A":["SQ","1","ConceptualVolumeTypeModifierCodeSequence"],"006B":["SQ","1","RTPrescriptionSequence"],"006C":["SQ","1","DosimetricObjectiveSequence"],"006D":["SQ","1","DosimetricObjectiveTypeCodeSequence"],"006E":["UI","1","DosimetricObjectiveUID"],"006F":["UI","1","ReferencedDosimetricObjectiveUID"],"0070":["SQ","1","DosimetricObjectiveParameterSequence"],"0071":["SQ","1","ReferencedDosimetricObjectivesSequence"],"0073":["CS","1","AbsoluteDosimetricObjectiveFlag"],"0074":["FD","1","DosimetricObjectiveWeight"],"0075":["CS","1","DosimetricObjectivePurpose"],"0076":["SQ","1","PlanningInputInformationSequence"],"0077":["LO","1","TreatmentSite"],"0078":["SQ","1","TreatmentSiteCodeSequence"],"0079":["SQ","1","FractionPatternSequence"],"007A":["UT","1","TreatmentTechniqueNotes"],"007B":["UT","1","PrescriptionNotes"],"007C":["IS","1","NumberOfIntervalFractions"],"007D":["US","1","NumberOfFractions"],"007E":["US","1","IntendedDeliveryDuration"],"007F":["UT","1","FractionationNotes"],"0080":["SQ","1","RTTreatmentTechniqueCodeSequence"],"0081":["SQ","1","PrescriptionNotesSequence"],"0082":["SQ","1","FractionBasedRelationshipSequence"],"0083":["CS","1","FractionBasedRelationshipIntervalAnchor"],"0084":["FD","1","MinimumHoursBetweenFractions"],"0085":["TM","1-n","IntendedFractionStartTime"],"0086":["LT","1","IntendedStartDayOfWeek"],"0087":["SQ","1","WeekdayFractionPatternSequence"],"0088":["SQ","1","DeliveryTimeStructureCodeSequence"],"0089":["SQ","1","TreatmentSiteModifierCodeSequence"],"0090":["CS","1","RoboticBaseLocationIndicator"],"0091":["SQ","1","RoboticPathNodeSetCodeSequence"],"0092":["UL","1","RoboticNodeIdentifier"],"0093":["FD","3","RTTreatmentSourceCoordinates"],"0094":["FD","1","RadiationSourceCoordinateSystemYawAngle"],"0095":["FD","1","RadiationSourceCoordinateSystemRollAngle"],"0096":["FD","1","RadiationSourceCoordinateSystemPitchAngle"],"0097":["SQ","1","RoboticPathControlPointSequence"],"0098":["SQ","1","TomotherapeuticControlPointSequence"],"0099":["FD","1-n","TomotherapeuticLeafOpenDurations"],"009A":["FD","1-n","TomotherapeuticLeafInitialClosedDurations"]},4e3:{"0000":["UL","1","GenericGroupLength"],"0010":["LT","1","Arbitrary"],4e3:["LT","1","TextComments"]},4008:{"0000":["UL","1","GenericGroupLength"],"0040":["SH","1","ResultsID"],"0042":["LO","1","ResultsIDIssuer"],"0050":["SQ","1","ReferencedInterpretationSequence"],"00FF":["CS","1","ReportProductionStatusTrial"],"0100":["DA","1","InterpretationRecordedDate"],"0101":["TM","1","InterpretationRecordedTime"],"0102":["PN","1","InterpretationRecorder"],"0103":["LO","1","ReferenceToRecordedSound"],"0108":["DA","1","InterpretationTranscriptionDate"],"0109":["TM","1","InterpretationTranscriptionTime"],"010A":["PN","1","InterpretationTranscriber"],"010B":["ST","1","InterpretationText"],"010C":["PN","1","InterpretationAuthor"],"0111":["SQ","1","InterpretationApproverSequence"],"0112":["DA","1","InterpretationApprovalDate"],"0113":["TM","1","InterpretationApprovalTime"],"0114":["PN","1","PhysicianApprovingInterpretation"],"0115":["LT","1","InterpretationDiagnosisDescription"],"0117":["SQ","1","InterpretationDiagnosisCodeSequence"],"0118":["SQ","1","ResultsDistributionListSequence"],"0119":["PN","1","DistributionName"],"011A":["LO","1","DistributionAddress"],"0200":["SH","1","InterpretationID"],"0202":["LO","1","InterpretationIDIssuer"],"0210":["CS","1","InterpretationTypeID"],"0212":["CS","1","InterpretationStatusID"],"0300":["ST","1","Impressions"],4e3:["ST","1","ResultsComments"]},4010:{"0000":["UL","1","GenericGroupLength"],"0001":["CS","1","LowEnergyDetectors"],"0002":["CS","1","HighEnergyDetectors"],"0004":["SQ","1","DetectorGeometrySequence"],1001:["SQ","1","ThreatROIVoxelSequence"],1004:["FL","3","ThreatROIBase"],1005:["FL","3","ThreatROIExtents"],1006:["OB","1","ThreatROIBitmap"],1007:["SH","1","RouteSegmentID"],1008:["CS","1","GantryType"],1009:["CS","1","OOIOwnerType"],"100A":["SQ","1","RouteSegmentSequence"],1010:["US","1","PotentialThreatObjectID"],1011:["SQ","1","ThreatSequence"],1012:["CS","1","ThreatCategory"],1013:["LT","1","ThreatCategoryDescription"],1014:["CS","1","ATDAbilityAssessment"],1015:["CS","1","ATDAssessmentFlag"],1016:["FL","1","ATDAssessmentProbability"],1017:["FL","1","Mass"],1018:["FL","1","Density"],1019:["FL","1","ZEffective"],"101A":["SH","1","BoardingPassID"],"101B":["FL","3","CenterOfMass"],"101C":["FL","3","CenterOfPTO"],"101D":["FL","6-n","BoundingPolygon"],"101E":["SH","1","RouteSegmentStartLocationID"],"101F":["SH","1","RouteSegmentEndLocationID"],1020:["CS","1","RouteSegmentLocationIDType"],1021:["CS","1-n","AbortReason"],1023:["FL","1","VolumeOfPTO"],1024:["CS","1","AbortFlag"],1025:["DT","1","RouteSegmentStartTime"],1026:["DT","1","RouteSegmentEndTime"],1027:["CS","1","TDRType"],1028:["CS","1","InternationalRouteSegment"],1029:["LO","1-n","ThreatDetectionAlgorithmAndVersion"],"102A":["SH","1","AssignedLocation"],"102B":["DT","1","AlarmDecisionTime"],1031:["CS","1","AlarmDecision"],1033:["US","1","NumberOfTotalObjects"],1034:["US","1","NumberOfAlarmObjects"],1037:["SQ","1","PTORepresentationSequence"],1038:["SQ","1","ATDAssessmentSequence"],1039:["CS","1","TIPType"],"103A":["CS","1","DICOSVersion"],1041:["DT","1","OOIOwnerCreationTime"],1042:["CS","1","OOIType"],1043:["FL","3","OOISize"],1044:["CS","1","AcquisitionStatus"],1045:["SQ","1","BasisMaterialsCodeSequence"],1046:["CS","1","PhantomType"],1047:["SQ","1","OOIOwnerSequence"],1048:["CS","1","ScanType"],1051:["LO","1","ItineraryID"],1052:["SH","1","ItineraryIDType"],1053:["LO","1","ItineraryIDAssigningAuthority"],1054:["SH","1","RouteID"],1055:["SH","1","RouteIDAssigningAuthority"],1056:["CS","1","InboundArrivalType"],1058:["SH","1","CarrierID"],1059:["CS","1","CarrierIDAssigningAuthority"],1060:["FL","3","SourceOrientation"],1061:["FL","3","SourcePosition"],1062:["FL","1","BeltHeight"],1064:["SQ","1","AlgorithmRoutingCodeSequence"],1067:["CS","1","TransportClassification"],1068:["LT","1","OOITypeDescriptor"],1069:["FL","1","TotalProcessingTime"],"106C":["OB","1","DetectorCalibrationData"],"106D":["CS","1","AdditionalScreeningPerformed"],"106E":["CS","1","AdditionalInspectionSelectionCriteria"],"106F":["SQ","1","AdditionalInspectionMethodSequence"],1070:["CS","1","AITDeviceType"],1071:["SQ","1","QRMeasurementsSequence"],1072:["SQ","1","TargetMaterialSequence"],1073:["FD","1","SNRThreshold"],1075:["DS","1","ImageScaleRepresentation"],1076:["SQ","1","ReferencedPTOSequence"],1077:["SQ","1","ReferencedTDRInstanceSequence"],1078:["ST","1","PTOLocationDescription"],1079:["SQ","1","AnomalyLocatorIndicatorSequence"],"107A":["FL","3","AnomalyLocatorIndicator"],"107B":["SQ","1","PTORegionSequence"],"107C":["CS","1","InspectionSelectionCriteria"],"107D":["SQ","1","SecondaryInspectionMethodSequence"],"107E":["DS","6","PRCSToRCSOrientation"]},"4FFE":{"0000":["UL","1","GenericGroupLength"],"0001":["SQ","1","MACParametersSequence"]},5e3:{"0000":["UL","1","GenericGroupLength"],"0005":["US","1","CurveDimensions"],"0010":["US","1","NumberOfPoints"],"0020":["CS","1","TypeOfData"],"0022":["LO","1","CurveDescription"],"0030":["SH","1-n","AxisUnits"],"0040":["SH","1-n","AxisLabels"],"0103":["US","1","DataValueRepresentation"],"0104":["US","1-n","MinimumCoordinateValue"],"0105":["US","1-n","MaximumCoordinateValue"],"0106":["SH","1-n","CurveRange"],"0110":["US","1-n","CurveDataDescriptor"],"0112":["US","1-n","CoordinateStartValue"],"0114":["US","1-n","CoordinateStepValue"],1001:["CS","1","CurveActivationLayer"],2e3:["US","1","AudioType"],2002:["US","1","AudioSampleFormat"],2004:["US","1","NumberOfChannels"],2006:["UL","1","NumberOfSamples"],2008:["UL","1","SampleRate"],"200A":["UL","1","TotalTime"],"200C":["ox","1","AudioSampleData"],"200E":["LT","1","AudioComments"],2500:["LO","1","CurveLabel"],2600:["SQ","1","CurveReferencedOverlaySequence"],2610:["US","1","CurveReferencedOverlayGroup"],3e3:["ox","1","CurveData"]},5200:{"0000":["UL","1","GenericGroupLength"],9229:["SQ","1","SharedFunctionalGroupsSequence"],9230:["SQ","1","PerFrameFunctionalGroupsSequence"]},5400:{"0000":["UL","1","GenericGroupLength"],"0100":["SQ","1","WaveformSequence"],"0110":["ox","1","ChannelMinimumValue"],"0112":["ox","1","ChannelMaximumValue"],1004:["US","1","WaveformBitsAllocated"],1006:["CS","1","WaveformSampleInterpretation"],"100A":["ox","1","WaveformPaddingValue"],1010:["ox","1","WaveformData"]},5600:{"0000":["UL","1","GenericGroupLength"],"0010":["OF","1","FirstOrderPhaseCorrectionAngle"],"0020":["OF","1","SpectroscopyData"]},6e3:{"0000":["UL","1","GenericGroupLength"],"0010":["US","1","OverlayRows"],"0011":["US","1","OverlayColumns"],"0012":["US","1","OverlayPlanes"],"0015":["IS","1","NumberOfFramesInOverlay"],"0022":["LO","1","OverlayDescription"],"0040":["CS","1","OverlayType"],"0045":["LO","1","OverlaySubtype"],"0050":["SS","2","OverlayOrigin"],"0051":["US","1","ImageFrameOrigin"],"0052":["US","1","OverlayPlaneOrigin"],"0060":["CS","1","OverlayCompressionCode"],"0061":["SH","1","OverlayCompressionOriginator"],"0062":["SH","1","OverlayCompressionLabel"],"0063":["CS","1","OverlayCompressionDescription"],"0066":["AT","1-n","OverlayCompressionStepPointers"],"0068":["US","1","OverlayRepeatInterval"],"0069":["US","1","OverlayBitsGrouped"],"0100":["US","1","OverlayBitsAllocated"],"0102":["US","1","OverlayBitPosition"],"0110":["CS","1","OverlayFormat"],"0200":["US","1","OverlayLocation"],"0800":["CS","1-n","OverlayCodeLabel"],"0802":["US","1","OverlayNumberOfTables"],"0803":["AT","1-n","OverlayCodeTableLocation"],"0804":["US","1","OverlayBitsForCodeWord"],1001:["CS","1","OverlayActivationLayer"],1100:["US","1","OverlayDescriptorGray"],1101:["US","1","OverlayDescriptorRed"],1102:["US","1","OverlayDescriptorGreen"],1103:["US","1","OverlayDescriptorBlue"],1200:["US","1-n","OverlaysGray"],1201:["US","1-n","OverlaysRed"],1202:["US","1-n","OverlaysGreen"],1203:["US","1-n","OverlaysBlue"],1301:["IS","1","ROIArea"],1302:["DS","1","ROIMean"],1303:["DS","1","ROIStandardDeviation"],1500:["LO","1","OverlayLabel"],3e3:["ox","1","OverlayData"],4e3:["LT","1","OverlayComments"]},"7F00":{"0000":["UL","1","GenericGroupLength"],"0010":["ox","1","VariablePixelData"],"0011":["US","1","VariableNextDataGroup"],"0020":["OW","1","VariableCoefficientsSDVN"],"0030":["OW","1","VariableCoefficientsSDHN"],"0040":["OW","1","VariableCoefficientsSDDN"]},"7FE0":{"0000":["UL","1","GenericGroupLength"],"0001":["OV","1","ExtendedOffsetTable"],"0002":["OV","1","ExtendedOffsetTableLengths"],"0008":["OF","1","FloatPixelData"],"0009":["OD","1","DoubleFloatPixelData"],"0010":["ox","1","PixelData"],"0020":["OW","1","CoefficientsSDVN"],"0030":["OW","1","CoefficientsSDHN"],"0040":["OW","1","CoefficientsSDDN"]},FFFA:{"0000":["UL","1","GenericGroupLength"],FFFA:["SQ","1","DigitalSignaturesSequence"]},FFFC:{"0000":["UL","1","GenericGroupLength"],FFFC:["OB","1","DataSetTrailingPadding"]},FFFE:{"0000":["UL","1","GenericGroupLength"],E000:["NONE","1","Item"],E00D:["NONE","1","ItemDelimitationItem"],E0DD:["NONE","1","SequenceDelimitationItem"]}};function Z(e,t){j[e]=t}const _={"0000":"Command","0002":"Meta Element","0004":"File Set","0008":"Identifying","0009":"SPI Identifying","0010":"Patient","0012":"Clinical Trial","0018":"Acquisition","0019":"SPI Acquisition","0020":"Image","0021":"SPI Image","0022":"Ophtalmology","0028":"Image Presentation","0032":"Study","0038":"Visit","003A":"Waveform","0040":"Procedure","0042":"Encapsulated Document","0050":"Device Informations","0054":"Nuclear Medicine","0060":"Histogram","0070":"Presentation State","0072":"Hanging Protocol","0088":"Storage","0100":"Authorization","0400":"Digital Signature",1e3:"Code Table",1010:"Zonal Map",2e3:"Film Session",2010:"Film Box",2020:"Image Box",2030:"Annotation",2040:"Overlay Box",2050:"Presentation LUT",2100:"Print Job",2110:"Printer",2120:"Queue",2130:"Print Content",2200:"Media Creation",3002:"RT Image",3004:"RT Dose",3006:"RT StructureSet",3008:"RT Treatment","300A":"RT Plan","300C":"RT Relationship","300E":"RT Approval",4e3:"Text",4008:"Results","4FFE":"MAC Parameters",5e3:"Curve",5002:"Curve",5004:"Curve",5006:"Curve",5008:"Curve","500A":"Curve","500C":"Curve","500E":"Curve",5400:"Waveform Data",6e3:"Overlays",6002:"Overlays",6004:"Overlays",6008:"Overlays","600A":"Overlays","600C":"Overlays","600E":"Overlays",FFFC:"Generic","7FE0":"Pixel Data",FFFF:"Unknown"},K={OB:!0,OD:!0,OF:!0,OL:!0,OV:!0,OW:!0,SQ:!0,SV:!0,UC:!0,UN:!0,UR:!0,UT:!0,UV:!0,ox:!0};function J(e){return void 0!==K[e]}const $={SH:!0,LO:!0,UC:!0,ST:!0,LT:!0,UT:!0,PN:!0};function ee(e){return void 0!==$[e]}const te={AE:"string",AS:"string",AT:void 0,CS:"string",DA:"string",DS:"string",DT:"string",FL:"Float32",FD:"Float64",IS:"string",LO:"string",LT:"string",OB:"Uint8",OD:"Uint64",OF:"Uint32",OL:"Uint32",OV:"Uint64",OW:"Uint16",PN:"string",SH:"string",SL:"Int32",SQ:void 0,SS:"Int16",ST:"string",SV:"Int64",TM:"string",UC:"string",UI:"string",UL:"Uint32",UN:"Uint8",UR:"string",US:"Uint16",UT:"string",UV:"Uint64"},ne={"1.2.840.10008.1.2":"Implicit VR Little Endian","1.2.840.10008.1.2.1":"Explicit VR Little Endian","1.2.840.10008.1.2.1.98":"Encapsulated Uncompressed Explicit VR Little Endian","1.2.840.10008.1.2.1.99":"Deflated Explicit VR Little Endian","1.2.840.10008.1.2.2":"Explicit VR Big Endian (Retired)","1.2.840.10008.1.2.4.50":"JPEG Baseline (Process 1)","1.2.840.10008.1.2.4.51":"JPEG Extended (Process 2 & 4)","1.2.840.10008.1.2.4.52":"JPEG Extended (Process 3 & 5) (Retired)","1.2.840.10008.1.2.4.53":"JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) (Retired)","1.2.840.10008.1.2.4.54":"JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9) (Retired)","1.2.840.10008.1.2.4.55":"JPEG Full Progression, Non-Hierarchical (Process 10 & 12) (Retired)","1.2.840.10008.1.2.4.56":"JPEG Full Progression, Non-Hierarchical (Process 11 & 13) (Retired)","1.2.840.10008.1.2.4.57":"JPEG Lossless, Non-Hierarchical (Process 14)","1.2.840.10008.1.2.4.58":"JPEG Lossless, Non-Hierarchical (Process 15) (Retired)","1.2.840.10008.1.2.4.59":"JPEG Extended, Hierarchical (Process 16 & 18) (Retired)","1.2.840.10008.1.2.4.60":"JPEG Extended, Hierarchical (Process 17 & 19) (Retired)","1.2.840.10008.1.2.4.61":"JPEG Spectral Selection, Hierarchical (Process 20 & 22) (Retired)","1.2.840.10008.1.2.4.62":"JPEG Spectral Selection, Hierarchical (Process 21 & 23) (Retired)","1.2.840.10008.1.2.4.63":"JPEG Full Progression, Hierarchical (Process 24 & 26) (Retired)","1.2.840.10008.1.2.4.64":"JPEG Full Progression, Hierarchical (Process 25 & 27) (Retired)","1.2.840.10008.1.2.4.65":"JPEG Lossless, Hierarchical (Process 28) (Retired)","1.2.840.10008.1.2.4.66":"JPEG Lossless, Hierarchical (Process 29) (Retired)","1.2.840.10008.1.2.4.70":"JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1])","1.2.840.10008.1.2.4.80":"JPEG-LS Lossless Image Compression","1.2.840.10008.1.2.4.81":"JPEG-LS Lossy (Near-Lossless) Image Compression","1.2.840.10008.1.2.4.90":"JPEG 2000 Image Compression (Lossless Only)","1.2.840.10008.1.2.4.91":"JPEG 2000 Image Compression","1.2.840.10008.1.2.4.92":"JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)","1.2.840.10008.1.2.4.93":"JPEG 2000 Part 2 Multi-component Image Compression","1.2.840.10008.1.2.4.94":"JPIP Referenced","1.2.840.10008.1.2.4.95":"JPIP Referenced Deflate","1.2.840.10008.1.2.4.100":"MPEG2 Main Profile / Main Level","1.2.840.10008.1.2.4.101":"MPEG2 Main Profile / High Level","1.2.840.10008.1.2.4.102":"MPEG-4 AVC/H.264 High Profile / Level 4.1","1.2.840.10008.1.2.4.103":"MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1","1.2.840.10008.1.2.4.104":"MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video","1.2.840.10008.1.2.4.105":"MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video","1.2.840.10008.1.2.4.106":"MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2","1.2.840.10008.1.2.4.107":"HEVC/H.265 Main Profile / Level 5.1","1.2.840.10008.1.2.4.108":"HEVC/H.265 Main 10 Profile / Level 5.1","1.2.840.10008.1.2.5":"RLE Lossless","1.2.840.10008.1.2.6.1":"RFC 2557 MIME encapsulation (Retired)","1.2.840.10008.1.2.6.2":"XML Encoding (Retired)","1.2.840.10008.1.2.7.1":"SMPTE ST 2110-20 Uncompressed Progressive Active Video","1.2.840.10008.1.2.7.2":"SMPTE ST 2110-20 Uncompressed Interlaced Active Video","1.2.840.10008.1.2.7.3":"SMPTE ST 2110-30 PCM Digital Audio","1.2.840.10008.1.20":"Papyrus 3 Implicit VR Little Endian (Retired)"},ie="1.2.840.10008.1.2",re="1.2.840.10008.1.2.1",oe="1.2.840.10008.1.2.2",ae="1.2.840.10008.1.2.4.50",se="1.2.840.10008.1.2.4.51",le="1.2.840.10008.1.2.4.57",ce="1.2.840.10008.1.2.4.70",ue="1.2.840.10008.1.2.5";class de{#L;#P;constructor(e,t){if(!e||void 0===e)throw new Error("Cannot create tag with no group.");if(4!==e.length)throw new Error("Cannot create tag with badly sized group: "+e);if(!t||void 0===t)throw new Error("Cannot create tag with no element.");if(4!==t.length)throw new Error("Cannot create tag with badly sized element: "+t);this.#L=e,this.#P=t}getGroup(){return this.#L}getElement(){return this.#P}toString(){return this.getKey()+": "+this.getNameFromDictionary()}equals(e){return null!=e&&this.#L===e.getGroup()&&this.#P===e.getElement()}getKey(){return this.#L+this.#P}getGroupName(){return _[this.#L]}isWithVR(){return!("FFFE"===this.#L&&("E000"===this.#P||"E00D"===this.#P||"E0DD"===this.#P))}isPrivate(){return parseInt(this.#L,16)%2==1}#w(){let e;return void 0!==j[this.#L]&&void 0!==j[this.#L][this.#P]&&(e=j[this.#L][this.#P]),e}getVrFromDictionary(){let e;const t=this.#w();return void 0!==t&&(e=t[0]),e}getNameFromDictionary(){let e;const t=this.#w();return void 0!==t&&(e=t[2]),e}}function he(e,t){let n=parseInt(e.getGroup(),16)-parseInt(t.getGroup(),16);return 0===n&&(n=parseInt(e.getElement(),16)-parseInt(t.getElement(),16)),n}function Se(e){if(!e||void 0===e)throw new Error("Cannot create tag with no key.");if(8!==e.length)throw new Error("Cannot create tag with badly sized key: "+e);return new de(e.substring(0,4),e.substring(4,8))}function ge(){return new de("FFFE","E000")}function pe(e){return"FFFEE000"===e.getKey()}function me(e){return"FFFEE00D"===e.getKey()}function fe(e){return"FFFEE0DD"===e.getKey()}function De(){return new de("7FE0","0010")}function ye(e){return"7FE00010"===e.getKey()}function Ce(e){if(null==e)return null;let t=null,n=null;const i=j,r=Object.keys(i);let o,a=null,s=!1;for(let o=0,l=r.length;o<l;++o){t=r[o],a=Object.keys(i[t]);for(let r=0,o=a.length;r<o;++r)if(n=a[r],i[t][n][2]===e){s=!0;break}if(s)break}return s&&(o=new de(t,n)),o}class ve{vr;value;tag;vl;undefinedLength;startOffset;endOffset;items;constructor(e){this.vr=e}}function Ie(e,t){let n;return void 0!==e[t]&&(n=e[t].value[0]),n}function Te(e){const t=e.byteLength,n=new Uint8Array(e.buffer,e.byteOffset,t),i=e.BYTES_PER_ELEMENT;let r;for(let e=0;e<t;e+=i)for(let t=e+i-1,o=e;t>o;t--,o++)r=n[o],n[o]=n[t],n[t]=r}class Le{#O;#A=!0;#b=function(){return new Int8Array(new Int16Array([1]).buffer)[0]>0}();#x;#R;constructor(e,t){this.#O=e,void 0!==t&&(this.#A=t),this.#x=this.#A!==this.#b,this.#R=new DataView(e)}readUint16(e){return this.#R.getUint16(e,this.#A)}readInt16(e){return this.#R.getInt16(e,this.#A)}readUint32(e){return this.#R.getUint32(e,this.#A)}readBigUint64(e){return this.#R.getBigUint64(e,this.#A)}readInt32(e){return this.#R.getInt32(e,this.#A)}readBigInt64(e){return this.#R.getBigInt64(e,this.#A)}readFloat32(e){return this.#R.getFloat32(e,this.#A)}readFloat64(e){return this.#R.getFloat64(e,this.#A)}readBinaryArray(e,t){const n=new Uint8Array(this.#O,e,t),i=8*n.length,r=new Uint8Array(i);let o=0,a=0;for(let e=0;e<i;++e)o=e%8,a=Math.floor(e/8),r[e]=255*!!(n[a]&1<<o);return r}readUint8Array(e,t){return new Uint8Array(this.#O,e,t)}readInt8Array(e,t){return new Int8Array(this.#O,e,t)}readUint16Array(e,t){const n=Uint16Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Uint16Array(this.#O,e,i),this.#x&&Te(r);else{r=new Uint16Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readUint16(t),t+=n}return r}readInt16Array(e,t){const n=Int16Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Int16Array(this.#O,e,i),this.#x&&Te(r);else{r=new Int16Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readInt16(t),t+=n}return r}readUint32Array(e,t){const n=Uint32Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Uint32Array(this.#O,e,i),this.#x&&Te(r);else{r=new Uint32Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readUint32(t),t+=n}return r}readUint64Array(e,t){const n=BigUint64Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new BigUint64Array(this.#O,e,i),this.#x&&Te(r);else{r=new BigUint64Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readBigUint64(t),t+=n}return r}readInt32Array(e,t){const n=Int32Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Int32Array(this.#O,e,i),this.#x&&Te(r);else{r=new Int32Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readInt32(t),t+=n}return r}readInt64Array(e,t){const n=BigInt64Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new BigInt64Array(this.#O,e,i),this.#x&&Te(r);else{r=new BigInt64Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readBigInt64(t),t+=n}return r}readFloat32Array(e,t){const n=Float32Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Float32Array(this.#O,e,i),this.#x&&Te(r);else{r=new Float32Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readFloat32(t),t+=n}return r}readFloat64Array(e,t){const n=Float64Array.BYTES_PER_ELEMENT,i=t/n;let r=null;if(e%n==0)r=new Float64Array(this.#O,e,i),this.#x&&Te(r);else{r=new Float64Array(i);let t=e;for(let e=0;e<i;++e)r[e]=this.readFloat64(t),t+=n}return r}readHex(e){const t=this.readUint16(e).toString(16);return"0000".substring(0,4-t.length)+t.toUpperCase()}}function Pe(){return"0.35.0-beta.11"}function we(e){return!(e.byteLength<132)&&"DICM"===new Uint8Array(e,128,4).reduce((function(e,t){return e+String.fromCharCode(t)}),"")}const Oe=String.fromCharCode("u200B");class Ae{decode(e){let t="";for(let n=0,i=e.length;n<i;++n)t+=String.fromCharCode(e[n]);return t}}function be(e){if(!e)return null;const t={L:"R",R:"L",A:"P",P:"A",H:"F",F:"H"};let n="";for(let i=0;i<e.length;i++){const r=t[e.substring(i,i+1)];r&&(n+=r)}return n}function xe(e){return e===ie}function Re(e){return e===oe}function Fe(e){return e===ae||e===se}function Ee(e){return e===le||e===ce}function qe(e){return null!==e.match(/1.2.840.10008.1.2.4.9/)}function Ue(e){return e===ue}function Me(e,t,n){let i=null;try{1===e||8===e?i=0===t?new Uint8Array(n):new Int8Array(n):16===e?i=0===t?new Uint16Array(n):new Int16Array(n):32===e&&(i=0===t?new Uint32Array(n):new Int32Array(n))}catch(e){if(e instanceof RangeError){const e=Math.floor(Math.log(n)/Math.log(2));c.error("Cannot allocate array of size: "+n+" (>2^"+e+").")}}return i}function Qe(e,t){return t?8:J(e)?12:8}const Ve="00280008",Ne="00280100",Be="00280103",Ge="7FE00010";class ke{#F={};#E;#q=new Ae;#U=this.#q;#M(e){return this.#q.decode(e)}#Q(e){return this.#U.decode(e)}getDefaultCharacterSet(){return this.#E}setDefaultCharacterSet(e){this.#E=e}setDecoderCharacterSet(e){this.#U=new TextDecoder(e)}getDicomElements(){return this.#F}safeGet(e){return Ie(this.#F,e)}#V(e,t){const n=e.readHex(t);t+=Uint16Array.BYTES_PER_ELEMENT;const i=e.readHex(t);return t+=Uint16Array.BYTES_PER_ELEMENT,{tag:new de(n,i),endOffset:t}}#N(e,t,n){const i={};let r=this.#B(e,t,n);if(t=r.endOffset,fe(r.tag))return{data:i,endOffset:r.endOffset,isSeqDelim:!0};if(i[r.tag.getKey()]={tag:r.tag,vr:"NONE",vl:r.vl,undefinedLength:r.undefinedLength},r.undefinedLength){let o=!1;for(;!o;)r=this.#B(e,t,n),t=r.endOffset,o=me(r.tag),o||(i[r.tag.getKey()]=r)}else{const o=t;for(t-=r.vl;t<o;)r=this.#B(e,t,n),t=r.endOffset,i[r.tag.getKey()]=r}return{data:i,endOffset:t,isSeqDelim:!1}}#G(e,t,n){const i=[];let r=this.#B(e,t,n);const o=r.vl;t=r.endOffset;let a=!1;for(;!a;)r=this.#B(e,t,n),t=r.endOffset,a=fe(r.tag),a||(r.vr="OB",i.push(r));return{data:i,endOffset:t,offsetTableVl:o}}#B(e,t,n,i){const r=this.#V(e,t),o=r.tag;if(void 0!==i&&o.equals(i)){const e=new ve("");return e.tag=o,e}t=r.endOffset;let a=null,s=!1;o.isWithVR()?n?(a=o.getVrFromDictionary(),void 0===a&&(a="UN"),s=!0):(a=this.#M(e.readUint8Array(t,2)),t+=2*Uint8Array.BYTES_PER_ELEMENT,s=J(a),s&&(t+=2*Uint8Array.BYTES_PER_ELEMENT)):(a="NONE",s=!0),function(e){return Object.keys(te).concat(["NONE","ox","xx","xs"]).includes(e)}(a)||(c.warn("Unknown VR: "+a+" (for tag "+o.getKey()+"), treating as 'UN'"),a="UN");let l=0;s?(l=e.readUint32(t),t+=Uint32Array.BYTES_PER_ELEMENT):(l=e.readUint16(t),t+=Uint16Array.BYTES_PER_ELEMENT);let u=!1;4294967295===l&&(u=!0,l=0),o.isPrivate()&&"UN"===a&&0===l&&(a="SQ");let d,h=t,S=h+l;if(ye(o)&&u){const i=this.#G(e,t,n);t=i.endOffset,h+=i.offsetTableVl,d=i.data,S=t,l=t-h}else if("SQ"===a){let i;if(d=[],u){let r=!1;for(;!r;)i=this.#N(e,t,n),r=i.isSeqDelim,t=i.endOffset,r||d.push(i.data);S=t,l=t-h}else if(0!==l){const r=t+l;for(;t<r;)i=this.#N(e,t,n),d.push(i.data),t=i.endOffset;S=t,l=t-h}}const g=new ve(a);return g.tag=o,g.vl=l,g.startOffset=h,g.endOffset=S,u&&(g.undefinedLength=u),d&&(g.items=d),g}#k(e,t,n,i){const r=e.tag,o=e.vl,a=e.vr,s=e.startOffset;let l=null;const u=te[a];if(ye(r))if(e.undefinedLength){l=[];for(let r=0;r<e.items.length;++r)l.push(this.#k(e.items[r],t,n,i));delete e.items}else if(i>8&&"OB"===a&&(c.warn("Reading DICOM pixel data with bitsAllocated>8 and OB VR, treating as OW"),e.vr="OW"),l=[],1===i)l.push(t.readBinaryArray(s,o));else if(8===i)0===n?l.push(t.readUint8Array(s,o)):l.push(t.readInt8Array(s,o));else{if(16!==i)throw new Error("Unsupported bits allocated: "+i);0===n?l.push(t.readUint16Array(s,o)):l.push(t.readInt16Array(s,o))}else if(void 0!==u)if("Uint8"===u)l=t.readUint8Array(s,o);else if("Uint16"===u)l=t.readUint16Array(s,o),"O"!==a[0]&&(l=Array.from(l));else if("Uint32"===u)l=t.readUint32Array(s,o),"O"!==a[0]&&(l=Array.from(l));else if("Uint64"===u)l=t.readUint64Array(s,o);else if("Int16"===u)l=Array.from(t.readInt16Array(s,o));else if("Int32"===u)l=Array.from(t.readInt32Array(s,o));else if("Int64"===u)l=t.readInt64Array(s,o);else if("Float32"===u)l=Array.from(t.readFloat32Array(s,o));else if("Float64"===u)l=Array.from(t.readFloat64Array(s,o));else{if("string"!==u)throw new Error("Unknown VR type: "+u);{const e=t.readUint8Array(s,o);l=ee(a)?this.#Q(e):this.#M(e),l=function(e){let t=e;const n=e.length-1;return e[n]===Oe&&(t=e.substring(0,n)),t=t.trim(),t}(l).split("\\")}}else if("xx"===a)l=Array.from(t.readUint16Array(s,o));else if("ox"===a)l=8===i?0===n?Array.from(t.readUint8Array(s,o)):Array.from(t.readInt8Array(s,o)):0===n?Array.from(t.readUint16Array(s,o)):Array.from(t.readInt16Array(s,o));else if("xs"===a)l=0===n?Array.from(t.readUint16Array(s,o)):Array.from(t.readInt16Array(s,o));else if("AT"===a){const e=t.readUint16Array(s,o);l=[];for(let t=0,n=e.length;t<n;t+=2){const n=e[t].toString(16),i=e[t+1].toString(16);let r="(";r+="0000".substring(0,4-n.length)+n.toUpperCase(),r+=",",r+="0000".substring(0,4-i.length)+i.toUpperCase(),r+=")",l.push(r)}}else if("SQ"===a){l=[];for(let r=0;r<e.items.length;++r){const o=e.items[r],a={},s=Object.keys(o);let c=i,u=n;for(let e=0;e<s.length;++e){let n=o[Ne];void 0!==n&&void 0!==n.value&&(c=n.value[0]),n=o[Be],void 0!==n&&void 0!==n.value&&(u=n.value[0]);const i=o[s[e]];i.value=this.#k(i,t,u,c),delete i.tag,delete i.vl,delete i.startOffset,delete i.endOffset,a[s[e]]=i}l.push(a)}delete e.items}else"NONE"===a||c.warn("Unknown VR: "+a+" (for tag "+e.tag.getKey()+")"),l=[];return l}#H(e,t,n,i){const r=Object.keys(e);for(let o=0;o<r.length;++o){const a=e[r[o]];void 0===a.value&&(a.value=this.#k(a,t,n,i)),delete a.tag,delete a.vl,delete a.startOffset,delete a.endOffset}}parse(e,t){let n=0,i="",r=null;const o=new Le(e);let a=new Le(e);n=128;const s=this.#M(o.readUint8Array(n,4));if(n+=4*Uint8Array.BYTES_PER_ELEMENT,"DICM"===s){r=this.#B(o,n,!1),r.value=this.#k(r,o),n=r.endOffset,this.#F[r.tag.getKey()]=r;const e=n+r.value[0];for(;n<e;)r=this.#B(o,n,!1),n=r.endOffset,this.#F[r.tag.getKey()]=r;if(r=this.#F["00020010"],void 0===r)throw new Error("Not a valid DICOM file (no TransferSyntaxUID found)");r.value=this.#k(r,o),i=r.value[0]}else{c.warn("No DICM prefix, trying to guess tansfer syntax."),r=this.#B(a,0,!1);const e=function(e){const t="0008",n=e.tag.getGroup();if("0800"!==n&&n!==t)throw new Error("Not a valid DICOM file (no magic DICM word found and first element not in 0008 group)");const i=e.vr,r=i.charCodeAt(0),o=i.charCodeAt(1),a=!(r>=65&&r<=90&&o>=65&&o<=90);let s=null;if(n===t)s=a?ie:re;else{if(a)throw new Error("Not a valid DICOM file (no magic DICM word foundand implicit VR big endian detected)");s=oe}const l=new ve("UI");return l.tag=new de("0002","0010"),l.value=[s],l.vl=l.value[0].length,l.startOffset=e.startOffset,l.endOffset=l.startOffset+l.vl,l}(r);this.#F[e.tag.getKey()]=e,i=e.value[0],n=0}if(!function(e){return e===ie||e===re||e===oe||Fe(e)||Ee(e)||qe(e)||Ue(e)}(i))throw new Error("Unsupported DICOM transfer syntax: '"+i+"' ("+function(e){let t="Unknown";return void 0!==ne[e]&&(t=ne[e]),t}(i)+")");let l=!1;xe(i)&&(l=!0),Re(i)&&(a=new Le(e,!1));let u=!1;for(;n<e.byteLength;){if(r=this.#B(a,n,l,t),void 0!==t&&r.tag.equals(t)){u=!0;break}n=r.endOffset;const e=r.tag.getKey();void 0===this.#F[e]?this.#F[e]=r:c.warn("Not saving duplicate tag: "+e)}if(isNaN(n))throw new Error("Problem while parsing, bad offset");u||e.byteLength===n||c.warn("Did not reach the end of the buffer: "+n+" != "+e.byteLength);let d=0,h=16;if(void 0!==this.#F[Ge]&&(r=this.#F[Be],void 0!==r?(r.value=this.#k(r,a),d=r.value[0]):c.warn("Reading DICOM pixel data with default pixelRepresentation."),r=this.#F[Ne],void 0!==r?(r.value=this.#k(r,a),h=r.value[0]):c.warn("Reading DICOM pixel data with default bitsAllocated.")),void 0!==this.#E&&this.setDecoderCharacterSet(this.#E),r=this.#F["00080005"],void 0!==r){let e;r.value=this.#k(r,a),1===r.value.length?e=r.value[0]:(e=r.value[1],c.warn("Unsupported character set with code extensions: '"+e+"'.")),this.setDecoderCharacterSet(function(e){let t="utf-8";return"ISO_IR 100"===e?t="iso-8859-1":"ISO_IR 101"===e?t="iso-8859-2":"ISO_IR 109"===e?t="iso-8859-3":"ISO_IR 110"===e?t="iso-8859-4":"ISO_IR 144"===e?t="iso-8859-5":"ISO_IR 127"===e?t="iso-8859-6":"ISO_IR 126"===e?t="iso-8859-7":"ISO_IR 138"===e?t="iso-8859-8":"ISO_IR 148"===e?t="iso-8859-9":"ISO_IR 13"===e?t="shift-jis":"ISO_IR 166"===e?t="iso-8859-11":"ISO 2022 IR 87"===e?t="iso-2022-jp":"ISO 2022 IR 149"===e||"ISO 2022 IR 58"===e||("ISO_IR 192"===e?t="utf-8":"GB18030"===e?t="gb18030":"GB2312"===e?t="gb2312":"GBK"===e&&(t="chinese")),t}(e))}if(this.#H(this.#F,a,d,h),r=this.#F[Ge],void 0!==r&&r.undefinedLength){let e=1;void 0!==this.#F[Ve]&&(e=Number(this.#F[Ve].value[0]));const t=r.value;if(t.length>1&&t.length>e){const n=t.length/e,i=[];let o=0;for(let r=0;r<e;++r){o=r*n;let e=0;for(let i=0;i<n;++i)e+=t[o+i].length;const a=new t[0].constructor(e);let s=0;for(let e=0;e<n;++e)a.set(t[o+e],s),s+=t[o+e].length;i[r]=a}r.value=i}}}}class He{#z={};add(e,t){void 0===this.#z[e]&&(this.#z[e]=[]),this.#z[e].push(t)}remove(e,t){if(void 0===this.#z[e])return;let n=0;for(let i=0;i<this.#z[e].length;++i)this.#z[e][i]===t&&(++n,this.#z[e].splice(i,1));0===n&&c.debug("No callback found on remove listener for type "+e)}fireEvent=e=>{if(void 0===this.#z[e.type])return;const t=this.#z[e.type].slice();for(let n=0;n<t.length;++n)t[n](e)}}function ze(e,t,n,i,r,o,a,s){void 0===a&&(a=!1),void 0===s&&(s=!1);let l=t;a?(o*=-1,s?l-=(r-1)*i:i*=-1):s&&(l+=(r-1)*i,i*=-1);const c=o-r*i;let u=0,d=0;return{next:function(){if(u<n){const t={value:e(l),done:!1,index:l};return l+=i,++u,++d,d===r&&(d=0,l+=c),t}return{done:!0,index:l}}}}function We(e){const t=[];let n=e.next();for(;!n.done;)t.push(n.value),n=e.next();return t}function Ye(e,t,n,i){const r=e.getGeometry().getSize();let o=2;i&&void 0!==i&&(o=i.getColAbsMax(2).index);const a=t.getValues(),l=new s(a.map((function(e,t){return t===o||t>2?e:0})));let c=r.indexToOffset(l);void 0===n&&(n=!1);let u=null;u=n?function(t){return e.getRescaledValueAtOffset(t)}:function(t){return e.getValueAtOffset(t)};const d=r.get(0),h=r.get(1),S=r.get(2);let g=r.getDimSize(2);const p=e.getNumberOfComponents(),m=1===e.getPlanarConfiguration(),f=function(e,t,n,i,r,o,a,s){return 1===p?ze(e,t,n,i,r,o,a,s):3===p?function(e,t,n,i,r,o,a,s,l){const c=[];return l?(c.push(ze(e,t,n,i,r,o,a,s)),c.push(ze(e,t+n*i,n,i,r,o,a,s)),c.push(ze(e,t+2*n*i,n,i,r,o,a,s))):(i*=3,o*=3,c.push(ze(e,t,n,i,r,o,a,s)),c.push(ze(e,t+1,n,i,r,o,a,s)),c.push(ze(e,t+2,n,i,r,o,a,s))),{next:function(){const e=c[0].next(),t=c[1].next(),n=c[2].next();return e.done?{done:!0,index:n.index}:{value:[e.value,t.value,n.value],done:!1,index:[e.index,t.index,n.index]}}}}(e,3*t,n,i,r,o,a,s,m):void 0};let D=null;if(i&&void 0!==i){const e=i.getColAbsMax(0),t=i.getColAbsMax(2),n=!1,r=!1;let o=null;if(2===t.index)o=d*h,D=0===e.index?f(u,c,o,1,d,d,n,r):f(u,c,o,d,h,1,n,r);else if(0===t.index)o=S*h,D=1===e.index?f(u,c,o,d,h,g,n,r):f(u,c,o,g,S,d,n,r);else{if(1!==t.index)throw new Error("Unknown direction: "+t.index);o=S*d,D=0===e.index?f(u,c,o,1,d,g,n,r):f(u,c,o,g,S,1,n,r)}}else if(1===e.getNumberOfComponents())D=function(e,t,n,i){void 0===i&&(i=1);let r=t;return{next:function(){if(r<n){const t={value:e(r),done:!1,index:r};return r+=i,t}return{done:!0,index:n}}}}(u,c,c+g);else{if(3!==e.getNumberOfComponents())throw new Error("Unsupported number of components: "+e.getNumberOfComponents());c*=3,g*=3,D=function(e,t,n,i,r){void 0===i&&(i=1),void 0===r&&(r=!1);let o=t,a=1;r?a=(n-t)/3:i*=3;let s=o+a,l=o+2*a;return{next:function(){if(o<n){const t={value:[e(o),e(s),e(l)],done:!1,index:[o,s,l]};return o+=i,s+=i,l+=i,t}return{done:!0,index:[n]}}}}(u,c,c+g,1,m)}return D}function Xe(e,t){let n=0,i=0;return{next:function(){if(n<t){i+1<e.length&&n>=e[i+1].index&&++i;const t={value:e[i].value,done:!1,index:n};return++n,t}return{done:!0,index:t}}}}class je{#h;#W;constructor(e,t){this.#h=e,this.#W=t}getSlope(){return this.#h}getIntercept(){return this.#W}apply(e){return e*this.#h+this.#W}equals(e){return null!=e&&this.getSlope()===e.getSlope()&&this.getIntercept()===e.getIntercept()}isID(){return 1===this.getSlope()&&0===this.getIntercept()}}class Ze{#e;constructor(e){if(!e||void 0===e)throw new Error("Cannot create size with no values.");if(0===e.length)throw new Error("Cannot create size with empty values.");if(!e.every((function(e){return!isNaN(e)&&0!==e})))throw new Error("Cannot create size with non number or zero values.");this.#e=e}get(e){return this.#e[e]}length(){return this.#e.length}toString(){return"("+this.#e.toString()+")"}getValues(){return this.#e.slice()}moreThanOne(e){return this.length()>=e+1&&1!==this.get(e)}canScroll3D(e){let t=2;return void 0!==e&&(t=e.getThirdColMajorDirection()),this.moreThanOne(t)}canScroll(e){let t=this.canScroll3D(e);for(let e=3;e<this.length();++e)t=t||this.moreThanOne(e);return t}getDimSize(e,t){if(e>this.length())return null;if(void 0===t)t=0;else if(t<0||t>e)throw new Error("Invalid start value for getDimSize");let n=1;for(let i=t;i<e;++i)n*=this.get(i);return n}getTotalSize(e){return this.getDimSize(this.length(),e)}equals(e){if(!e)return!1;const t=this.length();if(t!==e.length())return!1;for(let n=0;n<t;++n)if(this.get(n)!==e.get(n))return!1;return!0}isInBounds(e,t){if(!e)return!1;const n=this.length();if(n!==e.length())return!1;if(void 0===t){t=[];for(let e=0;e<n;++e)t.push(e)}else for(let e=0;e<n;++e)if(t[e]>n-1)throw new Error("Wrong input dir value: "+t[e]);for(let n=0;n<t.length;++n)if(i=e.get(t[n]),r=this.get(t[n]),!(i>=0&&i<r))return!1;var i,r;return!0}indexToOffset(e,t){if(e.length()<this.length())throw new Error("Incompatible index and size length");if(void 0===t)t=0;else if(t<0||t>this.length()-1)throw new Error("Invalid start value for indexToOffset");let n=0;for(let i=t;i<this.length();++i)n+=e.get(i)*this.getDimSize(i,t);return n}offsetToIndex(e){const t=new Array(this.length());let n=e,i=0;for(let e=this.length()-1;e>0;--e)i=this.getDimSize(e),t[e]=Math.floor(n/i),n-=t[e]*i;return t[0]=n,new s(t)}get2D(){return{x:this.get(0),y:this.get(1)}}}class _e{min;max;mean;stdDev;median;p25;p75;constructor(e,t,n,i){this.min=e,this.max=t,this.mean=n,this.stdDev=i}}function Ke(e,t){return function(e){return null!=e&&(e.includes("median")||e.includes("p25")||e.includes("p75"))}(t)?function(e){const t=Je(e);return e.sort((function(e,t){return e-t})),t.median=$e(e,.5),t.p25=$e(e,.25),t.p75=$e(e,.75),t}(e):Je(e)}function Je(e){let t=e[0],n=t,i=0,r=0,o=0;const a=e.length;for(let s=0;s<a;++s)o=e[s],o<t?t=o:o>n&&(n=o),i+=o,r+=o*o;const s=i/a;let l=r/a-s*s;l<0&&(l=0);const c=Math.sqrt(l);return new _e(t,n,s,c)}function $e(e,t){if(0===e.length)throw new Error("Empty array provided for percentile calculation.");if(t<0||t>1)throw new Error("Invalid ratio provided for percentile calculation: "+t);if(0===t)return e[0];if(1===t)return e[e.length-1];const n=(e.length-1)*t,i=Math.floor(n),r=e[i];return r+(e[i+1]-r)*(n-i)}function et(){return Math.random().toString(36).substring(2,15)}class tt{min;max;constructor(e,t){this.min=e,this.max=t}}class nt{#e;constructor(e){if(!e||void 0===e)throw new Error("Cannot create spacing with no values.");if(0===e.length)throw new Error("Cannot create spacing with empty values.");if(!e.every((function(e){return!isNaN(e)&&0!==e})))throw new Error("Cannot create spacing with non number or zero values.");this.#e=e}get(e){return this.#e[e]}length(){return this.#e.length}toString(){return"("+this.#e.toString()+")"}getValues(){return this.#e.slice()}equals(e){if(!e)return!1;const t=this.length();if(t!==e.length())return!1;for(let n=0;n<t;++n)if(this.get(n)!==e.get(n))return!1;return!0}get2D(){return{x:this.get(0),y:this.get(1)}}}class it{#Y;#X;#j;#Z={};#_;#K=b();#J=!1;constructor(e,t,n,i,r){this.#Y=e,this.#X=t,this.#j=n,void 0!==r&&(this.#_=r,this.#Z[r]=e),void 0!==i&&(this.#K=i)}getInitialTime(){return this.#_}getCurrentTotalNumberOfSlices(){const e=Object.keys(this.#Z);if(0===e.length)return this.#Y.length;let t=0;for(let n=0;n<e.length;++n)t+=this.#Z[e[n]].length;return t}hasSlicesAtTime(e){return void 0!==this.#Z[e]}getCurrentNumberOfSlicesBeforeTime(e){const t=Object.keys(this.#Z);if(0===t.length)return;let n=0;for(let i=0;i<t.length;++i){const r=t[i];if(parseInt(r,10)===e)break;n+=this.#Z[r].length}return n}getOrigin(){return this.#Y[0]}getOrigins(){return this.#Y}includesOrigin(e,t){for(let n=0;n<this.#Y.length;++n)if(this.#Y[n].isSimilar(e,t))return!0;return!1}getSize(e){let t=this.#X;if(e&&void 0!==e){let n=rt([this.#X.get(0),this.#X.get(1),this.#X.get(2)],e);n=n.map(Math.abs),t=new Ze(n.concat(this.#X.getValues().slice(3)))}return t}#$(){const e=function(e){if(e.length<=1)return;const t=[];for(let n=0;n<e.length-1;++n){const i=e[n],r=e[n+1],o=i.getDistance(r);if(0===o)throw new Error("Zero slice spacing "+i.toString()+" "+r.toString());t.push(o)}const n=Je(t),i=B(n.mean,4);return n.stdDev>w&&c.warn("Varying slice spacing, value: "+i+" (mean: "+n.mean+", min: "+n.min+", max: "+n.max+", stdDev: "+n.stdDev+")"),i}(this.#Y);if(void 0!==e&&this.#j.get(2)!==e){c.trace("Using geometric spacing "+e+" instead of tag spacing "+this.#j.get(2));const t=this.#j.getValues();t[2]=e,this.#j=new nt(t)}}getSpacing(e){this.#J&&(this.#$(),this.#J=!1);let t=this.#j;if(e&&void 0!==e){let n=rt([this.#j.get(0),this.#j.get(1),this.#j.get(2)],e);n=n.map(Math.abs),t=new nt(n)}return t}getRealSpacing(){return this.getSpacing(this.#K.getInverse().asOneAndZeros())}getOrientation(){return this.#K}getSliceIndex(e,t){let n=this.#Y;void 0!==t&&(n=this.#Z[t]);const i=e.getClosest(n),r=n[i],o=e.minus(r);return new P(this.#K.get(0,2),this.#K.get(1,2),this.#K.get(2,2)).isCodirectional(o)?i+1:i}appendOrigin(e,t,n){const i=function(t){return t.equals(e)};if(void 0!==n){if(void 0!==this.#Z[n].find(i))throw new Error("Cannot append same time origin twice");this.#Z[n].splice(t,0,e)}if(void 0===n||n===this.#_){if(void 0!==this.#Y.find(i))throw new Error("Cannot append same origin twice");this.#J=!0,this.#Y.splice(t,0,e);const n=this.#X.getValues();n[2]+=1,this.#X=new Ze(n)}}appendFrame(e,t){this.#Z[t]=[e];const n=this.#X.getValues(),i=this.#j.getValues();4===n.length?n[3]+=1:(n.push(2),i.push(1)),this.#X=new Ze(n),this.#j=new nt(i)}toString(){return"Origin: "+this.getOrigin()+", Size: "+this.getSize()+", Spacing: "+this.getSpacing()+", Orientation: "+this.getOrientation()}equals(e){return null!==e&&this.getOrigin().equals(e.getOrigin())&&this.getSize().equals(e.getSize())&&this.getSpacing().equals(e.getSpacing())}isInBounds(e){return this.isIndexInBounds(this.worldToIndex(e))}isIndexInBounds(e,t){return this.getSize().isInBounds(e,t)}getRange(){const e=this.getSize().length(),t=new Array(e);t.fill(0);const n=new s(t),i=new s(this.getSize().getValues());return[this.indexToWorld(n),this.indexToWorld(i)]}indexToWorld(e){const t=this.getSpacing(),n=new F(e.get(0)*t.get(0),e.get(1)*t.get(1),e.get(2)*t.get(2)),i=this.getOrientation().multiplyPoint3D(n),r=e.getValues(),o=this.getOrigin();return r[0]=o.getX()+i.getX(),r[1]=o.getY()+i.getY(),r[2]=o.getZ()+i.getZ(),new E(r)}pointToWorld(e){const t=this.getSpacing(),n=new F(e.getX()*t.get(0),e.getY()*t.get(1),e.getZ()*t.get(2)),i=this.getOrientation().multiplyPoint3D(n),r=this.getOrigin();return new F(r.getX()+i.getX(),r.getY()+i.getY(),r.getZ()+i.getZ())}worldToIndex(e){const t=this.getOrigin(),n=new F(e.get(0)-t.getX(),e.get(1)-t.getY(),e.get(2)-t.getZ()),i=this.getOrientation().getInverse().multiplyPoint3D(n),r=e.getValues(),o=this.getSpacing();return r[0]=Math.round(i.getX()/o.get(0)),r[1]=Math.round(i.getY()/o.get(1)),r[2]=Math.round(i.getZ()/o.get(2)),new s(r)}worldToPoint(e){const t=this.getOrigin(),n=new F(e.get(0)-t.getX(),e.get(1)-t.getY(),e.get(2)-t.getZ()),i=this.getOrientation().getInverse().multiplyPoint3D(n),r=e.getValues(),o=this.getSpacing();return r[0]=i.getX()/o.get(0),r[1]=i.getY()/o.get(1),r[2]=i.getZ()/o.get(2),new F(r[0],r[1],r[2])}}function rt(e,t){return t.getInverse().multiplyArray3D(e)}function ot(e,t){return t.multiplyArray3D(e)}function at(e){return("0"+e).slice(-2)}function st(e){if(void 0===e)return;if(1!==e.value.length)return;const t=e.value[0];let n=4,i=6;return 10===t.length&&(n=5,i=8),{year:parseInt(t.substring(0,4),10),monthIndex:t.length>=n+2?parseInt(t.substring(n,n+2),10)-1:0,day:t.length===i+2?parseInt(t.substring(i,i+2),10):0}}function lt(e){if(void 0===e)return;if(1!==e.value.length)return;const t=e.value[0],n=parseInt(t.substring(0,2),10),i=t.length>=4?parseInt(t.substring(2,4),10):0,r=t.length>=6?parseInt(t.substring(4,6),10):0,o=t.length>=8?t.substring(7,10):0;return{hours:n,minutes:i,seconds:r,milliseconds:0===o?0:parseInt(o,10)*Math.pow(10,3-o.length)}}function ct(e){return{year:e.getFullYear().toString(),monthIndex:at((e.getMonth()+1).toString()),day:at(e.getDate().toString())}}function ut(e){return{hours:at(e.getHours().toString()),minutes:at(e.getMinutes().toString()),seconds:at(e.getSeconds().toString())}}function dt(e){return e.year+e.monthIndex+e.day}function ht(e){return e.hours+e.minutes+e.seconds}function St(){return new A([1,0,0,0,0,1,0,-1,0])}const gt={Axial:"axial",Coronal:"coronal",Sagittal:"sagittal"};function pt(e){let t;return e===gt.Axial?t=b():e===gt.Coronal?t=St():e===gt.Sagittal&&(t=new A([0,0,-1,1,0,0,0,-1,0])),t}function mt(e){const t=new P(e.get(0,0),e.get(1,0),e.get(2,0)),n=new P(e.get(0,1),e.get(1,1),e.get(2,1)),i=new P(e.get(0,2),e.get(1,2),e.get(2,2));return ft(t)+ft(n)+ft(i)}function ft(e){let t=new P(Math.abs(e.getX()),Math.abs(e.getY()),Math.abs(e.getZ())),n="";const i=e.getX()<0?"R":"L",r=e.getY()<0?"A":"P",o=e.getZ()<0?"I":"S",a=1e-4;for(let e=0;e<3;e++)if(t.getX()>a&&t.getX()>t.getY()&&t.getX()>t.getZ())n+=i,t=new P(0,t.getY(),t.getZ());else if(t.getY()>a&&t.getY()>t.getX()&&t.getY()>t.getZ())n+=r,t=new P(t.getX(),0,t.getZ());else{if(!(t.getZ()>a&&t.getZ()>t.getX()&&t.getZ()>t.getY()))break;n+=o,t=new P(t.getX(),t.getY(),0)}return n}function Dt(e){let t;const n=yt(e);return void 0!==n&&(t=function(e){let t;return["LPS","LAI","RPI","RAS","ALS","ARI","PLI","PRS"].includes(e)?t=gt.Axial:["LSA","LIP","RSP","RIA","ILA","IRP","SLP","SRA"].includes(e)?t=gt.Coronal:["PSL","PIR","ASR","AIL","IAR","IPL","SAL","SPR"].includes(e)&&(t=gt.Sagittal),t}(mt(n.asOneAndZeros()))),t}function yt(e){let t;if(void 0!==e&&6===e.length){const n=new P(e[0],e[1],e[2]),i=new P(e[3],e[4],e[5]),r=n.crossProduct(i);t=new A([n.getX(),i.getX(),r.getX(),n.getY(),i.getY(),r.getY(),n.getZ(),i.getZ(),r.getZ()])}return t}function Ct(e,t){let n=b();return void 0!==t&&(n=e.asOneAndZeros().getInverse().multiply(t)),n.getAbs()}function vt(e){const t=e["00280010"];if(void 0===t)throw new Error("Missing DICOM image number of rows");if(0===t.value.length)throw new Error("Empty DICOM image number of rows");const n=e["00280011"];if(void 0===n)throw new Error("Missing DICOM image number of columns");if(0===n.value.length)throw new Error("Empty DICOM image number of columns");return[n.value[0],t.value[0]]}function It(e){if(void 0===e["00280030"])return null;const t=e["00280030"],n=[parseFloat(t.value[1]),parseFloat(t.value[0])];return void 0!==e["00180088"]&&n.push(parseFloat(e["00180088"].value[0])),new nt(n)}function Tt(e){return void 0!==e&&null!==e.match(/MONOCHROME/)}function Lt(e,t,n){let i="";if(void 0===e)i+=" "+t+" is undefined,";else if(0===e.value.length)i+=" "+t+" is empty,";else if(void 0!==n)for(let r=0;r<n.length;++r)e.value.includes(n[r])||(i+=" "+t+" does not contain "+n[r]+" (value: "+e.value+"),");return i}class Pt{#ee;#te;getWarning(){return this.#ee}checkElements(e){let t;this.#ee=void 0,vt(e);const n=e["00080060"];if(void 0!==n&&(t=n.value[0],"PT"===t)){const t=function(e){const t=e["00280004"],n=e["00020010"],i=e["00280002"];let r=1;if(void 0!==i&&(r=i.value[0]),void 0!==t&&void 0!==n){let e=t.value[0].toUpperCase();const i=n.value[0],o=qe(i),a=Fe(i),s=Ee(i);return(o||a||s)&&"MONOCHROME1"!==e&&"MONOCHROME2"!==e&&(e="RGB"),"RGB"===e&&1===r&&(e="PALETTE COLOR"),e}}(e),n=function(e){const t=e["00080016"];if(void 0!==t)return t.value[0]}(e);if(function(e){return!e&&/^1\.2\.840\.10008\.5\.1\.4\.1\.1\.7/.test(e)}(n)||!Tt(t))return this.#ee;const i=function(e){let t="";const n={};let i;t+=Lt(e["00280051"],"Corrected Image (00280051)",["ATTN","DECY"]),t+=Lt(e["00541102"],"Decay Correction (00541102)",["START"]),t+=Lt(e["00541001"],"Units (00541001)",["BQML"]);const r=e["00101030"],o=Lt(r," PatientWeight (00101030)");if(0===o.length){const e=parseFloat(r.value[0]);isNaN(e)?t+=" PatientWeight is not a number":i=e}else t+=o;const a=function(e){let t,n="";const i=st(e["00080021"]);let r,o,a;const s=e["00540016"];if(n+=Lt(s,"RadiopharmaceuticalInformationSequence (00540016)"),void 0!==s){1!==s.value.length&&c.warn("Found more than 1 istopes in RadiopharmaceuticalInformation Sequence.");const e="RadionuclideTotalDose (00181074)",l=s.value[0]["00181074"];if(t=Lt(l,e),0===t.length){const e=parseFloat(l.value[0]);isNaN(e)?n+=" TotalDose is not a number":r=e}else n+=t;const u="RadionuclideHalfLife (00181075)",d=s.value[0]["00181075"];if(t=Lt(d,u),0===t.length){const e=parseFloat(d.value[0]);isNaN(e)?n+=" HalfLife is not a number":o=e}else n+=t;const h=s.value[0]["00181078"];let S,g;if(void 0===h)S=i,g=lt(s.value[0]["00181072"]);else{const e=function(e){if(void 0===e)return;if(1!==e.value.length)return;const t=e.value[0].split("&")[0],n=new ve("DA");n.value=[t.substring(0,8)];const i=st(n),r=new ve("TM");return r.value=[t.substring(8)],{date:i,time:t.length>=9?lt(r):void 0}}(h);S=e.date,g=e.time}void 0===g&&(g={hours:0,minutes:0,seconds:0,milliseconds:0}),a=new Date(S.year,S.monthIndex,S.day,g.hours,g.minutes,g.seconds,g.milliseconds)}const l=lt(e["00080031"]);let u=new Date(i.year,i.monthIndex,i.day,l.hours,l.minutes,l.seconds,l.milliseconds);const d=e["00080022"],h=e["00080032"];if(void 0!==d&&void 0!==h){const t=st(d),i=lt(h),r=new Date(t.year,t.monthIndex,t.day,i.hours,i.minutes,i.seconds,i.milliseconds);if(u>r){const a="Series date/time is after Aquisition date/time (diff="+(u.getTime()-r.getTime()).toString()+"ms) ";c.debug(a);let s=0;const l="FrameReferenceTime (00541300)",d=e["00541300"];n+=Lt(d,l),void 0!==d&&(s=d.value[0]);let h=0;const S="ActualFrameDuration (0018,1242)",g=e["00181242"];if(n+=Lt(g,S),void 0!==g&&(h=g.value[0]),s>0&&h>0){h/=1e3,s/=1e3;const e=Math.log(2)/o,n=e*h,r=1/e*Math.log(n/(1-Math.exp(-n)))-s;u=new Date(t.year,t.monthIndex,t.day,i.hours,i.minutes,i.seconds+r,i.milliseconds)}}}let S;if(void 0!==u&&void 0!==a&&void 0!==r&&void 0!==o){const e=(u.getTime()-a.getTime())/1e3;S=r*Math.pow(2,-e/o)}return{value:S,warning:n}}(e);return t+=a.warning,0!==t.length?n.warning="Cannot calculate PET SUV:"+t:n.value=1e3*i/a.value,n}(e);this.#te=i.value,this.#ee=i.warning}return this.#ee}create(e,t,n){const i=vt(e),r=[i[0],i[1],1],o=e["00280008"];if(void 0!==o){const e=parseInt(o.value[0],10);e>1&&r.push(e)}const a=new Ze(r),s=function(e){let t=1,n=1;const i=["00280030","00181164","00182010","00280034"];for(let r=0;r<i.length;++r){const o=e[i[r]];if(o&&2===o.value.length){t=parseFloat(o.value[0]),n=parseFloat(o.value[1]);break}}return 0===n&&(c.warn("Zero column spacing."),n=1),0===t&&(c.warn("Zero row spacing."),t=1),new nt([n,t,1])}(e),l=e["00020010"].value[0],d=qe(l),h=Fe(l),S=Ee(l),g=e["00200032"];let p=new Array(0,0,0);void 0!==g&&(p=[parseFloat(g.value[0]),parseFloat(g.value[1]),parseFloat(g.value[2])]);const f=function(e){const t=e["00200037"];let n;return void 0!==t&&(n=yt(t.value.map((e=>parseFloat(e))))),n}(e),D=new F(p[0],p[1],p[2]),y=(C=e,void 0!==L.getTagTime?L.getTagTime(C):void 0);var C;const v=new it([D],a,s,f,y);let I;const T=e["00080018"];void 0!==T&&(I=T.value[0]);let P=1;const w=e["00280002"];void 0!==w&&(P=w.value[0]);const O=a.getTotalSize()*P;if(O!==t.length){if(c.warn("Badly sized pixel buffer: "+t.length+" != "+O),!(O<t.length))throw new Error("Underestimated buffer size, can't fix it...");t=t.slice(0,a.getTotalSize())}const A=new Un(v,t,[I]),b=e["00280004"];if(void 0!==b){let e=b.value[0].toUpperCase();(d||h||S)&&"MONOCHROME1"!==e&&"MONOCHROME2"!==e&&(e="RGB"),"RGB"===e&&1===P&&(e="PALETTE COLOR"),A.setPhotometricInterpretation(e)}const x=e["00280006"];void 0!==x&&A.setPlanarConfiguration(x.value[0]);let R=1;const E=e["00281053"];if(void 0!==E){const e=parseFloat(E.value[0]);isNaN(e)||(R=e)}let q=0;const U=e["00281052"];if(void 0!==U){const e=parseFloat(U.value[0]);isNaN(e)||(q=e)}const M={numberOfFiles:n},Q=e["00080060"];void 0!==Q&&(M.Modality=Q.value[0]);let V=!1,N=1;void 0!==this.#te&&(V=!0,N=this.#te,c.info("Applying PET SUV calibration: "+N),R*=N,q*=N);const B=new je(R,q);A.setRescaleSlopeAndIntercept(B);const G=function(t){return Ie(e,t)};if(M.TransferSyntaxUID=G("00020010"),M.MediaStorageSOPClassUID=G("00020002"),M.SOPClassUID=G("00080016"),M.Modality=G("00080060"),M.ImageType=G("00080008"),M.SamplesPerPixel=G("00280002"),M.PhotometricInterpretation=G("00280004"),M.PixelRepresentation=G("00280103"),M.BitsAllocated=G("00280100"),M.BitsStored=G("00280101"),M.HighBit=G("00280102"),M.StudyDate=G("00080020"),M.StudyTime=G("00080030"),M.StudyInstanceUID=G("0020000D"),M.StudyID=G("00200010"),M.SeriesInstanceUID=G("0020000E"),M.SeriesNumber=G("00200011"),M.ReferringPhysicianName=G("00080090"),M.PatientName=G("00100010"),M.PatientID=G("00100020"),M.PatientBirthDate=G("00100030"),M.PatientSex=G("00100040"),M.Manufacturer=G("00080070"),M.ManufacturerModelName=G("00081090"),M.DeviceSerialNumber=G("00181000"),M.SoftwareVersions=G("00181020"),M.ImageOrientationPatient=G("00200037"),M.FrameOfReferenceUID=G("00200052"),M.IsSigned=1===M.PixelRepresentation,V)M.pixelUnit="SUV";else{const t=function(e){return void 0!==L.getTagPixelUnit?L.getTagPixelUnit(e):function(e){let t;const n=["00281054","00541001"];for(let i=0;i<n.length;++i){const r=e[n[i]];if(void 0!==r){t=r.value[0];break}}if(void 0===t){const n=e["00080060"];void 0!==n&&"CT"===n.value[0]&&(t="HU")}return t}(e)}(e);void 0!==t&&(M.pixelUnit=t)}const k={},H=e["00281050"],z=e["00281051"],W=e["00281055"];if(void 0!==H&&void 0!==z){let e;for(let t=0;t<H.value.length;++t){const n=parseFloat(H.value[t]);let i=parseFloat(z.value[t]);n&&i&&0!==i&&(e="",void 0!==W&&(e=W.value[t]),""===e&&(e="Default"+t),i*=N,i<1&&(i=1),k[e]={wl:[new u(n*N,i)],name:e}),0===i&&c.warn("Zero window width found in DICOM.")}}if(M.windowPresets=k,"PALETTE COLOR"===A.getPhotometricInterpretation()){const t=e["00281201"],n=e["00281202"],i=e["00281203"];let r,o,a;const s=e["00281101"];if(void 0!==s&&3===s.value.length)if(16===s.value[2]){let l=!1,u=s.value[0];0===u&&(u=65536);const d=t.vl;if(d!==2*u&&(l=!0,c.info("16bits lut but size is not double. desc: "+u+" vl: "+d)),8===parseInt(e["00280100"].value[0],10)&&(l=!0,c.info("Scaling 16bits color lut since bits allocated is 8.")),l){const e=function(e){return e>>8};r=t.value.map(e),o=n.value.map(e),a=i.value.map(e)}}else if(8===s.value[2]){c.info("Scaling 16bits color lut since the lut descriptor is 8.");let e=t.value.slice(0);r=Array.from(new Uint8Array(e.buffer)),e=n.value.slice(0),o=Array.from(new Uint8Array(e.buffer)),e=i.value.slice(0),a=Array.from(new Uint8Array(e.buffer))}A.setPaletteColourMap(new m(r,o,a))}const Y=e["00082144"];return void 0!==Y&&(M.RecommendedDisplayFrameRate=parseInt(Y.value[0],10)),A.setMeta(M),A}}class wt{#A=!0;#R;constructor(e,t){void 0!==t&&(this.#A=t),this.#R=new DataView(e)}writeUint8(e,t){return this.#R.setUint8(e,t),e+Uint8Array.BYTES_PER_ELEMENT}writeInt8(e,t){return this.#R.setInt8(e,t),e+Int8Array.BYTES_PER_ELEMENT}writeUint16(e,t){return this.#R.setUint16(e,t,this.#A),e+Uint16Array.BYTES_PER_ELEMENT}writeInt16(e,t){return this.#R.setInt16(e,t,this.#A),e+Int16Array.BYTES_PER_ELEMENT}writeUint32(e,t){return this.#R.setUint32(e,t,this.#A),e+Uint32Array.BYTES_PER_ELEMENT}writeUint64(e,t){return this.#R.setBigUint64(e,t,this.#A),e+BigUint64Array.BYTES_PER_ELEMENT}writeInt32(e,t){return this.#R.setInt32(e,t,this.#A),e+Int32Array.BYTES_PER_ELEMENT}writeInt64(e,t){return this.#R.setBigInt64(e,t,this.#A),e+BigInt64Array.BYTES_PER_ELEMENT}writeFloat32(e,t){return this.#R.setFloat32(e,t,this.#A),e+Float32Array.BYTES_PER_ELEMENT}writeFloat64(e,t){return this.#R.setFloat64(e,t,this.#A),e+Float64Array.BYTES_PER_ELEMENT}writeHex(e,t){const n=parseInt(t,16);return this.#R.setUint16(e,n,this.#A),e+Uint16Array.BYTES_PER_ELEMENT}writeBinaryArray(e,t){if(t.length%8!=0)throw new Error("Cannot write boolean array as binary.");let n=null,i=null;for(let r=0,o=t.length;r<o;r+=8){n=0;for(let e=0;e<8;++e)i=0===t[r+e]?0:1,n+=i<<e;e=this.writeUint8(e,n)}return e}writeUint8Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeUint8(e,t[n]);return e}writeInt8Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeInt8(e,t[n]);return e}writeUint16Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeUint16(e,t[n]);return e}writeInt16Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeInt16(e,t[n]);return e}writeUint32Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeUint32(e,t[n]);return e}writeUint64Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeUint64(e,t[n]);return e}writeInt32Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeInt32(e,t[n]);return e}writeInt64Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeInt64(e,t[n]);return e}writeFloat32Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeFloat32(e,t[n]);return e}writeFloat64Array(e,t){for(let n=0,i=t.length;n<i;++n)e=this.writeFloat64(e,t[n]);return e}}let Ot=0;class At{action;value;constructor(e){this.action=e}}const bt={copy:function(e){return e},remove:function(){return null},clear:function(e){return e.value=[],e},replace:function(e,t){return e.value=[t],e}};function xt(e){const t="1.2.826.0.1.3680043.9.7278.1.";let n="";if("ImplementationClassUID"===e)n=t+"0.35.0-beta.11";else{const i="."+(new Date).toISOString().replace(/\D/g,"").substring(0,14);Ot+=1;const r="."+Ot;n=t;const o=29+r.length+i.length,a=Math.min(e.length,64-o);if(a>1){let t="";for(let n=0;n<a;++n)t+=e.charCodeAt(n);n+=t.substring(0,a)}n+=i+r}return n}function Rt(e){return e%2==0}function Ft(e){const t=te[e];return void 0!==t&&"string"===t}function Et(e,t){const n=new Uint8Array(e.length+1);return n.set(e),n.set(t,e.length),n}class qt{encode(e){const t=new Uint8Array(e.length);for(let n=0,i=e.length;n<i;++n)t[n]=e.charCodeAt(n);return t}}const Ut="00080005",Mt="00280100";class Qt{#ne=!1;#ie=!0;#re={default:{action:"copy",value:null}};#oe=this.#re;#ae=[];#se=new qt;#le=this.#se;setUseUnVrForPrivateSq(e){this.#ne=e}setFixUnknownVR(e){this.#ie=e}setRules(e,t){if(this.#oe=e,this.#ae=[],t){const t=Object.keys(e);for(const n of t){const t=e[n];if("replace"===t.action&&void 0!==t.value&&null!==t.value){let e,t=!1;if(8===n.length&&(t=void 0!==Se(n).getNameFromDictionary()),t)e=n;else{const t=Ce(n);void 0!==t&&(e=t.getKey())}void 0!==e&&this.#ae.push(e)}}}}#ce(e){return this.#se.encode(e)}#ue(e){return this.#le.encode(e)}useSpecialTextEncoder(){this.#le=new TextEncoder}getElementToWrite(e){const t=e.tag.getGroupName(),n=e.tag.getNameFromDictionary();let i;return i=void 0!==this.#oe[e.tag.getKey()]?this.#oe[e.tag.getKey()]:void 0!==n&&void 0!==this.#oe[n]?this.#oe[n]:void 0!==this.#oe[t]?this.#oe[t]:this.#oe.default,bt[i.action](e,i.value)}#de(e,t,n,i){let r;for(let o=0;o<n.length;++o){if(r=n[o],0===r.length)continue;let a=!1;const s=r.find((e=>pe(e.tag)));void 0!==s&&void 0!==s.undefinedLength&&(a=s.undefinedLength);const l=new ve("NONE");l.vl=a?4294967295:s.vl,l.tag=ge(),l.value=[],t=this.#he(e,l,t,i);for(const n of r)pe(n.tag)||me(n.tag)||(t=this.#he(e,n,t,i));if(a){const n=new ve("NONE");n.vl=0,n.tag=new de("FFFE","E00D"),n.value=[],t=this.#he(e,n,t,i)}}return t}#Se(e,t,n,i,r){const o=n;if("NONE"===t.vr);else if(i instanceof Uint8Array)n=i.length===8*t.vl?e.writeBinaryArray(n,i):e.writeUint8Array(n,i);else if(i instanceof Int8Array)n=e.writeInt8Array(n,i);else if(i instanceof Uint16Array)n=e.writeUint16Array(n,i);else if(i instanceof Int16Array)n=e.writeInt16Array(n,i);else if(i instanceof Uint32Array)n=e.writeUint32Array(n,i);else if(i instanceof Int32Array)n=e.writeInt32Array(n,i);else if(i instanceof BigUint64Array)n=e.writeUint64Array(n,i);else if(i instanceof BigInt64Array)n=e.writeInt64Array(n,i);else{const o=te[t.vr];if(void 0!==o)if("Uint8"===o)n=e.writeUint8Array(n,i);else if("Uint16"===o)n=e.writeUint16Array(n,i);else if("Int16"===o)n=e.writeInt16Array(n,i);else if("Uint32"===o)n=e.writeUint32Array(n,i);else if("Int32"===o)n=e.writeInt32Array(n,i);else if("Uint64"===o)n=e.writeUint64Array(n,i);else if("Int64"===o)n=e.writeInt64Array(n,i);else if("Float32"===o)n=e.writeFloat32Array(n,i);else if("Float64"===o)n=e.writeFloat64Array(n,i);else{if("string"!==o)throw new Error("Unknown VR type: "+o);n=e.writeUint8Array(n,i)}else if("SQ"===t.vr)n=this.#de(e,n,i,r);else if("AT"===t.vr)for(let t=0;t<i.length;++t){const r=i[t]+"",o=r.substring(1,5),a=r.substring(6,10),s=[parseInt(o,16),parseInt(a,16)];n=e.writeUint16Array(n,s)}else"xs"===t.vr?n=i instanceof Int16Array?e.writeInt16Array(n,i):e.writeUint16Array(n,i):c.warn("Unknown VR: "+t.vr)}if("SQ"!==t.vr&&"NONE"!==t.vr){const e=n-o;if(e!==t.vl){let n="Offset difference and VL are not equal: "+e+" != "+t.vl;n+=" (",void 0!==t.tag&&(n+=t.tag+", "),n+="vr:"+t.vr+")",c.warn(n)}}return n}#ge(e,t,n,i,r){let o=!1;if(void 0!==t.undefinedLength&&(o=t.undefinedLength),o){const o={};o.FFFEE000={tag:ge(),vr:"NONE",vl:0,value:[]};for(let e=0;e<i.length;++e)o[e]={tag:ge(),vr:t.vr,vl:i[e].length,value:i[e]};n=this.#de(e,n,[o],r)}else{let o=i[0];i.length>1&&(o=function(e){const t=e.length,n=e[0].length;if(void 0===n)return e;const i=t*n,r=new e[0].constructor(i);for(let i=0;i<t;i++){const t=i*n;r.set(e[i],t)}return r}(i)),n=this.#Se(e,t,n,o,r)}return n}#he(e,t,n,i){const r=t.tag.isWithVR(),o=!(!i&&r)||J(t.vr);n=e.writeHex(n,t.tag.getGroup()),n=e.writeHex(n,t.tag.getElement());let a=t.vr;this.#ne&&t.tag.isPrivate()&&"SQ"===a&&(c.warn("Write element using VR=UN for private sequence."),a="UN"),r&&!i&&(n=e.writeUint8Array(n,this.#ce(a)),o&&(n+=2));let s=!1;("SQ"===t.vr||ye(t.tag))&&void 0!==t.undefinedLength&&(s=t.undefinedLength);let l=!1;pe(t.tag)&&void 0!==t.undefinedLength&&(l=t.undefinedLength);let u=t.vl;(s||l)&&(u=4294967295),n=o?e.writeUint32(n,u):e.writeUint16(n,u);let d=t.value;if(void 0===d&&(d=[]),n=ye(t.tag)?this.#ge(e,t,n,d,i):this.#Se(e,t,n,d,i),s){const t=new ve("NONE");t.vl=0,t.tag=new de("FFFE","E0DD"),t.value=[],n=this.#he(e,t,n,i)}return n}getBuffer(e){const t=e["00020010"].value[0],n=xe(t),i=Re(t);if(void 0!==e[Ut]){const t=e[Ut].value[0];void 0!==t&&"ISO-IR 6"!==t&&(c.debug("Change charset to UTF, was: "+t),this.useSpecialTextEncoder(),e[Ut].value=["ISO_IR 192"])}let r;void 0!==e[Mt]&&(r=e[Mt].value[0]);let o=132,a=0;const s=[],l=[];let u,d,h=0;const S=new de("0002","0000"),g=new de("0002","0001"),p=new de("0002","0012"),m=new de("0002","0013"),f=this.#ae.slice(),D=Object.keys(e);for(let t=0,c=D.length;t<c;++t){const c=e[D[t]];if(c.tag=Se(D[t]),u=this.getElementToWrite(c),!(null===u||S.equals(u.tag)||g.equals(u.tag)||p.equals(u.tag)||m.equals(u.tag))){a=0;const e=f.indexOf(u.tag.getKey());-1!==e&&f.splice(e,1),this.#ie&&Vt(u,!i),this.#pe(u,u.value,n,r),d=u.tag.getGroupName(),a+=Qe(u.vr,"Meta Element"!==d&&n),a+=u.vl,"Meta Element"===d?(s.push(u),h+=a):l.push(u),o+=a}}for(const e of f){const t=Se(e),i=new ve(t.getVrFromDictionary());let r;if(i.tag=t,void 0!==this.#oe[e])r=this.#oe[e].value;else{const e=t.getNameFromDictionary();r=this.#oe[e].value}let a=Qe(i.vr,n);a+=this.#pe(i,[r],n),l.push(i),o+=a}const y=Nt("FileMetaInformationVersion");let C=Qe(y.vr,!1);C+=this.#pe(y,[0,1],!1),s.push(y),h+=C,o+=C;const v=Nt("ImplementationClassUID");let I=Qe(v.vr,!1);const T=xt("ImplementationClassUID").replace("-beta",".99");I+=this.#pe(v,[T],!1),s.push(v),h+=I,o+=I;const L=Nt("ImplementationVersionName");let P=Qe(L.vr,!1);const w="DWV_"+"0.35.0-beta.11".replace("-beta",".99");P+=this.#pe(L,[w],!1),s.push(L),h+=P,o+=P;const O=function(e,t){return he(e.tag,t.tag)};s.sort(O),l.sort(O);const A=Nt("FileMetaInformationGroupLength");let b=Qe(A.vr,!1);b+=this.#pe(A,new Uint32Array([h]),!1),o+=b;const x=new ArrayBuffer(o),R=new wt(x),F=new wt(x,!i);let E=128;E=R.writeUint8Array(E,this.#ce("DICM")),E=this.#he(R,A,E,!1);for(let e=0,t=s.length;e<t;++e)E=this.#he(R,s[e],E,!1);const q=132+b+h;E!==q&&c.warn("Bad size calculation... meta offset: "+E+", calculated size:"+q+" (diff:"+(E-q)+")");for(let e=0,t=l.length;e<t;++e)E=this.#he(F,l[e],E,n);return E!==o&&c.warn("Bad size calculation... final offset: "+E+", calculated size:"+o+" (diff:"+(E-o)+")"),x}#pe(e,t,n,i){let r=0;if("SQ"===e.vr){if(null!==t&&0!==t){const o=[];let a=!1;void 0!==e.undefinedLength&&(a=e.undefinedLength,delete e.undefinedLength);for(let e=0;e<t.length;++e){const s=t[e],l=[];let c=0;if(null===s||0===s)continue;let u=i;const d=s[Mt];void 0!==d&&void 0!==d.value&&(u=d.value[0]);const h=Object.keys(s);for(let e=0,t=h.length;e<t;++e){const t=h[e],i=s[t];i.tag=Se(t),pe(i.tag)||(c+=this.#pe(i,i.value,n,u),l.push(i),c+=Qe(i.vr,n))}const S={tag:ge(),vr:"NONE",vl:c,value:[]};a&&(S.undefinedLength=a),l.push(S),c+=Qe(S.vr,n),a&&(c+=Qe("NONE",n));const g=function(e,t){return he(e.tag,t.tag)};l.sort(g),r+=c,o.push(l)}a&&(r+=Qe("NONE",n)),e.value=o,e.vl=r,a&&(e.undefinedLength=a)}}else{if(Ft(o=e.vr)||"OB"===o){const n=function(e){let t="";return Ft(e)&&(t="UI"===e?"\0":" "),t}(e.vr);if(Ft(e.vr)){let i;ee(e.vr)?(t=this.#ue(t.join("\\")),i=this.#ue(n)):(t=this.#ce(t.join("\\")),i=this.#ce(n)),Rt(t.length)||(t=Et(t,i))}else"OB"===e.vr&&(t=function(e){if(null==e||void 0===e.length)throw new Error("Cannot pad undefined or null OB value.");if(0!==e.length&&void 0!==e[0].length){let t=0;for(let n=0;n<e.length;++n)t+=e[n].length;Rt(t)||(e[e.length-1]=Et(e[e.length-1],[0]))}else Rt(e.length)||(e=Et(e,[0]));return e}(t))}if(r=0,"AT"===e.vr)r=4*t.length;else if("xs"===e.vr)r=t.length*Uint16Array.BYTES_PER_ELEMENT;else if(function(e){const t=te[e];return void 0!==t&&"string"!==t}(e.vr)||"ox"===e.vr){if(ye(e.tag)&&Array.isArray(t)){r=0;for(let e=0;e<t.length;++e)r+=t[e].length}else r=t.length;const o=te[e.vr];if(ye(e.tag)||"ox"===e.vr)if(e.undefinedLength){const e=Qe("NONE",n);r+=e,r+=e*t.length,r+=e}else void 0!==i&&(1===i?r/=8:16===i&&(r*=Uint16Array.BYTES_PER_ELEMENT));else{if(void 0===o)throw new Error("Unsupported element: "+e.vr);{const e=function(e){let t;return"Uint8"===e?t=Uint8Array.BYTES_PER_ELEMENT:"Uint16"===e?t=Uint16Array.BYTES_PER_ELEMENT:"Int16"===e?t=Int16Array.BYTES_PER_ELEMENT:"Uint32"===e?t=Uint32Array.BYTES_PER_ELEMENT:"Int32"===e?t=Int32Array.BYTES_PER_ELEMENT:"Float32"===e?t=Float32Array.BYTES_PER_ELEMENT:"Float64"===e?t=Float64Array.BYTES_PER_ELEMENT:"Uint64"===e?t=BigUint64Array.BYTES_PER_ELEMENT:"Int64"===e&&(t=BigInt64Array.BYTES_PER_ELEMENT),t}(o);if(void 0===e)throw new Error("Unknown bytes per element for VR type: "+o);r*=e}}}else r=t.length;e.value=t,e.vl=r}var o;return r}}function Vt(e,t){if("UN"===e.vr){const n=e.tag.getVrFromDictionary();if(void 0!==n&&e.vr!==n){e.vr=n;const i=te[e.vr];if(void 0!==i&&"Uint8"!==i&&"string"!==i){const n=function(e,t,n){let i;if(void 0===e.buffer)return i;const r=new Le(e.buffer,n),o=e.byteOffset,a=e.length,s=te[t];return"Uint16"===s?i=r.readUint16Array(o,a):"Uint32"===s?i=r.readUint32Array(o,a):"Uint64"===s?i=r.readUint64Array(o,a):"Int16"===s?i=Array.from(r.readInt16Array(o,a)):"Int32"===s?i=Array.from(r.readInt32Array(o,a)):"Int64"===s?i=r.readInt64Array(o,a):"Float32"===s?i=Array.from(r.readFloat32Array(o,a)):"Float64"===s&&(i=Array.from(r.readFloat64Array(o,a))),i}(e.value,e.vr,t);void 0!==n&&(e.value=n)}c.info("Element "+e.tag.getGroup()+" "+e.tag.getElement()+" VR changed from UN to "+e.vr)}}}function Nt(e){const t=Ce(e),n=new ve(t.getVrFromDictionary());return n.tag=t,n}function Bt(e){const t=Object.keys(e),n={};for(let i=0,r=t.length;i<r;++i){const r=Ce(t[i]);if(void 0===r)continue;const o=r.getVrFromDictionary();let a,s=!1;const l=e[t[i]];if("SQ"===o){const e=[];if(void 0!==l.undefinedLength&&(s=l.undefinedLength),void 0!==l.value&&null!==l.value)for(let t=0;t<l.value.length;++t)e.push(Bt(l.value[t]));else c.trace("Undefined or null simpleTag SQ value.");a=e}else a=Array.isArray(l)?l:[l];const u=new ve(o);u.tag=r,u.value=a,s&&(u.undefinedLength=s),n[r.getKey()]=u}return n}const Gt={CodeValue:"00080100",CodingSchemeDesignator:"00080102",CodeMeaning:"00080104",LongCodeValue:"00080119",URNCodeValue:"00080120"};class kt{meaning;value;longValue;urnValue;schemeDesignator;constructor(e){this.meaning=e}toString(){return"("+this.value+", "+this.schemeDesignator+", '"+this.meaning+"')"}}function Ht(e,t){return Object.keys(e).length===Object.keys(t).length&&Object.keys(e).every((n=>Object.prototype.hasOwnProperty.call(t,n)&&e[n]===t[n]))}function zt(e){const t=new kt(e[Gt.CodeMeaning].value[0]);if(void 0!==e[Gt.CodeValue])t.value=e[Gt.CodeValue].value[0];else if(void 0!==e[Gt.LongCodeValue])t.longValue=e[Gt.LongCodeValue].value[0];else{if(void 0===e[Gt.URNCodeValue])throw new Error("Invalid code with no value, no long value and no urn value.");t.urnValue=e[Gt.URNCodeValue].value[0]}if(void 0!==t.value||void 0!==t.longValue){if(void 0===e[Gt.CodingSchemeDesignator])throw new Error("No coding sheme designator when code value or long value is present");t.schemeDesignator=e[Gt.CodingSchemeDesignator].value[0]}return t}function Wt(e){const t={};return void 0!==e.value?t.CodeValue=e.value:void 0!==e.longValue?t.LongCodeValue=e.longValue:void 0!==e.urnValue&&(t.URNCodeValue=e.urnValue),void 0!==e.schemeDesignator&&(t.CodingSchemeDesignator=e.schemeDesignator),t.CodeMeaning=e.meaning,t}const Yt={111030:"Image Region",112039:"Tracking Identifier",112040:"Tracking Unique Identifier",113048:"Pixel by pixel Maximum",113049:"Pixel by pixel mean",113051:"Pixel by pixel Minimum",113061:"Standard Deviation",113076:"Segmentation",121055:"Path",121207:"Height",121322:"Source image for image processing operation",121324:"Source Image",122438:"Reference Points",125007:"Measurement Group",125309:"Short label",128773:"Reference Geometry"},Xt={1483009:"Angle",42798e3:"Area",103355008:"Width",103339001:"Long axis",103340004:"Short axis",131190003:"Radius",261665006:"Unknown",410668003:"Length",718499004:"Color"},jt={1:"No units",mm:"Millimeter",deg:"Degree - plane angle",cm2:"Square centimeter","cm2/ml":"Square centimeter per milliliter","/cm":"Per centimeter","g/ml":"Gram per milliliter","g/ml{SUVbw}":"Standardized Uptake Value body weight","mg/ml":"Milligram per milliliter","umol/ml":"Micromole per milliliter","Bq/ml":"Becquerels per milliliter","mg/min/ml":"Milligrams per minute per milliliter","umol/min/ml":"Micromole per minute per milliliter","ml/min/g":"Milliliter per minute per gram","ml/g":"Milliliter per gram","ml/min/ml":"Milliliter per minute per milliliter","ml/ml":"Milliliter per milliliter","%":"Percentage","[hnsf'U]":"Hounsfield unit","10*23/ml":"Electron density","{counts}":"Counts","{counts}/s":"Counts per second","{propcounts}":"Proportional to counts","{propcounts}/s":"Proportional to counts per second"};function Zt(e,t){let n,i;return"DCM"===t?n=Yt[e]:"SCT"===t?n=Xt[e]:"UCUM"===t&&(n=jt[e]),void 0!==n&&(i=new kt(n),i.schemeDesignator=t,i.value=e),i}function _t(){return Zt("125007","DCM")}function Kt(){return Zt("128773","DCM")}function Jt(){return Zt("121324","DCM")}function $t(){return Zt("112039","DCM")}function en(){return Zt("125309","DCM")}function tn(){return Zt("122438","DCM")}function nn(){return Zt("718499004","SCT")}const rn={angle:{key:"1483009",scheme:"SCT"},length:{key:"410668003",scheme:"SCT"},surface:{key:"42798000",scheme:"SCT"},height:{key:"121207",scheme:"DCM"},width:{key:"103355008",scheme:"SCT"},radius:{key:"131190003",scheme:"SCT"},a:{key:"103339001",scheme:"SCT"},b:{key:"103340004",scheme:"SCT"},min:{key:"113051",scheme:"DCM"},max:{key:"113048",scheme:"DCM"},mean:{key:"113049",scheme:"DCM"},stddev:{key:"113061",scheme:"DCM"}};function on(e){let t;for(const n in rn){const i=rn[n];if(i.scheme===e.schemeDesignator&&i.key===e.value){t=n;break}}return t}const an={"unit.mm":"mm","unit.cm2":"cm2","unit.degree":"deg",HU:"[hnsf'U]",MGML:"mg/ml",ED:"10*23/ml",PCT:"%",CNTS:"{counts}",NONE:"1",CM2:"cm2",CM2ML:"cm2/ml",PCNT:"%",CPS:"{counts}/s",BQML:"Bq/ml",MGMINML:"mg/min/ml",UMOLMINML:"umol/min/ml",MLMING:"ml/min/g",MLG:"ml/g","1CM":"/cm",UMOLML:"umol/ml",PROPCNTS:"{propcounts}",PROPCPS:"{propcounts}/s",MLMINML:"ml/min/ml",MLML:"ml/ml",GML:"g/ml",SUV:"g/ml{SUVbw}"};function sn(e){let t;for(const n in an){const i=an[n];if("UCUM"===e.schemeDesignator&&i===e.value){t=n;break}}return t}const ln="00620005",cn="00620009",un="0062000C",dn="0062000D",hn="00620003",Sn="0062000F",gn="00620020";class pn{number;label;algorithmType;algorithmName;displayValue;displayRGBValue;propertyTypeCode;propertyCategoryCode;trackingUid;trackingId;constructor(e,t,n){this.number=e,this.label=t,this.algorithmType=n}}function mn(e){const t=new pn(e["00620004"].value[0],e[ln]?e[ln].value[0]:"n/a",e["00620008"].value[0]);if(void 0!==e[cn]&&(t.algorithmName=e[cn].value[0]),void 0!==e[un])t.displayValue=e[un].value[0];else if(void 0!==e[dn]){const i=e[dn].value,r=function(e){return function(e){function t(e){let t=null;return t=e<=.0031308?12.92*e:1.055*Math.pow(e,.416666667)-.055,Math.min(1,Math.max(0,t))}const n=e.x/100,i=e.y/100,r=e.z/100;return{r:Math.round(255*t(3.2406*n-1.5372*i-.4986*r)),g:Math.round(255*t(-.9689*n+1.8758*i+.0415*r)),b:Math.round(255*t(.0557*n-.204*i+1.057*r))}}(function(e){function t(e){let t=null;return t=e>.206896552?Math.pow(e,3):.128418549*e-.017712903,t}const n=v,i=(e.l+16)/116;return{x:n.x*t(i+e.a/500),y:n.y*t(i),z:n.z*t(i-e.b/200)}}(e))}({l:.001525902*(n={l:i[0],a:i[1],b:i[2]}).l,a:.003891051*n.a-128,b:.003891051*n.b-128});t.displayRGBValue=r}var n;if(void 0===e[hn])throw new Error("Missing Segmented Property Category Code Sequence.");if(t.propertyCategoryCode=zt(e[hn].value[0]),void 0===e[Sn])throw new Error("Missing Segmented Property Type Code Sequence.");return t.propertyTypeCode=zt(e[Sn].value[0]),void 0!==e[gn]&&(t.trackingId=e[gn].value[0],t.trackingUid=e["00620021"].value[0]),t}function fn(e){let t=e.algorithmType;void 0===t&&(t="MANUAL");const n={SegmentNumber:e.number,SegmentLabel:e.label,SegmentAlgorithmType:t};if("MANUAL"!==t&&void 0!==e.algorithmName&&(n.SegmentAlgorithmName=e.algorithmName),e.displayRGBValue){const t=C(I(e.displayRGBValue));n.RecommendedDisplayCIELabValue=[Math.round(t.l),Math.round(t.a),Math.round(t.b)]}else n.RecommendedDisplayGrayscaleValue=e.displayValue;return e.propertyCategoryCode&&(n.SegmentedPropertyCategoryCodeSequence={value:[Wt(e.propertyCategoryCode)]}),e.propertyTypeCode&&(n.SegmentedPropertyTypeCodeSequence={value:[Wt(e.propertyTypeCode)]}),e.trackingId&&(n.TrackingID=e.trackingId,n.TrackingUID=e.trackingUid),n}const Dn="00089124",yn="00082112",Cn="00081150",vn="00081155",In="00209116",Tn="00289110";class Ln{dimIndex;imagePosPat;derivationImages;refSegmentNumber;imageOrientationPatient;spacing;constructor(e,t,n,i){this.dimIndex=e,this.imagePosPat=t,this.derivationImages=n,this.refSegmentNumber=i}}function Pn(e){const t=[];if(void 0!==e[Dn]){const n=e[Dn].value;for(let e=0;e<n.length;++e){const i=[];if(void 0!==n[e][yn]){const t=n[e][yn].value;for(let e=0;e<t.length;++e){const n={};void 0!==t[e][Cn]&&(n.referencedSOPClassUID=t[e][Cn].value[0]),void 0!==t[e][vn]&&(n.referencedSOPInstanceUID=t[e][vn].value[0]),i.push(n)}}t.push({sourceImages:i})}}const n=e["00209111"].value[0]["00209157"].value,i=e["0062000A"].value,r=parseInt(i[0]["0062000B"].value[0],0),o=e["00209113"].value[0]["00200032"].value;for(let e=0;e<o.length;++e)o[e]=parseFloat(o[e]);const a=new Ln(n,o,t,r);if(void 0!==e[In]){const t=e[In];if(0!==t.value.length){const e=t.value[0]["00200037"].value;void 0!==e&&(a.imageOrientationPatient=e)}}if(void 0!==e[Tn]){const t=e[Tn];if(0!==t.value.length){const e=It(t.value[0]);void 0!==e&&(a.spacing=e)}else c.warn("No shared functional group pixel measure sequence items.")}return a}function wn(e){const t={FrameContentSequence:{value:[{DimensionIndexValues:e.dimIndex}]},PlanePositionSequence:{value:[{ImagePositionPatient:e.imagePosPat}]},SegmentIdentificationSequence:{value:[{ReferencedSegmentNumber:e.refSegmentNumber}]}};if(void 0!==e.derivationImages){const n=Wt(Zt("121322","DCM")),i=Wt(Zt("113076","DCM")),r=[];for(const t of e.derivationImages){const e=[];for(const i of t.sourceImages)e.push({PurposeOfReferenceCodeSequence:{value:[n]},ReferencedSOPClassUID:i.referencedSOPClassUID,ReferencedSOPInstanceUID:i.referencedSOPInstanceUID});r.push({DerivationCodeSequence:{value:[i]},SourceImageSequence:{value:e}})}t.DerivationImageSequence={value:r}}return t}function On(e,t){return JSON.stringify(e)===JSON.stringify(t)}function An(e,t){const n=e[t.tag];if(1===t.type||2===t.type){if(void 0===n)throw new Error("Missing or empty "+t.name)}else if(void 0===n)return;let i,r=!1;if(i=1===n.value.length?n.value[0]:n.value,Array.isArray(i))for(let e=0;e<t.enum.length;++e){if(!Array.isArray(t.enum[e]))throw new Error("Cannot compare array and non array tag value.");if(k(t.enum[e],i)){r=!0;break}}else r=t.enum.includes(i);if(!r)throw new Error("Unsupported "+t.name+" value: "+i)}function bn(e,t,n){const i=e.getGeometry().getSize().getDimSize(2),r={};for(let o=0;o<i;++o){const a=n+o,s=e.getValueAtOffset(a);for(const e of t){const t=e.number-1;s===e.number&&(void 0===r[t]&&(r[t]=new Uint8Array(i)),r[t][o]=1)}}return r}const xn=[{name:"TransferSyntaxUID",tag:"00020010",type:"1",enum:[ie,re,oe]},{name:"MediaStorageSOPClassUID",tag:"00020002",type:"1",enum:["1.2.840.10008.5.1.4.1.1.66.4"]},{name:"SOPClassUID",tag:"00020002",type:"1",enum:["1.2.840.10008.5.1.4.1.1.66.4"]},{name:"Modality",tag:"00080060",type:"1",enum:["SEG"]},{name:"SegmentationType",tag:"00620001",type:"1",enum:["BINARY"]},{name:"DimensionOrganizationType",tag:"00209311",type:"3",enum:["3D"]},{name:"ImageType",tag:"00080008",type:"1",enum:[["DERIVED","PRIMARY"]]},{name:"SamplesPerPixel",tag:"00280002",type:"1",enum:[1]},{name:"PhotometricInterpretation",tag:"00280004",type:"1",enum:["MONOCHROME2"]},{name:"PixelRepresentation",tag:"00280103",type:"1",enum:[0]},{name:"BitsAllocated",tag:"00280100",type:"1",enum:[1]},{name:"BitsStored",tag:"00280101",type:"1",enum:[1]},{name:"HighBit",tag:"00280102",type:"1",enum:[0]}];function Rn(){const e={};for(let t=0;t<xn.length;++t){const n=xn[t];e[n.name]=n.enum[0]}return e}class Fn{#ee;getWarning(){return this.#ee}checkElements(e){}create(e,t){for(let t=0;t<xn.length;++t)An(e,xn[t]);const n=vt(e),i=new Ze([n[0],n[1],1]),r=i.getTotalSize();let o=1;const a=e["00280008"];if(void 0!==a&&(o=parseInt(a.value[0],10)),o!==t.length/r)throw new Error("Buffer and numberOfFrames meta are not equal."+o+" "+t.length/r);const l=function(e){const t=e["00209221"];if(void 0===t||1!==t.value.length)throw new Error("Unsupported dimension organization sequence length");const n=t.value[0]["00209164"].value[0],i=[],r=e["00209222"];if(void 0!==r){const e=r.value;if(2!==e.length)throw new Error("Unsupported dimension index sequence length");let t;for(let r=0;r<e.length;++r){const o=e[r]["00209164"].value[0];if(o!==n)throw new Error("Dimension Index Sequence contains a unknown Dimension Organization");t=e[r]["00209165"].value[0];const a={DimensionOrganizationUID:o,DimensionIndexPointer:t};void 0!==e[r]["00209421"]&&(a.DimensionDescriptionLabel=e[r]["00209421"].value[0]),i.push(a)}if("(0020,0032)"!==t)throw new Error("Unsupported non image position as last index")}return{organizations:{value:[{DimensionOrganizationUID:n}]},indices:{value:i}}}(e),u=e["00620002"];if(void 0===u)throw new Error("Missing or empty segmentation sequence");const d=[],h=[0],S=[0],g=[0];for(let e=0;e<u.value.length;++e){const t=mn(u.value[e]);void 0!==t.displayRGBValue&&(h[t.number]=t.displayRGBValue.r,S[t.number]=t.displayRGBValue.g,g[t.number]=t.displayRGBValue.b),d.push(t)}let p,f,D,y=!1;h.length>1&&(y=!0,p=new m(h,S,g));const C=e[52009229];if(void 0!==C){const e=C.value[0];if(void 0!==e["00209116"]){const t=e["00209116"];0!==t.value.length?D=t.value[0]["00200037"].value:c.warn("No shared functional group plane orientation sequence items.")}if(void 0!==e["00289110"]){const t=e["00289110"];0!==t.value.length?f=It(t.value[0]):c.warn("No shared functional group pixel measure sequence items.")}}const v=function(e,t){return e.some((function(e){return On(t,e)}))},I=function(e,t){return e.findIndex((function(e){return On(t,e)}))},T=e[52009230];if(void 0===T)throw new Error("Missing or empty per frame functional sequence");if(o!==T.value.length)throw new Error("perFrameFuncGroupSequence meta and numberOfFrames are not equal.");const L=[];for(let e=0;e<T.value.length;++e)L.push(Pn(T.value[e]));const O=[];for(let e=0;e<L.length;++e){if(v(O,L[e].imagePosPat)||O.push(L[e].imagePosPat),void 0!==L[e].imageOrientationPatient)if(void 0===D)D=L[e].imageOrientationPatient;else if(!k(D,L[e].imageOrientationPatient))throw new Error("Unsupported multi orientation dicom seg.");if(void 0!==L[e].spacing)if(void 0===f)f=L[e].spacing;else if(!f.equals(L[e].spacing))throw new Error("Unsupported multi resolution dicom seg.")}if(void 0===f)throw new Error("No spacing found for DICOM SEG");if(3!==f.length())throw new Error("Incomplete spacing found for DICOM SEG");if(void 0===D)throw new Error("No imageOrientationPatient found for DICOM SEG");if(6!==D.length)throw new Error("Incomplete imageOrientationPatient found for DICOM SEG");const b=new P(parseFloat(D[0]),parseFloat(D[1]),parseFloat(D[2])),x=new P(parseFloat(D[3]),parseFloat(D[4]),parseFloat(D[5])),R=b.crossProduct(x),E=new A([b.getX(),x.getX(),R.getX(),b.getY(),x.getY(),R.getY(),b.getZ(),x.getZ(),R.getZ()]);O.sort(function(e){const t=e.getInverse();return function(e,n){const i=t.multiplyArray3D(e),r=t.multiplyArray3D(n);return i[2]-r[2]}}(E));const q=function(e){return new F(e[0],e[1],e[2])},U=[];for(let e=0;e<O.length;++e)U.push(q(O[e]));const M=new it([U[0]],i,f,E),Q=function(e){let t=e>w;return t&&(t=e>10*w,t?(t=e>100*w,t||c.warn("Using larger+ real world epsilon in SEG pos pat adding")):c.warn("Using larger real world epsilon in SEG pos pat adding")),t},V=[];V.push(O[0]);let N=0;for(let e=1;e<O.length;++e){++N;let t=new s([0,0,N]),n=M.indexToWorld(t).get3D();const i=U[e];let r=i.getDistance(n);const o=r;for(;Q(r);)if(c.debug("Adding intermediate pos pats for DICOM seg at "+n.toString()),V.push([n.getX(),n.getY(),n.getZ()]),++N,t=new s([0,0,N]),n=M.indexToWorld(t).get3D(),r=i.getDistance(n),r>o)throw new Error("Test distance is increasing when adding intermediate pos pats");V.push(O[e])}const B=V.length,G=new it([U[0]],i,f,E),H=["0"];for(let e=1;e<B;++e)G.appendOrigin(q(V[e]),e),H.push(e.toString());const z=function(e){return function(t){return t.number===e}},W=new t.constructor(r*B);W.fill(0);let Y=null,X=null;for(let e=0;e<L.length;++e){N=I(V,L[e].imagePosPat),X=r*e,Y=r*N;const n=d.find(z(L[e].refSegmentNumber));for(let e=0;e<r;++e)if(0!==t[X+e]){W[Y+e]=y?n.number:n.displayValue}}const j=new Un(G,W,H);y&&(j.setPhotometricInterpretation("PALETTE COLOR"),j.setPaletteColourMap(p));const Z=Rn(),_=function(t){return Ie(e,t)};Z.StudyDate=_("00080020"),Z.StudyTime=_("00080030"),Z.StudyInstanceUID=_("0020000D"),Z.StudyID=_("00200010"),Z.SeriesDate=_("00080021"),Z.SeriesTime=_("00080031"),Z.SeriesInstanceUID=_("0020000E"),Z.SeriesNumber=_("00200011"),Z.ReferringPhysicianName=_("00080090"),Z.PatientName=_("00100010"),Z.PatientID=_("00100020"),Z.PatientBirthDate=_("00100030"),Z.PatientSex=_("00100040"),Z.Manufacturer=_("00080070"),Z.ManufacturerModelName=_("00081090"),Z.DeviceSerialNumber=_("00181000"),Z.SoftwareVersions=_("00181020"),Z.DimensionOrganizationSequence=l.organizations,Z.DimensionIndexSequence=l.indices,Z.custom={segments:d,frameInfos:L,SOPInstanceUID:e["00080018"].value[0]},Z.numberOfFiles=B;const K=e["00200052"];K&&(Z.FrameOfReferenceUID=K.value[0]);const J=e["00282110"];return J&&(Z.LossyImageCompression=J.value[0]),j.setMeta(Z),j}toDicom(e,t,n,i){const r=e.getMeta();void 0===t&&(t=r.segments);const o=e.getGeometry(),a=o.getSize();r.Rows=a.get(1),r.Columns=a.get(0);const s=new Date;r.ContentDate=dt(ct(s)),r.ContentTime=ht(ut(s)),void 0!==n&&(r.StudyInstanceUID=n.getMeta().StudyInstanceUID);const l=[];for(const e of t)l.push(fn(e));var u,d;r.SegmentSequence={value:l},r.SharedFunctionalGroupsSequence={value:[{PlaneOrientationSequence:{value:[(d=o.getOrientation(),{ImageOrientationPatient:[d.get(0,0),d.get(1,0),d.get(2,0),d.get(0,1),d.get(1,1),d.get(2,1)]})]},PixelMeasuresSequence:{value:[(u=o.getSpacing(),{SpacingBetweenSlices:u.get(2),PixelSpacing:[u.get(1),u.get(0)]})]}}]};const h=function(e,t){const n=e.getGeometry().getSize(),i=n.getDimSize(2),r={};for(let o=0;o<n.get(2);++o){const n=bn(e,t,o*i),a=Object.keys(n);for(const e of a)void 0===r[e]&&(r[e]={}),r[e][o]=n[e]}return r}(e,t),S=[],g=[],p=[];for(const i of t){const t=i.number,r=t-1;if(void 0===h[r])continue;const o=Object.keys(h[r]);for(let i=o.length-1;i>=0;--i){const a=Number.parseInt(o[i],10);g.push(h[r][a]);const s=e.getGeometry().getOrigins()[a],l=[s.getX(),s.getY(),s.getZ()],c={dimIndex:[t,o.length-i],imagePosPat:l,refSegmentNumber:t};if(void 0!==n){const e=n.getGeometry().worldToIndex(new E([s.getX(),s.getY(),s.getZ()]));c.derivationImages=[{sourceImages:[{referencedSOPInstanceUID:n.getImageUid(e),referencedSOPClassUID:n.getMeta().SOPClassUID}]}],p.push({ReferencedSOPInstanceUID:n.getImageUid(e),ReferencedSOPClassUID:n.getMeta().SOPClassUID})}S.push(c)}}r.NumberOfFrames=g.length.toString();const m=[];for(const e of S)m.push(wn(e));if(r.PerFrameFunctionalGroupsSequence={value:m},void 0!==n){const e=[];e.push({ReferencedInstanceSequence:{value:p},SeriesInstanceUID:n.getMeta().SeriesInstanceUID}),r.ReferencedSeriesSequence={value:e}}void 0!==i&&function(e,t){const n=Object.keys(t);for(const i of n)void 0!==e[i]&&c.trace("Overwritting tag: "+i),e[i]=t[i]}(r,i);const f=Bt(r),D=a.getDimSize(2),y=g.length*D/8,C=new ve("OB");return C.tag=new de("7FE0","0010"),C.vl=y,C.value=g,f["7FE00010"]=C,f}}function En(e){return(new Pt).create(e,e["7FE00010"].value[0],1)}function qn(e){return(new Fn).create(e,e["7FE00010"].value[0])}class Un{#me;#O;#fe;#n=new je(1,0);#De=null;#ye=!0;#Ce=!0;#ve="MONOCHROME2";#Ie;#Te=0;#Le;#Pe={};#we=null;#Oe=null;#Ae=null;#be=new He;constructor(e,t,n){this.#me=e,this.#O=t,this.#fe=n,this.#Le=this.#O.length/this.#me.getSize().getTotalSize()}getImageUid(e){let t=this.#fe[0];return 1!==this.#fe.length&&void 0!==e&&(t=this.#fe[this.getSecondaryOffset(e)]),t}getOriginForImageUid(e){let t;const n=this.#fe.indexOf(e);return-1!==n&&(t=this.getGeometry().getOrigins()[n]),t}includesImageUid(e){return this.#fe.includes(e)}containsImageUids(e){return function(e,t){if(null===e||null===t||void 0===e||void 0===t)return!1;if(0===e.length||0===t.length||t.length>e.length)return!1;for(const n of t)if(!e.includes(n))return!1;return!0}(this.#fe,e)}getGeometry(){return this.#me}getBuffer(){return this.#O}canQuantify(){return 1===this.getNumberOfComponents()}canWindowLevel(){return this.isMonochrome()}isMonochrome(){return Tt(this.getPhotometricInterpretation())}canScroll(e){const t=this.getGeometry().getSize();let n=1;return void 0!==this.#Pe.numberOfFiles&&(n=this.#Pe.numberOfFiles),t.canScroll(e)||1!==n}#xe(){return this.#me.getSize().getTotalSize(2)}getSecondaryOffset(e){return this.#me.getSize().indexToOffset(e,2)}getRescaleSlopeAndIntercept(e){let t=this.#n;if(!this.isConstantRSI()){if(void 0===e)throw new Error("Cannot get non constant RSI with empty slice index.");const n=this.getSecondaryOffset(e);void 0!==this.#De[n]?t=this.#De[n]:c.warn("undefined non constant rsi at "+n)}return t}#Re(e){return this.#De[e]}setRescaleSlopeAndIntercept(e,t){if(this.#ye=this.#ye&&e.isID(),this.#Ce){if(!this.#n.equals(e))if(void 0===t)this.#n=e;else{this.#Ce=!1,this.#De=[];for(let e=0,t=this.#xe();e<t;++e)this.#De.push(this.#n);this.#n=null,this.#De.splice(t,0,e)}}else{if(void 0===t)throw new Error("Cannot store non constant RSI with empty slice index.");this.#De.splice(t,0,e)}}isIdentityRSI(){return this.#ye}isConstantRSI(){return this.#Ce}getPhotometricInterpretation(){return this.#ve}setPhotometricInterpretation(e){this.#ve=e}setPaletteColourMap(e){this.#Ie=e,this.#Fe({type:"imagecontentchange"})}getPaletteColourMap(){return this.#Ie}updatePaletteColourMap(e,t){this.#Ie.red[e]=t.r,this.#Ie.green[e]=t.g,this.#Ie.blue[e]=t.b,this.#Fe({type:"imagecontentchange"})}getPlanarConfiguration(){return this.#Te}setPlanarConfiguration(e){this.#Te=e}getNumberOfComponents(){return this.#Le}getMeta(){return this.#Pe}setMeta(e){this.#Pe=e}getValueAtOffset(e){return this.#O[e]}getOffsets(e){let t;if("number"==typeof e){if(1!==this.#Le)throw new Error("Number of components is not 1 for getting single value.");t=[e]}else if(void 0!==e.r&&void 0!==e.g&&void 0!==e.b){if(3!==this.#Le)throw new Error("Number of components is not 3 for getting RGB value.");t=[e.r,e.g,e.b]}const n=[];let i;for(let e=0;e<this.#O.length;e+=this.#Le){i=!0;for(let n=0;n<this.#Le;++n)if(this.#O[e+n]!==t[n]){i=!1;break}i&&n.push(e)}return n}hasValues(e){if(void 0===e||0===e.length)return[];const t=[];for(let n=0;n<e.length;++n)1===this.#Le?t.push([e[n]]):3===this.#Le&&t.push([e[n].r,e[n].g,e[n].b]);let n;1===this.#Le?n=function(e,t){return e[0]===t[0]}:3===this.#Le&&(n=function(e,t){return e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2]});const i=function(e){return function(t){return n(t,e)}},r=new Array(e.length);r.fill(!1);const o=t.slice();let a,s;for(let e=0,n=this.#O.length;e<n;e+=this.#Le){s=[];for(let n=0;n<o.length;++n){a=!0;for(let t=0;t<this.#Le;++t)if(this.#O[e+t]!==o[n][t]){a=!1;break}a&&(r[t.findIndex(i(o[n]))]=!0,s.push(n))}for(let e=0;e<s.length;++e)o.splice(s[e],1);if(0===o.length)break}return r}clone(){const e=this.#O.slice(0),t=new Un(this.getGeometry(),e,this.#fe);if(this.isConstantRSI())t.setRescaleSlopeAndIntercept(this.getRescaleSlopeAndIntercept());else for(let e=0;e<this.#xe();++e)t.setRescaleSlopeAndIntercept(this.#Re(e),e);return t.setPhotometricInterpretation(this.getPhotometricInterpretation()),t.setPlanarConfiguration(this.getPlanarConfiguration()),t.setMeta(this.getMeta()),t}#Ee(e){let t=this.#O;if(this.#O=Me(8*this.#O.BYTES_PER_ELEMENT,this.#Pe.IsSigned?1:0,e),null===this.#O)throw new Error("Cannot reallocate data for image.");this.#O.set(t),t=null}appendSlice(e){if(null===e)throw new Error("Cannot append null slice");const t=e.getGeometry().getSize();let n=this.#me.getSize();if(1!==t.get(2))throw new Error("Cannot append more than one slice");if(n.get(0)!==t.get(0))throw new Error("Cannot append a slice with different number of columns");if(n.get(1)!==t.get(1))throw new Error("Cannot append a slice with different number of rows");if(!this.#me.getOrientation().equals(e.getGeometry().getOrientation(),1e-4))throw new Error("Cannot append a slice with different orientation");if(this.#ve!==e.getPhotometricInterpretation())throw new Error("Cannot append a slice with different photometric interpretation");for(const t in this.#Pe)if("windowPresets"!==t&&"numberOfFiles"!==t&&"custom"!==t&&this.#Pe[t]!==e.getMeta()[t])throw new Error("Cannot append a slice with different "+t+": "+this.#Pe[t]+" != "+e.getMeta()[t]);const i=e.getDataRange(),r=this.getDataRange();this.#we={min:Math.min(i.min,r.min),max:Math.max(i.max,r.max)};const o=e.getRescaledDataRange(),a=this.getRescaledDataRange();this.#Oe={min:Math.min(o.min,a.min),max:Math.max(o.max,a.max)};const l=e.getGeometry().getInitialTime();let c=!1;void 0===l||this.#me.hasSlicesAtTime(l)||(this.appendFrame(l,e.getGeometry().getOrigin()),n=this.#me.getSize(),c=!0);const u=function(e,t){const n=t.getInitialTime(),i=[];return i.push(0),i.push(0),i.push(e.getSliceIndex(t.getOrigin(),n)),void 0!==n&&i.push(n),new s(i)}(this.#me,e.getGeometry()),d=this.#Le*n.getDimSize(2);if(void 0===this.#Pe.numberOfFiles)throw new Error("Missing number of files for buffer manipulation.");const h=d*this.#Pe.numberOfFiles;this.#O.length!==h&&this.#Ee(h);const S=u.get(2);let g=S;void 0!==l&&(g+=this.#me.getCurrentNumberOfSlicesBeforeTime(l));const p=g*d,m=this.#me.getCurrentTotalNumberOfSlices()*d;p<m&&this.#O.set(this.#O.subarray(p,m),p+d),this.#O.set(e.getBuffer(),p),c||this.#me.appendOrigin(e.getGeometry().getOrigin(),S,l),this.setRescaleSlopeAndIntercept(e.getRescaleSlopeAndIntercept(),g);const f=this.#fe.length;if(this.#fe.splice(g,0,e.getImageUid()),void 0!==this.#Pe.windowPresets){const t=this.#Pe.windowPresets,n=e.getMeta().windowPresets,i=Object.keys(n);let r=null;for(let e=0;e<i.length;++e){r=i[e];const o=n[r],a=t[r];if(void 0!==a){if((void 0===a.perslice||!1===a.perslice)&&!a.wl[0].equals(o.wl[0])){a.perslice=!0;for(let e=0;e<f-1;++e)a.wl.push(a.wl[0])}void 0!==a.perslice&&!0===a.perslice&&t[r].wl.splice(g,0,o.wl[0])}else t[r]=n[r]}}this.#Fe({type:"imagegeometrychange"})}appendFrameBuffer(e,t){const n=this.#me.getSize(),i=this.#Le*n.getDimSize(2);if(void 0===this.#Pe.numberOfFiles)throw new Error("Missing number of files for frame buffer manipulation.");const r=i*this.#Pe.numberOfFiles;this.#O.length!==r&&this.#Ee(r),t>=this.#Pe.numberOfFiles?c.warn("Ignoring frame at index "+t+" (size: "+this.#Pe.numberOfFiles+")"):(this.#O.set(e,i*t),this.appendFrame(t,new F(0,0,0)))}appendFrame(e,t){this.#me.appendFrame(t,e),this.#Fe({type:"appendframe"})}getDataRange(){return this.#we||(this.#we=this.calculateDataRange()),this.#we}getRescaledDataRange(){return this.#Oe||(this.#Oe=this.calculateRescaledDataRange()),this.#Oe}getHistogram(){if(!this.#Ae){const e=this.calculateHistogram();this.#we=e.dataRange,this.#Oe=e.rescaledDataRange,this.#Ae=e.histogram}return this.#Ae}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)};setAtOffsets(e,t){let n,i;if("number"==typeof t){if(1!==this.#Le)throw new Error("Number of components is not 1 for setting single value.");n=[t]}else if(void 0!==t.r&&void 0!==t.g&&void 0!==t.b){if(3!==this.#Le)throw new Error("Number of components is not 3 for setting RGB value.");n=[t.r,t.g,t.b]}for(let t=0,r=e.length;t<r;++t){i=e[t];for(let e=0;e<this.#Le;++e)this.#O[i+e]=n[e]}this.#Fe({type:"imagecontentchange"})}setAtOffsetsAndGetOriginals(e,t){const n=[];for(let i=0;i<e.length;++i){const r=e[i];let o=r[0],a=this.#O[o];const s=[];s.push({index:0,value:a});for(let e=0;e<r.length;++e){o=r[e];const n=this.#O[o];a!==n&&(s.push({index:e,value:n}),a=n),this.#O[o]=t}n.push(s)}return this.#Fe({type:"imagecontentchange"}),n}setAtOffsetsWithIterator(e,t){const n=Array.isArray(t);for(let i=0;i<e.length;++i){const r=e[i];let o;o=Xe(n?t[i]:[{index:0,value:t}],r.length);let a=o.next();for(;!a.done;){const e=r[a.index];this.#O[e]=a.value,a=o.next()}}this.#Fe({type:"imagecontentchange"})}getValue(e,t,n,i){const r=new s([e,t,n,i||0]);return this.getValueAtOffset(this.getGeometry().getSize().indexToOffset(r))}getValueAtIndex(e){return this.getValueAtOffset(this.getGeometry().getSize().indexToOffset(e))}getRescaledValue(e,t,n,i){void 0===i&&(i=0);let r=this.getValue(e,t,n,i);if(!this.isIdentityRSI())if(this.isConstantRSI())r=this.getRescaleSlopeAndIntercept().apply(r);else{const o=new s([e,t,n,i]);r=this.getRescaleSlopeAndIntercept(o).apply(r)}return r}getRescaledValueAtIndex(e){return this.getRescaledValueAtOffset(this.getGeometry().getSize().indexToOffset(e))}getRescaledValueAtOffset(e){let t=this.getValueAtOffset(e);if(!this.isIdentityRSI())if(this.isConstantRSI())t=this.getRescaleSlopeAndIntercept().apply(t);else{const n=this.getGeometry().getSize().offsetToIndex(e);t=this.getRescaleSlopeAndIntercept(n).apply(t)}return t}calculateDataRange(){let e=this.getValueAtOffset(0),t=e,n=0;const i=this.getGeometry().getSize();let r=i.getTotalSize();i.length()>=3&&(r=i.getDimSize(3));for(let i=0;i<r;++i)n=this.getValueAtOffset(i),n>t&&(t=n),n<e&&(e=n);return{min:e,max:t}}calculateRescaledDataRange(){if(this.isIdentityRSI())return this.getDataRange();if(this.isConstantRSI()){const e=this.getDataRange(),t=this.getRescaleSlopeAndIntercept().apply(e.min),n=this.getRescaleSlopeAndIntercept().apply(e.max);return{min:t<n?t:n,max:t>n?t:n}}{let e=this.getRescaledValueAtOffset(0),t=e,n=0;const i=this.getGeometry().getSize();let r=i.getTotalSize();3===i.length()&&(r=i.getDimSize(3));for(let i=0;i<r;++i)n=this.getRescaledValueAtOffset(i),n>t&&(t=n),n<e&&(e=n);return{min:e,max:t}}}calculateHistogram(){const e=this.getGeometry().getSize(),t=[];let n=this.getValueAtOffset(0),i=n,r=0,o=this.getRescaledValueAtOffset(0),a=o,s=0;for(let l=0,c=e.getTotalSize();l<c;++l)r=this.getValueAtOffset(l),r>i&&(i=r),r<n&&(n=r),s=this.getRescaledValueAtOffset(l),s>a&&(a=s),s<o&&(o=s),t[s]=(t[s]||0)+1;const l={min:n,max:i},c={min:o,max:a},u=[];for(let e=o;e<=a;++e)u.push([e,t[e]||0]);return{dataRange:l,rescaledDataRange:c,histogram:u}}convolute2D(e){if(9!==e.length)throw new Error("The convolution matrix does not have a length of 9; it has "+e.length);const t=this.clone(),n=t.getBuffer(),i=this.getGeometry().getSize(),r=i.getDimSize(2)*this.getNumberOfComponents();for(let t=0;t<i.get(2);++t)this.convoluteBuffer(e,n,t*r);return t}convoluteBuffer(e,t,n){const i=this.getGeometry().getSize(),r=i.get(0),o=i.get(1),a=this.getNumberOfComponents();let s=1,l=1;3===a&&(0===this.getPlanarConfiguration()?s=3:l=i.getDimSize(2));const c=[];c[0]=(-r-1)*s,c[1]=-r*s,c[2]=(1-r)*s,c[3]=-s,c[4]=0,c[5]=1*s,c[6]=(r-1)*s,c[7]=r*s,c[8]=(r+1)*s;const u=[];u[0]=c[4],u[1]=c[4],u[2]=c[5],u[3]=c[4],u[4]=c[4],u[5]=c[5],u[6]=c[7],u[7]=c[7],u[8]=c[8];const d=[];d[0]=c[1],d[1]=c[1],d[2]=c[2],d[3]=c[4],d[4]=c[4],d[5]=c[5],d[6]=c[7],d[7]=c[7],d[8]=c[8];const h=[];h[0]=c[1],h[1]=c[1],h[2]=c[2],h[3]=c[4],h[4]=c[4],h[5]=c[5],h[6]=c[4],h[7]=c[4],h[8]=c[5];const S=[];S[0]=c[3],S[1]=c[4],S[2]=c[5],S[3]=c[3],S[4]=c[4],S[5]=c[5],S[6]=c[6],S[7]=c[7],S[8]=c[8];const g=[];g[0]=c[0],g[1]=c[1],g[2]=c[2],g[3]=c[3],g[4]=c[4],g[5]=c[5],g[6]=c[3],g[7]=c[4],g[8]=c[5];const p=[];p[0]=c[3],p[1]=c[4],p[2]=c[4],p[3]=c[3],p[4]=c[4],p[5]=c[4],p[6]=c[6],p[7]=c[7],p[8]=c[7];const m=[];m[0]=c[0],m[1]=c[1],m[2]=c[1],m[3]=c[3],m[4]=c[4],m[5]=c[4],m[6]=c[6],m[7]=c[7],m[8]=c[7];const f=[];f[0]=c[0],f[1]=c[1],f[2]=c[1],f[3]=c[3],f[4]=c[4],f[5]=c[4],f[6]=c[3],f[7]=c[4],f[8]=c[4];let D=n,y=0,C=[];for(let n=0;n<a;++n){D+=n*l;for(let n=0;n<o;++n)for(let i=0;i<r;++i){C=c,0===i&&0===n?C=u:0===i&&n===o-1?C=h:i===r-1&&0===n?C=p:i===r-1&&n===o-1?C=f:0===i&&n!==o-1&&0!==n?C=d:i===r-1&&n!==o-1&&0!==n?C=m:0!==i&&i!==r-1&&0===n?C=S:0!==i&&i!==r-1&&n===o-1&&(C=g),y=0;for(let t=0;t<9;++t)y+=this.getValueAtOffset(D+C[t])*e[t];t[D]=y,D+=s}}}transform(e){const t=this.clone(),n=t.getBuffer();for(let i=0,r=n.length;i<r;++i)n[i]=e(t.getValueAtOffset(i));return t}compose(e,t){const n=this.clone(),i=n.getBuffer();for(let n=0,r=i.length;n<r;++n)i[n]=Math.floor(t(this.getValueAtOffset(n),e.getValueAtOffset(n)));return n}}const Mn={CT:{mediastinum:new u(40,400),lung:new u(-500,1500),bone:new u(500,2e3),brain:new u(40,80),head:new u(90,350)}};class Qn{create(e,t){const n=new Bn(t);"MONOCHROME1"===t.getPhotometricInterpretation()&&n.setColourMap("invPlain");let i={};void 0!==t.getMeta().windowPresets&&(i=t.getMeta().windowPresets),i.minmax={name:"minmax"};const r=t.getMeta().Modality;let o;o=void 0!==L.wlPresets&&void 0!==L.wlPresets[r]?L.wlPresets[r]:Mn[r];for(const e in o){const t=o[e];i[e]={wl:[new u(t.center,t.width)],name:e}}return n.setWindowPresets(i),n.init(),n}}const Vn=["wlchange","wlpresetadd","colourmapchange","positionchange","opacitychange","alphafuncchange"];function Nn(e,t){return(new Qn).create(e,t)}class Bn{#qe;#Ue;#Ce;#Me={minmax:{name:"minmax"}};#Qe=null;#Ve;#Ne="plain";#Be=null;#K;#be=new He;constructor(e){this.#qe=e,this.#qe.addEventListener("appendframe",(()=>{const e=this.getCurrentIndex();if(3===e.length()){const t=e.getValues();t.push(0),this.setCurrentIndex(new s(t))}}))}getImage(){return this.#qe}setImage(e){this.#qe=e}getOrientation(){return this.#K}setOrientation(e){this.#K=e}init(){this.setInitialIndex()}setInitialIndex(){const e=this.#qe.getGeometry().getSize(),t=new Array(e.length());t.fill(0),t[0]=Math.floor(e.get(0)/2),t[1]=Math.floor(e.get(1)/2),t[2]=Math.floor(e.get(2)/2),this.setCurrentIndex(new s(t),!0)}getPlaybackMilliseconds(e){return e||(e=10),Math.round(1e3/e)}#Ge=function(e,t){return 255};getAlphaFunction(){return this.#Ge}setAlphaFunction(e){this.#Ge=e,this.#Fe({type:"alphafuncchange"})}#ke(){if(this.#Qe&&void 0!==this.#Me[this.#Qe]&&void 0!==this.#Me[this.#Qe].perslice&&!0===this.#Me[this.#Qe].perslice){this.getCurrentIndex()||this.setInitialIndex();const e=this.getCurrentIndex(),t=this.#qe.getSecondaryOffset(e),n=this.#Me[this.#Qe].wl[t];this.setWindowLevel(n,this.#Qe,!0)}if(void 0===this.#Ve&&this.setWindowLevelPresetById(0,!0),void 0===this.#Ce||this.#qe.isConstantRSI()!==this.#Ce){let e,t;this.#Ce=this.#qe.isConstantRSI(),this.#Ce?(e=this.#qe.getRescaleSlopeAndIntercept(),t=!0):(e=new je(1,0),t=!1);const n=new l(e,this.#qe.getMeta().BitsStored);this.#Ue=new h(n,this.#qe.getMeta().IsSigned,t)}const e=this.#Ue.getVoiLut();let t;if(void 0!==e&&(t=e.getWindowLevel()),void 0===e||!this.#Ve.equals(t)){const e=new d(this.#Ve);this.#Ue.setVoiLut(e)}return this.#Ue}getWindowPresets(){return this.#Me}getWindowPresetsNames(){return Object.keys(this.#Me)}setWindowPresets(e){this.#Me=e}addWindowPresets(e){const t=Object.keys(e);let n=null;for(let i=0;i<t.length;++i)if(n=t[i],void 0!==this.#Me[n]){if(void 0!==this.#Me[n].perslice&&!0===this.#Me[n].perslice)throw new Error("Cannot add perslice preset");this.#Me[n]=e[n]}else this.#Me[n]=e[n],this.#Fe({type:"wlpresetadd",name:n})}getCurrentWindowPresetName(){return this.#Qe}getColourMap(){return this.#Ne}#He(){return f[this.#Ne]}setColourMap(e){if(!f[e])throw new Error("Unknown colour map: '"+e+"'");this.#Ne=e,this.#Fe({type:"colourmapchange",value:[e]})}getCurrentPosition(){return this.#Be}getCurrentIndex(){const e=this.getCurrentPosition();return e?this.getImage().getGeometry().worldToIndex(e):null}getCurrentImageUid(){return this.#qe.getImageUid(this.getCurrentIndex())}getOriginForImageUid(e){return this.#qe.getOriginForImageUid(e)}includesImageUid(e){return this.#qe.includesImageUid(e)}isPositionInBounds(e){void 0===e&&(e=this.#Be);const t=this.#qe.getGeometry(),n=t.worldToIndex(e),i=[this.getScrollDimIndex()];return 4===n.length()&&i.push(3),t.isIndexInBounds(n,i)}getOrigin(e){const t=this.#qe.getGeometry();let n=0;return void 0!==e&&(n=t.worldToIndex(e).get(2)),t.getOrigins()[n]}setCurrentIndex(e,t){const n=this.#qe.getGeometry().indexToWorld(e);return this.setCurrentPosition(n,t)}setCurrentPosition(e,t){void 0===t&&(t=!1);const n=this.#qe.getGeometry(),i=n.worldToIndex(e),r=[this.getScrollDimIndex()];if(4===i.length()&&r.push(3),!n.isIndexInBounds(i,r))return this.#Be=e,t||this.#Fe({type:"positionchange",value:[i.getValues(),e.getValues()],valid:!1}),!1;let o=null,a=null;if(this.getCurrentPosition()&&(a=this.getCurrentIndex()),a)if(a.canCompare(i))o=a.compare(i);else{o=[];const e=Math.min(a.length(),i.length());for(let t=0;t<e;++t)a.get(t)!==i.get(t)&&o.push(t);const t=Math.max(a.length(),i.length());for(let n=e;n<t;++n)o.push(n)}else{o=[];for(let e=0;e<i.length();++e)o.push(e)}if(this.#Be=e,!t){const t={type:"positionchange",value:[i.getValues(),e.getValues()],diffDims:o,data:{imageUid:this.#qe.getImageUid(i)}};if(this.#qe.canQuantify()){const e=this.#qe.getRescaledValueAtIndex(i);t.value.push(e)}this.#Fe(t)}return!0}setWindowLevel(e,t,n){if(void 0===t&&(t="manual"),"manual"!==t&&void 0===this.#Me[t])throw new Error("Unknown window level preset: '"+t+"'");void 0===n&&(n=!1);const i=!e.equals(this.#Ve),r=this.#Qe!==t;(i||r)&&(this.#Ve=e,this.#Qe=t,"manual"===t&&(void 0!==this.#Me[t]?this.#Me[t].wl[0]=e:this.addWindowPresets({manual:{wl:[e],name:"manual"}})),this.#Fe({type:"wlchange",value:[e.center,e.width,t],wc:e.center,ww:e.width,skipGenerate:n}))}getWindowLevel(){return this.#ke().getVoiLut().getWindowLevel()}setWindowLevelPreset(e,t){const n=this.getWindowPresets()[e];if(void 0===n)throw new Error("Unknown window level preset: '"+e+"'");"minmax"===e&&void 0===n.wl&&(n.wl=[this.getWindowLevelMinMax()]);let i=n.wl[0];if(void 0!==n.perslice&&!0===n.perslice){const e=this.#qe.getSecondaryOffset(this.getCurrentIndex());i=n.wl[e]}this.setWindowLevel(i,e,t)}setWindowLevelPresetById(e,t){const n=Object.keys(this.getWindowPresets());this.setWindowLevelPreset(n[e],t)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)};getWindowLevelMinMax(){const e=this.getImage().getRescaledDataRange(),t=e.min;let n=e.max-t;return n<1&&(c.warn("Zero or negative window width, defaulting to one."),n=1),new u(t+n/2,n)}setWindowLevelMinMax(){const e=this.getWindowLevelMinMax();this.setWindowLevel(e,"minmax")}generateImageData(e,t){void 0===t&&(this.getCurrentIndex()||this.setInitialIndex(),t=this.getCurrentIndex());const n=this.getImage(),i=!n.isConstantRSI(),r=Ye(n,t,i,this.getOrientation()),o=n.getPhotometricInterpretation();switch(o){case"MONOCHROME1":case"MONOCHROME2":!function(e,t,n,i,r){let o=0,a=0,s=t.next();for(;!s.done;)a=i.getValue(s.value),e.data[o]=r.red[a],e.data[o+1]=r.green[a],e.data[o+2]=r.blue[a],e.data[o+3]=n(s.value,s.index),o+=4,s=t.next()}(e,r,this.getAlphaFunction(),this.#ke(),this.#He());break;case"PALETTE COLOR":!function(e,t,n,i,r){const o=function(e){return e>>8};r&&c.info("Scaling 16bits data to 8bits.");let a=0,s=0,l=t.next();for(;!l.done;)s=l.value,r?(e.data[a]=o(i.red[s]),e.data[a+1]=o(i.green[s]),e.data[a+2]=o(i.blue[s])):(e.data[a]=i.red[s],e.data[a+1]=i.green[s],e.data[a+2]=i.blue[s]),e.data[a+3]=n(s,l.index),a+=4,l=t.next()}(e,r,this.getAlphaFunction(),n.getPaletteColourMap(),16===n.getMeta().BitsStored);break;case"RGB":!function(e,t,n){let i=0,r=t.next();for(;!r.done;)e.data[i]=r.value[0],e.data[i+1]=r.value[1],e.data[i+2]=r.value[2],e.data[i+3]=n(r.value,r.index),i+=4,r=t.next()}(e,r,this.getAlphaFunction());break;case"YBR_FULL":!function(e,t,n){let i=0,r=null,o=t.next();for(;!o.done;)a=o.value[0],s=o.value[1],r={r:a+1.402*((l=o.value[2])-128),g:a-.34414*(s-128)-.71414*(l-128),b:a+1.772*(s-128)},e.data[i]=r.r,e.data[i+1]=r.g,e.data[i+2]=r.b,e.data[i+3]=n(o.value,o.index),i+=4,o=t.next();var a,s,l}(e,r,this.getAlphaFunction());break;default:throw new Error("Unsupported photometric interpretation: "+o)}}getScrollDimIndex(){let e=null;const t=this.getOrientation();return e=void 0!==t?t.getThirdColMajorDirection():2,e}isAquisitionOrientation(){return x(this.#K)}}class Gn{#ze;#j;#We;#Ye;#Xe;constructor(e,t){this.#ze=e,this.#j=e.getRealSpacing(),this.#We=e.getOrientation(),this.#Ye=t,this.#Xe=function(e,t){let n=e.asOneAndZeros().multiply(t);return e.asOneAndZeros().getAbs().equals(St().getAbs())&&(n=n.getAbs()),n}(this.#We,t)}getViewOrientation(){return this.#Ye}getTargetOrientation(){return this.#Xe}getOffset3DFromPlaneOffset(e){const t=new P(e.x,e.y,0),n=this.getTargetDeOrientedVector3D(t);return new P(n.getX()*this.#j.get(0),n.getY()*this.#j.get(1),n.getZ()*this.#j.get(2))}getPlaneOffsetFromOffset3D(e){const t=new P(e.x/this.#j.get(0),e.y/this.#j.get(1),e.z/this.#j.get(2)),n=this.getTargetOrientedVector3D(t);return{x:n.getX(),y:n.getY()}}getTargetOrientedVector3D(e){let t=e;return void 0!==this.#Xe&&(t=this.#Xe.getInverse().multiplyVector3D(e)),t}getTargetDeOrientedVector3D(e){let t=e;return void 0!==this.#Xe&&(t=this.#Xe.multiplyVector3D(e)),t}getTargetDeOrientedPoint3D(e){let t=e;return void 0!==this.#Xe&&(t=this.#Xe.multiplyPoint3D(e)),t}getImageOrientedVector3D(e){let t=e;if(void 0!==this.#Ye){const n=ot([e.getX(),e.getY(),e.getZ()],this.#Ye);t=new P(n[0],n[1],n[2])}return t}getImageOrientedPoint3D(e){let t=e;if(void 0!==this.#Ye){const n=ot([e.getX(),e.getY(),e.getZ()],this.#Ye);t=new F(n[0],n[1],n[2])}return t}getImageDeOrientedVector3D(e){let t=e;if(void 0!==this.#Ye){const n=rt([e.getX(),e.getY(),e.getZ()],this.#Ye);t=new P(n[0],n[1],n[2])}return t}getImageDeOrientedPoint3D(e){let t=e;if(void 0!==this.#Ye){const n=rt([e.getX(),e.getY(),e.getZ()],this.#Ye);t=new F(n[0],n[1],n[2])}return t}getPositionFromPlanePoint(e,t){const n=new F(e.getX(),e.getY(),t),i=this.getImageOrientedPoint3D(n);return this.#ze.pointToWorld(i)}getPlanePointFromPosition(e){const t=this.#ze.worldToPoint(e);return this.getImageDeOrientedPoint3D(t)}getCosines(){return[(e=this.#Xe).get(0,0),e.get(1,0),e.get(2,0),e.get(0,1),e.get(1,1),e.get(2,1)];var e}getPlanePoints(e){const t=this.worldToIndex(e),n=this.indexToWorld(t),i=this.getPlanePointFromPosition(n),r=this.getPositionFromPlanePoint(new R(0,0),i.getZ()),o=this.#ze.getOrigins(),a=o[r.getClosest(o)],s=r.getValues(),l=a.getValues(),c=this.getNativeScrollDimIndex();s[c]=l[c];const u=this.getCosines();return[new F(s[0],s[1],s[2]),new F(u[0],u[1],u[2]),new F(u[3],u[4],u[5])]}worldToIndex(e){return this.#ze.worldToIndex(e)}indexToWorld(e){return this.#ze.indexToWorld(e)}isAquisitionOrientation(){return x(this.#Ye)}getTargetOrientedPositiveXYZ(e){const t=rt([e.x,e.y,e.z],this.#Xe);return{x:t[0],y:t[1],z:t[2]}}getScrollDimIndex(){let e=null;return e=void 0!==this.#Ye?this.#Ye.getThirdColMajorDirection():2,e}getNativeScrollDimIndex(){let e=null;return e=void 0!==this.#We?this.#We.getThirdColMajorDirection():2,e}}class kn{#R;constructor(e){this.#R=e}getCurrentPosition(){return this.#R.getCurrentPosition()}setCurrentPosition(e,t){let n=!1;return void 0!==e&&(n=this.#R.setCurrentPosition(e,t)),n}}class Hn{#je;#me;#Ze;constructor(e){this.#je=new kn(e),this.#me=e.getImage().getGeometry(),this.#Ze=e.getScrollDimIndex()}getGeometry(){return this.#me}getScrollDimIndex(){return this.#Ze}getMaximumDimValue(e){return this.#me.getSize().get(e)-1}getMaximumScrollValue(){return this.getMaximumDimValue(this.#Ze)}getCurrentPosition(){return this.#je.getCurrentPosition()}getCurrentPositionDimValue(e){return this.getCurrentIndex().get(e)}getCurrentPositionScrollValue(){return this.getCurrentPositionDimValue(this.#Ze)}getCurrentPositionAtDimValue(e,t){const n=this.getCurrentIndex().getValues();return n[e]=t,this.#me.indexToWorld(new s(n))}getCurrentPositionAtScrollValue(e){return this.getCurrentPositionAtDimValue(this.#Ze,e)}getCurrentIndex(){return this.#me.worldToIndex(this.getCurrentPosition())}setCurrentPosition(e,t){let n=!1;return void 0!==e&&(n=this.#je.setCurrentPosition(e,t)),n}setCurrentPositionSafe(e,t){let n=!1;return this.isPositionInBounds(e)&&(n=this.setCurrentPosition(e,t)),n}merge(e){if(this.#Ze!==e.getScrollDimIndex())throw new Error("Cannot merge helper of a view with different orientation");this.#me=function(e,t){const n=function(e,t){return e.map(((e,n)=>Math.min(e,t[n])))},i=new Ze((r=e.getSize().getValues(),o=t.getSize().getValues(),r.map(((e,t)=>Math.max(e,o[t])))));var r,o;const a=new nt(n(e.getSpacing().getValues(),t.getSpacing().getValues())),s=e.getRange(),l=t.getRange(),c=n(s[0].getValues(),l[0].getValues()),u=[];for(let e=0;e<i.get(2);++e){const t=c.slice();t[2]=c[2]+e*a.get(2),u.push(new F(t[0],t[1],t[2]))}return new it(u,i,a,e.getOrientation())}(this.#me,e.getGeometry())}isPositionInBounds(e){const t=this.#me.worldToIndex(e),n=[this.#Ze];return 4===t.length()&&n.push(3),this.#me.isIndexInBounds(t,n)}getIncrementPosition(e){const t=this.getCurrentIndex().next(e);return this.#me.indexToWorld(t)}getDecrementPosition(e){const t=this.getCurrentIndex().previous(e);return this.#me.indexToWorld(t)}incrementPosition(e){return this.setCurrentPositionSafe(this.getIncrementPosition(e))}decrementPosition(e){return this.setCurrentPositionSafe(this.getDecrementPosition(e))}incrementPositionAlongScroll(){return this.incrementPosition(this.#Ze)}decrementPositionAlongScroll(){return this.decrementPosition(this.#Ze)}}class zn{#R;#_e;#Ke;#Je;#$e=!1;constructor(e){if(void 0===e.getImage())throw new Error("View does not have an image, cannot setup controller");this.#R=e,this.#_e=new Gn(e.getImage().getGeometry(),e.getOrientation()),this.#Ke=new Hn(e),"SEG"===e.getImage().getMeta().Modality&&(this.#$e=!0)}getPlaneHelper(){return this.#_e}isMask(){return this.#$e}initialise(){this.setWindowLevelPresetById(0),this.setCurrentPosition(this.getPositionFromPlanePoint(new R(0,0)))}getModality(){return this.#R.getImage().getMeta().Modality}getWindowLevelPresetsNames(){return this.#R.getWindowPresetsNames()}addWindowLevelPresets(e){return this.#R.addWindowPresets(e)}setWindowLevelPreset(e){this.#R.setWindowLevelPreset(e)}setWindowLevelPresetById(e){this.#R.setWindowLevelPresetById(e)}isPlaying(){return void 0!==this.#Je}getPositionHelper(){return this.#Ke}getCurrentPosition(){return this.#Ke.getCurrentPosition()}getCurrentIndex(){return this.#Ke.getCurrentIndex()}getCurrentImageUid(){return this.#R.getCurrentImageUid()}getOriginForImageUid(e){return this.#R.getOriginForImageUid(e)}includesImageUid(e){return this.#R.includesImageUid(e)}getCurrentOrientedIndex(){let e=this.getCurrentIndex();if(void 0!==this.#R.getOrientation()){const t=this.#_e.getImageDeOrientedVector3D(new P(e.get(0),e.get(1),e.get(2)));e=new s([t.getX(),t.getY(),t.getZ()])}return e}getScrollDimIndex(){return this.#R.getScrollDimIndex()}getCurrentIndexScrollValue(){return this.getCurrentIndex().get(this.#R.getScrollDimIndex())}getOrigin(e){return this.#R.getOrigin(e)}isAquisitionOrientation(){return this.#R.isAquisitionOrientation()}getPlanePoints(e){return this.#_e.getPlanePoints(e)}getCurrentScrollPosition(){const e=this.#R.getScrollDimIndex();return this.#R.getCurrentPosition().get(e)}generateImageData(e,t){this.#R.generateImageData(e,t)}setImage(e){this.#R.setImage(e)}get2DSpacing(){return this.#R.getImage().getGeometry().getSpacing(this.#R.getOrientation()).get2D()}getRescaledImageValue(e){const t=this.#R.getImage();if(!t.canQuantify())return;const n=t.getGeometry(),i=n.worldToIndex(e);let r;return n.isIndexInBounds(i)&&(r=t.getRescaledValueAtIndex(i)),r}getPixelUnit(){return this.#R.getImage().getMeta().pixelUnit}#et(e,t,n,i){const r=We(Ye(e,t,n,i)),o=e.getGeometry().getSize(i).getValues();o[2]=1;const a=new Ze(o),s=e.getGeometry().getSpacing(i).getValues();s[2]=1;const l=new nt(s),c=new F(0,0,0),u=new it([c],a,l);return new Un(u,r)}getImageRegionValues(e,t,n){let i=this.#R.getImage();const r=this.#R.getOrientation();let o=n,a=!0;x(r)||(i=this.#et(i,o,a,r),o=new s([0,0,0]),a=!1);const l=function(e,t,n,i,r){if(1!==e.getNumberOfComponents())throw new Error("Unsupported number of components for region iterator: "+e.getNumberOfComponents());void 0===n&&(n=!1);let o=null;o=n?function(t){return e.getRescaledValueAtOffset(t)}:function(t){return e.getValueAtOffset(t)};const a=e.getGeometry().getSize();void 0===i&&(i=new R(0,0)),void 0===r&&(r=new R(a.get(0)-1,a.get(1)));const s=a.indexToOffset(t.getWithNew2D(i.getX(),i.getY())),l=a.indexToOffset(t.getWithNew2D(r.getX(),r.getY()-1)),c=Math.max(1,r.getX()-i.getX());return function(e,t,n,i,r,o){let a=t,s=0;return{next:function(){if(a<n){const t={value:e(a),done:!1,index:a};return s+=1,a+=1,s===r&&(s=0,a+=o),t}return{done:!0,index:n}}}}(o,s,l+1,0,c,a.get(0)-c)}(i,o,a,e,t);let c=[];return l&&(c=We(l)),c}getImageVariableRegionValues(e,t){let n=this.#R.getImage();const i=this.#R.getOrientation();let r=t,o=!0;x(i)||(n=this.#et(n,r,o,i),r=new s([0,0,0]),o=!1);const a=function(e,t,n,i){if(1!==e.getNumberOfComponents())throw new Error("Unsupported number of components for region iterator: "+e.getNumberOfComponents());void 0===n&&(n=!1);let r=null;r=n?function(t){return e.getRescaledValueAtOffset(t)}:function(t){return e.getValueAtOffset(t)};const o=e.getGeometry().getSize(),a=[];let s,l=null,c=null,u=null;for(let e=0;e<i.length;++e){s=i[e];const t=s[1][0]-s[0][0];0!==t&&(u=e,l||(l=s[0]),a.push([s[0][0],t,o.get(0)-s[1][0]]))}if(null!==u&&(c=i[u][1]),0!==a.length)return function(e,t,n,i,r){let o=t,a=0,s=0;return{next:function(){if(o<n){const t={value:e(o),done:!1,index:o};return s+=1,o+=1,s===r[a][1]&&(s=0,o+=r[a][2],a+=1,a<r.length&&(o+=r[a][0])),t}return{done:!0,index:n}}}}(r,o.indexToOffset(t.getWithNew2D(l[0],l[1])),o.indexToOffset(t.getWithNew2D(c[0],c[1]))+1,0,a)}(n,r,o,e);let l=[];return a&&(l=We(a)),l}canQuantifyImage(){return this.#R.getImage().canQuantify()}canWindowLevel(){return this.isMonochrome()}isMonochrome(){return this.#R.getImage().isMonochrome()}canScroll(){return this.#R.getImage().canScroll(this.#R.getOrientation())}getImageSize(){return this.#R.getImage().getGeometry().getSize(this.#R.getOrientation())}moreThanOne(e){return this.getImageSize().moreThanOne(e)}getImageWorldSize(){const e=this.#R.getImage().getGeometry(),t=e.getSize(this.#R.getOrientation()).get2D(),n=e.getSpacing(this.#R.getOrientation()).get2D();return{x:t.x*n.x,y:t.y*n.y}}getImageRescaledDataRange(){return this.#R.getImage().getRescaledDataRange()}equalImageMeta(e){const t=this.#R.getImage().getMeta(),n=Object.keys(e);for(let i=0;i<n.length;++i){const r=n[i];if(void 0===t[r])return!1;if(t[r]!==e[r])return!1}return!0}isPositionInBounds(e){return this.#R.isPositionInBounds(e)}setCurrentPosition(e,t){return this.#R.setCurrentPosition(e,t)}getPositionFromPlanePoint(e,t){void 0===t&&(t=this.getCurrentIndexScrollValue());const n=new F(e.getX(),e.getY(),t),i=this.#_e.getImageOrientedPoint3D(n),r=this.#R.getImage().getGeometry().pointToWorld(i);return this.getCurrentPosition().mergeWith3D(r)}getPlanePositionFromPosition(e){const t=this.#R.getImage().getGeometry().worldToPoint(e),n=this.#_e.getImageDeOrientedPoint3D(t);return new R(n.getX(),n.getY())}getIndexFromPosition(e){return this.#R.getImage().getGeometry().worldToIndex(e)}setCurrentIndex(e,t){return this.#R.setCurrentIndex(e,t)}getPlanePositionFromPlanePoint(e){const t=this.getCurrentIndexScrollValue(),n=new F(e.getX(),e.getY(),t),i=this.#_e.getTargetDeOrientedPoint3D(n),r=this.#R.getImage().getGeometry().getRealSpacing();return new F(i.getX()*r.get(0),i.getY()*r.get(1),i.getZ()*r.get(2))}getOffset3DFromPlaneOffset(e){return this.#_e.getOffset3DFromPlaneOffset(e)}play(){if(this.canScroll())if(void 0===this.#Je){const e=this.#R.getImage(),t=e.getMeta().RecommendedDisplayFrameRate,n=this.#R.getPlaybackMilliseconds(t),i=e.getGeometry().getSize().canScroll3D();this.#Je=window.setInterval((()=>{let e=!1;if(e=i?this.#Ke.incrementPositionAlongScroll():this.#Ke.incrementPosition(3),!e){const e=this.getCurrentIndex().getValues(),t=this.#R.getOrientation();i?e[t.getThirdColMajorDirection()]=0:e[3]=0;const n=new s(e),r=this.#R.getImage().getGeometry();this.setCurrentPosition(r.indexToWorld(n))}}),n)}else this.stop()}stop(){void 0!==this.#Je&&(clearInterval(this.#Je),this.#Je=void 0)}getWindowLevel(){return this.#R.getWindowLevel()}getCurrentWindowPresetName(){return this.#R.getCurrentWindowPresetName()}setWindowLevel(e){this.#R.setWindowLevel(e)}getColourMap(){return this.#R.getColourMap()}setColourMap(e){this.#R.setColourMap(e)}setViewAlphaFunction(e){this.#R.setAlphaFunction(e)}bindImageAndLayer(e){const t=this.#R.getImage();t.addEventListener("imagecontentchange",e.onimagecontentchange),t.addEventListener("imagegeometrychange",e.onimagegeometrychange)}unbindImageAndLayer(e){const t=this.#R.getImage();t.removeEventListener("imagecontentchange",e.onimagecontentchange),t.removeEventListener("imagegeometrychange",e.onimagegeometrychange)}}const Wn=["mousedown","mousemove","mouseup","mouseout","wheel","dblclick","touchstart","touchmove","touchend"];function Yn(e){let t=0,n=0;if(0!==e.length&&void 0!==e[0].target){let i=e[0].target.offsetParent;for(;i;)isNaN(i.offsetLeft)||(t+=i.offsetLeft),isNaN(i.offsetTop)||(n+=i.offsetTop),i=i.offsetParent}else c.debug("No touch target offset parent.");const i=[];for(let r=0;r<e.length;++r)i.push(new R(e[r].pageX-t,e[r].pageY-n));return i}function Xn(e){let t=[];return void 0!==e.targetTouches&&0!==e.targetTouches.length?t=Yn(e.targetTouches):void 0!==e.changedTouches&&0!==e.changedTouches.length&&(t=Yn(e.changedTouches)),t}function jn(e){return new R(e.offsetX,e.offsetY)}function Zn(e,t){const n=document.createElement("canvas");n.width=e,n.height=t;const i=document.createElement("canvas");i.width=1,i.height=1;const r=n.getContext("2d"),o=i.getContext("2d");return r&&(r.fillRect(e-1,t-1,1,1),o.drawImage(n,e-1,t-1,1,1,0,0,1,1)),o&&0!==o.getImageData(0,0,1,1).data[3]}class _n{#tt;#nt=null;#it=null;#rt=null;#ot=null;#at=!0;#st=null;#lt;#ct;#ut=1;#dt={x:1,y:1};#ht={x:1,y:1};#St={x:1,y:1,z:1};#gt={x:0,y:0};#pt={x:0,y:0};#mt={x:0,y:0};#ft={x:0,y:0};#Dt={x:0,y:0};#yt=null;#Ct;#be=new He;#vt=!1;#It;#Tt;constructor(e){this.#tt=e,this.#tt.className+=" viewLayer"}getDataId(){return this.#Ct}getScale(){return this.#dt}getAbsoluteZoomOffset(){return{x:this.#ft.x*this.#ht.x,y:this.#ft.y*this.#ht.y}}setImageSmoothing(e){this.#vt=e}setView(e,t){this.#Ct=t,e.addEventListener("wlchange",this.#Lt),e.addEventListener("colourmapchange",this.#Pt),e.addEventListener("positionchange",this.#wt),e.addEventListener("alphafuncchange",this.#Ot);for(let t=0;t<Vn.length;++t)e.addEventListener(Vn[t],this.#Fe);this.#nt=new zn(e),this.bindImage()}getViewController(){return this.#nt}getImageData(){return this.#st}onimageset=e=>{this.#Ct===e.dataid&&(this.#nt.setImage(e.value[0]),this.#At(this.#nt.getImageSize().get2D()),this.#yt=!0)};bindImage(){this.#nt&&this.#nt.bindImageAndLayer(this)}unbindImage(){this.#nt&&this.#nt.unbindImageAndLayer(this)}onimagecontentchange=e=>{this.#Ct===e.dataid&&(this.#at=this.#nt.isPositionInBounds(),this.#yt=!0,this.draw())};onimagegeometrychange=e=>{if(this.#Ct===e.dataid){const e=this.#nt.getImageSize().get2D();if(this.#lt.x!==e.x||this.#lt.y!==e.y){if(void 0!==this.#It&&void 0!==this.#Tt){const e=this.#nt.getOrigin(),t=this.#Tt.minus(e),n=this.#nt.getOrigin(this.#nt.getCurrentPosition()),i=this.#It.minus(n);this.setBaseOffset(t,i)}this.#At(e),this.#yt=!0,this.draw()}}};getId(){return this.#tt.id}removeFromDOM(){this.#tt.remove()}getBaseSize(){return this.#lt}getImageWorldSize(){return this.#nt.getImageWorldSize()}getOpacity(){return this.#ut}setOpacity(e){if(e===this.#ut)return;this.#ut=Math.min(Math.max(e,0),1);const t={type:"opacitychange",value:[this.#ut]};this.#Fe(t)}addFlipOffsetX(){this.#Dt.x+=this.#it.width/this.#dt.x,this.#gt.x+=this.#Dt.x}addFlipOffsetY(){this.#Dt.y+=this.#it.height/this.#dt.y,this.#gt.y+=this.#Dt.y}flipScaleX(){this.#St.x*=-1}flipScaleY(){this.#St.y*=-1}flipScaleZ(){this.#St.z*=-1}setScale(e,t){const n=this.#nt.getPlaneHelper(),i=n.getTargetOrientedPositiveXYZ({x:e.x*this.#St.x,y:e.y*this.#St.y,z:e.z*this.#St.z}),r={x:this.#ht.x*i.x,y:this.#ht.y*i.y};if(1===Math.abs(e.x)&&1===Math.abs(e.y)&&1===Math.abs(e.z)){const e={x:this.#gt.x-this.#ft.x,y:this.#gt.y-this.#ft.y};this.#ft={x:0,y:0},this.#gt=e}else if(void 0!==t){let e=n.getPlaneOffsetFromOffset3D({x:t.getX(),y:t.getY(),z:t.getZ()});e={x:e.x+this.#pt.x,y:e.y+this.#pt.y};const i=Ji(this.#gt,this.#dt,r,e),o={x:this.#ft.x+i.x-this.#gt.x,y:this.#ft.y+i.y-this.#gt.y};this.#ft=o,this.#gt=i}this.#dt=r}initScale(e,t){const n=this.#nt.getPlaneHelper().getTargetOrientedPositiveXYZ({x:e.x*this.#St.x,y:e.y*this.#St.y,z:e.z*this.#St.z}),i={x:this.#ht.x*n.x,y:this.#ht.y*n.y};this.#dt=i,this.#ft={x:t.x/this.#ht.x,y:t.y/this.#ht.y},this.#gt={x:this.#gt.x+this.#ft.x,y:this.#gt.y+this.#ft.y}}setBaseOffset(e,t,n,i){const r=this.#nt.getPlaneHelper(),o=r.getNativeScrollDimIndex(),a=r.getPlaneOffsetFromOffset3D({x:0===o?e.getX():t.getX(),y:1===o?e.getY():t.getY(),z:2===o?e.getZ():t.getZ()}),s=this.#pt.x!==a.x||this.#pt.y!==a.y;return void 0!==n&&void 0!==i&&(this.#It=n,this.#Tt=i),s&&(this.#gt={x:this.#gt.x-this.#pt.x+a.x,y:this.#gt.y-this.#pt.y+a.y},this.#pt=a),s}setOffset(e){const t=this.#nt.getPlaneHelper().getPlaneOffsetFromOffset3D(e);this.#gt={x:t.x+this.#mt.x+this.#pt.x+this.#ft.x+this.#Dt.x,y:t.y+this.#mt.y+this.#pt.y+this.#ft.y+this.#Dt.y}}displayToPlaneIndex(e){const t=this.displayToPlanePos(e);return new s([Math.floor(t.getX()),Math.floor(t.getY())])}displayToPlaneScale(e){return new R(e.getX()/this.#dt.x,e.getY()/this.#dt.y)}displayToPlanePos(e){const t=this.displayToPlaneScale(e);return new R(t.getX()+this.#gt.x,t.getY()+this.#gt.y)}planePosToDisplay(e){let t=(e.getX()-this.#gt.x+this.#pt.x)*this.#dt.x,n=(e.getY()-this.#gt.y+this.#pt.y)*this.#dt.y;return(t<0||t>=this.#it.width)&&(t=void 0),(n<0||n>=this.#it.height)&&(n=void 0),new R(t,n)}displayToMainPlanePos(e){const t=this.displayToPlanePos(e);return new R(t.getX()-this.#pt.x,t.getY()-this.#pt.y)}display(e){this.#tt.style.display=e?"":"none"}isVisible(){return""===this.#tt.style.display}draw(){if(!this.#at)return;let e={type:"renderstart",layerid:this.getId(),dataid:this.getDataId()};this.#Fe(e),this.#yt&&this.#bt(),this.#ot.globalAlpha=this.#ut,this.clear(),this.#ot.setTransform(this.#dt.x,0,0,this.#dt.y,-1*this.#gt.x*this.#dt.x,-1*this.#gt.y*this.#dt.y),this.#ot.imageSmoothingEnabled=this.#vt,this.#ot.drawImage(this.#rt,0,0),e={type:"renderend",layerid:this.getId(),dataid:this.getDataId()},this.#Fe(e)}initialise(e,t,n){this.#ct=t,this.#ut=Math.min(Math.max(n,0),1),this.#it=document.createElement("canvas"),this.#tt.appendChild(this.#it),this.#it.getContext?(this.#ot=this.#it.getContext("2d"),this.#ot?(this.#rt=document.createElement("canvas"),this.#At(e),this.#yt=!0):alert("Error: failed to get the 2D context.")):alert("Error: no canvas.getContext method.")}#At(e){if(!Zn(e.x,e.y))throw new Error("Cannot create canvas with size "+e.x+", "+e.y);this.#lt=e,this.#rt.width=this.#lt.x,this.#rt.height=this.#lt.y,this.#ot.clearRect(0,0,this.#lt.x,this.#lt.y),this.#st=this.#ot.createImageData(this.#lt.x,this.#lt.y)}fitToContainer(e,t,n){let i=!1;if(this.#it.width!==e.x||this.#it.height!==e.y){if(!Zn(e.x,e.y))throw new Error("Cannot resize canvas "+e.x+", "+e.y);this.#it.width=e.x,this.#it.height=e.y,i=!0}const r={x:t*this.#ct.x,y:t*this.#ct.y},o={x:this.#dt.x*r.x/this.#ht.x,y:this.#dt.y*r.y/this.#ht.y};this.#dt.x===o.x&&this.#dt.y===o.y||(this.#ht=r,this.#dt=o,i=!0);const a={x:n.x/r.x,y:n.y/r.y},s={x:e.x/r.x,y:e.y/r.y},l={x:0!==this.#Dt.x?s.x:0,y:0!==this.#Dt.y?s.y:0};this.#mt.x===a.x&&this.#mt.y===a.y&&this.#Dt.x===l.x&&this.#Dt.y===l.y||(this.#gt={x:this.#gt.x+a.x-this.#mt.x+l.x-this.#Dt.x,y:this.#gt.y+a.y-this.#mt.y+l.y-this.#Dt.y},this.#Dt=l,this.#mt=a,i=!0),i&&this.draw()}bindInteraction(){this.#tt.style.pointerEvents="auto";const e=Wn;for(let t=0;t<e.length;++t){const n=e[t],i="wheel"!==n;this.#tt.addEventListener(n,this.#Fe,{passive:i})}}unbindInteraction(){this.#tt.style.pointerEvents="none";const e=Wn;for(let t=0;t<e.length;++t)this.#tt.removeEventListener(e[t],this.#Fe)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{e.srclayerid=this.getId(),e.dataid=this.#Ct,this.#be.fireEvent(e)};#bt(){this.#nt.generateImageData(this.#st),this.#rt.getContext("2d").putImageData(this.#st,0,0),this.#yt=!1}#Lt=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#yt=!0,this.draw())};#Pt=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#yt=!0,this.draw())};#wt=e=>{if(void 0===e.skipGenerate||!0!==e.skipGenerate){let t=!0;if(void 0!==e.valid&&(t=e.valid),t){const t=[0,1,2],n=t.indexOf(this.#nt.getScrollDimIndex());t.splice(n,1),0===e.diffDims.filter((function(e){return-1===t.indexOf(e)})).length&&this.#at||(this.#at=!0,this.#yt=!0,this.draw())}else this.#at&&(this.#at=!1,this.clear())}};#Ot=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#yt=!0,this.draw())};setCurrentPosition(e,t){return this.#nt.setCurrentPosition(e)}clear(){this.#ot.save(),this.#ot.setTransform(1,0,0,1,0,0),this.#ot.clearRect(0,0,this.#it.width,this.#it.height),this.#ot.restore()}}class Kn{#xt=0;getSum(){return this.#xt}add(e){this.#xt+=function(e){if(void 0===e.wheelDeltaY)return-e.deltaY;{const t=45;return e.wheelDeltaY>t?1:e.wheelDeltaY<-t?-1:-e.deltaY/60}}(e)}clear(){this.#xt=0}isTick(){return Math.abs(this.#xt)>=1}}class Jn{#Rt;#Ft=new Kn;constructor(e){this.#Rt=e}wheel(e){this.#Ft.add(e);const t=this.#Ft.getSum()>=0;if(!this.#Ft.isTick())return;this.#Ft.clear(),e.preventDefault();const n=Ki(e),i=this.#Rt.getLayerGroupByDivId(n.groupDivId),r=i.getPositionHelper();i.canScroll()?t?r.incrementPositionAlongScroll():r.decrementPositionAlongScroll():i.moreThanOne(3)&&(t?r.incrementPosition(3):r.decrementPosition(3))}}class $n{#Et;#qt;constructor(e,t){this.#Et=e,this.#qt=t}getBegin(){return this.#Et}getEnd(){return this.#qt}equals(e){return null!==e&&this.getBegin().equals(e.getBegin())&&this.getEnd().equals(e.getEnd())}getDeltaX(){return this.getEnd().getX()-this.getBegin().getX()}getDeltaY(){return this.getEnd().getY()-this.getBegin().getY()}getLength(){return Math.sqrt(this.getDeltaX()*this.getDeltaX()+this.getDeltaY()*this.getDeltaY())}getWorldLength(e){let t=null;if(null!==e){const n=this.getDeltaX()*e.x,i=this.getDeltaY()*e.y;t=Math.sqrt(n*n+i*i)}return t}getMidpoint(){return new R((this.getBegin().getX()+this.getEnd().getX())/2,(this.getBegin().getY()+this.getEnd().getY())/2)}getCentroid(){return this.getMidpoint()}getSlope(){return this.getDeltaY()/this.getDeltaX()}getIntercept(){return(this.getEnd().getX()*this.getBegin().getY()-this.getBegin().getX()*this.getEnd().getY())/this.getDeltaX()}getInclination(){return 180-180*Math.atan2(this.getDeltaY(),this.getDeltaX())/Math.PI}quantify(e){const t={},n=e.get2DSpacing(),i=this.getWorldLength(n);return null!==i&&(t.length={value:i,unit:"unit.mm"}),t}}function ei(e,t){const n=e.getDeltaX(),i=e.getDeltaY(),r=t.getDeltaX(),o=t.getDeltaY(),a=n*r+i*o,s=n*o-i*r;return 360-(180-180*Math.atan2(s,a)/Math.PI)}function ti(e,t){const n=e.getDeltaX(),i=e.getDeltaY();return n*t.getDeltaX()+i*t.getDeltaY()==0}function ni(e,t,n,i){void 0===i&&(i={x:1,y:1});const r=-i.x*i.x/(i.y*i.y*e.getSlope());return ri(r,t.getY()-r*t.getX(),t,n,i)}function ii(e,t,n,i){const r=ri(e.getSlope(),e.getIntercept(),e.getBegin(),t,i);let o;return o=function(e,t){const n=Math.min(t.getBegin().getX(),t.getEnd().getX()),i=Math.max(t.getBegin().getX(),t.getEnd().getX()),r=Math.min(t.getBegin().getY(),t.getEnd().getY()),o=Math.max(t.getBegin().getY(),t.getEnd().getY());return e.getX()>=n&&e.getX()<=i&&e.getY()>=r&&e.getY()<=o}(r.getBegin(),e)?r.getBegin():r.getEnd(),ni(e,o,n,i)}function ri(e,t,n,i,r){void 0===r&&(r={x:1,y:1});let o=0,a=0,s=0,l=0;if(O(e,0,w))o=n.getX()-i/(2*r.x),a=n.getY(),s=n.getX()+i/(2*r.x),l=n.getY();else if(Math.abs(e)>1e6)o=n.getX(),a=n.getY()-i/(2*r.y),s=n.getX(),l=n.getY()+i/(2*r.y);else{const c=r.x*r.x,u=r.y*r.y,d=i/(2*Math.sqrt(c+u*e*e));o=n.getX()-d,a=e*o+t,s=n.getX()+d,l=e*s+t}return new $n(new R(o,a),new R(s,l))}var oi=o(944),ai=o.n(oi);class si{#Ut;#Mt;constructor(e,t){this.#Ut=e,this.#Mt=t}getName(){return"AddAnnotation-"+this.#Ut.id}execute(){this.#Mt.addAnnotation(this.#Ut)}undo(){this.#Mt.removeAnnotation(this.#Ut.id)}}class li{#Ut;#Mt;constructor(e,t){this.#Ut=e,this.#Mt=t}getName(){return"RemoveAnnotation-"+this.#Ut.id}execute(){this.#Mt.removeAnnotation(this.#Ut.id)}undo(){this.#Mt.addAnnotation(this.#Ut)}}class ci{#Ut;#Mt;#Qt;#Vt;constructor(e,t,n,i){this.#Ut=e,this.#Mt=i,this.#Qt=t,this.#Vt=n}getName(){return"UpdateAnnotation-"+this.#Ut.id}execute(){const e=Object.keys(this.#Vt);for(const t of e)this.#Ut[t]=this.#Vt[t];this.#Mt.updateAnnotation(this.#Ut,e)}undo(){const e=Object.keys(this.#Qt);for(const t of e)this.#Ut[t]=this.#Qt[t];this.#Mt.updateAnnotation(this.#Ut,e)}}class ui{#Nt=10;#Bt="Verdana";#Gt="#fff";#kt="#ffff80";#Ht={x:1,y:1};#zt={x:1,y:1};#Wt=2;#Yt={x:.25,y:.25};#Xt=.2;#jt=3;getFontFamily(){return this.#Bt}getFontSize(){return this.#Nt}getStrokeWidth(){return this.#Wt}getTextColour(){return this.#Gt}getLineColour(){return this.#kt}setLineColour(e){this.#kt=e}setBaseScale(e){this.#Ht=e}setZoomScale(e){this.#zt=e}getBaseScale(){return this.#Ht}getZoomScale(){return this.#zt}scale(e){return e/this.#Ht.x}applyZoomScale(e){return{x:e/this.#zt.x,y:e/this.#zt.y}}applyZoomRatio(e){return e*this.#zt.x/this.#zt.y}getShadowOffset(){return this.#Yt}getTagOpacity(){return this.#Xt}getTextPadding(){return this.#jt}getFontStr(){return"normal "+this.getFontSize()+"px sans-serif"}getLineHeight(){return this.getFontSize()+this.getFontSize()/5}getScaledFontSize(){return this.scale(this.getFontSize())}getScaledStrokeWidth(){return this.scale(this.getStrokeWidth())}getShadowLineColour(){return e=this.getLineColour(),n=e,.001172549*(t={r:parseInt(n.substring(1,3),16),g:parseInt(n.substring(3,5),16),b:parseInt(n.substring(5,7),16)}).r+.002301961*t.g+447059e-9*t.b<.5?"#fff":"#000";var e,t,n}}const di={arrow:{"*":""},circle:{"*":"{surface}"},ellipse:{"*":"{surface}"},protractor:{"*":"{angle}"},rectangle:{"*":"{surface}"},roi:{"*":""},ruler:{"*":"{length}"}};function hi(e){return"label"===e.name()}function Si(e){return"shape"===e.name()}function gi(e){return"position-group"===e.name()}function pi(e){const t=e.getChildren(Si)[0];if(t instanceof ai().Line)return t}function mi(e,t){const n=e.getChildren((function(e){return e.id()==="anchor"+t}))[0];if(n instanceof ai().Ellipse)return n}function fi(e){return function(t){return t.id()===e}}function Di(e,t,n,i){const r=i.applyZoomScale(6),o={x:Math.abs(r.x),y:Math.abs(r.y)};return new(ai().Ellipse)({x:e,y:t,stroke:"#999",fill:"rgba(100,100,100,0.7",strokeWidth:i.getStrokeWidth(),strokeScaleEnabled:!1,radius:o,radiusX:o.x,radiusY:o.y,name:"anchor",id:n.toString(),dragOnTop:!1,draggable:!0,visible:!1})}function yi(e){return parseInt(e.substring(6),10)}class Ci{#Rt;#Zt;constructor(e,t){this.#Rt=e,this.#Zt=t}#_t=null;#Kt=null;#Jt;#Ut;#$t=!1;setShape(e,t,n){if(this.#Kt=e,this.#Jt=t,this.#Ut=n,this.#Kt){if(this.#en(),this.#_t=n.getFactory(),null===this.#_t)throw new Error("Could not find a factory to update shape.");this.#tn()}}getShape(){return this.#Kt}getAnnotation(){return this.#Ut}isActive(){return this.#$t}enable(){this.#$t=!0,this.#Kt&&(this.#nn(!0),this.#Kt.getLayer()&&this.#Kt.getLayer().draw())}disable(){this.#$t=!1,this.#Kt&&(this.#nn(!1),this.#Kt.getLayer()&&this.#Kt.getLayer().draw())}reset(){this.#Kt=void 0,this.#Jt=void 0,this.#Ut=void 0}resetAnchors(){this.#en(),this.#tn(),this.#nn(!0)}#in(e){this.#Kt&&this.#Kt.getParent()&&this.#Kt.getParent().find(".anchor").forEach(e)}#nn(e){this.#in((function(t){t.visible(e)}))}setAnchorsActive(e){let t=null;t=e?e=>{this.#rn(e)}:e=>{this.#on(e)},this.#in(t)}#en(){this.#in((function(e){e.remove()}))}#tn(){if(!this.#Kt||!this.#Kt.getLayer())return;const e=this.#Kt.getParent(),t=this.#_t.getAnchors(this.#Kt,this.#Rt.getStyle());for(let n=0;n<t.length;++n)this.#rn(t[n]),e.add(t[n])}#rn(e){let t;e.on("dragstart.edit",(e=>{e.cancelBubble=!0,t={mathShape:this.#Ut.mathShape,referencePoints:this.#Ut.referencePoints}})),e.on("dragmove.edit",(e=>{const t=e.target;t instanceof ai().Shape&&(function(e,t){const n=t.getParent();!function(e,t,n){let i=!1;e.x()<t.getX()?(e.x(t.getX()),i=!0):e.x()>n.getX()&&(e.x(n.getX()),i=!0),e.y()<t.getY()?(e.y(t.getY()),i=!0):e.y()>n.getY()&&(e.y(n.getY()),i=!0)}(t,new R(-n.x(),-n.y()),new R(e.x-n.x(),e.y-n.y()))}(this.#Jt.getBaseSize(),t),void 0!==this.#_t.constrainAnchorMove&&this.#_t.constrainAnchorMove(t),this.#_t.updateAnnotationOnAnchorMove(this.#Ut,t),this.#_t.updateShapeGroupOnAnchorMove(this.#Ut,t,this.#Rt.getStyle()),t.getLayer()?t.getLayer().draw():c.warn("No layer to draw the anchor!"),e.cancelBubble=!0)})),e.on("dragend.edit",(e=>{const n={mathShape:this.#Ut.mathShape,referencePoints:this.#Ut.referencePoints},i=new ci(this.#Ut,t,n,this.#Jt.getDrawController());this.#Rt.addToUndoStack(i),this.#Zt({type:"annotationupdate",data:this.#Ut,dataid:this.#Jt.getDataId(),keys:Object.keys(n)}),t={mathShape:n.mathShape,referencePoints:n.referencePoints},e.cancelBubble=!0})),e.on("mousedown touchstart",(e=>{e.target.moveToTop()})),e.on("mouseover.edit",(e=>{const t=e.target;t instanceof ai().Shape&&(t.stroke("#ddd"),t.getLayer()?t.getLayer().draw():c.warn("No layer to draw the anchor!"))})),e.on("mouseout.edit",(e=>{const t=e.target;t instanceof ai().Shape&&(t.stroke("#999"),t.getLayer()?t.getLayer().draw():c.warn("No layer to draw the anchor!"))}))}#on(e){e.off("dragstart.edit"),e.off("dragmove.edit"),e.off("dragend.edit"),e.off("mousedown touchstart"),e.off("mouseover.edit"),e.off("mouseout.edit")}}class vi{#an;constructor(){this.createTrashIcon()}createTrashIcon(){this.#an=new(ai().Group);const e=new(ai().Line)({points:[-10,-10,10,10],stroke:"red"}),t=new(ai().Line)({points:[10,-10,-10,10],stroke:"red"});this.#an.width(20),this.#an.height(20),this.#an.add(e),this.#an.add(t)}activate(e){const t=e.getKonvaStage(),n=t.scale(),i=e.getKonvaLayer(),r={x:1/n.x,y:1/n.y};this.#an.x(t.offset().x+t.width()/(2*n.x)),this.#an.y(t.offset().y+t.height()/(15*n.y)),this.#an.scale(r),i.add(this.#an),i.draw()}changeChildrenColourOnTrashHover(e,t,n){if(this.isOverTrash(e))return this.changeGroupChildrenColour(this.#an,"orange"),void this.changeGroupChildrenColour(t,"red");this.changeGroupChildrenColour(this.#an,"red"),this.changeGroupChildrenColour(t,n)}changeGroupChildrenColour(e,t){e.getChildren().forEach((function(e){e instanceof ai().Shape&&void 0!==e.stroke&&e.stroke(t)}))}remove(){this.#an.remove()}isOverTrash(e){const t=this.#an.width()*Math.abs(this.#an.scaleX())/2,n=this.#an.height()*Math.abs(this.#an.scaleY())/2;return Math.abs(e.x-this.#an.x())<t&&Math.abs(e.y-this.#an.y())<n}}class Ii{#Rt;#sn;#an;#ln="pointer";#cn;#un;#Zt;constructor(e,t){this.#Rt=e,this.#Zt=t,this.#sn=new Ci(e,t),this.#an=new vi}setEditorShape(e,t){const n=t.getDrawController();e&&e instanceof ai().Shape&&e!==this.#sn.getShape()&&n.isAnnotationGroupEditable()&&(this.#sn.disable(),this.#sn.setShape(e,t,t.getDrawController().getAnnotation(e.getParent().id())),this.#sn.enable())}getEditorShapeGroup(){let e;if(!this.#sn.isActive()||(e=this.#sn.getShape().getParent(),e instanceof ai().Group))return e}getEditorAnnotation(){let e;return this.#sn.isActive()&&(e=this.#sn.getAnnotation()),e}disableAndResetEditor(){this.#sn.disable(),this.#sn.reset()}#dn(e,t){const n=t.getKonvaStage();return{x:n.offset().x+e.x/n.scale().x,y:n.offset().y+e.y/n.scale().y}}storeMouseOverCursor(e){this.#ln=e}#hn(){this.#cn=document.body.style.cursor,document.body.style.cursor=this.#ln,this.#un.opacity(.75)}onMouseOutShapeGroup(){void 0!==this.#cn&&(document.body.style.cursor=this.#cn,this.#cn=void 0),void 0!==this.#un&&this.#un.opacity(1)}#Sn(e){e.on("mouseover",(()=>{this.#un=e,this.#hn()})),e.on("mouseout",(()=>{this.onMouseOutShapeGroup(),this.#un=void 0}))}#gn(e){e.off("mouseover"),e.off("mouseout")}addShapeGroupListeners(e,t,n){this.#Sn(e),this.#pn(e,t,n),this.#mn(e,t,n),e.on("dblclick",(()=>{const e=t.textExpr,i=t=>{const i=t.textExpr,r=new ci(t,{textExpr:e},{textExpr:i},n.getDrawController());this.#Rt.addToUndoStack(r),r.execute()};void 0!==L.openRoiDialog?L.openRoiDialog(t,i):function(e,t){const n=prompt("Label",e.textExpr);null!==n&&(e.textExpr=n,t(e))}(t,i)}))}#pn(e,t,n){const i=n.getKonvaLayer(),r=e.getChildren(Si)[0];if(!(r instanceof ai().Shape))return;let o,a,s,l;r.draggable(!0),r.on("dragstart.draw",(e=>{l=r.stroke(),o={x:r.x(),y:r.y()},a={x:e.target.x(),y:e.target.y()},s={mathShape:t.mathShape,referencePoints:t.referencePoints},this.#an.activate(n),this.#sn.setAnchorsActive(!1),i.draw()})),r.on("dragmove.draw",(o=>{const s=function(e,t){return{min:new R(0,0),max:new R(e.x-Math.abs(t.width()),e.y-Math.abs(t.height()))}}(n.getBaseSize(),r);if(s&&!function(e,t,n){const i=e.getClientRect({relativeTo:e.getParent()});return i.x>t.getX()&&i.x<n.getX()&&i.y>t.getY()&&i.y<n.getY()}(r,s.min,s.max))return r.x(a.x),void r.y(a.y);const c={x:o.target.x()-a.x,y:o.target.y()-a.y},u=e.getChildren(),d=void 0===t.labelPosition;for(const e of u)e===o.target||"label"===e.name()&&!d||"connector"===e.name()||e.move(c);a={x:o.target.x(),y:o.target.y()};const h=t.getFactory();h.updateAnnotationOnTranslation(t,c),h.updateLabelContent(t,e,this.#Rt.getStyle()),h.updateConnector(e);const S=jn(o.evt),g={x:S.getX(),y:S.getY()},p=this.#dn(g,n);this.#an.changeChildrenColourOnTrashHover(p,e,l),i.draw()})),r.on("dragend.draw",(a=>{if(this.#an.remove(),void 0===a||void 0===a.evt)return;const c=r.x(),u=r.y(),d=jn(a.evt),h={x:d.getX(),y:d.getY()},S=this.#dn(h,n);if(this.#an.isOverTrash(S)){e.x(o.x),e.y(o.y),this.#sn.disable(),this.#sn.reset(),this.#an.changeGroupChildrenColour(e,l),t.mathShape=s.mathShape,t.referencePoints=s.referencePoints;const i=new li(t,n.getDrawController());this.#Rt.addToUndoStack(i),i.execute(),this.onMouseOutShapeGroup()}else{const e={x:c-o.x,y:u-o.y};if(0!==e.x||0!==e.y){const e={mathShape:t.mathShape,referencePoints:t.referencePoints},i=new ci(t,s,e,n.getDrawController());this.#Rt.addToUndoStack(i),this.#Zt({type:"annotationupdate",data:t,dataid:n.getDataId(),keys:Object.keys(e)}),s={mathShape:e.mathShape,referencePoints:e.referencePoints}}this.#sn.setAnchorsActive(!0),this.#sn.resetAnchors()}i.draw(),o={x:r.x(),y:r.y()}}))}#mn(e,t,n){const i=e.getChildren(hi)[0];if(!(i instanceof ai().Label))return;let r,o;i.draggable(!0),i.on("dragstart.draw",(()=>{r={x:i.x(),y:i.y()},o=t.labelPosition})),i.on("dragmove.draw",(()=>{t.getFactory().updateConnector(e)})),i.on("dragend.draw",(()=>{const e=i.x()-r.x,a=i.y()-r.y;if(0!==e||0!==a){const e=new R(i.x(),i.y());t.labelPosition=e;const r=new ci(t,{labelPosition:o},{labelPosition:e},n.getDrawController());this.#Rt.addToUndoStack(r),this.#Zt({type:"annotationupdate",data:t,dataid:n.getDataId(),keys:["labelPosition"]}),o=e}r={x:i.x(),y:i.y()}}))}removeShapeListeners(e){this.#gn(e),e.off("dblclick");const t=e.getChildren(Si)[0];t instanceof ai().Shape&&(t.draggable(!1),t.off("dragstart.draw"),t.off("dragmove.draw"),t.off("dragend.draw"));const n=e.getChildren(hi)[0];n instanceof ai().Label&&(n.draggable(!1),n.off("dragstart.draw"),n.off("dragend.draw"))}}class Ti{#fn=[];constructor(e){void 0!==e&&(this.#fn=e)}getPoint(e){return this.#fn[e]}getPoints(){return this.#fn}getLength(){return this.#fn.length}addPoint(e){this.#fn.push(e)}addPoints(e){this.#fn=this.#fn.concat(e)}getCentroid(){let e=0,t=0,n=0;for(let i=0;i<this.#fn.length;++i){const r=this.#fn[i];let o;o=i===this.#fn.length-1?this.#fn[0]:this.#fn[i+1];const a=r.getX()*o.getY()-o.getX()*r.getY();e+=a,t+=(r.getX()+o.getX())*a,n+=(r.getY()+o.getY())*a}e*=.5;const i=1/(6*e);return t*=i,n*=i,new R(t,n)}}var Li=o(324),Pi=o.n(Li);class wi{constructor(e,t){this.pointArray=e?e.slice():[],this.controlPointIndexArray=t?t.slice():[]}getPoint(e){return this.pointArray[e]}isControlPoint(e){const t=this.pointArray.indexOf(e);if(-1!==t)return-1!==this.controlPointIndexArray.indexOf(t);throw new Error("Error: isControlPoint called with not in list point.")}getLength(){return this.pointArray.length}addPoint(e){this.pointArray.push(e)}addControlPoint(e){const t=this.pointArray.indexOf(e);if(-1===t)throw new Error("Cannot mark a non registered point as control point.");this.controlPointIndexArray.push(t)}addPoints(e){this.pointArray=this.pointArray.concat(e)}appenPath(e){const t=this.pointArray.length;this.pointArray=this.pointArray.concat(e.pointArray);const n=[];for(let i=0;i<e.controlPointIndexArray.length;++i)n[i]=e.controlPointIndexArray[i]+t;this.controlPointIndexArray=this.controlPointIndexArray.concat(n)}}class Oi{constructor(e,t){this.bucketCount=1<<e,this.mask=this.bucketCount-1,this.size=0,this.loc=0,this.cost=void 0!==t?t:function(e){return e},this.buckets=this.buildArray(this.bucketCount)}push(e){const t=this.getBucket(e);e.next=this.buckets[t],this.buckets[t]=e,this.size++}pop(){if(0===this.size)throw new Error("Cannot pop, bucketQueue is empty.");for(;null===this.buckets[this.loc];)this.loc=(this.loc+1)%this.bucketCount;const e=this.buckets[this.loc];return this.buckets[this.loc]=e.next,e.next=null,this.size--,e}remove(e){if(!e)return!1;const t=this.getBucket(e);let n=this.buckets[t];for(;null!==n&&(null===n.next||e.x!==n.next.x||e.y!==n.next.y);)n=n.next;return null!==n&&(n.next=n.next.next,this.size--,!0)}isEmpty(){return 0===this.size}getBucket(e){return this.cost(e)&this.mask}buildArray(e){const t=new Array(e);for(let e=0;e<t.length;e++)t[e]=null;return t}}const Ai=2/(3*Math.PI);function bi(e,t,n,i,r){const o=e[i][n],a=t[i][n];let s=Math.sqrt(o*o+a*a);s=Math.max(s,1e-100),r.x=o/s,r.y=a/s}class xi{constructor(){this.width=-1,this.height=-1,this.curPoint=null,this.searchGranBits=8,this.searchGran=1<<this.searchGranBits,this.pointsPerPost=500,this.greyscale=null,this.laplace=null,this.gradient=null,this.gradX=null,this.gradY=null,this.parents=null,this.working=!1,this.trained=!1,this.trainingPoints=null,this.edgeWidth=2,this.trainingLength=32,this.edgeGran=256,this.edgeTraining=null,this.gradPointsNeeded=32,this.gradGran=1024,this.gradTraining=null,this.insideGran=256,this.insideTraining=null,this.outsideGran=256,this.outsideTraining=null}getTrainingIdx(e,t){return Math.round((e-1)*t)}getTrainedEdge(e){return this.edgeTraining[this.getTrainingIdx(this.edgeGran,e)]}getTrainedGrad(e){return this.gradTraining[this.getTrainingIdx(this.gradGran,e)]}getTrainedInside(e){return this.insideTraining[this.getTrainingIdx(this.insideGran,e)]}getTrainedOutside(e){return this.outsideTraining[this.getTrainingIdx(this.outsideGran,e)]}setWorking(e){this.working=e}setDimensions(e,t){this.width=e,this.height=t}setData(e){if(-1===this.width||-1===this.height)throw new Error("Dimensions have not been set.");this.greyscale=function(e,t,n){const i={data:[]};for(let r=0;r<n;r++){i.data[r]=[];for(let n=0;n<t;n++){const o=4*(r*t+n);i.data[r][n]=(e[o]+e[o+1]+e[o+2])/765}}return i.dx=function(e,t){return e+1===this.data[t].length&&e--,this.data[t][e+1]-this.data[t][e]},i.dy=function(e,t){return t+1===this.data.length&&t--,this.data[t][e]-this.data[t+1][e]},i.gradMagnitude=function(e,t){const n=this.dx(e,t),i=this.dy(e,t);return Math.sqrt(n*n+i*i)},i.laplace=function(e,t){let n=-16*this.data[t][e];return n+=this.data[t-2][e],n+=this.data[t-1][e-1]+2*this.data[t-1][e]+this.data[t-1][e+1],n+=this.data[t][e-2]+2*this.data[t][e-1]+2*this.data[t][e+1]+this.data[t][e+2],n+=this.data[t+1][e-1]+2*this.data[t+1][e]+this.data[t+1][e+1],n+=this.data[t+2][e],n},i}(e,this.width,this.height),this.laplace=function(e){const t=[];t[0]=[],t[1]=[];for(let n=1;n<e.data.length;n++)t[0][n]=1,t[1][n]=1;for(let n=2;n<e.data.length-2;n++){t[n]=[],t[n][0]=1,t[n][1]=1;for(let i=2;i<e.data[n].length-2;i++)t[n][i]=e.laplace(i,n)>.33?0:1;t[n][e.data[n].length-2]=1,t[n][e.data[n].length-1]=1}t[e.data.length-2]=[],t[e.data.length-1]=[];for(let n=1;n<e.data.length;n++)t[e.data.length-2][n]=1,t[e.data.length-1][n]=1;return t}(this.greyscale),this.gradient=function(e){const t=[];let n=0,i=0,r=0;for(r=0;r<e.data.length-1;r++){for(t[r]=[],i=0;i<e.data[r].length-1;i++)t[r][i]=e.gradMagnitude(i,r),n=Math.max(t[r][i],n);t[r][e.data[r].length-1]=t[r][e.data.length-2]}t[e.data.length-1]=[];for(let n=0;n<t[0].length;n++)t[e.data.length-1][n]=t[e.data.length-2][n];for(r=0;r<t.length;r++)for(i=0;i<t[r].length;i++)t[r][i]=1-t[r][i]/n;return t}(this.greyscale),this.gradX=function(e){const t=[];for(let n=0;n<e.data.length;n++){t[n]=[];for(let i=0;i<e.data[n].length-1;i++)t[n][i]=e.dx(i,n);t[n][e.data[n].length-1]=t[n][e.data[n].length-2]}return t}(this.greyscale),this.gradY=function(e){const t=[];for(let n=0;n<e.data.length-1;n++){t[n]=[];for(let i=0;i<e.data[n].length;i++)t[n][i]=e.dy(i,n)}t[e.data.length-1]=[];for(let n=0;n<e.data[0].length;n++)t[e.data.length-1][n]=t[e.data.length-2][n];return t}(this.greyscale);const t=function(e,t,n,i){const r={inside:[],outside:[]},o={x:-1,y:-1};for(let a=0;a<t.length;a++){r.inside[a]=[],r.outside[a]=[];for(let s=0;s<t[a].length;s++){bi(t,n,s,a,o);let l=Math.round(s+e*o.y),c=Math.round(a-e*o.x),u=Math.round(s-e*o.y),d=Math.round(a+e*o.x);l=Math.max(Math.min(l,t[a].length-1),0),u=Math.max(Math.min(u,t[a].length-1),0),c=Math.max(Math.min(c,t.length-1),0),d=Math.max(Math.min(d,t.length-1),0),r.inside[a][s]=i.data[c][l],r.outside[a][s]=i.data[d][u]}}return r}(this.edgeWidth,this.gradX,this.gradY,this.greyscale);this.inside=t.inside,this.outside=t.outside,this.edgeTraining=[],this.gradTraining=[],this.insideTraining=[],this.outsideTraining=[]}findTrainingPoints(e){const t=[];if(null!==this.parents)for(let n=0;n<this.trainingLength&&e;n++)t.push(e),e=this.parents[e.y][e.x];return t}resetTraining(){this.trained=!1}doTraining(e){if(this.trainingPoints=this.findTrainingPoints(e),this.trainingPoints.length<8)return;const t=[];this.calculateTraining(t,this.edgeGran,this.greyscale,this.edgeTraining),this.calculateTraining(t,this.gradGran,this.gradient,this.gradTraining),this.calculateTraining(t,this.insideGran,this.inside,this.insideTraining),this.calculateTraining(t,this.outsideGran,this.outside,this.outsideTraining),this.trainingPoints.length<this.gradPointsNeeded&&this.addInStaticGrad(this.trainingPoints.length,this.gradPointsNeeded),this.trained=!0}calculateTraining(e,t,n,i){let r=0;for(e.length=t,r=0;r<t;r++)e[r]=0;let o=1;for(r=0;r<this.trainingPoints.length;r++){const i=this.trainingPoints[r],a=this.getTrainingIdx(t,n[i.y][i.x]);e[a]+=1,o=Math.max(o,e[a])}for(r=0;r<t;r++)e[r]=1-e[r]/o;!function(e,t){t[0]=.4*e[0]+.5*e[1]+.1*e[1],t[1]=.25*e[0]+.4*e[1]+.25*e[2]+.1*e[3];for(let n=2;n<e.length-2;n++)t[n]=.05*e[n-2]+.25*e[n-1]+.4*e[n]+.25*e[n+1]+.05*e[n+2];const n=e.length;t[n-2]=.25*e[n-1]+.4*e[n-2]+.25*e[n-3]+.1*e[n-4],t[n-1]=.4*e[n-1]+.5*e[n-2]+.1*e[n-3]}(e,i)}addInStaticGrad(e,t){for(let n=0;n<this.gradGran;n++)this.gradTraining[n]=Math.min(this.gradTraining[n],1-n*(t-e)/(t*this.gradGran))}gradDirection(e,t,n,i){return function(e,t,n,i,r,o){const a={x:-1,y:-1},s={x:-1,y:-1};bi(e,t,n,i,a),bi(e,t,r,o,s);let l=a.y*(r-n)-a.x*(o-i),c=s.y*(r-n)-s.x*(o-i);return l<0&&(l=-l,c=-c),n!==r&&i!==o&&(l*=Math.SQRT1_2,c*=Math.SQRT1_2),Ai*(Math.acos(l)+Math.acos(c))}(this.gradX,this.gradY,e,t,n,i)}dist(e,t,n,i){let r=this.gradient[i][n];e!==n&&t!==i||(r*=Math.SQRT1_2);const o=this.laplace[i][n],a=this.gradDirection(e,t,n,i);return this.trained?.3*this.getTrainedGrad(r)+.3*o+.1*(a+this.getTrainedEdge(this.greyscale.data[t][e])+this.getTrainedInside(this.inside[t][e])+this.getTrainedOutside(this.outside[t][e])):.43*r+.43*o+.11*a}adj(e){const t=[],n=Math.max(e.x-1,0),i=Math.max(e.y-1,0),r=Math.min(e.x+1,this.greyscale.data[0].length-1),o=Math.min(e.y+1,this.greyscale.data.length-1);let a=0;for(let s=i;s<=o;s++)for(let i=n;i<=r;i++)i===e.x&&s===e.y||(t[a++]={x:i,y:s});return t}#Dn=e=>Math.round(this.searchGran*this.cost[e.y][e.x]);setPoint(e){this.setWorking(!0),this.curPoint=e;let t=0,n=0;for(this.visited=[],n=0;n<this.height;n++)for(this.visited[n]=[],t=0;t<this.width;t++)this.visited[n][t]=!1;for(this.parents=[],n=0;n<this.height;n++)this.parents[n]=[];for(this.cost=[],n=0;n<this.height;n++)for(this.cost[n]=[],t=0;t<this.width;t++)this.cost[n][t]=Number.MAX_VALUE;this.cost[e.y][e.x]=0,this.pq=new Oi(this.searchGranBits,this.#Dn),this.pq.push(e)}doWork(){if(!this.working)return;this.timeout=null;let e=0;const t=[];for(;!this.pq.isEmpty()&&e<this.pointsPerPost;){const n=this.pq.pop();t.push(n),t.push(this.parents[n.y][n.x]),this.visited[n.y][n.x]=!0;const i=this.adj(n);for(let e=0;e<i.length;e++){const t=i[e],r=this.cost[n.y][n.x]+this.dist(n.x,n.y,t.x,t.y);r<this.cost[t.y][t.x]&&(this.cost[t.y][t.x]!==Number.MAX_VALUE&&this.pq.remove(t),this.cost[t.y][t.x]=r,this.parents[t.y][t.x]=n,this.pq.push(t))}e++}return t}}class Ri{#yn;constructor(e){this.#yn=e}getPosition(e){let t=e.labelPosition;return void 0===t&&(t=this.#yn(e)),t}create(e,t){const n=new(ai().Text)({fontSize:t.getFontSize(),fontFamily:t.getFontFamily(),fill:e.colour,padding:t.getTextPadding(),shadowColor:t.getShadowLineColour(),shadowOffset:t.getShadowOffset(),name:"text"}),i=e.getText();n.setText(i);const r=t.applyZoomScale(1),o={x:2*r.x,y:2*r.y},a=this.getPosition(e),s=new(ai().Label)({x:a.getX(),y:a.getY(),scale:o,visible:0!==i.length,name:"label"});return s.add(n),s.add(new(ai().Tag)({fill:e.colour,opacity:t.getTagOpacity()})),s}updatePosition(e,t){const n=t.getChildren((function(e){return"label"===e.name()}))[0];if(!(n instanceof ai().Label))return;const i=this.getPosition(e);n.position({x:i.getX(),y:i.getY()})}getLabelAnchorsPosition(e){const t=e.x(),n=e.y(),i=e.width()*e.scale().x,r=e.height()*e.scale().y;return[new R(t+i/2,n),new R(t,n+r/2),new R(t+i/2,n+r),new R(t+i,n+r/2)]}getClosestPoints(e,t){let n=e[0].getDistance(t[0]),i=e[0],r=t[0];for(const o of e)for(const e of t){const t=o.getDistance(e);t<n&&(n=t,i=o,r=e)}return[i,r]}getConnector(e,t,n){const i=this.getLabelAnchorsPosition(t),r=this.getClosestPoints(e,i);return new(ai().Line)({points:[r[0].getX(),r[0].getY(),r[1].getX(),r[1].getY()],stroke:t.getText().fill(),strokeWidth:n.getStrokeWidth(),strokeScaleEnabled:!1,visible:t.visible(),dash:[10,7],name:"connector"})}updateConnector(e,t){const n=e.getChildren((function(e){return"label"===e.name()}))[0];if(!(n instanceof ai().Label))return;const i=this.getLabelAnchorsPosition(n),r=this.getClosestPoints(t,i),o=e.getChildren((function(e){return"connector"===e.name()}))[0];o instanceof ai().Line&&o.points([r[0].getX(),r[0].getY(),r[1].getX(),r[1].getY()])}updateContent(e,t){const n=t.getChildren((function(e){return"label"===e.name()}))[0];if(!(n instanceof ai().Label))return;const i=e.getText();n.getText().setText(i),n.visible()&&n.visible(0!==i.length)}}class Fi{#Cn;#vn;constructor(e,t){this.#Cn=e,this.#vn=t}getCenter(){return this.#Cn}getCentroid(){return this.#Cn}getRadius(){return this.#vn}equals(e){return null!==e&&this.getCenter().equals(e.getCenter())&&this.getRadius()===e.getRadius()}getSurface(){return Math.PI*this.getRadius()*this.getRadius()}getWorldSurface(e){return function(e,t,n){let i=null;return null!==t&&null!==n&&(i=e*t*n),i}(this.getSurface(),e.x,e.y)}getRound(){const e=this.getCenter().getX(),t=this.getCenter().getY(),n=this.getRadius(),i=Math.pow(n,2),r=t+n,o=[];for(let a=t-n;a<r;++a){const n=i-Math.pow(a-t,2);if(Math.abs(n)<1e-7)continue;const r=Math.sqrt(n);r<.5||o.push([[Math.round(e-r),Math.round(a)],[Math.round(e+r),Math.round(a)]])}return o}quantify(e,t,n){const i={},r=e.get2DSpacing();i.radius={value:this.getRadius()*r.x,unit:"unit.mm"};const o=this.getWorldSurface(r);if(null!==o&&(i.surface={value:o/100,unit:"unit.cm2"}),e.canQuantifyImage()){const r=this.getRound();if(0!==r.length){const o=e.getImageVariableRegionValues(r,t),a=e.getPixelUnit(),s=Ke(o,n);i.min={value:s.min,unit:a},i.max={value:s.max,unit:a},i.mean={value:s.mean,unit:a},i.stdDev={value:s.stdDev,unit:a},void 0!==s.median&&(i.median={value:s.median,unit:a}),void 0!==s.p25&&(i.p25={value:s.p25,unit:a}),void 0!==s.p75&&(i.p75={value:s.p75,unit:a})}}return i}}class Ei{#Cn;#In;#Tn;constructor(e,t,n){this.#Cn=e,this.#In=t,this.#Tn=n}getCenter(){return this.#Cn}getCentroid(){return this.#Cn}getA(){return this.#In}getB(){return this.#Tn}equals(e){return null!==e&&this.getCenter().equals(e.getCenter())&&this.getA()===e.getA()&&this.getB()===e.getB()}getSurface(){return Math.PI*this.getA()*this.getB()}getWorldSurface(e){return function(e,t,n){let i=null;return null!==t&&null!==n&&(i=e*t*n),i}(this.getSurface(),e.x,e.y)}getRound(){const e=this.getCenter().getX(),t=this.getCenter().getY(),n=this.getA(),i=this.getB(),r=n/i,o=Math.pow(i,2),a=t+i,s=[];for(let n=t-i;n<a;++n){const i=o-Math.pow(n-t,2);if(Math.abs(i)<1e-7)continue;const a=r*Math.sqrt(i);a<.5||s.push([[Math.round(e-a),Math.round(n)],[Math.round(e+a),Math.round(n)]])}return s}quantify(e,t,n){const i={},r=e.get2DSpacing();i.a={value:this.getA()*r.x,unit:"unit.mm"},i.b={value:this.getB()*r.y,unit:"unit.mm"};const o=this.getWorldSurface(r);if(null!==o&&(i.surface={value:o/100,unit:"unit.cm2"}),e.canQuantifyImage()){const r=this.getRound();if(0!==r.length){const o=e.getImageVariableRegionValues(r,t),a=e.getPixelUnit(),s=Ke(o,n);i.min={value:s.min,unit:a},i.max={value:s.max,unit:a},i.mean={value:s.mean,unit:a},i.stdDev={value:s.stdDev,unit:a},void 0!==s.median&&(i.median={value:s.median,unit:a}),void 0!==s.p25&&(i.p25={value:s.p25,unit:a}),void 0!==s.p75&&(i.p75={value:s.p75,unit:a})}}return i}}function qi(e,t,n){const i=e.getValues(),r=i.slice(),o=[],a=t[0],l=t[1],c=a/l,u=Math.pow(l,2),d=n[0],h=n[1];for(let e=0;e<l;++e){const t=Math.round(c*Math.sqrt(u-Math.pow(e,2))),n=i[h]+e,a=i[h]-e;for(let e=0;e<t;++e){const t=i[d]+e,l=i[d]-e;r[d]=t,r[h]=n,o.push(new s(r.slice())),a!==n&&(r[h]=a,o.push(new s(r.slice()))),l!==t&&(r[d]=l,r[h]=n,o.push(new s(r.slice())),a!==n&&(r[h]=a,o.push(new s(r.slice()))))}}return o}class Ui{#fn;constructor(e){if(e.length>3)throw new Error("Too many points for a protractor");this.#fn=e.slice(0,3)}getPoint(e){return this.#fn[e]}getLength(){return this.#fn.length}getCentroid(){return this.#fn[1]}quantify(e,t){const n={};if(3===this.#fn.length){let e=ei(new $n(this.#fn[0],this.#fn[1]),new $n(this.#fn[1],this.#fn[2]));e>180&&(e=360-e),n.angle={value:e,unit:"unit.degree"}}return n}}class Mi{#Et;#qt;constructor(e,t){this.#Et=new R(Math.min(e.getX(),t.getX()),Math.min(e.getY(),t.getY())),this.#qt=new R(Math.max(e.getX(),t.getX()),Math.max(e.getY(),t.getY()))}getBegin(){return this.#Et}getEnd(){return this.#qt}equals(e){return null!==e&&this.getBegin().equals(e.getBegin())&&this.getEnd().equals(e.getEnd())}getSurface(){const e=this.getBegin(),t=this.getEnd();return Math.abs(t.getX()-e.getX())*Math.abs(t.getY()-e.getY())}getWorldSurface(e){return function(e,t,n){let i=null;return null!==t&&null!==n&&(i=e*t*n),i}(this.getSurface(),e.x,e.y)}getRealWidth(){return this.getEnd().getX()-this.getBegin().getX()}getRealHeight(){return this.getEnd().getY()-this.getBegin().getY()}getWidth(){return Math.abs(this.getRealWidth())}getHeight(){return Math.abs(this.getRealHeight())}getRound(){return{min:new R(Math.round(this.getBegin().getX()),Math.round(this.getBegin().getY())),max:new R(Math.round(this.getEnd().getX()),Math.round(this.getEnd().getY()))}}getCentroid(){return new R(this.getBegin().getX()+this.getWidth()/2,this.getBegin().getY()+this.getHeight()/2)}quantify(e,t,n){const i={},r=e.get2DSpacing();i.width={value:this.getWidth()*r.x,unit:"unit.mm"},i.height={value:this.getHeight()*r.y,unit:"unit.mm"};const o=this.getWorldSurface(r);if(null!==o&&(i.surface={value:o/100,unit:"unit.cm2"}),e.canQuantifyImage()){const r=this.getRound(),o=e.getImageRegionValues(r.min,r.max,t),a=e.getPixelUnit(),s=Ke(o,n);i.min={value:s.min,unit:a},i.max={value:s.max,unit:a},i.mean={value:s.mean,unit:a},i.stdDev={value:s.stdDev,unit:a},void 0!==s.median&&(i.median={value:s.median,unit:a}),void 0!==s.p25&&(i.p25={value:s.p25,unit:a}),void 0!==s.p75&&(i.p75={value:s.p75,unit:a})}return i}}function Qi(e,t,n){const i=e.getValues(),r=i.slice(),o=[],a=t[0],l=Math.floor(a/2),c=t[1],u=Math.floor(c/2),d=n[0],h=n[1];for(let e=0;e<c;++e){r[h]=i[h]-u+e;for(let e=0;e<a;++e)r[d]=i[d]-l+e,o.push(new s(r.slice()))}return o}class Vi{#Ln=0;#Pn=0;getMin(){return this.#Ln}setMin(e){this.#Ln=e}getMax(){return this.#Pn}setMax(e){this.#Pn=e}getName(){return"Threshold"}#wn=null;setOriginalImage(e){this.#wn=e}getOriginalImage(){return this.#wn}update(){const e=this.getOriginalImage(),t=e.getDataRange().min;return e.transform((e=>e<this.getMin()||e>this.getMax()?t:e))}}class Ni{getName(){return"Sharpen"}#wn=null;setOriginalImage(e){this.#wn=e}getOriginalImage(){return this.#wn}update(){return this.getOriginalImage().convolute2D([0,-1,0,-1,5,-1,0,-1,0])}}class Bi{getName(){return"Sobel"}#wn=null;setOriginalImage(e){this.#wn=e}getOriginalImage(){return this.#wn}update(){const e=this.getOriginalImage(),t=e.convolute2D([1,0,-1,2,0,-2,1,0,-1]),n=e.convolute2D([1,2,1,0,0,0,-1,-2,-1]);return t.compose(n,(function(e,t){return Math.sqrt(e*e+t*t)}))}}class Gi{#On;#Ct;#Rt;constructor(e,t,n){this.#On=e,this.#Ct=t,this.#Rt=n}getName(){return"Filter-"+this.#On.getName()}execute(){this.#Rt.setImage(this.#Ct,this.#On.update()),this.#Rt.render(this.#Ct);const e={type:"filterrun",id:this.getName(),dataId:this.#Ct};this.onExecute(e)}undo(){this.#Rt.setImage(this.#Ct,this.#On.getOriginalImage()),this.#Rt.render(this.#Ct);const e={type:"filterundo",id:this.getName(),dataid:this.#Ct};this.onUndo(e)}onExecute(e){}onUndo(e){}}const ki={},Hi={},zi={WindowLevel:class{#Rt;#An=!1;#bn;#xn;constructor(e){this.#Rt=e,this.#xn=new Jn(e)}#Rn(e,t){const n=this.#Rt.getLayerGroupByDivId(t).getActiveViewLayer();void 0!==n&&n.getViewController().isMonochrome()&&(this.#An=!0,this.#bn=e)}#Fn(e,t){if(!this.#An)return;const n=this.#Rt.getLayerGroupByDivId(t).getActiveViewLayer();if(void 0===n)return;const i=n.getViewController(),r=e.getX()-this.#bn.getX(),o=this.#bn.getY()-e.getY(),a=i.getImageRescaledDataRange(),s=.01*(a.max-a.min),l=i.getWindowLevel().center,c=i.getWindowLevel().width,d=l+Math.round(o*s);let h=c+Math.round(r*s);var S;h=(S=h)<1?1:S;const g=new u(d,h);i.setWindowLevel(g),this.#bn=e}#En(){this.#An&&(this.#An=!1)}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Rn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup=e=>{this.#En()};mouseout=e=>{this.#En()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Rn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchend=e=>{this.#En()};dblclick=e=>{const t=Ki(e),n=jn(e),i=this.#Rt.getLayerGroupByDivId(t.groupDivId).getActiveViewLayer();if(void 0===i)return;const r=i.displayToPlaneIndex(n),o=i.getViewController();if(!o.isMonochrome())return;const a=this.#Rt.getData(i.getDataId()).image,s=new u(a.getRescaledValueAtIndex(o.getCurrentIndex().getWithNew2D(r.get(0),r.get(1))),o.getWindowLevel().width);o.setWindowLevel(s)};wheel=e=>{this.#xn.wheel(e)};keydown=e=>{e.context="WindowLevel",this.#Rt.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Scroll:class{#Rt;#An=!1;#bn;#xn;#qn;#Un=!1;#Mn;constructor(e){this.#Rt=e,this.#xn=new Jn(e)}#Qn(e){let t=e.getActiveViewLayer();if(void 0===t){const n=e.getActiveDrawLayer();if(void 0===n)return void c.warn("No draw layer to do scroll");t=e.getViewLayerById(n.getReferenceLayerId())}return t}#Rn(e,t){this.#Vn();const n=this.#Rt.getLayerGroupByDivId(t),i=this.#Qn(n);if(void 0===i)return void c.warn("No view layer to start scroll");const r=i.getViewController();r.isPlaying()&&r.stop();const o=i.displayToPlanePos(e),a=r.getPositionFromPlanePoint(o);r.setCurrentPosition(a),this.#An=!0,this.#bn=e}#Fn(e,t){if(!this.#An)return void(this.#Un&&this.#Nn(e,t));const n=this.#Rt.getLayerGroupByDivId(t),i=n.getPositionHelper(),r=e.getY()-this.#bn.getY(),o=Math.abs(r)>15,a=e.getX()-this.#bn.getX(),s=Math.abs(a)>15;o&&n.canScroll()?r>0?i.decrementPositionAlongScroll():i.incrementPositionAlongScroll():s&&n.moreThanOne(3)&&(a>0?i.incrementPosition(3):i.decrementPosition(3)),(s||o)&&(this.#bn=e)}#En(){this.#An&&(this.#An=!1)}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Rn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup=e=>{this.#En()};mouseout=e=>{this.#En(),this.#Vn()};touchstart=e=>{this.#qn=setTimeout((()=>{this.dblclick(e)}),500);const t=Xn(e),n=Ki(e);this.#Rn(t[0],n.groupDivId)};touchmove=e=>{null!==this.#qn&&(clearTimeout(this.#qn),this.#qn=null);const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchend=e=>{null!==this.#qn&&(clearTimeout(this.#qn),this.#qn=null),this.#En()};wheel=e=>{this.#xn.wheel(e)};keydown=e=>{e.context="Scroll",this.#Rt.onKeydown(e)};dblclick=e=>{const t=Ki(e),n=this.#Rt.getLayerGroupByDivId(t.groupDivId).getActiveViewLayer();void 0!==n&&n.getViewController().play()};#Nn(e,t){const n=this.#Rt.getLayerGroupByDivId(t);this.#Mn=t,n.showTooltip(e)}#Vn(){void 0!==this.#Mn&&(this.#Rt.getLayerGroupByDivId(this.#Mn).removeTooltipDiv(),this.#Mn=void 0)}activate(e){e||this.#Vn()}setFeatures(e){void 0!==e.displayTooltip&&(this.#Un=e.displayTooltip)}init(){}},ZoomAndPan:class{#Rt;#An=!1;#bn;#Bn;#Gn;#kn;constructor(e){this.#Rt=e}#Qn(e){let t=e.getActiveViewLayer();if(void 0===t){const n=e.getActiveDrawLayer();if(void 0===n)return void c.warn("No draw layer to do zoom/pan");t=e.getViewLayerById(n.getReferenceLayerId())}return t}#Rn(e){this.#An=!0,this.#bn=e,this.#Bn=!1}#Hn=e=>{this.#An=!0,this.#bn=e[0],this.#Bn=!1,this.#Gn=new $n(e[0],e[1]),this.#kn=this.#Gn.getMidpoint()};#Fn(e,t){if(!this.#An)return;this.#Bn=!0;const n=e.getX()-this.#bn.getX(),i=e.getY()-this.#bn.getY(),r=this.#Rt.getLayerGroupByDivId(t),o=this.#Qn(r);if(void 0===o)return void c.warn("No view layer to update zoom/pan");const a=o.getViewController(),s=o.displayToPlaneScale(new R(n,i)),l=a.getOffset3DFromPlaneOffset({x:s.getX(),y:s.getY()});r.addTranslation({x:l.getX(),y:l.getY(),z:l.getZ()}),r.draw(),this.#bn=e}#zn=(e,t)=>{if(!this.#An)return;this.#Bn=!0;const n=new $n(e[0],e[1]).getLength()/this.#Gn.getLength(),i=this.#Rt.getLayerGroupByDivId(t),r=i.getPositionHelper();if(1===n){const t=e[0].getY()-this.#bn.getY();if(Math.abs(t)<15)return;i.canScroll()&&(t>0?r.incrementPositionAlongScroll():r.decrementPositionAlongScroll())}else{const e=(n-1)/10;if(Math.abs(e)%.1<=.05&&void 0!==this.#kn){const t=this.#Qn(i);if(void 0===t)return void c.warn("No view layer to do touch zoom/pan");const n=t.getViewController(),r=t.displayToMainPlanePos(this.#kn),o=n.getPlanePositionFromPlanePoint(r);i.addScale(e,o),i.draw()}}};#Wn(e,t){const n=this.#Rt.getLayerGroupByDivId(t),i=this.#Qn(n);if(void 0===i)return void c.warn("No view layer to set current position");const r=i.getViewController(),o=i.displayToPlanePos(e),a=r.getPositionFromPlanePoint(o);r.setCurrentPosition(a)}#En(){this.#An&&(this.#An=!1)}mousedown=e=>{const t=jn(e);this.#Rn(t)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup=e=>{if(!this.#Bn){const t=jn(e),n=Ki(e);this.#Wn(t,n.groupDivId)}this.#En()};mouseout=e=>{this.#En()};touchstart=e=>{const t=Xn(e);1===t.length?this.#Rn(t[0]):2===t.length&&this.#Hn(t)};touchmove=e=>{const t=Xn(e),n=Ki(e);1===t.length?this.#Fn(t[0],n.groupDivId):2===t.length&&this.#zn(t,n.groupDivId)};touchend=e=>{if(!this.#Bn){const t=jn(e),n=Ki(e);this.#Wn(t,n.groupDivId)}this.#En()};wheel=e=>{e.preventDefault();const t=-e.deltaY/500,n=Ki(e),i=jn(e),r=this.#Rt.getLayerGroupByDivId(n.groupDivId),o=this.#Qn(r);if(void 0===o)return void c.warn("No view layer to do wheel zoom/pan");const a=o.getViewController(),s=o.displayToMainPlanePos(i),l=a.getPlanePositionFromPlanePoint(s);r.addScale(t,l),r.draw()};keydown=e=>{e.context="ZoomAndPan",this.#Rt.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Opacity:class{#Rt;#An=!1;#bn;#xn;constructor(e){this.#Rt=e,this.#xn=new Jn(e)}#Rn(e){this.#An=!0,this.#bn=e}#Fn(e,t){if(!this.#An)return;const n=e.getX()-this.#bn.getX();if(Math.abs(n)>15){const i=this.#Rt.getLayerGroupByDivId(t).getActiveLayer(),r=i.getOpacity();i.setOpacity(r+n/200),i.draw(),this.#bn=e}}#En(){this.#An&&(this.#An=!1)}mousedown=e=>{const t=jn(e);this.#Rn(t)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup=e=>{this.#En()};mouseout=e=>{this.#En()};touchstart=e=>{const t=Xn(e);this.#Rn(t[0])};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchend=e=>{this.#En()};wheel=e=>{this.#xn.wheel(e)};keydown=e=>{e.context="Opacity",this.#Rt.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Draw:class{#Rt;#xn;#Yn;#Xn=!1;#jn=null;#_t=null;#Zn=null;#_n;#fn=[];#Kn=null;#Jn=!0;#$n=[];#ei;#ti=!1;#z={};#ni=!1;#ii=[];constructor(e){this.#Rt=e,this.#xn=new Jn(e),this.#ei=new Ii(e,this.#Fe),this.#Yn=e.getStyle()}#ri(e,t){const n=this.#Rt.getLayerGroupByDivId(t);let i=n.getActiveDrawLayer();if(void 0===i){const e=n.getActiveViewLayer().getDataId(),r=this.#Rt.getData(e).image.getMeta().SeriesInstanceUID;if(this.#$n.includes(r))return void this.#Fe({type:"warn",message:"Cannot create draw layer, data is in black list"});const o=this.#Rt.createAnnotationData(e);this.#Rt.addAndRenderAnnotationData(o,t,e),i=n.getActiveDrawLayer(),i.setShapeHandler(this.#ei),n.setActiveLayerByDataId(i.getDataId())}const r=i.getDrawController().getAnnotationGroup(),o=i.getKonvaStage();if(this.#Yn.setZoomScale(o.scale()),r.isEditable()){const t=o.getIntersection({x:e.getX(),y:e.getY()});t?this.#oi(i,t):this.#ai(n,e)}}#Qn(e){const t=e.getActiveDrawLayer();if(void 0!==t)return e.getViewLayerById(t.getReferenceLayerId());c.warn("No draw layer to do draw")}#ai(e,t){this.#ei.disableAndResetEditor(),this.#si();const n=this.#Qn(e);void 0!==n?(this.#Kn=n.displayToPlanePos(t),this.#fn.push(this.#Kn)):c.warn("No view layer to start shape")}#si(){this.#Xn=!0,this.#_t=new this.#jn[this.#_n],this.#fn=[]}#li(){this.#Xn=!1,this.#fn=[]}#oi(e,t){let n=t.getParent();t instanceof ai().Tag&&(n=n.getParent());const i=n.find(".shape")[0];i instanceof ai().Shape&&(this.#Fe({type:"annotationselect",annotationid:n.id(),dataid:e.getDataId()}),this.#ei.setEditorShape(i,e))}#ci(e,t){const n=this.#Rt.getLayerGroupByDivId(t),i=this.#Qn(n);if(void 0===i)return void c.warn("No view layer to update shape");const r=i.displayToPlanePos(e);(Math.abs(r.getX()-this.#Kn.getX())>0||Math.abs(r.getY()-this.#Kn.getY())>0)&&(this.#ni&&this.#fn.pop(),this.#Kn=r,this.#ni=!0,this.#fn.push(this.#Kn),this.#ui(this.#fn,n))}#di(e){if(0!==this.#fn.length){if(this.#fn.length===this.#_t.getNPoints()){const t=this.#Rt.getLayerGroupByDivId(e);this.#hi(this.#fn,t),this.#li()}this.#ni=!1}else c.warn("Draw mouseup but no points...")}mousedown=e=>{if(this.#Xn)return;const t=jn(e),n=Ki(e);this.#ri(t,n.groupDivId)};mousemove=e=>{if(!this.#Xn)return;const t=jn(e),n=Ki(e);this.#ci(t,n.groupDivId)};mouseup=e=>{if(!this.#Xn)return;const t=Ki(e);this.#di(t.groupDivId)};dblclick=e=>{if(this.#_t&&void 0!==this.#_t.getNPoints())return;if(!this.#Xn)return;if(0===this.#fn.length)return void c.warn("Draw dblclick but no points...");const t=Ki(e),n=this.#Rt.getLayerGroupByDivId(t.groupDivId);this.#hi(this.#fn,n),this.#li()};mouseout=e=>{if(!this.#Xn)return;const t=Ki(e);this.#di(t.groupDivId)};touchstart=e=>{if(this.#Xn)return;const t=Xn(e),n=Ki(e);this.#ri(t[0],n.groupDivId)};touchmove=e=>{if(!this.#Xn)return;const t=Ki(e),n=Xn(e),i=this.#Rt.getLayerGroupByDivId(t.groupDivId),r=this.#Qn(i);if(void 0===r)return void c.warn("No view layer to handle touch move");const o=r.displayToPlanePos(n[0]);(Math.abs(o.getX()-this.#Kn.getX())>0||Math.abs(o.getY()-this.#Kn.getY())>0)&&(1!==this.#fn.length&&this.#fn.pop(),this.#Kn=o,this.#fn.push(this.#Kn),this.#fn.length<this.#_t.getNPoints()&&(clearTimeout(this.timer),this.timer=setTimeout((()=>{this.#fn.push(this.#Kn)}),this.#_t.getTimeout())),this.#ui(this.#fn,i))};touchend=e=>{this.dblclick(e)};wheel=e=>{this.#Jn&&this.#xn.wheel(e)};keydown=e=>{this.#Xn||(e.context="Draw",this.#Rt.onKeydown(e));const t=this.#ei.getEditorAnnotation();if(("Delete"===e.key||"Backspace"===e.key)&&void 0!==t){const e=this.#Rt.getActiveLayerGroup().getActiveDrawLayer();if(void 0===e)return void c.warn("No draw layer to handle key down");const n=e.getDrawController(),i=new li(t,n);this.#Rt.addToUndoStack(i),i.execute(),this.#ei.onMouseOutShapeGroup()}if("Escape"===e.key&&null!==this.#Zn){const e=this.#Zn.getLayer();this.#Zn.destroy(),this.#Zn=null,this.#li(),e.draw()}};#ui(e,t){this.#Zn&&(this.#Zn.destroy(),this.#Zn=null);const n=t.getActiveDrawLayer();if(void 0===n)return void c.warn("No draw layer to handle new points");const i=n.getDrawController(),r=n.getKonvaLayer(),o=t.getViewLayerById(n.getReferenceLayerId());if(void 0===o)return void c.warn("No view layer to handle new points");const a=o.getViewController();if(this.#ti){const e=["#ffff80","#ff80ff","#80ffff","#80ff80","8080ff","ff8080"],t=n.getId(),i=t.substring(t.length-1),r=e[parseInt(i,10)-1];void 0!==r&&this.#Yn.setLineColour(r)}const s=new Yi,l=i.getAnnotationGroup().getColour();s.colour=void 0!==l?l:this.#Yn.getLineColour(),s.init(a),this.#_t.setAnnotationMathShape(s,e),this.#Zn=this.#_t.createShapeGroup(s,this.#Yn),n.setLabelVisibility(this.#Zn),this.#Zn.getChildren(Si)[0].listening(!1),r.listening(!1),r.add(this.#Zn),r.draw()}#hi(e,t){this.#Zn&&(this.#Zn.destroy(),this.#Zn=null);const n=t.getActiveDrawLayer();if(void 0===n)return void c.warn("No draw layer to handle final points");const i=n.getKonvaLayer(),r=n.getDrawController(),o=t.getViewLayerById(n.getReferenceLayerId());if(void 0===o)return void c.warn("No view layer to handle final points");const a=o.getViewController(),s=new Yi,l=r.getAnnotationGroup().getColour();s.colour=void 0!==l?l:this.#Yn.getLineColour(),s.id=et(),s.init(a),this.#_t.setAnnotationMathShape(s,e);const u=new si(s,r);this.#Rt.addToUndoStack(u),u.execute(),i.listening(!0)}#Si(e){const t=e.getId();return void 0===this.#ii[t]&&(this.#ii[t]=()=>{e.activateCurrentPositionShapes(!0)}),this.#ii[t]}#gi(e,t){e.setShapeHandler(this.#ei),e.activateCurrentPositionShapes(t),t?this.#Rt.addEventListener("positionchange",this.#Si(e)):this.#Rt.removeEventListener("positionchange",this.#Si(e))}activate(e){e||this.#ei.onMouseOutShapeGroup();const t=this.#Rt.getDrawLayers();for(const n of t)void 0!==n&&this.#gi(n,e);this.#Rt.addEventListener("drawlayeradd",(t=>{const n=this.#Rt.getDrawLayers((function(e){return e.getId()===t.layerid}));1===n.length&&this.#gi(n[0],e)}))}setOptions(e){this.#jn=e}getOptionsType(){return"factory"}setFeatures(e){if(void 0!==e.autoShapeColour&&(this.#ti=e.autoShapeColour),void 0!==e.shapeColour&&(this.#Yn.setLineColour(e.shapeColour),this.#ti=!1),void 0!==e.shapeName){if(!this.hasShape(e.shapeName))throw new Error("Unknown shape: '"+e.shapeName+"'");this.#_n=e.shapeName}void 0!==e.mouseOverCursor&&this.#ei.storeMouseOverCursor(e.mouseOverCursor),void 0!==e.withScroll&&(this.#Jn=e.withScroll),void 0!==e.blacklist&&(this.#$n=e.blacklist)}init(){}getEventNames(){return["annotationupdate","annotationselect","warn"]}addEventListener(e,t){void 0===this.#z[e]&&(this.#z[e]=[]),this.#z[e].push(t)}removeEventListener(e,t){if(void 0!==this.#z[e])for(let n=0;n<this.#z[e].length;++n)this.#z[e][n]===t&&this.#z[e].splice(n,1)}#Fe=e=>{if(void 0!==this.#z[e.type])for(let t=0;t<this.#z[e.type].length;++t)this.#z[e.type][t](e)};hasShape(e){return void 0!==this.#jn[e]}},Filter:class{#Rt;constructor(e){this.#Rt=e}#pi=null;#mi=0;#be=new He;activate(e){for(const t in this.#pi)e?(this.#pi[t].addEventListener("filterrun",this.#Fe),this.#pi[t].addEventListener("filter-undo",this.#Fe)):(this.#pi[t].removeEventListener("filterrun",this.#Fe),this.#pi[t].removeEventListener("filter-undo",this.#Fe))}setOptions(e){this.#pi={};for(const t in e)this.#pi[t]=new e[t](this.#Rt)}getOptionsType(){return"instance"}init(){for(const e in this.#pi)this.#pi[e].init()}keydown=e=>{e.context="Filter",this.#Rt.onKeydown(e)};getEventNames(){return["filterrun","filterundo"]}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)};getSelectedFilter(){return this.#mi}setFeatures(e){if(void 0!==e.filterName){if(!this.hasFilter(e.filterName))throw new Error("Unknown filter: '"+e.filterName+"'");this.#mi&&this.#mi.activate(!1),this.#mi=this.#pi[e.filterName],this.#mi.activate(!0)}if(void 0!==e.run&&e.run){let t={};void 0!==e.runArgs&&(t=e.runArgs),this.getSelectedFilter().run(t)}}getFilterList(){return this.#pi}hasFilter(e){return this.#pi[e]}},Floodfill:class{#Rt;constructor(e){this.#Rt=e}#fi=5;#Di=0;#yi=2e3;#Ci=null;#vi=null;#Ii=10;#Ti=null;#An=!1;#Ut;#Li;#Pi=null;#wi=[];#Oi=!1;#Yn=new ui;#be=new He;setExtend(e){this.#Oi=e}getExtend(){return this.#Oi}#Qn(e){const t=e.getActiveDrawLayer();if(void 0!==t)return e.getViewLayerById(t.getReferenceLayerId());c.warn("No draw layer to do floodfill")}#Ai=(e,t)=>{const n=this.#Rt.getLayerGroupByDivId(t),i=this.#Qn(n);if(void 0===i)return void c.warn("No view layer to get index");const r=i.displayToPlaneIndex(e);return{x:r.get(0),y:r.get(1)}};#bi(e,t,n){this.#wi=[];const i={data:this.#Ci.data,width:this.#Ci.width,height:this.#Ci.height,bytes:4};this.#vi=Pi().floodFill(i,e.x,e.y,t),this.#vi=Pi().gaussBlurOnlyBorder(this.#vi,this.#fi);let r=Pi().traceContours(this.#vi);if(r=Pi().simplifyContours(r,this.#Di,this.#yi),r.length>0&&r[0].points[0].x){if(n)return r[0].points;for(let e=0,t=r[0].points.length;e<t;e++)this.#wi.push(new R(r[0].points[e].x,r[0].points[e].y));return this.#wi}return[]}#xi(e,t,n){if(this.#Pi=this.#bi(e,t,!1),0!==this.#Pi.length){const e=n.getActiveDrawLayer();if(void 0===e)return c.warn("No draw layer to paint border"),!1;const t=e.getDrawController(),i=new Ti(this.#Pi);let r;if(void 0===this.#Ut){this.#Ut=new Yi,this.#Ut.colour=this.#Yn.getLineColour(),this.#Ut.id=et();const o=n.getViewLayerById(e.getReferenceLayerId());if(void 0===o)return c.warn("No view layer to paint border"),!1;const a=o.getViewController();this.#Ut.init(a),this.#Ut.mathShape=i,r=new si(this.#Ut,t)}else{const e=this.#Ut.mathShape;r=new ci(this.#Ut,{mathShape:e},{mathShape:i},t)}this.#Rt.addToUndoStack(r),r.execute()}return 0!==this.#Pi.length}extend(e,t,n){if(!this.#Li)throw"'initialpoint' not found. User must click before use extend!";const i=n.getPositionHelper(),r=this.#Qn(n);if(void 0===r)return void c.warn("No view layer to extend floodfill");const o=r.getViewController(),a=o.getCurrentIndex(),s=o.getImageSize(),l=this.#Ti||this.#Ii;for(let e=a.get(2),r=t||s.get(2);e<r&&this.#xi(this.#Li,l,n);e++)i.incrementPositionAlongScroll();o.setCurrentIndex(a);for(let t=a.get(2),r=e||0;t>r&&this.#xi(this.#Li,l,n);t--)i.decrementPositionAlongScroll();o.setCurrentIndex(a)}onThresholdChange(e){}#Rn(e,t){const n=this.#Rt.getLayerGroupByDivId(t);let i,r=n.getActiveDrawLayer();if(void 0===r){i=n.getActiveViewLayer();const e=i.getDataId(),o=this.#Rt.createAnnotationData(e);this.#Rt.addAndRenderAnnotationData(o,t,e),r=n.getActiveDrawLayer(),n.setActiveLayerByDataId(r.getDataId())}else if(i=n.getViewLayerById(r.getReferenceLayerId()),void 0===i)return void c.warn("No view layer to start floodfill");this.#Ci=i.getImageData(),this.#Ci?(this.#Yn.setZoomScale(r.getKonvaLayer().getAbsoluteScale()),this.#An=!0,this.#Li=this.#Ai(e,t),this.#xi(this.#Li,this.#Ii,n),this.onThresholdChange(this.#Ii)):c.error("No image found")}#Fn(e,t){if(!this.#An)return;const n=this.#Ai(e,t);this.#Ti=Math.round(Math.sqrt(Math.pow(this.#Li.x-n.x,2)+Math.pow(this.#Li.y-n.y,2))/2),this.#Ti=this.#Ti<this.#Ii?this.#Ii:this.#Ti-this.#Ii,this.#xi(this.#Li,this.#Ti,this.#Rt.getLayerGroupByDivId(t)),this.onThresholdChange(this.#Ti)}#En(){this.#An&&(this.#An=!1)}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Rn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup=e=>{this.#En()};mouseout=e=>{this.#En()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Rn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchend=e=>{this.#En()};keydown=e=>{e.context="Floodfill",this.#Rt.onKeydown(e)};activate(e){e&&(this.#Yn.setBaseScale(this.#Rt.getBaseScale()),this.setFeatures({shapeColour:this.#Yn.getLineColour()}))}init(){}getEventNames(){return["drawcreate","drawchange","drawmove","drawdelete"]}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}setFeatures(e){void 0!==e.shapeColour&&this.#Yn.setLineColour(e.shapeColour)}},Livewire:class{#Rt;constructor(e){this.#Rt=e}#An=!1;#bn;#Ut;#Yn=new ui;#Ri=new wi;#Fi=new wi;#wi=[];#Ei=5;#be=new He;#qi(e){const t=e.get(1);for(let e=0;e<t;++e)this.#wi[e]=[]}#Ui(){this.#Ri=new wi,this.#Fi=new wi}#Mi=new xi;#Rn(e,t){const n=this.#Rt.getLayerGroupByDivId(t);let i,r=n.getActiveDrawLayer();i=void 0===r?n.getActiveViewLayer():n.getViewLayerById(r.getReferenceLayerId());const o=i.getViewController().getImageSize();this.#Mi.setDimensions(o.get(0),o.get(1)),this.#Mi.setData(i.getImageData().data);const a=i.displayToPlaneIndex(e);if(this.#An){const e=Math.abs(a.get(0)-this.#bn.getX()),t=Math.abs(a.get(1)-this.#bn.getY());if(e<this.#Ei&&t<this.#Ei)this.#Qi();else{this.#Ri=this.#Fi,this.#qi(o);const e={x:a.get(0),y:a.get(1)};this.#Mi.doTraining(e),this.#Ri.addControlPoint(this.#Fi.getPoint(0))}}else{if(this.#An=!0,this.#bn=new R(a.get(0),a.get(1)),this.#Ui(),this.#qi(o),void 0===r){const e=i.getDataId(),o=this.#Rt.createAnnotationData(e);this.#Rt.addAndRenderAnnotationData(o,t,e),r=n.getActiveDrawLayer(),n.setActiveLayerByDataId(r.getDataId())}this.#Yn.setZoomScale(r.getKonvaLayer().getAbsoluteScale());const e={x:a.get(0),y:a.get(1)};this.#Mi.doTraining(e);const s=new R(a.get(0),a.get(1));this.#Ri.addPoint(s),this.#Ri.addControlPoint(s)}}#Fn(e,t){if(!this.#An)return;const n=this.#Rt.getLayerGroupByDivId(t),i=n.getActiveDrawLayer();if(void 0===i)return void c.warn("No draw layer to update livewire");const r=n.getViewLayerById(i.getReferenceLayerId());if(void 0===r)return void c.warn("No view layer to update livewire");const o=r.displayToPlaneIndex(e);let a={x:o.get(0),y:o.get(1)};this.#Mi.setPoint(a);let s=[],l=!1;for(;!this.#wi[a.y][a.x]&&!l;)if(s=this.#Mi.doWork(),0===s.length)l=!0;else for(let e=0;e<s.length-1;e+=2){const t=s[e],n=s[e+1];this.#wi[t.y][t.x]=n}for(this.#Fi=new wi,l=!1;a&&!l;)this.#Fi.addPoint(new R(a.x,a.y)),this.#wi[a.y]&&this.#wi[a.y][a.x]?a=this.#wi[a.y][a.x]:l=!0;this.#Fi.appenPath(this.#Ri);const u=i.getDrawController(),d=new Ti(this.#Fi.pointArray);let h;if(void 0===this.#Ut){this.#Ut=new Yi,this.#Ut.colour=this.#Yn.getLineColour(),this.#Ut.id=et();const e=r.getViewController();this.#Ut.init(e),this.#Ut.mathShape=d,h=new si(this.#Ut,u)}else{const e=this.#Ut.mathShape;h=new ci(this.#Ut,{mathShape:e},{mathShape:d},u)}this.#Rt.addToUndoStack(h),h.execute()}#Qi(){this.#An=!1}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Rn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mouseup(e){}mouseout=e=>{};dblclick=e=>{this.#Qi()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Rn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchend=e=>{};keydown=e=>{e.context="Livewire",this.#Rt.onKeydown(e)};activate(e){e&&(this.#Yn.setBaseScale(this.#Rt.getBaseScale()),this.setFeatures({shapeColour:this.#Yn.getLineColour()}))}init(){}getEventNames(){return["drawcreate","drawchange","drawmove","drawdelete"]}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}setFeatures(e){void 0!==e.shapeColour&&this.#Yn.setLineColour(e.shapeColour)}}},Wi={draw:{ArrowFactory:class{#Vi="arrow";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof R}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.referencePoints=[t[1]],e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(i);const r=this.#zi(e,t);for(const e of r)n.add(e);const o=this.#Ni.create(e,t);n.add(o);const a=this.#Wi(i);return n.add(this.#Ni.getConnector(a,o,t)),n}#Wi(e){const t=e.points(),n=e.x(),i=e.y(),r=(t[0]+t[2])/2+n,o=(t[1]+t[3])/2+i;return[new R(r,o)]}#Yi(e){const t=e.points(),n=e.x(),i=e.y();return[new R(t[0]+n,t[1]+i),new R(t[2]+n,t[3]+i)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=t.getParent();if(!(n instanceof ai().Group))return;const i=this.#ji(n),r=mi(n,0),o=mi(n,1),a=new R(r.x()-i.x(),r.y()-i.y()),s=new R(o.x()-i.x(),o.y()-i.y());e.mathShape=a,e.referencePoints=[s],e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=e.referencePoints[0],r=new $n(n,i),o=r.getBegin(),a=new R(o.getX()+t.x,o.getY()+t.y),s=r.getEnd(),l=new R(s.getX()+t.x,s.getY()+t.y);e.mathShape=a,e.referencePoints=[l],e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){return e[0]}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape,i=e.referencePoints[0],r=new $n(n,i),o=new(ai().Line)({points:[n.getX(),n.getY(),i.getX(),i.getY()],stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"}),a=ni(r,n,20,t.getZoomScale()),s=ni(r,i,20,t.getZoomScale());return o.hitFunc((function(e){e.beginPath(),e.moveTo(a.getBegin().getX(),a.getBegin().getY()),e.lineTo(a.getEnd().getX(),a.getEnd().getY()),e.lineTo(s.getEnd().getX(),s.getEnd().getY()),e.lineTo(s.getBegin().getX(),s.getBegin().getY()),e.closePath(),e.fillStrokeShape(o)})),o}#ji(e){return pi(e)}#zi(e,t){const n=e.mathShape,i=e.referencePoints[0],r=new $n(n,i),o=ii(r,40,20,t.getZoomScale());return[new(ai().Line)({points:[r.getBegin().getX(),r.getBegin().getY(),o.getBegin().getX(),o.getBegin().getY(),o.getEnd().getX(),o.getEnd().getY()],fill:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,closed:!0,name:"shape-triangle"})]}#Bi(e){return e.mathShape}#Xi(e,t,n){const i=e.mathShape,r=e.referencePoints[0],o=new $n(i,r),a=t.getParent();if(!(a instanceof ai().Group))return;const s=this.#ji(a);s.position({x:0,y:0}),s.points([i.getX(),i.getY(),r.getX(),r.getY()]);const l=a.getChildren((function(e){return"shape-triangle"===e.name()}))[0];if(!(l instanceof ai().Line))return;const u=mi(a,0),d=mi(a,1);switch(t.id()){case"anchor0":u.x(t.x()),u.y(t.y());break;case"anchor1":d.x(t.x()),d.y(t.y());break;default:c.error("Unhandled anchor id: "+t.id())}const h=ii(o,40,20,n.getZoomScale());l.position({x:0,y:0}),l.points([o.getBegin().getX(),o.getBegin().getY(),h.getBegin().getX(),h.getBegin().getY(),h.getEnd().getX(),h.getEnd().getY()]);const S=ni(o,i,20,n.getZoomScale()),g=ni(o,r,20,n.getZoomScale());s.hitFunc((function(e){e.beginPath(),e.moveTo(S.getBegin().getX(),S.getBegin().getY()),e.lineTo(S.getEnd().getX(),S.getEnd().getY()),e.lineTo(g.getEnd().getX(),g.getEnd().getY()),e.lineTo(g.getBegin().getX(),g.getBegin().getY()),e.closePath(),e.fillStrokeShape(s)}))}#Zi(e,t){}#_i(e,t){}},CircleFactory:class{#Vi="circle";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof Fi}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(this.#Hi(e,t));const r=this.#Ni.create(e,t);n.add(this.#Ni.create(e,t));const o=this.#Wi(i);return n.add(this.#Ni.getConnector(o,r,t)),n}#Wi(e){const t=e.x(),n=e.y(),i=e.radius()*Math.sqrt(2)/2;return[new R(t-i,n-i),new R(t+i,n-i),new R(t-i,n+i),new R(t+i,n+i)]}#Yi(e){const t=e.x(),n=e.y(),i=e.radius();return[new R(t-i,n),new R(t+i,n),new R(t,n+i),new R(t,n-i)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){const t=e.getParent();if(!(t instanceof ai().Group))return;const n=mi(t,0),i=mi(t,1),r=mi(t,2),o=mi(t,3);switch(e.id()){case"anchor0":n.y(i.y());break;case"anchor1":i.y(n.y());break;case"anchor2":r.x(o.x());break;case"anchor3":o.x(r.x());break;default:c.error("Unhandled anchor id: "+e.id())}}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=e.mathShape,i=new R(n.getCenter().getX(),n.getCenter().getY()),r=new R(t.x(),t.y()),o=i.getDistance(r);e.mathShape=new Fi(i,o),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=n.getCenter(),r=new R(i.getX()+t.x,i.getY()+t.y);e.mathShape=new Fi(r,n.getRadius()),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){const t=Math.abs(e[0].getX()-e[1].getX()),n=Math.abs(e[0].getY()-e[1].getY()),i=Math.round(Math.sqrt(t*t+n*n));return new Fi(e[0],i)}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape;return new(ai().Circle)({x:n.getCenter().getX(),y:n.getCenter().getY(),radius:n.getRadius(),stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"})}#ji(e){const t=e.getChildren(Si)[0];if(t instanceof ai().Circle)return t}#Bi(e){const t=e.mathShape,n=t.getCenter(),i=t.getRadius();return new R(n.getX()-i,n.getY()+i)}#Xi(e,t,n){const i=e.mathShape,r=i.getCenter(),o=i.getRadius(),a=t.getParent();if(!(a instanceof ai().Group))return;this.#ji(a).radius(o);const s=mi(a,0),l=mi(a,1),u=mi(a,2),d=mi(a,3),h=l.x()<s.x()?-1:1,S=d.y()<u.y()?1:-1;switch(t.id()){case"anchor0":s.x(t.x()),l.x(r.getX()+h*o),u.y(r.getY()+o),d.y(r.getY()-o);break;case"anchor1":l.x(t.x()),s.x(r.getX()-h*o),u.y(r.getY()+o),d.y(r.getY()-o);break;case"anchor2":u.y(t.y()),s.x(r.getX()-o),l.x(r.getX()+o),d.y(r.getY()-S*o);break;case"anchor3":d.y(t.y()),s.x(r.getX()-o),l.x(r.getX()+o),u.y(r.getY()+S*o);break;default:c.error("Unhandled anchor id: "+t.id())}}#Zi(e,t){const n=e.mathShape;let i=0,r=0;void 0!==t&&(i=t.x(),r=t.y());const o=new(ai().Group);o.name("shadow");const a=n.getRound();for(let e=0;e<a.length;++e){const t=a[e],n=t[0][0],s=t[0][1],l=t[1][0],c=new(ai().Rect)({x:n-i,y:s-r,width:l-n,height:1,fill:"grey",strokeWidth:0,strokeScaleEnabled:!1,opacity:.3,name:"shadow-element"});o.add(c)}return o}#_i(e,t){const n=t.getChildren((function(e){return"shadow"===e.name()}))[0];void 0!==n&&(n.destroy(),t.add(this.#Zi(e,t)))}},EllipseFactory:class{#Vi="ellipse";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof Ei}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(this.#Hi(e,t));const r=this.#Ni.create(e,t);n.add(this.#Ni.create(e,t));const o=this.#Wi(i);return n.add(this.#Ni.getConnector(o,r,t)),n}#Wi(e){const t=e.x(),n=e.y(),i=e.radiusX()*Math.sqrt(2)/2,r=e.radiusY()*Math.sqrt(2)/2;return[new R(t-i,n-r),new R(t+i,n-r),new R(t-i,n+r),new R(t+i,n+r)]}#Yi(e){const t=e.x(),n=e.y(),i=e.radius();return[new R(t-i.x,n),new R(t+i.x,n),new R(t,n+i.y),new R(t,n-i.y)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){const t=e.getParent();if(!(t instanceof ai().Group))return;const n=mi(t,0),i=mi(t,1),r=mi(t,2),o=mi(t,3);switch(e.id()){case"anchor0":n.y(i.y());break;case"anchor1":i.y(n.y());break;case"anchor2":r.x(o.x());break;case"anchor3":o.x(r.x());break;default:c.error("Unhandled anchor id: "+e.id())}}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=e.mathShape,i=n.getCenter();let r=n.getA(),o=n.getB();switch(t.id()){case"anchor0":r=i.getX()-t.x();break;case"anchor1":r=t.x()-i.getX();break;case"anchor2":o=t.y()-i.getY();break;case"anchor3":o=i.getY()-t.y();break;default:c.error("Unhandled anchor id: "+t.id())}e.mathShape=new Ei(i,Math.abs(r),Math.abs(o)),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=n.getCenter(),r=new R(i.getX()+t.x,i.getY()+t.y);e.mathShape=new Ei(r,n.getA(),n.getB()),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){const t=Math.abs(e[0].getX()-e[1].getX()),n=Math.abs(e[0].getY()-e[1].getY());return new Ei(e[0],t,n)}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape,i=n.getCenter(),r={x:n.getA(),y:n.getB()};return new(ai().Ellipse)({x:i.getX(),y:i.getY(),radius:r,radiusX:r.x,radiusY:r.y,stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"})}#ji(e){const t=e.getChildren(Si)[0];if(t instanceof ai().Ellipse)return t}#Bi(e){const t=e.mathShape,n=t.getCenter();return new R(n.getX()-t.getA(),n.getY()+t.getB())}#Xi(e,t,n){const i=e.mathShape,r=i.getCenter(),o=i.getA(),a=i.getB(),s=t.getParent();if(!(s instanceof ai().Group))return;this.#ji(s).radius({x:o,y:a});const l=mi(s,0),u=mi(s,1),d=mi(s,2),h=mi(s,3),S=u.x()<l.x()?-1:1,g=h.y()<d.y()?1:-1;switch(t.id()){case"anchor0":l.x(t.x()),u.x(r.getX()+S*o),d.y(r.getY()+a),h.y(r.getY()-a);break;case"anchor1":u.x(t.x()),l.x(r.getX()-S*o),d.y(r.getY()+a),h.y(r.getY()-a);break;case"anchor2":d.y(t.y()),l.x(r.getX()-o),u.x(r.getX()+o),h.y(r.getY()-g*a);break;case"anchor3":h.y(t.y()),l.x(r.getX()-o),u.x(r.getX()+o),d.y(r.getY()+g*a);break;default:c.error("Unhandled anchor id: "+t.id())}}#Zi(e,t){const n=e.mathShape;let i=0,r=0;void 0!==t&&(i=t.x(),r=t.y());const o=new(ai().Group);o.name("shadow");const a=n.getRound();for(let e=0;e<a.length;++e){const t=a[e],n=t[0][0],s=t[0][1],l=t[1][0],c=new(ai().Rect)({x:n-i,y:s-r,width:l-n,height:1,fill:"grey",strokeWidth:0,strokeScaleEnabled:!1,opacity:.3,name:"shadow-element"});o.add(c)}return o}#_i(e,t){const n=t.getChildren((function(e){return"shadow"===e.name()}))[0];void 0!==n&&(n.destroy(),t.add(this.#Zi(e,t)))}},ProtractorFactory:class{#Vi="protractor";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof Ui}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 3}getTimeout(){return 500}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=e.mathShape,i=new(ai().Group);i.name(this.getGroupName()),i.visible(!0),i.id(e.id);const r=this.#Hi(e,t);if(i.add(this.#Hi(e,t)),n.getLength()===this.getNPoints()){const n=this.#zi(e,t);for(const e of n)i.add(e);const o=this.#Ni.create(e,t);i.add(this.#Ni.create(e,t));const a=this.#Wi(r);i.add(this.#Ni.getConnector(a,o,t))}return i}#Wi(e){const t=e.points(),n=e.x(),i=e.y();return[new R(t[2]+n,t[3]+i)]}#Yi(e){const t=e.points(),n=e.x(),i=e.y();return[new R(t[0]+n,t[1]+i),new R(t[2]+n,t[3]+i),new R(t[4]+n,t[5]+i)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=t.getParent();if(!(n instanceof ai().Group))return;const i=this.#ji(n),r=mi(n,0),o=mi(n,1),a=mi(n,2),s=new R(r.x()-i.x(),r.y()-i.y()),l=new R(o.x()-i.x(),o.y()-i.y()),c=new R(a.x()-i.x(),a.y()-i.y());e.mathShape=new Ui([s,l,c]),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=[];for(let e=0;e<3;++e)i.push(new R(n.getPoint(e).getX()+t.x,n.getPoint(e).getY()+t.y));e.mathShape=new Ui(i),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){return new Ui(e)}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape,i=[];for(let e=0;e<n.getLength();++e)i.push(n.getPoint(e).getX()),i.push(n.getPoint(e).getY());const r=new(ai().Line)({points:i,stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"});return n.getLength()===this.getNPoints()&&r.hitFunc((function(e){e.beginPath(),e.moveTo(n.getPoint(0).getX(),n.getPoint(0).getY()),e.lineTo(n.getPoint(1).getX(),n.getPoint(1).getY()),e.lineTo(n.getPoint(2).getX(),n.getPoint(2).getY()),e.closePath(),e.fillStrokeShape(r)})),r}#ji(e){return pi(e)}#zi(e,t){const n=e.mathShape,i=new $n(n.getPoint(0),n.getPoint(1)),r=new $n(n.getPoint(1),n.getPoint(2));let o=ei(i,r),a=i.getInclination();o>180&&(o=360-o,a+=o);const s=33*Math.min(i.getLength(),r.getLength())/100;return[new(ai().Arc)({innerRadius:s,outerRadius:s,stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,angle:o,rotation:-a,x:n.getPoint(1).getX(),y:n.getPoint(1).getY(),name:"shape-arc"})]}#Bi(e){const t=e.mathShape,n=new $n(t.getPoint(0),t.getPoint(1)),i=new $n(t.getPoint(1),t.getPoint(2)),r=(n.getMidpoint().getX()+i.getMidpoint().getX())/2,o=(n.getMidpoint().getY()+i.getMidpoint().getY())/2;return new R(r,o)}#Xi(e,t,n){const i=e.mathShape,r=new $n(i.getPoint(0),i.getPoint(1)),o=new $n(i.getPoint(1),i.getPoint(2)),a=t.getParent();if(!(a instanceof ai().Group))return;const s=this.#ji(a);s.position({x:0,y:0}),s.points([i.getPoint(0).getX(),i.getPoint(0).getY(),i.getPoint(1).getX(),i.getPoint(1).getY(),i.getPoint(2).getX(),i.getPoint(2).getY()]);const l=a.getChildren((function(e){return"shape-arc"===e.name()}))[0];if(!(l instanceof ai().Arc))return;const c=mi(a,0),u=mi(a,1),d=mi(a,2);switch(t.id()){case"anchor0":c.x(t.x()),c.y(t.y());break;case"anchor1":u.x(t.x()),u.y(t.y());break;case"anchor2":d.x(t.x()),d.y(t.y())}let h=ei(r,o),S=r.getInclination();h>180&&(h=360-h,S+=h);const g=33*Math.min(r.getLength(),o.getLength())/100;l.innerRadius(g),l.outerRadius(g),l.angle(h),l.rotation(-S);const p={x:u.x(),y:u.y()};l.position(p),s.hitFunc((function(e){e.beginPath(),e.moveTo(i.getPoint(0).getX(),i.getPoint(0).getY()),e.lineTo(i.getPoint(1).getX(),i.getPoint(1).getY()),e.lineTo(i.getPoint(2).getX(),i.getPoint(2).getY()),e.closePath(),e.fillStrokeShape(s)}))}#Zi(e,t){}#_i(e,t){}},RectangleFactory:class{#Vi="rectangle";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof Mi}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(i);const r=this.#Ni.create(e,t);n.add(r);const o=this.#Wi(i);return n.add(this.#Ni.getConnector(o,r,t)),n}#Wi(e){const t=e.x(),n=e.y(),i=e.width(),r=e.height();return[new R(t+i/2,n),new R(t,n+r/2),new R(t+i/2,n+r),new R(t+i,n+r/2)]}#Yi(e){const t=e.x(),n=e.y(),i=e.width(),r=e.height();return[new R(t,n),new R(t+i,n),new R(t+i,n+r),new R(t,n+r)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=t.getParent();if(!(n instanceof ai().Group))return;const i=mi(n,0),r=mi(n,2),o=new R(i.x(),i.y()),a=new R(r.x(),r.y());e.mathShape=new Mi(o,a),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=n.getBegin(),r=new R(i.getX()+t.x,i.getY()+t.y),o=n.getEnd(),a=new R(o.getX()+t.x,o.getY()+t.y);e.mathShape=new Mi(r,a),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){return new Mi(e[0],e[1])}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape;return new(ai().Rect)({x:n.getBegin().getX(),y:n.getBegin().getY(),width:n.getWidth(),height:n.getHeight(),stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"})}#ji(e){const t=e.getChildren(Si)[0];if(t instanceof ai().Rect)return t}#Bi(e){const t=e.mathShape;return new R(t.getBegin().getX(),t.getEnd().getY())}#Xi(e,t,n){const i=e.mathShape,r=i.getBegin(),o=t.getParent();if(!(o instanceof ai().Group))return;const a=this.#ji(o);a.position({x:r.getX(),y:r.getY()}),a.size({width:i.getWidth(),height:i.getHeight()});const s=mi(o,0),l=mi(o,1),u=mi(o,2),d=mi(o,3);switch(t.id()){case"anchor0":s.x(t.x()),s.y(t.y()),l.y(t.y()),d.x(t.x());break;case"anchor1":l.x(t.x()),l.y(t.y()),s.y(t.y()),u.x(t.x());break;case"anchor2":u.x(t.x()),u.y(t.y()),d.y(t.y()),l.x(t.x());break;case"anchor3":d.x(t.x()),d.y(t.y()),u.y(t.y()),s.x(t.x());break;default:c.error("Unhandled anchor id: "+t.id())}}#Zi(e,t){const n=e.mathShape.getRound(),i=n.max.getX()-n.min.getX(),r=n.max.getY()-n.min.getY();return new(ai().Rect)({x:n.min.getX(),y:n.min.getY(),width:i,height:r,fill:"grey",strokeWidth:0,strokeScaleEnabled:!1,opacity:.3,name:"shadow"})}#_i(e,t){const n=t.getChildren((function(e){return"shadow"===e.name()}))[0];void 0!==n&&(n.destroy(),t.add(this.#Zi(e,t)))}},RoiFactory:class{#Vi="roi";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof Ti}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){}getTimeout(){return 100}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(this.#Hi(e,t));const r=this.#Ni.create(e,t);n.add(this.#Ni.create(e,t));const o=this.#Wi(i);return n.add(this.#Ni.getConnector(o,r,t)),n}#Yi(e){const t=e.points(),n=e.x(),i=e.y(),r=[];for(let e=0;e<t.length;e+=2)r.push(new R(t[e]+n,t[e+1]+i));return r}#Wi(e){const t=e.points(),n=e.x(),i=e.y(),r=[];for(let e=0;e<t.length;e+=2){const o=(e+2)%t.length,a=(t[e]+t[o])/2+n,s=(t[e+1]+t[o+1])/2+i;r.push(new R(a,s))}return r}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=t.getParent();if(!(n instanceof ai().Group))return;const i=this.#ji(n),r=e.mathShape.getPoints().slice(),o=new R(t.x()-i.x(),t.y()-i.y());r[yi(t.id())]=o,e.mathShape=new Ti(r),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=[];for(let e=0;e<n.getLength();++e)i.push(new R(n.getPoint(e).getX()+t.x,n.getPoint(e).getY()+t.y));e.mathShape=new Ti(i),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){return new Ti(e)}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape,i=[];for(let e=0;e<n.getLength();++e)i.push(n.getPoint(e).getX()),i.push(n.getPoint(e).getY());return new(ai().Line)({points:i,stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape",closed:!0})}#ji(e){return pi(e)}#Bi(e){const t=e.mathShape;return new R(t.getPoint(0).getX(),t.getPoint(0).getY())}#Xi(e,t,n){const i=t.getParent();if(!(i instanceof ai().Group))return;const r=this.#ji(i),o=r.points(),a=2*yi(t.id());o[a]=t.x()-r.x(),o[a+1]=t.y()-r.y(),r.points(o);const s=i.getChildren((function(e){return e.id()===t.id()}))[0];s.x(t.x()),s.y(t.y())}#Zi(e,t){}#_i(e,t){}},RulerFactory:class{#Vi="ruler";#Ni=new Ri(this.#Bi);static supports(e){return e instanceof $n}getName(){return this.#Vi}getGroupName(){return this.#Vi+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#Gi(t),e.setTextExpr(this.#ki()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#Hi(e,t);n.add(this.#Hi(e,t));const r=this.#zi(e,t);for(const e of r)n.add(e);const o=this.#Ni.create(e,t);n.add(this.#Ni.create(e,t));const a=this.#Wi(i);return n.add(this.#Ni.getConnector(a,o,t)),n}#Wi(e){const t=e.points(),n=e.x(),i=e.y(),r=(t[0]+t[2])/2+n,o=(t[1]+t[3])/2+i;return[new R(r,o)]}#Yi(e){const t=e.points(),n=e.x(),i=e.y();return[new R(t[0]+n,t[1]+i),new R(t[2]+n,t[3]+i)]}getAnchors(e,t){const n=this.#Yi(e),i=[];for(let e=0;e<n.length;++e)i.push(Di(n[e].getX(),n[e].getY(),"anchor"+e,t));return i}constrainAnchorMove(e){}updateShapeGroupOnAnchorMove(e,t,n){const i=t.getParent();i instanceof ai().Group&&(this.#Xi(e,t,n),this.updateLabelContent(e,i,n),void 0===e.labelPosition?this.#Ni.updatePosition(e,i):this.updateConnector(i))}updateAnnotationOnAnchorMove(e,t){const n=t.getParent();if(!(n instanceof ai().Group))return;const i=this.#ji(n),r=mi(n,0),o=mi(n,1),a=new R(r.x()-i.x(),r.y()-i.y()),s=new R(o.x()-i.x(),o.y()-i.y());e.mathShape=new $n(a,s),e.updateQuantification()}updateAnnotationOnTranslation(e,t){const n=e.mathShape,i=n.getBegin(),r=new R(i.getX()+t.x,i.getY()+t.y),o=n.getEnd(),a=new R(o.getX()+t.x,o.getY()+t.y);e.mathShape=new $n(r,a),e.updateQuantification()}updateLabelContent(e,t,n){this.#Ni.updateContent(e,t)}updateConnector(e){const t=this.#ji(e),n=this.#Wi(t);this.#Ni.updateConnector(e,n)}#Gi(e){return new $n(e[0],e[1])}#ki(){return void 0!==L.labelTexts&&void 0!==L.labelTexts[this.#Vi]?L.labelTexts[this.#Vi]:di[this.#Vi]}#Hi(e,t){const n=e.mathShape,i=new(ai().Line)({points:[n.getBegin().getX(),n.getBegin().getY(),n.getEnd().getX(),n.getEnd().getY()],stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape"}),r=ni(n,n.getBegin(),20,t.getZoomScale()),o=ni(n,n.getEnd(),20,t.getZoomScale());return i.hitFunc((function(e){e.beginPath(),e.moveTo(r.getBegin().getX(),r.getBegin().getY()),e.lineTo(r.getEnd().getX(),r.getEnd().getY()),e.lineTo(o.getEnd().getX(),o.getEnd().getY()),e.lineTo(o.getBegin().getX(),o.getBegin().getY()),e.closePath(),e.fillStrokeShape(i)})),i}#ji(e){return pi(e)}#zi(e,t){const n=e.mathShape,i=ni(n,n.getBegin(),20,t.getZoomScale()),r=new(ai().Line)({points:[i.getBegin().getX(),i.getBegin().getY(),i.getEnd().getX(),i.getEnd().getY()],stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape-tick0"}),o=ni(n,n.getEnd(),20,t.getZoomScale());return[r,new(ai().Line)({points:[o.getBegin().getX(),o.getBegin().getY(),o.getEnd().getX(),o.getEnd().getY()],stroke:e.colour,strokeWidth:t.getStrokeWidth(),strokeScaleEnabled:!1,name:"shape-tick1"})]}#Bi(e){const t=e.mathShape,n=t.getBegin(),i=t.getEnd();let r=n;return n.getY()<i.getY()&&(r=i),r}#Xi(e,t,n){const i=e.mathShape,r=t.getParent();if(!(r instanceof ai().Group))return;const o=this.#ji(r);o.position({x:0,y:0}),o.points([i.getBegin().getX(),i.getBegin().getY(),i.getEnd().getX(),i.getEnd().getY()]);const a=r.getChildren((function(e){return"shape-tick0"===e.name()}))[0];if(!(a instanceof ai().Line))return;const s=r.getChildren((function(e){return"shape-tick1"===e.name()}))[0];if(!(s instanceof ai().Line))return;const l=mi(r,0),u=mi(r,1);switch(t.id()){case"anchor0":l.x(t.x()),l.y(t.y());break;case"anchor1":u.x(t.x()),u.y(t.y());break;default:c.error("Unhandled anchor id: "+t.id())}const d=ni(i,i.getBegin(),20,n.getZoomScale());a.position({x:0,y:0}),a.points([d.getBegin().getX(),d.getBegin().getY(),d.getEnd().getX(),d.getEnd().getY()]);const h=ni(i,i.getEnd(),20,n.getZoomScale());s.position({x:0,y:0}),s.points([h.getBegin().getX(),h.getBegin().getY(),h.getEnd().getX(),h.getEnd().getY()]),o.hitFunc((function(e){e.beginPath(),e.moveTo(d.getBegin().getX(),d.getBegin().getY()),e.lineTo(d.getEnd().getX(),d.getEnd().getY()),e.lineTo(h.getEnd().getX(),h.getEnd().getY()),e.lineTo(h.getBegin().getX(),h.getBegin().getY()),e.closePath(),e.fillStrokeShape(o)}))}#Zi(e,t){}#_i(e,t){}}},filter:{Threshold:class{#Rt;constructor(e){this.#Rt=e}#On=new Vi;#Ki=!0;#be=new He;activate(e){e&&(this.#Ki=!0)}init(){}run(e){if(void 0===e.dataId)throw new Error("No dataId to run threshod filter on.");if(this.#On.setMin(e.min),this.#On.setMax(e.max),this.#Ki){const t=this.#Rt.getData(e.dataId).image;this.#On.setOriginalImage(t),this.#Ki=!1}const t=new Gi(this.#On,e.dataId,this.#Rt);t.onExecute=this.#Fe,t.onUndo=this.#Fe,t.execute(),this.#Rt.addToUndoStack(t)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}},Sobel:class{#Rt;constructor(e){this.#Rt=e}#be=new He;activate(e){}init(){}run(e){if(void 0===e.dataId)throw new Error("No dataId to run sobel filter on.");const t=new Bi,n=this.#Rt.getData(e.dataId).image;t.setOriginalImage(n);const i=new Gi(t,e.dataId,this.#Rt);i.onExecute=this.#Fe,i.onUndo=this.#Fe,i.execute(),this.#Rt.addToUndoStack(i)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}},Sharpen:class{#Rt;constructor(e){this.#Rt=e}#be=new He;activate(e){}init(){}run(e){if(void 0===e.dataId)throw new Error("No dataId to run sharpen filter on.");const t=new Ni,n=this.#Rt.getData(e.dataId).image;t.setOriginalImage(n);const i=new Gi(t,e.dataId,this.#Rt);i.onExecute=this.#Fe,i.onUndo=this.#Fe,i.execute(),this.#Rt.addToUndoStack(i)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}}}};class Yi{id;referenceSopUID;mathShape;referencePoints;colour;quantification;textExpr;labelPosition;planeOrigin;planePoints;#nt;getOrientationName(){let e;return void 0!==this.planePoints&&(e=Dt(this.planePoints[1].getValues().concat(this.planePoints[2].getValues()))),e}init(e){void 0===this.referenceSopUID?(this.#nt=e,this.referenceSopUID=e.getCurrentImageUid(),this.planeOrigin=e.getOriginForImageUid(this.referenceSopUID),e.isAquisitionOrientation()||(this.planePoints=e.getPlanePoints(e.getCurrentPosition()))):c.debug("Cannot initialise annotation twice")}isCompatibleView(e){let t=!1;if(void 0===this.planePoints)e.isAquisitionOrientation()&&(t=!0);else{const n=e.getCosines(),i=new F(n[0],n[1],n[2]),r=new F(n[3],n[4],n[5]);i.equals(this.planePoints[1])&&r.equals(this.planePoints[2])&&(t=!0)}return t}setViewController(e){e.includesImageUid(this.referenceSopUID)&&this.isCompatibleView(e.getPlaneHelper())&&(this.#nt=e,this.planeOrigin=e.getOriginForImageUid(this.referenceSopUID))}#Ji(){let e;if(void 0!==this.#nt){let t=this.planeOrigin;void 0!==this.planePoints&&(t=this.planePoints[0]);const n=new E([t.getX(),t.getY(),t.getZ()]);e=this.#nt.getIndexFromPosition(n)}return e}getCentroid(){let e;if(void 0!==this.#nt&&void 0!==this.mathShape.getCentroid){const t=this.#Ji(),n=this.#nt.getScrollDimIndex(),i=t.getValues()[n],r=this.mathShape.getCentroid();e=this.#nt.getPositionFromPlanePoint(r,i)}return e}setTextExpr(e){if(void 0!==this.#nt){const t=this.#nt.getModality();void 0!==e[t]?this.textExpr=e[t]:this.textExpr=e["*"]}else c.warn("Cannot set text expr without a view controller")}getText(){return function(e,t){let n="";if(null==e)return n;if(n=e,null==t)return n;const i=Q(e);for(let e=0;e<i.length;++e){const r=t[i[e]];if(null!=r&&null!==r.value&&void 0!==r.value){let t=r.value.toPrecision(4);null!==r.unit&&void 0!==r.unit&&0!==r.unit.length&&("unit.degree"!==r.unit&&(t+=" "),t+=q.t(r.unit));const o="{"+i[e]+"}";n=n.replace(o,t)}}return n}(this.textExpr,this.quantification)}updateQuantification(){void 0!==this.#nt&&void 0!==this.mathShape.quantify&&(this.quantification=this.mathShape.quantify(this.#nt,this.#Ji(),Q(this.textExpr)))}getFactory(){let e;if(void 0!==Hi.draw)for(const t in Hi.draw){const n=Hi.draw[t];if(n.supports(this.mathShape)){e=new n;break}}if(void 0===e)for(const t in Wi.draw){const n=Wi.draw[t];if(n.supports(this.mathShape)){e=new n;break}}return void 0===e&&c.warn("No shape factory found for math shape"),e}}class Xi{#$i;#Pe={};#be=new He;#er;#tr;constructor(e){this.#$i=void 0!==e?e:[],this.#er=!0}getList(){return this.#$i}getLength(){return this.#$i.length}isEditable(){return this.#er}setEditable(e){this.#er=e,this.#Fe({type:"annotationgroupeditablechange",data:e})}getColour(){return this.#tr}setColour(e){this.#tr=e}add(e){this.#$i.push(e),this.#Fe({type:"annotationadd",data:e})}update(e,t){const n=this.#$i.findIndex((t=>t.id===e.id));-1!==n?((t.includes("mathShape")||t.includes("textExpr"))&&e.updateQuantification(),this.#$i[n]=e,this.#Fe({type:"annotationupdate",data:e,keys:t})):c.warn("Cannot find annotation to update")}remove(e){const t=this.#$i.findIndex((t=>t.id===e));if(-1!==t){const e=this.#$i.splice(t,1)[0];this.#Fe({type:"annotationremove",data:e})}else c.warn("Cannot find annotation to remove")}setViewController(e){for(const t of this.#$i)t.setViewController(e),t.updateQuantification()}find(e){return this.#$i.find((t=>t.id===e))}getMeta(){return this.#Pe}hasMeta(e){return void 0!==this.#Pe[e]}getMetaValue(e){return this.#Pe[e]}setMetaValue(e,t){this.#Pe[e]=t}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}}class ji{#nr;getAnnotation(e){return this.#nr.find(e)}getAnnotationGroup(){return this.#nr}isAnnotationGroupEditable(){return this.#nr.isEditable()}setAnnotationGroupEditable(e){this.#nr.setEditable(e)}addAnnotation(e){this.#nr.add(e)}updateAnnotation(e,t){this.#nr.update(e,t)}removeAnnotation(e){this.#nr.remove(e)}removeAnnotationWithCommand(e,t){const n=this.getAnnotation(e);if(void 0===n)return void c.warn("Cannot create remove command for undefined annotation: "+e);const i=new li(n,this);t(i),i.execute()}updateAnnotationWithCommand(e,t,n,i){const r=this.getAnnotation(e);if(void 0===r)return void c.warn("Cannot create update command for undefined annotation: "+e);const o=new ci(r,t,n,this);i(o),o.execute()}removeAllAnnotationsWithCommand(e){for(const t of this.#nr.getList())this.removeAnnotationWithCommand(t.id,e)}constructor(e){this.#nr=void 0!==e?e:new Xi}hasAnnotationMeta(e){return this.#nr.hasMeta(e)}setAnnotationMeta(e,t){this.#nr.setMetaValue(e,t)}}class Zi{#tt;#ir=null;#lt;#ct;#ht={x:1,y:1};#St={x:1,y:1,z:1};#pt={x:0,y:0};#mt={x:0,y:0};#ft={x:0,y:0};#Dt={x:0,y:0};#Mt;#_e;#Ct;#rr;#or;#ei;#ar=!0;constructor(e){this.#tt=e,this.#tt.className+=" drawLayer"}setShapeHandler(e){this.#ei=e}getDataId(){return this.#Ct}getReferenceLayerId(){return this.#rr}#be=new He;getKonvaStage(){return this.#ir}getKonvaLayer(){return this.#ir.getLayers()[0]}getDrawController(){return this.#Mt}setPlaneHelper(e){this.#_e=e}getId(){return this.#tt.id}removeFromDOM(){this.#tt.remove()}getBaseSize(){return this.#lt}getOpacity(){return this.#ir.opacity()}setOpacity(e){this.#ir.opacity(Math.min(Math.max(e,0),1))}addFlipOffsetX(){const e=this.#ir.scale(),t=this.#ir.size();this.#Dt.x+=t.width/e.x;const n=this.#ir.offset();n.x+=this.#Dt.x,this.#ir.offset(n)}addFlipOffsetY(){const e=this.#ir.scale(),t=this.#ir.size();this.#Dt.y+=t.height/e.y;const n=this.#ir.offset();n.y+=this.#Dt.y,this.#ir.offset(n)}flipScaleX(){this.#St.x*=-1}flipScaleY(){this.#St.y*=-1}flipScaleZ(){this.#St.z*=-1}setScale(e,t){const n=this.#_e.getTargetOrientedPositiveXYZ({x:e.x*this.#St.x,y:e.y*this.#St.y,z:e.z*this.#St.z}),i={x:this.#ht.x*n.x,y:this.#ht.y*n.y},r=this.#ir.offset();if(1===Math.abs(e.x)&&1===Math.abs(e.y)&&1===Math.abs(e.z)){const e={x:r.x-this.#ft.x,y:r.y-this.#ft.y};this.#ft={x:0,y:0},this.#ir.offset(e)}else if(void 0!==t){let e=this.#_e.getPlaneOffsetFromOffset3D({x:t.getX(),y:t.getY(),z:t.getZ()});e={x:e.x+this.#pt.x,y:e.y+this.#pt.y};const n=Ji(r,this.#ir.scale(),i,e),o={x:this.#ft.x+n.x-r.x,y:this.#ft.y+n.y-r.y};this.#ft=o,this.#ir.offset(n)}this.#ir.scale(i),this.#sr(i)}initScale(e,t){const n=this.#_e.getTargetOrientedPositiveXYZ({x:e.x*this.#St.x,y:e.y*this.#St.y,z:e.z*this.#St.z}),i={x:this.#ht.x*n.x,y:this.#ht.y*n.y};this.#ir.scale(i),this.#ft={x:t.x/this.#ht.x,y:t.y/this.#ht.y};const r=this.#ir.offset();this.#ir.offset({x:r.x+this.#ft.x,y:r.y+this.#ft.y})}setOffset(e){const t=this.#_e.getPlaneOffsetFromOffset3D(e);this.#ir.offset({x:t.x+this.#mt.x+this.#pt.x+this.#ft.x+this.#Dt.x,y:t.y+this.#mt.y+this.#pt.y+this.#ft.y+this.#Dt.y})}setBaseOffset(e,t){const n=this.#_e.getNativeScrollDimIndex(),i=this.#_e.getPlaneOffsetFromOffset3D({x:0===n?e.getX():t.getX(),y:1===n?e.getY():t.getY(),z:2===n?e.getZ():t.getZ()}),r=this.#pt.x!==i.x||this.#pt.y!==i.y;if(r){const e=this.#ir.offset();this.#ir.offset({x:e.x-this.#pt.x+i.x,y:e.y-this.#pt.y+i.y}),this.#pt=i}return r}display(e){this.#tt.style.display=e?"":"none"}isVisible(){return""===this.#tt.style.display}draw(){this.#ir.draw()}initialise(e,t,n){this.#lt=e,this.#ct=t,this.#rr=n,this.#ir=new(ai().Stage)({container:this.#tt,width:this.#lt.x,height:this.#lt.y,listening:!1}),this.#ir.getContent().setAttribute("style","");const i=new(ai().Layer)({listening:!1,visible:!0});this.#ir.add(i)}setAnnotationGroup(e,t,n){if(this.#Ct=t,e.addEventListener("annotationadd",(e=>{this.#lr(e.data,!0),this.getKonvaLayer().draw()})),e.addEventListener("annotationupdate",(e=>{this.#cr(e.data),this.getKonvaLayer().draw()})),e.addEventListener("annotationremove",(e=>{this.#ur(e.data),this.getKonvaLayer().draw()})),e.addEventListener("annotationgroupeditablechange",(e=>{this.activateCurrentPositionShapes(e.data)})),this.#Mt=new ji(e),0!==e.getLength())for(const t of e.getList())this.#lr(t,!1),n(new si(t,this.getDrawController()))}activateCurrentPositionShapes(e){const t=this.getKonvaLayer();if(this.#ir.listening(!1),void 0!==this.#ei){this.#ei.disableAndResetEditor();const e=t.getChildren();for(const t of e)t instanceof ai().Group&&t.getChildren().forEach((e=>{e instanceof ai().Group&&this.#ei.removeShapeListeners(e)}))}const n=this.getDrawController();if(e&&n.getAnnotationGroup().isEditable()){this.#ir.listening(!0);const e=this.#dr().getChildren();0!==e.length&&t.listening(!0),void 0!==this.#ei&&e.forEach((e=>{if(e instanceof ai().Group){const t=n.getAnnotation(e.id());this.#ei.addShapeGroupListeners(e,t,this)}}))}t.draw()}#hr(e){let t;return t=void 0!==e.planePoints?e.planePoints:[e.planeOrigin],this.#Sr(t)}#Sr(e){let t="";for(const n of e)0!==t.length&&(t+="-"),t+=G([B(n.getX(),2),B(n.getY(),2),B(n.getZ(),2)]);return t}#gr(e){let t;const n=this.#hr(e),i=this.getKonvaLayer().getChildren(fi(n));if(0!==i.length){const n=i[0];if(!(n instanceof ai().Group))return;const r=n.getChildren(fi(e.id));0!==r.length&&r[0]instanceof ai().Group&&(t=r[0])}return t}#lr(e,t){if(!e.isCompatibleView(this.#_e))return;const n=this.#hr(e);let i=this.getKonvaLayer().getChildren(fi(n))[0];if(void 0===i&&(i=new(ai().Group)({id:n,name:"position-group",visible:t}),this.getKonvaLayer().add(i)),!(i instanceof ai().Group))return;const r=new ui,o=this.getKonvaStage();r.setZoomScale(o.scale());const a=e.getFactory().createShapeGroup(e,r);i.add(a),t&&void 0!==this.#ei&&this.#ei.addShapeGroupListeners(a,e,this),this.setLabelVisibility(a)}#ur(e){const t=this.#gr(e);return t instanceof ai().Group?(t.remove(),!0):(c.debug("No shape group to remove"),!1)}#cr(e){this.#ur(e)&&this.#lr(e,!0)}fitToContainer(e,t,n){this.#ir.width(e.x),this.#ir.height(e.y);const i={x:t*this.#ct.x,y:t*this.#ct.y},r={x:this.#ir.scale().x*i.x/this.#ht.x,y:this.#ir.scale().y*i.y/this.#ht.y};this.#ir.scale().x===r.x&&this.#ir.scale().y===r.y||(this.#ht=i,this.#ir.scale(r));const o={x:n.x/i.x,y:n.y/i.y},a={x:e.x/i.x,y:e.y/i.y},s={x:0!==this.#Dt.x?a.x:0,y:0!==this.#Dt.y?a.y:0};this.#mt.x===o.x&&this.#mt.y===o.y&&this.#Dt.x===s.x&&this.#Dt.y===s.y||(this.#ir.offset({x:this.#ir.offset().x+o.x-this.#mt.x+s.x-this.#Dt.x,y:this.#ir.offset().y+o.y-this.#mt.y+s.y-this.#Dt.y}),this.#Dt=s,this.#mt=o)}isAnnotationVisible(e){const t=this.#pr(e);return void 0!==t&&t.isVisible()}setAnnotationVisibility(e,t){const n=this.#pr(e);return void 0!==n&&(void 0===t&&(t=!n.isVisible()),n.visible(t),this.draw(),!0)}setLabelsVisibility(e){this.#ar=e;const t=this.getKonvaLayer().getChildren();for(const n of t)if(n instanceof ai().Group){const t=n.getChildren();for(const n of t)n instanceof ai().Group&&this.#mr(n,e)}}#mr(e,t){const n=e.getChildren(hi)[0];if(n instanceof ai().Label&&(void 0===t&&(t=!n.isVisible()),void 0!==n.getText()&&0!==n.getText().text().length)){n.visible(t);const i=e.getChildren((e=>"Line"===e.className&&"connector"===e.name()))[0];i&&i.visible(t)}}setLabelVisibility(e){this.#mr(e,this.#ar)}deleteDraw(e,t){}deleteDraws(e){}getNumberOfDraws(){const e=this.getKonvaLayer().getChildren();let t=0;for(const n of e)n instanceof ai().Group&&(t+=n.getChildren().length);return t}bindInteraction(){this.#ir.listening(!0),this.#tt.style.pointerEvents="auto";const e=Wn;for(let t=0;t<e.length;++t)this.#tt.addEventListener(e[t],this.#Fe)}unbindInteraction(){this.#ir.listening(!1),this.#tt.style.pointerEvents="none";const e=Wn;for(let t=0;t<e.length;++t)this.#tt.removeEventListener(e[t],this.#Fe)}setCurrentPosition(e,t){void 0===t&&(t=this.#_e.worldToIndex(e));const n=this.#_e.getPlanePoints(e);let i;i=this.#_e.isAquisitionOrientation()?[n[0]]:n;const r=this.#Sr(i);return this.#fr(r),this.#Fe({type:"positionchange",value:[t.getValues(),e.getValues()],valid:!0}),!0}#fr(e){this.#or=e;const t=this.getKonvaLayer().getChildren(gi);let n;for(let i=0,r=t.length;i<r;++i)n=!1,void 0!==e&&t[i].id()===e&&(n=!0),t[i].visible(n);this.getKonvaLayer().draw()}#dr(){if(void 0===this.#or)return;const e=this.getKonvaLayer().getChildren((e=>e.id()===this.#or));let t;return 1===e.length?e[0]instanceof ai().Group&&(t=e[0]):0===e.length?(t=new(ai().Group),t.name("position-group"),t.id(this.#or),t.visible(!0),this.getKonvaLayer().add(t)):c.warn("Unexpected number of draw position groups"),t}#pr(e){return this.getKonvaLayer().findOne("#"+e)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{e.srclayerid=this.getId(),e.dataid=this.#Ct,this.#be.fireEvent(e)};#sr(e){const t=2/e.x,n=2/e.y,i=this.#ir.find("Label");for(let e=0;e<i.length;++e)i[e].scale({x:t,y:n})}}function _i(e){const t=e.split("-layer-");return 2!==t.length&&c.warn("Not the expected layer div id format..."),{groupDivId:t[0],layerIndex:t[1],layerId:e}}function Ki(e){let t=null;const n=e.target.closest(".layer");return n&&void 0!==n.id&&(t=_i(n.id)),t}function Ji(e,t,n,i){const r=(i.x-e.x)*t.x,o=(i.y-e.y)*t.y;return{x:i.x-r/n.x,y:i.y-o/n.y}}class $i{#tt;#Dr=[];#dt={x:1,y:1,z:1};#Ht={x:1,y:1,z:1};#gt={x:0,y:0,z:0};#yr=void 0;#be=new He;#Cr=!1;#vr=[];#Ir;#Be;#vt=!1;#Ke;getPositionHelper(){if(void 0===this.#Ke)for(const e of this.#Dr)if(e instanceof _n){const t=e.getViewController().getPositionHelper();void 0===this.#Ke?this.#Ke=t:this.#Ke.merge(t)}return this.#Ke}constructor(e){this.#tt=e}getShowCrosshair(){return this.#Cr}setShowCrosshair(e){this.#Cr=e,e?(this.addEventListener("offsetchange",this.#Tr),this.addEventListener("zoomchange",this.#Tr),this.#Lr()):(this.removeEventListener("offsetchange",this.#Tr),this.removeEventListener("zoomchange",this.#Tr),this.#Pr())}setImageSmoothing(e){this.#vt=e;for(const t of this.#Dr)t instanceof _n&&t.setImageSmoothing(e)}#Tr=e=>{this.#Lr()};getDivId(){let e;return null!==this.#tt&&(e=this.#tt.id),e}getScale(){return this.#dt}getBaseScale(){return this.#Ht}getAddedScale(){return{x:this.#dt.x/this.#Ht.x,y:this.#dt.y/this.#Ht.y,z:this.#dt.z/this.#Ht.z}}getOffset(){return this.#gt}getNumberOfLayers(){let e=0;return this.#Dr.forEach((t=>{void 0!==t&&e++})),e}includes(e){if(void 0===e)return!1;for(const t of this.#Dr)if(void 0!==t&&t.getId()===e)return!0;return!1}getViewLayers(e){void 0===e&&(e=function(){return!0});const t=[];for(const n of this.#Dr)n instanceof _n&&e(n)&&t.push(n);return t}someViewLayer(e){let t=!1;for(const n of this.#Dr)if(n instanceof _n&&e(n)){t=!0;break}return t}getDrawLayers(e){void 0===e&&(e=function(){return!0});const t=[];for(const n of this.#Dr)n instanceof Zi&&e(n)&&t.push(n);return t}getNumberOfViewLayers(){let e=0;return this.#Dr.forEach((t=>{void 0!==t&&t instanceof _n&&e++})),e}getActiveLayer(){let e;return void 0!==this.#yr&&(e=this.#Dr[this.#yr]),e}getActiveViewLayer(){let e;const t=this.getActiveLayer();return void 0!==t&&t instanceof _n&&(e=t),e}getBaseViewLayer(){let e;for(const t of this.#Dr)if(t instanceof _n){e=t;break}if(void 0!==e)return e;c.warn("No layer found")}getViewLayerById(e){const t=this.getViewLayers((function(t){return t.getId()===e}));let n;return 1===t.length&&(n=t[0]),n}getViewLayersByDataId(e){return this.getViewLayers((function(t){return t.getDataId()===e}))}searchViewLayers(e){const t=[];for(const n of this.#Dr)n instanceof _n&&n.getViewController().equalImageMeta(e)&&t.push(n);return t}getViewDataIndices(){const e=[];for(const t of this.#Dr)t instanceof _n&&e.push(t.getDataId());return e}getActiveDrawLayer(){let e;const t=this.getActiveLayer();return void 0!==t&&t instanceof Zi&&(e=t),e}getDrawLayerById(e){const t=this.getDrawLayers((function(t){return t.getId()===e}));let n;return 1===t.length&&(n=t[0]),n}getDrawLayersByDataId(e){return this.getDrawLayers((function(t){return t.getDataId()===e}))}setActiveLayer(e){this.#yr=e,this.#Fe({type:"activelayerchange",value:[this.#Dr[e]]})}setActiveLayerByDataId(e){let t;for(let n=0;n<this.#Dr.length;++n)if(void 0!==this.#Dr[n]&&this.#Dr[n].getDataId()===e){t=n;break}void 0!==t?this.setActiveLayer(t):c.warn("No layer to set as active with dataId: "+e)}addViewLayer(){const e=this.#Dr.length,t=this.#wr();this.#tt.append(t);const n=new _n(t);return n.setImageSmoothing(this.#vt),this.#Dr.push(n),this.setActiveLayer(e),this.#Or(n),this.#Ke=void 0,n}addDrawLayer(){this.#yr=this.#Dr.length;const e=this.#wr();this.#tt.append(e);const t=new Zi(e);return this.#Dr.push(t),this.#Ar(t),t}#Or(e){e.addEventListener("positionchange",this.updateLayersToPositionChange);for(const t of Vn)e.addEventListener(t,this.#Fe);e.addEventListener("renderstart",this.#Fe),e.addEventListener("renderend",this.#Fe)}#br(e){e.removeEventListener("positionchange",this.updateLayersToPositionChange);for(const t of Vn)e.removeEventListener(t,this.#Fe);e.removeEventListener("renderstart",this.#Fe),e.removeEventListener("renderend",this.#Fe),e.unbindImage()}#Ar(e){e.addEventListener("positionchange",this.updateLayersToPositionChange),e.addEventListener("positionchange",this.#Fe),e.addEventListener("drawcreate",this.#Fe),e.addEventListener("drawdelete",this.#Fe)}#xr(e){e.removeEventListener("positionchange",this.updateLayersToPositionChange),e.removeEventListener("positionchange",this.#Fe),e.removeEventListener("drawcreate",this.#Fe),e.removeEventListener("drawdelete",this.#Fe)}#wr(){const e=document.createElement("div");return e.id=this.getDivId()+"-layer-"+this.#Dr.length,e.className="layer",e.style.pointerEvents="none",e}empty(){this.#Dr=[],this.#yr=void 0,this.#Pr();const e=this.#tt.getElementsByClassName("layer");if(e)for(;e.length>0;)e[0].remove()}removeLayersByDataId(e){for(const t of this.#Dr)void 0!==t&&t.getDataId()===e&&this.removeLayer(t)}removeLayer(e){const t=this.#Dr.findIndex((t=>t===e));if(-1===t)throw new Error("Cannot find layer to remove");this.#yr===t&&(this.#yr=void 0),e instanceof _n?this.#br(e):this.#xr(e),this.#Dr[t]=void 0,e.removeFromDOM()}#Lr(e){let t;void 0===e&&(e=this.#Be),this.#Pr();for(const e of this.#Dr)if(e instanceof _n){t=e;break}if(void 0===t)return void c.warn("No layer to show crosshair");const n=t.getViewController().getPlanePositionFromPosition(e),i=t.planePosToDisplay(n);if(void 0!==i.getY()){const e=document.createElement("hr");e.id=this.getDivId()+"-scroll-crosshair-horizontal",e.className="horizontal",e.style.width=this.#tt.offsetWidth+"px",e.style.left="0px",e.style.top=i.getY()+"px",this.#vr.push(e),this.#tt.appendChild(e)}if(void 0!==i.getX()){const e=document.createElement("hr");e.id=this.getDivId()+"-scroll-crosshair-vertical",e.className="vertical",e.style.width=this.#tt.offsetHeight+"px",e.style.left=i.getX()+"px",e.style.top="0px",this.#vr.push(e),this.#tt.appendChild(e)}}#Pr(){for(const e of this.#vr)e.remove();this.#vr=[]}showTooltip(e){this.removeTooltipDiv();const t=this.getBaseViewLayer(),n=t.getViewController(),i=t.displayToPlanePos(e),r=n.getPositionFromPlanePoint(i),o=n.getRescaledImageValue(r);if(void 0!==o){const t=document.createElement("span");t.id="scroll-tooltip",t.style.left=e.getX()+10+"px",t.style.top=e.getY()+10+"px";let i=B(o,3).toString();void 0!==n.getPixelUnit()&&(i+=" "+n.getPixelUnit()),t.appendChild(document.createTextNode(i)),this.#Ir=t,this.#tt.appendChild(t)}}removeTooltipDiv(){void 0!==this.#Ir&&(this.#Ir.remove(),this.#Ir=void 0)}isPositionInBounds(e){return this.someViewLayer((function(t){return t.getViewController().isPositionInBounds(e)}))}canScroll(){return this.someViewLayer((function(e){return e.getViewController().canScroll()}))}moreThanOne(e){return this.someViewLayer((function(t){return t.getViewController().moreThanOne(e)}))}updateLayersToPositionChange=e=>{for(const e of this.#Dr)void 0!==e&&(e.removeEventListener("positionchange",this.updateLayersToPositionChange),e.removeEventListener("positionchange",this.#Fe));const t=new s(e.value[0]),n=new E(e.value[1]);this.#Be=n,this.#Cr&&this.#Lr(n);const i={};let r,o;for(const a of this.#Dr){if(void 0===a)continue;let s=!1;if(a instanceof _n){const e=a.getViewController(),t=e.getOrigin(),l=e.getOrigin(n);let c,u;if(void 0===o)r=t,o=l,c=new P(0,0,0),u=new P(0,0,0);else if(e.isPositionInBounds(n)&&void 0!==l){const e=r.minus(t);c=new P(e.getX(),e.getY(),e.getZ());const n=o.minus(l);u=new P(n.getX(),n.getY(),n.getZ())}void 0!==c&&void 0!==u&&(s=a.setBaseOffset(c,u,o,r),i[a.getId()]={scroll:c,plane:u})}if(a instanceof Zi){const e=i[a.getReferenceLayerId()];void 0!==e&&(s=a.setBaseOffset(e.scroll,e.plane))}let l=!1;a.getId()!==e.srclayerid&&(l=a.setCurrentPosition(n,t)),!l&&s&&a.draw()}for(const e of this.#Dr)void 0!==e&&(e.addEventListener("positionchange",this.updateLayersToPositionChange),e.addEventListener("positionchange",this.#Fe))};getDivToWorldSizeRatio(){if(0===this.#tt.offsetWidth&&0===this.#tt.offsetHeight)throw new Error("Cannot fit to zero sized container.");const e=this.getMaxWorldSize();if(void 0!==e){if(0===this.#tt.offsetHeight){const t=this.#tt.offsetWidth/e.x,n=e.y*t;this.#tt.style.height=n+"px"}return Math.min(this.#tt.offsetWidth/e.x,this.#tt.offsetHeight/e.y)}}fitToContainer(e){const t=this.getMaxWorldSize();if(void 0===t)return;const n={x:this.#tt.offsetWidth,y:this.#tt.offsetHeight},i={x:-.5*(n.x-Math.floor(t.x*e)),y:-.5*(n.y-Math.floor(t.y*e))};for(const t of this.#Dr)void 0!==t&&t.fitToContainer(n,e,i);this.#Cr&&this.#Lr()}getMaxWorldSize(){let e={x:0,y:0};for(const t of this.#Dr)if(t instanceof _n){const n=t.getImageWorldSize();n.x>e.x&&(e.x=n.x),n.y>e.y&&(e.y=n.y)}return 0===e.x&&0===e.y&&(e=void 0),e}flipScaleZ(){this.#Ht.z*=-1,this.setScale(this.#Ht)}addScale(e,t){const n={x:this.#dt.x*(1+e),y:this.#dt.y*(1+e),z:this.#dt.z*(1+e)};this.setScale(n,t)}setScale(e,t){this.#dt=e;for(const e of this.#Dr)void 0!==e&&e.setScale(this.#dt,t);const n=[e.x,e.y,e.z];void 0!==t&&(n.push(t.getX()),n.push(t.getY()),n.push(t.getZ())),this.#Fe({type:"zoomchange",value:n})}addTranslation(e){this.setOffset({x:this.#gt.x-e.x,y:this.#gt.y-e.y,z:this.#gt.z-e.z})}setOffset(e){this.#gt=e;for(const e of this.#Dr)void 0!==e&&e.setOffset(this.#gt);this.#Fe({type:"offsetchange",value:[this.#gt.x,this.#gt.y,this.#gt.z]})}reset(){this.setScale(this.#Ht),this.setOffset({x:0,y:0,z:0})}draw(){for(const e of this.#Dr)void 0!==e&&e.draw()}display(e){for(const t of this.#Dr)void 0!==t&&t.display(e)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}}const er={WindowLevelBinder:class{getEventType=function(){return"wlchange"};getCallback=function(e){return function(t){const n=e.getViewLayersByDataId(t.dataid);if(0!==n.length){const e=n[0].getViewController();if(2===t.value.length){const n=new u(t.value[0],t.value[1]);e.setWindowLevel(n)}3===t.value.length&&e.setWindowLevelPreset(t.value[2])}}}},PositionBinder:class{getEventType=function(){return"positionchange"};getCallback=function(e){return function(t){const n=t.value[1],i=e.getBaseViewLayer().getViewController(),r=i.getCurrentPosition(),o=r.length(),a=n.length;a!==o&&(a===o-1?n.push(r.get(o-1)):a===o+1&&n.pop()),i.setCurrentPosition(new E(n))}}},ZoomBinder:class{getEventType=function(){return"zoomchange"};getCallback=function(e){return function(t){const n={x:t.value[0],y:t.value[1],z:t.value[2]};let i;6===t.value.length&&(i=new F(t.value[3],t.value[4],t.value[5])),e.setScale(n,i),e.draw()}}},OffsetBinder:class{getEventType=function(){return"offsetchange"};getCallback=function(e){return function(t){e.setOffset({x:t.value[0],y:t.value[1],z:t.value[2]}),e.draw()}}},OpacityBinder:class{getEventType=function(){return"opacitychange"};getCallback=function(e){return function(t){if(void 0===t.dataid)return;const n=e.getViewLayersByDataId(t.dataid),i=e.getBaseViewLayer();0!==n.length&&i!==n[0]&&(n[0].setOpacity(t.value),n[0].draw())}}},ColourMapBinder:class{getEventType=function(){return"colourmapchange"};getCallback=function(e){return function(t){const n=e.getViewLayersByDataId(t.dataid);0!==n.length&&n[0].getViewController().setColourMap(t.value[0])}}}};class tr{#Rr=[];#Fr;#vt=!1;#Er=[];#ii=null;getLayerGroup(e){return this.#Rr[e]}getNumberOfLayerGroups(){return this.#Rr.length}getActiveLayerGroup(){return this.getLayerGroup(this.#Fr)}setActiveLayerGroup(e){void 0!==this.getLayerGroup(e)?this.#Fr=e:c.warn("No layer group to set as active with index: "+e)}getViewLayersByDataId(e){let t=[];for(const n of this.#Rr)t=t.concat(n.getViewLayersByDataId(e));return t}getViewLayers(e){let t=[];for(const n of this.#Rr)t=t.concat(n.getViewLayers(e));return t}getDrawLayersByDataId(e){let t=[];for(const n of this.#Rr)t=t.concat(n.getDrawLayersByDataId(e));return t}getDrawLayers(e){let t=[];for(const n of this.#Rr)t=t.concat(n.getDrawLayers(e));return t}addLayerGroup(e){this.#Fr=this.#Rr.length;const t=new $i(e);t.setImageSmoothing(this.#vt);const n=this.#ii&&0!==this.#ii.length;return n&&this.unbindLayerGroups(),this.#Rr.push(t),n&&this.bindLayerGroups(),t}getLayerGroupByDivId(e){return this.#Rr.find((function(t){return t.getDivId()===e}))}setBinders(e){if(null==e)throw new Error("Cannot set null or undefined binders");0!==this.#Er.length&&this.unbindLayerGroups(),this.#Er=e.slice(),this.bindLayerGroups()}empty(){this.unbindLayerGroups();for(const e of this.#Rr)e.empty();this.#Rr=[],this.#Fr=void 0}removeLayersByDataId(e){for(const t of this.#Rr)t.removeLayersByDataId(e)}removeLayerGroup(e){const t=this.#Rr.findIndex((t=>t===e));if(-1===t)throw new Error("Cannot find layerGroup to remove");this.unbindLayerGroups(),e.empty(),this.#Rr.splice(t,1),this.#Fr===t&&(this.#Fr=void 0),this.bindLayerGroups()}reset(){for(const e of this.#Rr)e.reset()}draw(){for(const e of this.#Rr)e.draw()}fitToContainer(){let e;const t=[];for(let n=0;n<this.#Rr.length;++n){const i=this.#Rr[n].getDivToWorldSizeRatio();void 0!==i&&(t.push(n),(void 0===e||i<e)&&(e=i))}if(void 0!==e)for(let n=0;n<this.#Rr.length;++n)t.includes(n)&&this.#Rr[n].fitToContainer(e)}bindLayerGroups(){if(0!==this.#Rr.length&&1!==this.#Rr.length&&0!==this.#Er.length){this.#ii=new Array(this.#Rr.length);for(let e=0;e<this.#Rr.length;++e)for(let t=0;t<this.#Er.length;++t)this.#qr(e,this.#Er[t])}}unbindLayerGroups(){if(0!==this.#Rr.length&&1!==this.#Rr.length&&0!==this.#Er.length&&this.#ii){for(let e=0;e<this.#Rr.length;++e)for(let t=0;t<this.#Er.length;++t)this.#Ur(e,this.#Er[t]);this.#ii=null}}setImageSmoothing(e){this.#vt=e;for(const t of this.#Rr)t.setImageSmoothing(e)}#Mr(e,t){void 0===this.#ii[t]&&(this.#ii[t]=[]);let n=this.#ii[t].find((function(t){return t.binder===e}));return void 0===n&&(n={binder:e,callback:n=>{this.#Ur(t,e),e.getCallback(this.#Rr[t])(n),this.#qr(t,e)}},this.#ii[t].push(n)),n.callback}#qr(e,t){for(let n=0;n<this.#Rr.length;++n)n!==e&&this.#Rr[e].addEventListener(t.getEventType(),this.#Mr(t,n))}#Ur(e,t){for(let n=0;n<this.#Rr.length;++n)n!==e&&this.#Rr[e].removeEventListener(t.getEventType(),this.#Mr(t,n))}}class nr{#Ct;constructor(e){this.#Ct=e}fromJSON(e){const t=JSON.parse(e);let n=null;if("0.1"===t.version)n=this.#Qr(t);else if("0.2"===t.version)n=this.#Vr(t);else if("0.3"===t.version)n=this.#Nr(t);else if("0.4"===t.version)n=this.#Br(t);else{if("0.5"!==t.version)throw new Error("Unknown state file format version: '"+t.version+"'.");n=this.#Gr(t)}return n}apply(e,t){const n=e.getActiveLayerGroup().getBaseViewLayer().getViewController(),i=new u(t["window-center"],t["window-width"]);n.setWindowLevel(i),n.setCurrentIndex(new s(t.position));const r=e.getActiveLayerGroup().getBaseScale();let o=null,a=null;if(void 0!==t.scaleCenter){o={x:t.scale*r.x,y:t.scale*r.y,z:1};const e=t.scaleCenter.x-t.scaleCenter.x*t.scale,n=t.scaleCenter.y-t.scaleCenter.y*t.scale,i=e+t.translation.x*o.x,s=n+t.translation.y*o.y;a={x:-i/o.x,y:-s/o.y,z:0}}else o={x:t.scale.x*r.x,y:t.scale.y*r.y,z:r.z},a={x:t.offset.x,y:t.offset.y,z:0};e.getActiveLayerGroup().setScale(o),e.getActiveLayerGroup().setOffset(a),e.setDrawings(t.drawings,t.drawingsDetails,this.#Ct)}#Qr(e){const t=function(e){const t=[],n={};let i,r;for(let o=0,a=e.length;o<a;++o){t[o]=[];for(let a=0,s=e[o].length;a<s;++a){i=e[o][a];const s=[];for(let e=0,t=i.length;e<t;++e){r=ai().Node.create(i[e]),r.visible(!0);let t={x:0,y:0};const o=r.getChildren((function(e){return"shape"===e.name()}))[0];if(o.stroke(T(o.stroke())),"line-group"===r.name()){r.name("ruler-group");const e=new(ai().Line)({points:[o.points()[0],o.points()[1],o.points()[0],o.points()[1]],name:"shape-tick0"});r.add(e);const t=new(ai().Line)({points:[o.points()[2],o.points()[3],o.points()[2],o.points()[3]],name:"shape-tick1"});r.add(t)}const a=r.getChildren((function(e){return"arc"===e.name()}));1===a.length&&a[0].name("shape-arc");const l=r.getChildren((function(e){return"text"===e.name()}));let c=new(ai().Text)({name:"text",text:""});1===l.length?(t.x=l[0].x(),t.y=l[0].y(),l[0].remove(),c=l[0]):0!==o.points().length&&(t={x:o.points()[0],y:o.points()[1]});const u=new(ai().Label)({x:t.x,y:t.y,name:"label"});u.add(c),u.add(new(ai().Tag)),r.add(u),s.push(JSON.stringify(r.toObject()));let d=c.text();const h=d.length;let S=null;"ruler-group"===r.name()?(S={length:{value:parseFloat(d.substring(0,h-2)),unit:d.substring(-2)}},d="{length}"):"ellipse-group"===r.name()||"rectangle-group"===r.name()?(S={surface:{value:parseFloat(d.substring(0,h-3)),unit:d.substring(-3)}},d="{surface}"):"protractor-group"!==r.name()&&"rectangle-group"!==r.name()||(S={angle:{value:parseFloat(d.substring(0,h-1)),unit:d.substring(-1)}},d="{angle}"),n[r.id()]={textExpr:d,longText:"",quant:S}}t[o].push(s)}}return{drawings:t,drawingsDetails:n}}(e.drawings);return e.drawings=ir(t.drawings).toObject(),e.drawingsDetails=rr(t.drawingsDetails),(e=or(e)).drawings=ar(e.drawings),e}#Vr(e){return e.drawings=ir(e.drawings).toObject(),e.drawingsDetails=rr(function(e){const t={},n="string"==typeof e?JSON.parse(e):e;for(let e=0,i=n.length;e<i;++e)for(let i=0,r=n[e].length;i<r;++i)for(let r=0,o=n[e][i].length;r<o;++r){const o=n[e][i][r];t[o.id]={textExpr:o.textExpr,longText:o.longText,quant:o.quant}}return t}(e.drawingsDetails)),(e=or(e)).drawings=ar(e.drawings),e}#Nr(e){return e.drawingsDetails=rr(e.drawingsDetails),(e=or(e)).drawings=ar(e.drawings),e}#Br(e){return(e=or(e)).drawings=ar(e.drawings),e}#Gr(e){return e}}function ir(e){let t,n,i;const r=new(ai().Layer)({listening:!1,visible:!0}),o="string"==typeof e?JSON.parse(e):e;for(let e=0,l=o.length;e<l;++e)for(let l=0,c=o[e].length;l<c;++l)if(n=o[e][l],0!==n.length){i=new(ai().Group)({id:(a=new s([1,1,e,l]),"slice-"+a.get(2)+"_frame-"+(4===a.length()?a.get(3):0)),name:"position-group",visible:!1});for(let e=0,r=n.length;e<r;++e)t=ai().Node.create(n[e]),t.draggable(!0),t.getChildren().forEach((function(e){e.draggable(!1)})),i.add(t);r.add(i)}var a;return r}function rr(e){const t={},n=Object.keys(e);for(let i=0,r=n.length;i<r;++i){const r=e[n[i]];t[n[i]]={meta:{textExpr:r.textExpr,longText:r.longText,quantification:r.quant}}}return t}function or(e){const t=e.position;return e.position=[t.i,t.j,t.k],e}function ar(e){const t=e.children;for(let e=0,n=t.length;e<n;++e){const n=t[e],i=n.attrs.id.split("_"),r=parseInt(i[0].substring(6),10),o=parseInt(i[1].substring(6),10);let a="#2-";a+=0===r&&0!==o?o:r,n.attrs.id=a}return e}function sr(e){let t;return"null"!==window.location.origin&&(t=window.location.origin),new URL(e,t)}function lr(e){const t={};let n=null;if(e&&-1!==(n=e.indexOf("?"))){t.base=e.substring(0,n);let i=e.indexOf("#");-1===i&&(i=e.length);const r=e.substring(n+1,i);t.query=function(e){const t={};if(e){const n=e.split("&");for(let e=0;e<n.length;++e){const i=n[e].split("=");t[i[0]]?(t[i[0]]instanceof Array||(t[i[0]]=[t[i[0]]]),t[i[0]].push(i[1])):t[i[0]]=i[1]}}return t}(r)}return t}class cr{#kr=[];#Hr=0;#be=new He;getStackSize(){return this.#kr.length}getCurrentStackIndex(){return this.#Hr}add(e){this.#kr=this.#kr.slice(0,this.#Hr),this.#kr.push(e),++this.#Hr,this.#Fe({type:"undoadd",command:e.getName()})}remove(e){let t=!1;const n=this.#kr.findIndex((function(t){return t.getName()===e}));return-1!==n&&(this.#kr.splice(n,1),--this.#Hr,t=!0,this.#Fe({type:"undoremove",command:e})),t}undo(){this.#Hr>0&&(--this.#Hr,this.#kr[this.#Hr].undo(),this.#Fe({type:"undo",command:this.#kr[this.#Hr].getName()}))}redo(){this.#Hr<this.#kr.length&&(this.#kr[this.#Hr].execute(),this.#Fe({type:"redo",command:this.#kr[this.#Hr].getName()}),++this.#Hr)}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)}}class ur{#zr;#Wr=null;#ii=[];#Yr={};constructor(e){this.#zr=e}init(){for(const e in this.#zr)this.#zr[e].init();this.enableShortcuts(!0)}enableShortcuts(e){e?window.addEventListener("keydown",this.#Xr("window","keydown"),!0):window.removeEventListener("keydown",this.#Xr("window","keydown"),!0)}getToolList(){return this.#zr}hasTool(e){return void 0!==this.getToolList()[e]}getSelectedTool(){return this.#Wr}getSelectedToolEventHandler(e){return this.getSelectedTool()[e]}setSelectedTool(e){if(!this.hasTool(e))throw new Error("Unknown tool: '"+e+"'");this.#Wr&&this.#Wr.activate(!1),this.#Wr=this.#zr[e],this.#Wr.activate(!0)}setToolFeatures(e){this.getSelectedTool()&&this.getSelectedTool().setFeatures(e)}bindLayerGroup(e,t){const n=e.getDivId();e.addEventListener("activelayerchange",this.#jr(n)),this.#Zr(n,t)}#Zr(e,t){void 0!==this.#Yr[e]&&this.#_r(this.#Yr[e]),this.#Yr[e]=t,this.#Kr(t)}#jr(e){return t=>{const n=t.value[0];void 0!==n&&this.#Zr(e,n)}}#Kr(e){e.bindInteraction();const t=Wn;for(let n=0;n<t.length;++n)e.addEventListener(t[n],this.#Xr(e.getId(),t[n]))}#_r(e){e.unbindInteraction();const t=Wn;for(let n=0;n<t.length;++n)e.removeEventListener(t[n],this.#Xr(e.getId(),t[n]))}#Xr(e,t){if(void 0===this.#ii[e]&&(this.#ii[e]=[]),void 0===this.#ii[e][t]){const n=e=>{if(this.#Wr){const t=this.#Wr[e.type];t&&t(e)}};this.#ii[e][t]=n}return this.#ii[e][t]}}class dr{#Jr=[];#$r=2;#eo;constructor(e){this.#eo=e}setNumberOfDimensions(e){this.#$r=e}setNToLoad(e){for(let t=0;t<e;++t){this.#Jr[t]=[];for(let e=0;e<this.#$r;++e)this.#Jr[t][e]=0}}onprogress=e=>{if(!e.lengthComputable)return;if(void 0===e.subindex)return;if(void 0===e.index)return;const t=100*e.loaded/e.total;this.#Jr[e.index][e.subindex]=t;let n=null;n=void 0!==e.item?e.item:{loaded:this.#to(e.index),total:100,source:e.source},this.#eo({lengthComputable:!0,loaded:this.#no(),total:100,item:n})};#to(e){let t=0;for(let n=0;n<this.#$r;++n)t+=this.#Jr[e][n];return t/this.#$r}#no(){let e=0;const t=this.#Jr.length;for(let n=0;n<t;++n)e+=this.#to(n);return Math.round(e/t)}getMonoProgressHandler(e,t){return n=>{n.index=e,n.subindex=t,this.onprogress(n)}}getUndefinedMonoProgressHandler(e){return t=>{t.subindex=e,this.onprogress(t)}}}class hr{#io=null;#ro=[];#oo=null;#ao=0;#so=0;#lo;#E;getDefaultCharacterSet(){return this.#E}setDefaultCharacterSet(e){this.#E=e}#co(e){this.#io=e,this.#ao=0,this.#so=0,this.#lo=!1,this.#uo(),this.#do()}#ho(e){this.#ro.push(e)}#uo(){this.#ro=[]}#So(e){this.#oo=e}#do(){this.#oo=null}#go=e=>{this.#ao++,this.#ao===this.#io.length&&this.onload({source:this.#io})};#po=e=>{this.#so++,this.#so===this.#io.length&&this.onloadend({source:this.#io})};#mo(e,t){return n=>{n.source=t,e(n)}}load(e,t){this.onloadstart({source:e}),1===e.length&&(M(e[0],"DICOMDIR")||M(e[0],".dcmdir"))?this.#fo(e[0],t):this.#Do(e,t)}#yo(e,t,n){return i=>{const r=i.target.status;200!==r&&0!==r?(this.onerror({source:t,error:"GET "+i.target.responseURL+" "+i.target.status+" ("+i.target.statusText+")",target:i.target}),this.#po()):e.load(i.target.response,t,n)}}#Do(e,t){if(void 0===e||0===e.length)return;this.#co(e);const n=new dr(this.onprogress);n.setNToLoad(e.length);const i=[];for(let e=0;e<go.length;++e)i.push(new go[e]);let r=e[0],o=null,a=!1;for(let s=0;s<i.length;++s)if(o=i[s],o.canLoadUrl(r,t)){a=!0,o.setOptions({numberOfFiles:e.length,defaultCharacterSet:this.getDefaultCharacterSet()}),o.onprogress=n.getUndefinedMonoProgressHandler(1),o.onloaditem=this.onloaditem,o.onload=this.#go,o.onloadend=this.#po,o.onerror=this.onerror,o.onabort=this.onabort,this.#So(o);break}if(!a)throw new Error("No loader found for url: "+r);let s=0;const l=()=>{s<this.#ro.length-1&&!this.#lo&&(++s,this.#ro[s].send(null))};for(let i=0;i<e.length;++i){if(r=e[i],!o.canLoadUrl(r,t))throw new Error("Input url of different type: "+r);const a=new XMLHttpRequest;if(a.open("GET",r,!0),void 0!==t){if(void 0!==t.requestHeaders){const e=t.requestHeaders;for(let t=0;t<e.length;++t)void 0!==e[t].name&&void 0!==e[t].value&&a.setRequestHeader(e[t].name,e[t].value)}void 0!==t.withCredentials&&(a.withCredentials=t.withCredentials)}a.onprogress=this.#mo(n.getMonoProgressHandler(i,0),r),a.onload=this.#yo(o,r,i),a.onloadend=l;const s=this.#mo(this.onerror,r);a.onerror=e=>{this.#po(),s(e)};const c=this.#mo(this.ontimeout,r);a.ontimeout=e=>{this.#po(),c(e)};const u=this.#mo(this.onabort,r);a.onabort=e=>{this.#po(),u(e)},1===o.loadUrlAs()&&(a.responseType="arraybuffer"),this.#ho(a)}let c=this.#ro.length;void 0!==t&&void 0!==t.batchSize&&0!==c&&(c=Math.min(t.batchSize,this.#ro.length));for(let e=0;e<c;++e)this.#lo||(s=e,this.#ro[s].send(null))}#fo(e,t){const n=new XMLHttpRequest;n.open("GET",e,!0),n.responseType="arraybuffer",n.onload=n=>{const i=n.target.status;if(200!==i&&0!==i)this.onerror({source:e,error:"GET "+n.target.responseURL+" "+n.target.status+" ("+n.target.statusText+")",target:n.target}),this.onloadend({});else{const i=function(e){const t=new ke;t.parse(e);const n=t.getDicomElements();if(void 0===n["00041220"]||void 0===n["00041220"].value)return void c.warn("No Directory Record Sequence found in DICOMDIR.");const i=n["00041220"].value;if(0===i.length)return void c.warn("The Directory Record Sequence of the DICOMDIR is empty.");const r=[];let o=null,a=null;for(let e=0;e<i.length;++e){if(void 0===i[e]["00041430"]||void 0===i[e]["00041430"].value)continue;const t=i[e]["00041430"].value[0];if("STUDY"===t)a=[],r.push(a);else if("SERIES"===t)o=[],a.push(o);else if("IMAGE"===t){if(void 0===i[e]["00041500"]||void 0===i[e]["00041500"].value)continue;const t=i[e]["00041500"].value;o.push(t.join("/"))}}return r}(n.target.response)[0][0],r=e.split("/").slice(0,-1).join("/"),o=[];for(let e=0;e<i.length;++e)o.push(r+"/"+i[e]);this.#Do(o,t)}},n.onerror=t=>{this.#mo(this.onerror,e)(t),this.onloadend({})},n.onabort=t=>{this.#mo(this.onabort,e)(t),this.onloadend({})},n.send(null)}abort(){this.#lo=!0;for(let e=0;e<this.#ro.length;++e)4!==this.#ro[e].readyState&&this.#ro[e].abort();this.#oo&&this.#oo.isLoading()&&this.#oo.abort()}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}ontimeout(e){}onabort(e){}}class Sr{constructor(e){this.poolSize=e,this.taskQueue=[],this.freeThreads=[];for(let t=0;t<e;++t)this.freeThreads.push(new gr(this));this.runningThreads=[]}addWorkerTask(e){if(this.freeThreads.length===this.poolSize&&this.onworkstart({type:"work-start"}),this.freeThreads.length>0){const t=this.freeThreads.shift();this.runningThreads.push(t),t.run(e)}else this.taskQueue.push(e)}abort(){this.#Co(),this.onabort({type:"work-abort"}),this.onworkend({type:"work-end"})}onTaskEnd(e){if(this.taskQueue.length>0){const t=this.taskQueue.shift();e.run(t)}else{e.stop(),this.freeThreads.push(e);for(let t=0;t<this.runningThreads.length;++t)this.runningThreads[t].getId()===e.getId()&&this.runningThreads.splice(t,1);this.freeThreads.length===this.poolSize&&(this.onwork({type:"work"}),this.onworkend({type:"work-end"}))}}handleWorkerError=e=>{this.#Co(),this.onerror({error:e}),this.onworkend({type:"work-end"})};#Co(){this.taskQueue=[];for(let e=0;e<this.runningThreads.length;++e)this.runningThreads[e].stop();this.runningThreads=[]}onworkstart(e){}onworkitem(e){}onwork(e){}onworkend(e){}onerror(e){}onabort(e){}}class gr{constructor(e){this.parentPool=e,this.id=Math.random().toString(36).substring(2,15),this.runningTask=null,this.worker}getId(){return this.id}run(e){this.runningTask=e,void 0===this.worker&&(this.worker=new Worker(this.runningTask.script),this.worker.onmessage=this.onmessage,this.worker.onerror=this.onerror),this.worker.postMessage(this.runningTask.startMessage)}stop(){void 0!==this.worker&&(this.worker.terminate(),this.worker=void 0)}onmessage=e=>{e.itemNumber=this.runningTask.info.itemNumber,e.numberOfItems=this.runningTask.info.numberOfItems,e.index=this.runningTask.info.index,this.parentPool.onworkitem(e),this.parentPool.onTaskEnd(this)};onerror=e=>{e.itemNumber=this.runningTask.info.itemNumber,e.numberOfItems=this.runningTask.info.numberOfItems,e.index=this.runningTask.info.index,this.parentPool.handleWorkerError(e),this.stop()}}class pr{constructor(e,t,n){this.script=e,this.startMessage=t,this.info=n}}const mr="undefined"!=typeof JpegImage,fr="undefined"!=typeof jpeg&&void 0!==jpeg.lossless,Dr="undefined"!=typeof JpxImage,yr={jpeg2000:"","jpeg-lossless":"","jpeg-baseline":"",rle:""};class Cr{#vo;#Io=new Sr(10);#To=!1;constructor(e,t){this.#vo=e}decode(e,t,n){this.#To||(this.#To=!0,this.#Io.onworkstart=this.ondecodestart,this.#Io.onworkitem=this.ondecodeditem,this.#Io.onwork=this.ondecoded,this.#Io.onworkend=this.ondecodeend,this.#Io.onerror=this.onerror,this.#Io.onabort=this.onabort);const i=new pr(this.#vo,{buffer:e,meta:t},n);this.#Io.addWorkerTask(i)}abort(){this.#Io.abort()}ondecodestart(e){}ondecodeditem(e){}ondecoded(e){}ondecodeend(e){}onerror(e){}onabort(e){}}class vr{#Lo;#Po;constructor(e,t){this.#Lo=e,this.#Po=t}#wo=0;decode(e,t,n){++this.#wo;let i=null,r=null;if("jpeg-lossless"===this.#Lo){if(!fr)throw new Error("No JPEG Lossless decoder provided");const n=t.bitsAllocated/8,o=new Uint8Array(e);i=new jpeg.lossless.Decoder;const a=i.decode(o.buffer,0,o.buffer.byteLength,n);8===t.bitsAllocated?r=t.isSigned?new Int8Array(a.buffer):new Uint8Array(a.buffer):16===t.bitsAllocated&&(r=t.isSigned?new Int16Array(a.buffer):new Uint16Array(a.buffer))}else if("jpeg-baseline"===this.#Lo){if(!mr)throw new Error("No JPEG Baseline decoder provided");i=new JpegImage,i.parse(e),r=i.getData(i.width,i.height)}else if("jpeg2000"===this.#Lo){if(!Dr)throw new Error("No JPEG 2000 decoder provided");i=new JpxImage,i.parse(e),r=i.tiles[0].items}else"rle"===this.#Lo&&(i=new dwvdecoder.RleDecoder,r=i.decode(e,t.bitsAllocated,t.isSigned,t.sliceSize,t.samplesPerPixel,t.planarConfiguration));this.ondecodeditem({data:[r],index:n.index,numberOfItems:n.numberOfItems,itemNumber:n.itemNumber}),this.#wo===this.#Po&&(this.ondecoded({}),this.ondecodeend({}))}abort(){this.onabort({}),this.ondecodeend({})}ondecodestart(e){}ondecodeditem(e){}ondecoded(e){}ondecodeend(e){}onerror(e){}onabort(e){}}class Ir{#To=!1;#Oo=null;constructor(e,t){void 0!==yr&&void 0!==yr[e]?this.#Oo=new Cr(yr[e],t):this.#Oo=new vr(e,t)}decode(e,t,n){this.#To||(this.#To=!0,this.#Oo.ondecodestart=this.ondecodestart,this.#Oo.ondecodeditem=this.ondecodeditem,this.#Oo.ondecoded=this.ondecoded,this.#Oo.ondecodeend=this.ondecodeend,this.#Oo.onerror=this.onerror,this.#Oo.onabort=this.onabort),this.#Oo.decode(e,t,n)}abort(){this.#Oo.abort()}ondecodestart(e){}ondecodeditem(e){}ondecoded(e){}ondecodeend(e){}onerror(e){}onabort(e){}}const Tr={NumericValue:"0040A30A",FloatingPointValue:"0040A161",RationalNumeratorValue:"0040A162",RationalDenominatorValue:"0040A163",MeasurementUnitsCodeSequence:"004008EA"};class Lr{numericValue;floatingPointValue;rationalNumeratorValue;rationalDenominatorValue;measurementUnitsCode;toString(){return this.numericValue+" "+this.measurementUnitsCode.toString()}}function Pr(e){const t={};return void 0!==e.measurementUnitsCode&&(t.MeasurementUnitsCodeSequence={value:[Wt(e.measurementUnitsCode)]}),void 0!==e.floatingPointValue&&(t.FloatingPointValue=e.floatingPointValue),void 0!==e.rationalNumeratorValue&&(t.RationalNumeratorValue=e.rationalNumeratorValue),void 0!==e.rationalDenominatorValue&&(t.RationalDenominatorValue=e.rationalDenominatorValue),void 0!==e.numericValue&&(t.NumericValue=e.numericValue),t}const wr={MeasuredValueSequence:"0040A300",NumericValueQualifierCodeSequence:"0040A301"};class Or{measuredValue;numericValueQualifierCode;toString(){let e=this.measuredValue.toString();return void 0!==this.numericValueQualifierCode&&(e+=" "+this.numericValueQualifierCode.toString()),e}}function Ar(e){const t={};return void 0!==e.measuredValue&&(t.MeasuredValueSequence={value:[Pr(e.measuredValue)]}),void 0!==e.numericValueQualifierCode&&(t.NumericValueQualifierCodeSequence={value:[Wt(e.numericValueQualifierCode)]}),t}const br={ReferencedSOPClassUID:"00081150",ReferencedSOPInstanceUID:"00081155"};class xr{referencedSOPClassUID;referencedSOPInstanceUID;toString(){return this.referencedSOPInstanceUID+" (class: "+this.referencedSOPClassUID+")"}}function Rr(e){const t=new xr;return void 0!==e[br.ReferencedSOPClassUID]&&(t.referencedSOPClassUID=e[br.ReferencedSOPClassUID].value[0]),void 0!==e[br.ReferencedSOPInstanceUID]&&(t.referencedSOPInstanceUID=e[br.ReferencedSOPInstanceUID].value[0]),t}function Fr(e){const t={};return void 0!==e.referencedSOPClassUID&&(t.ReferencedSOPClassUID=e.referencedSOPClassUID),void 0!==e.referencedSOPInstanceUID&&(t.ReferencedSOPInstanceUID=e.referencedSOPInstanceUID),t}const Er={ReferencedFrameNumber:"00081160",ReferencedSOPSequence:"00081199",ReferencedSegmentNumber:"0062000B"};class qr{referencedSOPSequence;referencedFrameNumber;referencedSegmentNumber;fiducialUID;toString(){return this.referencedSOPSequence.toString()}}function Ur(e){const t={};return void 0!==e.referencedFrameNumber&&(t.ReferencedFrameNumber=e.referencedFrameNumber),void 0!==e.referencedSOPSequence&&(t.ReferencedSOPSequence={value:[Fr(e.referencedSOPSequence)]}),void 0!==e.referencedSegmentNumber&&(t.ReferencedSegmentNumber=e.referencedSegmentNumber),t}const Mr={PixelOriginInterpretation:"00480301",GraphicData:"00700022",GraphicType:"00700023",FiducialUID:"0070031A"},Qr="POINT",Vr="MULTIPOINT",Nr="POLYLINE",Br="CIRCLE",Gr="ELLIPSE";class kr{graphicData;graphicType;pixelOriginInterpretation;fiducialUID;toString(){return this.graphicType+" {"+this.graphicData+"}"}}function Hr(e){const t={};return void 0!==e.pixelOriginInterpretation&&(t.PixelOriginInterpretation=e.pixelOriginInterpretation),void 0!==e.graphicData&&(t.GraphicData=e.graphicData),void 0!==e.graphicType&&(t.GraphicType=e.graphicType),void 0!==e.fiducialUID&&(t.FiducialUID=e.fiducialUID),t}const zr={GraphicData:"00700022",GraphicType:"00700023",ReferencedFrameofReferenceUID:"30060024",FiducialUID:"0070031A"};class Wr{graphicData;graphicType;referencedFrameofReferenceUID;fiducialUID;toString(){return this.graphicType+"{"+this.graphicData+"}"}}function Yr(e){const t={};return void 0!==e.graphicData&&(t.GraphicData=e.graphicData),void 0!==e.graphicType&&(t.GraphicType=e.graphicType),void 0!==e.referencedFrameofReferenceUID&&(t.ReferencedFrameofReferenceUID=e.referencedFrameofReferenceUID),void 0!==e.fiducialUID&&(t.FiducialUID=e.fiducialUID),t}const Xr={ReferencedSOPSequence:"00081199",RelationshipType:"0040A010",ValueType:"0040A040",ConceptNameCodeSequence:"0040A043",ConceptCodeSequence:"0040A168",ContentSequence:"0040A730",DateTime:"0040A120",Date:"0040A121",Time:"0040A122",UID:"0040A124",PersonName:"0040A123",TextValue:"0040A160",ContinuityOfContent:"0040A050"},jr="CONTAINS",Zr="HAS PROPERTIES",_r="SELECTED FROM",Kr={text:"TEXT",num:"NUM",code:"CODE",date:"DATE",time:"TIME",datetime:"DATETIME",uidref:"UIDREF",pname:"PNAME",composite:"COMPOSITE",image:"IMAGE",waveform:"WAVEFORM",scoord:"SCOORD",scoord3d:"SCOORD3D",tcoord:"TCOORD",container:"CONTAINER",table:"TABLE"},Jr={TEXT:"TextValue",DATE:"Date",TIME:"Time",DATETIME:"DateTime",UIDREF:"UID",PNAME:"PersonName",CONTAINER:"ContinuityOfContent"};class $r{valueType;conceptNameCode;relationshipType;contentSequence;value;constructor(e){this.valueType=e}toString(e){void 0===e&&(e="");let t="";if(void 0!==this.relationshipType&&(t+="("+this.relationshipType+") "),t+=this.valueType+": ",void 0!==this.conceptNameCode&&(t+=this.conceptNameCode.toString()),t+=" = "+this.value.toString(),void 0!==this.contentSequence)for(const n of this.contentSequence)t+="\n"+e+"- "+n.toString(e+"  ");return t}}function eo(e){let t="";void 0!==e[Xr.ValueType]&&(t=e[Xr.ValueType].value[0]);const n=new $r(t);if(void 0!==e[Xr.RelationshipType]&&(n.relationshipType=e[Xr.RelationshipType].value[0]),void 0!==e[Xr.ConceptNameCodeSequence]&&(n.conceptNameCode=zt(e[Xr.ConceptNameCodeSequence].value[0])),t===Kr.code)n.value=zt(e[Xr.ConceptCodeSequence].value[0]);else if(t===Kr.num)n.value=function(e){const t=new Or;return void 0!==e[wr.MeasuredValueSequence]&&(t.measuredValue=function(e){const t=new Lr;return void 0!==e[Tr.NumericValue]&&(t.numericValue=e[Tr.NumericValue].value[0]),void 0!==e[Tr.FloatingPointValue]&&(t.floatingPointValue=e[Tr.FloatingPointValue].value[0]),void 0!==e[Tr.RationalNumeratorValue]&&(t.rationalNumeratorValue=e[Tr.RationalNumeratorValue].value[0]),void 0!==e[Tr.RationalDenominatorValue]&&(t.rationalDenominatorValue=e[Tr.RationalDenominatorValue].value[0]),void 0!==e[Tr.MeasurementUnitsCodeSequence]&&(t.measurementUnitsCode=zt(e[Tr.MeasurementUnitsCodeSequence].value[0])),t}(e[wr.MeasuredValueSequence].value[0])),void 0!==e[wr.NumericValueQualifierCodeSequence]&&(t.numericValueQualifierCode=zt(e[wr.NumericValueQualifierCodeSequence].value[0])),t}(e);else if(t===Kr.image)n.value=function(e){const t=new qr;return void 0!==e[Er.ReferencedFrameNumber]&&(t.referencedFrameNumber=e[Er.ReferencedFrameNumber].value[0]),void 0!==e[Er.ReferencedSOPSequence]&&(t.referencedSOPSequence=Rr(e[Er.ReferencedSOPSequence].value[0])),void 0!==e[Er.ReferencedSegmentNumber]&&(t.referencedSegmentNumber=e[Er.ReferencedSegmentNumber].value[0]),t}(e);else if(t===Kr.composite)n.value=Rr(e[Xr.ReferencedSOPSequence].value[0]);else if(t===Kr.scoord)n.value=function(e){const t=new kr;return void 0!==e[Mr.GraphicData]&&(t.graphicData=e[Mr.GraphicData].value),void 0!==e[Mr.GraphicType]&&(t.graphicType=e[Mr.GraphicType].value[0]),void 0!==e[Mr.PixelOriginInterpretation]&&(t.pixelOriginInterpretation=e[Mr.PixelOriginInterpretation].value[0]),void 0!==e[Mr.FiducialUID]&&(t.fiducialUID=e[Mr.FiducialUID].value[0]),t}(e);else if(t===Kr.scoord3d)n.value=function(e){const t=new Wr;return void 0!==e[zr.GraphicData]&&(t.graphicData=e[zr.GraphicData].value),void 0!==e[zr.GraphicType]&&(t.graphicType=e[zr.GraphicType].value[0]),void 0!==e[zr.ReferencedFrameofReferenceUID]&&(t.referencedFrameofReferenceUID=e[zr.ReferencedFrameofReferenceUID].value[0]),void 0!==e[zr.FiducialUID]&&(t.fiducialUID=e[zr.FiducialUID].value[0]),t}(e);else{const i=Jr[t];void 0!==i?n.value=e[Xr[i]].value[0]:console.warn("Unsupported input ValueType: "+t)}if(void 0!==e[Xr.ContentSequence]){n.contentSequence=[];for(const t of e[Xr.ContentSequence].value)n.contentSequence.push(eo(t))}return n}function to(e){let t={};if(void 0!==e.relationshipType&&(t.RelationshipType=e.relationshipType),void 0!==e.valueType&&(t.ValueType=e.valueType),void 0!==e.conceptNameCode&&(t.ConceptNameCodeSequence={value:[Wt(e.conceptNameCode)]}),"CODE"===e.valueType)t.ConceptCodeSequence={value:[Wt(e.value)]};else if(e.valueType===Kr.num)t={...t,...Ar(e.value)};else if(e.valueType===Kr.image)t={...t,...Ur(e.value)};else if(e.valueType===Kr.composite)t={...t,...Fr(e.value)};else if(e.valueType===Kr.scoord)t={...t,...Hr(e.value)};else if(e.valueType===Kr.scoord3d)t={...t,...Yr(e.value)};else{const n=Jr[e.valueType];void 0!==n?t[n]=e.value:console.warn("Unsupported output ValueType: "+e.valueType)}if(void 0!==e.contentSequence){t.ContentSequence={value:[]};for(const n of e.contentSequence)t.ContentSequence.value.push(to(n))}return t}function no(e,t,n){const i=function(e){const t=rn[e];let n;return void 0!==t&&(n=Zt(t.key,t.scheme)),n}(e);if(void 0===i)return;const r=new $r(Kr.num);r.relationshipType=jr,r.conceptNameCode=i;const o=new Lr;o.numericValue=t,o.measurementUnitsCode=function(e){const t=an[e];let n;return void 0!==t?n=Zt(t,"UCUM"):void 0===t&&(n=Zt("1","UCUM")),n}(n);const a=new Or;return a.measuredValue=o,r.value=a,r}class io{#ee;getWarning(){return this.#ee}checkElements(e){this.#ee=void 0;const t=eo(e);return void 0!==t.conceptNameCode?t.conceptNameCode.value!==_t().value&&(this.#ee="Not a measurement group"):this.#ee="No root concept name code",this.#ee}#Ao(e){const t=new Yi;t.mathShape=function(e){const t=e.graphicData.length;if(t%2!=0)throw new Error("Expecting even number of coordinates in scroord data");const n=[];for(let i=0;i<t;i+=2)n.push(new R(parseFloat(e.graphicData[i]),parseFloat(e.graphicData[i+1])));let i=!1;const r=n.length;if(r>2){const e=n[0],t=n[r-1];i=e.equals(t)}let o;if(e.graphicType===Qr){if(1!==n.length)throw new Error("Expecting 1 point for point");o=n[0]}else if(e.graphicType===Br){if(2!==n.length)throw new Error("Expecting 2 points for circles");const e=n[0],t=n[1].getDistance(e);o=new Fi(e,t)}else if(e.graphicType===Gr){if(4!==n.length)throw new Error("Expecting 4 points for ellipses");const e=n[0].getDistance(n[1])/2,t=n[2].getDistance(n[3])/2,i=new R(n[0].getX()+e,n[0].getY());o=new Ei(i,e,t)}else if(e.graphicType===Nr)if(i)if(5===n.length){const e=new $n(n[0],n[1]),t=new $n(n[1],n[2]),i=new $n(n[2],n[3]),r=new $n(n[3],n[4]);o=ti(e,t)&&ti(t,i)&&ti(i,r)?new Mi(n[0],n[2]):new Ti(n.slice(0,-1))}else o=new Ti(n.slice(0,-1));else 2===n.length?o=new $n(n[0],n[1]):3===n.length&&(o=new Ui([n[0],n[1],n[2]]));return o}(e.value),t.id=et(),t.textExpr="";for(const n of e.contentSequence){if(n.valueType===Kr.image&&n.relationshipType===_r&&Ht(n.conceptNameCode,Jt())&&(t.referenceSopUID=n.value.referencedSOPSequence.referencedSOPInstanceUID),n.valueType===Kr.uidref&&n.relationshipType===Zr&&Ht(n.conceptNameCode,$t())&&(t.id=n.value),n.valueType===Kr.text&&n.relationshipType===Zr&&Ht(n.conceptNameCode,en())&&(t.textExpr=n.value,void 0!==n.contentSequence))for(const e of n.contentSequence)e.valueType===Kr.scoord&&e.relationshipType===Zr&&Ht(e.conceptNameCode,tn())&&(t.labelPosition=new R(e.value.graphicData[0],e.value.graphicData[1]));if(n.valueType===Kr.text&&n.relationshipType===Zr&&Ht(n.conceptNameCode,nn())&&(t.colour=n.value),n.valueType===Kr.scoord&&n.relationshipType===Zr&&Ht(n.conceptNameCode,tn())&&n.value.graphicType===Vr){const e=[];for(let t=0;t<n.value.graphicData.length;t+=2)e.push(new R(n.value.graphicData[t],n.value.graphicData[t+1]));t.referencePoints=e}if(n.valueType===Kr.scoord3d&&n.relationshipType===Zr&&Ht(n.conceptNameCode,Kt())&&n.value.graphicType===Vr){const e=n.value.graphicData,i=[],r=Math.floor(e.length/3);for(let t=0;t<r;++t){const n=3*t;i.push(new F(e[n],e[n+1],e[n+2]))}t.planePoints=i}if(n.valueType===Kr.num&&n.relationshipType===jr){const e=on(n.conceptNameCode);if(void 0===e)continue;const i=n.value.measuredValue,r=sn(i.measurementUnitsCode);void 0===t.quantification&&(t.quantification={}),t.quantification[e]={value:i.numericValue,unit:r}}}return t}create(e){const t=[],n=eo(e);for(const e of n.contentSequence)e.valueType===Kr.scoord&&t.push(this.#Ao(e));const i=new Xi(t),r=function(t){return Ie(e,t)};i.setMetaValue("StudyInstanceUID",r("0020000D")),i.setMetaValue("Modality",r("00080060")),i.setMetaValue("PatientName",r("00100010")),i.setMetaValue("PatientID",r("00100020")),i.setMetaValue("PatientBirthDate",r("00100030")),i.setMetaValue("PatientSex",r("00100040"));const o=e["00081115"];if(void 0!==o){const e=o.value[0]["0020000E"];void 0!==e&&i.setMetaValue("ReferencedSeriesSequence",{value:[{SeriesInstanceUID:e.value[0]}]})}return i}#bo(e){const t=new $r(Kr.scoord);t.relationshipType=jr,e.mathShape instanceof $n?t.conceptNameCode=Zt("121055","DCM"):t.conceptNameCode=Zt("111030","DCM"),t.value=function(e){const t=new kr;if(e instanceof R)t.graphicData=[e.getX().toString(),e.getY().toString()],t.graphicType=Qr;else if(e instanceof $n)t.graphicData=[e.getBegin().getX().toString(),e.getBegin().getY().toString(),e.getEnd().getX().toString(),e.getEnd().getY().toString()],t.graphicType=Nr;else if(e instanceof Ui){t.graphicData=[];for(let n=0;n<3;++n)t.graphicData.push(e.getPoint(n).getX().toString()),t.graphicData.push(e.getPoint(n).getY().toString());t.graphicType=Nr}else if(e instanceof Ti){t.graphicData=[];for(let n=0;n<e.getLength();++n)t.graphicData.push(e.getPoint(n).getX().toString()),t.graphicData.push(e.getPoint(n).getY().toString());const n=e.getPoint(0);t.graphicData.push(n.getX().toString()),t.graphicData.push(n.getY().toString()),t.graphicType=Nr}else if(e instanceof Fi){const n=e.getCenter(),i=new R(n.getX()+e.getRadius(),n.getY());t.graphicData=[n.getX().toString(),n.getY().toString(),i.getX().toString(),i.getY().toString()],t.graphicType=Br}else if(e instanceof Ei){const n=e.getCenter(),i=e.getA(),r=e.getB();t.graphicData=[(n.getX()-i).toString(),n.getY().toString(),(n.getX()+i).toString(),n.getY().toString(),n.getX().toString(),(n.getY()-r).toString(),n.getX().toString(),(n.getY()+r).toString()],t.graphicType=Gr}else if(e instanceof Mi){const n=e.getBegin(),i=e.getEnd();t.graphicData=[n.getX().toString(),n.getY().toString(),n.getX().toString(),i.getY().toString(),i.getX().toString(),i.getY().toString(),i.getX().toString(),n.getY().toString(),n.getX().toString(),n.getY().toString()],t.graphicType=Nr}return t}(e.mathShape);const n=[],i=new $r(Kr.image);i.relationshipType=_r,i.conceptNameCode=Jt();const r=new xr;r.referencedSOPClassUID="",r.referencedSOPInstanceUID=e.referenceSopUID;const o=new qr;o.referencedSOPSequence=r,i.value=o,n.push(i);const a=new $r(Kr.uidref);a.relationshipType=Zr,a.conceptNameCode=$t(),a.value=e.id,n.push(a);const s=new $r(Kr.text);if(s.relationshipType=Zr,s.conceptNameCode=en(),s.value=e.textExpr,void 0!==e.labelPosition){const t=new $r(Kr.scoord);t.relationshipType=Zr,t.conceptNameCode=tn();const n=new kr;n.graphicType=Qr;const i=[e.labelPosition.getX().toString(),e.labelPosition.getY().toString()];n.graphicData=i,t.value=n,s.contentSequence=[t]}n.push(s);const l=new $r(Kr.text);if(l.relationshipType=Zr,l.conceptNameCode=nn(),l.value=e.colour,n.push(l),void 0!==e.referencePoints){const t=new $r(Kr.scoord);t.relationshipType=Zr,t.conceptNameCode=tn();const i=new kr;i.graphicType=Vr;const r=[];for(const t of e.referencePoints)r.push(t.getX().toString()),r.push(t.getY().toString());i.graphicData=r,t.value=i,n.push(t)}if(void 0!==e.planePoints){const t=new $r(Kr.scoord3d);t.relationshipType=Zr,t.conceptNameCode=Kt();const i=new Wr;i.graphicType=Vr;const r=[];for(const t of e.planePoints)r.push(t.getX().toString()),r.push(t.getY().toString()),r.push(t.getZ().toString());i.graphicData=r,t.value=i,n.push(t)}if(void 0!==e.quantification)for(const t in e.quantification){const i=no(t,e.quantification[t].value,e.quantification[t].unit);void 0!==i&&n.push(i)}return t.contentSequence=n,t}toDicom(e,t){let n=e.getMeta();n.TransferSyntaxUID="1.2.840.10008.1.2.1",n.SOPClassUID="1.2.840.10008.5.1.4.1.1.88.11",n.MediaStorageSOPClassUID="1.2.840.10008.5.1.4.1.1.88.11",n.CompletionFlag="PARTIAL",n.VerificationFlag="UNVERIFIED";const i=new Date;n.ContentDate=dt(ct(i)),n.ContentTime=ht(ut(i));const r=[];for(const t of e.getList())r.push(this.#bo(t));if(0!==r.length){const e=new $r(Kr.container);e.conceptNameCode=_t(),e.contentSequence=r,n={...n,...to(e)}}return void 0!==t&&function(e,t){const n=Object.keys(t);for(const i of n)void 0!==e[i]&&c.trace("Overwritting tag: "+i),e[i]=t[i]}(n,t),Bt(n)}}class ro{meta;image;annotationGroup;constructor(e){this.meta=e}}class oo{#xo={};#Ro=-1;#be=new He;getNextDataId(){return++this.#Ro,this.#Ro.toString()}getDataIds(){return Object.keys(this.#xo)}reset(){this.#xo={}}get(e){return this.#xo[e]}getDataIdsFromSopUids(e){const t=[];if(void 0===e||0===e.length)return t;const n=Object.keys(this.#xo);for(const i of n)void 0!==this.#xo[i].image&&this.#xo[i].image.containsImageUids(e)&&t.push(i);return t}setImage(e,t){this.#xo[e].image=t,this.#Fe({type:"dataimageset",value:[t],dataid:e}),t.addEventListener("imagecontentchange",this.#Fo(e)),t.addEventListener("imagegeometrychange",this.#Fo(e))}add(e,t){if(void 0!==this.#xo[e])throw new Error("Data id already used in storage: "+e);this.#xo[e]=t,this.#Fe({type:"dataadd",dataid:e}),void 0!==t.image&&(t.image.addEventListener("imagecontentchange",this.#Fo(e)),t.image.addEventListener("imagegeometrychange",this.#Fo(e))),void 0!==t.annotationGroup&&(t.annotationGroup.addEventListener("annotationadd",this.#Fo(e)),t.annotationGroup.addEventListener("annotationupdate",this.#Fo(e)),t.annotationGroup.addEventListener("annotationremove",this.#Fo(e)))}remove(e){if(void 0!==this.#xo[e]){const t=this.#xo[e].image;void 0!==t&&(t.removeEventListener("imagecontentchange",this.#Fo(e)),t.removeEventListener("imagegeometrychange",this.#Fo(e)));const n=this.#xo[e].annotationGroup;void 0!==n&&(n.removeEventListener("annotationadd",this.#Fo(e)),n.removeEventListener("annotationupdate",this.#Fo(e)),n.removeEventListener("annotationremove",this.#Fo(e))),delete this.#xo[e],this.#Fe({type:"dataremove",dataid:e})}}update(e,t){if(void 0===this.#xo[e])throw new Error("Cannot find data to update: "+e);const n=this.#xo[e];void 0!==n.image&&void 0!==t.image&&n.image.appendSlice(t.image);let i="";i=void 0!==t.meta["00020010"]?"00200013":"imageUid",n.meta=function(e,t,n,i){const r={};if(!n)throw new Error("Cannot merge object with an undefined id key: "+n);if(!Object.prototype.hasOwnProperty.call(e,n))throw new Error("Id key not found in first object while merging: "+n+", obj: "+e);if(!Object.prototype.hasOwnProperty.call(t,n))throw new Error("Id key not found in second object while merging: "+n+", obj: "+t);let o=!1;if(Object.prototype.hasOwnProperty.call(e[n],"merged")&&e[n].merged&&(o=!0),!Object.prototype.hasOwnProperty.call(e[n],i))throw new Error("Id value not found in first object while merging: "+n+", valueKey: "+i+", ojb: "+e);if(!Object.prototype.hasOwnProperty.call(t[n],i))throw new Error("Id value not found in second object while merging: "+n+", valueKey: "+i+", ojb: "+t);let a=e[n][i];const s=t[n][i][0];if(r[n]=e[n],o){for(let e=0;e<a.length;++e)if(a[e]===s)throw new Error("The first object already contains id2: "+s+", id1: "+a);r[n][i].push(s)}else{if(a=a[0],a===s)throw new Error("Cannot merge object with same ids: "+a+", id2: "+s);r[n][i].push(s),r[n].merged=!0}const l=Object.keys(e),c=Object.keys(t).filter((function(e){return l.indexOf(e)<0})),u=l.concat(c);for(let l=0;l<u.length;++l){const c=u[l];if(c!==n){let n,l,u,d,h;if(Object.prototype.hasOwnProperty.call(e,c)&&(n=e[c],Object.prototype.hasOwnProperty.call(n,i)&&(l=n[i])),Object.prototype.hasOwnProperty.call(t,c)&&(u=t[c],Object.prototype.hasOwnProperty.call(u,i)&&(d=u[i])),void 0!==n?h=n:void 0!==u&&(h=u),!H(l,d))if(o){if(Array.isArray(l)){h[i]={};for(let e=0;e<a.length;++e)h[i][a[e]]=l}else h[i]=l;void 0===h[i]&&(h[i]={}),h[i][s]=d}else{const e={};e[a]=l,e[s]=d,h[i]=e}r[c]=h}}return r}(n.meta,t.meta,i,"value"),this.#Fe({type:"dataupdate",dataid:e})}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe=e=>{this.#be.fireEvent(e)};#Fo(e){return t=>{t.dataid=e,this.#Fe(t)}}}class ao{#Eo;setOptions(e){this.#Eo=e}#Oo=null;#qo=[];#Uo=[];#Mo=[];#Qo=[];#Vo(e){let t;const n=e["00080060"];if(void 0!==n){const e=n.value[0];"SEG"===e?t=new Fn:"SR"===e&&(t=new io)}return void 0===t&&void 0!==e["7FE00010"]&&(t=new Pt),t}#No(e,t){const n=this.#qo[e].getDicomElements(),i=this.#Qo[e];if(void 0===i)return!1;try{const r=new ro(n);i instanceof io?r.annotationGroup=i.create(n):r.image=i.create(n,this.#Uo[e],this.#Eo.numberOfFiles),this.onloaditem({data:r,source:t,warn:i.getWarning()})}catch(e){return this.onerror({error:e,source:t}),this.onloadend({source:t}),!1}return!0}#Bo(e,t){this.#No(e,t)&&this.onload({source:t}),this.onloadend({source:t})}#Go(e,t){this.onprogress({lengthComputable:!0,loaded:100,total:100,index:e,source:t}),this.#Bo(e,t)}#ko(e,t,n){const i=this.#qo[e],r={bitsAllocated:i.getDicomElements()["00280100"].value[0],isSigned:1===i.getDicomElements()["00280103"].value[0]},o=i.getDicomElements()["00280011"],a=i.getDicomElements()["00280010"];void 0!==o&&void 0!==a&&(r.sliceSize=o.value[0]*a.value[0]);const s=i.getDicomElements()["00280002"];void 0!==s&&(r.samplesPerPixel=s.value[0]);const l=i.getDicomElements()["00280006"];void 0!==l&&(r.planarConfiguration=l.value[0]);const c=t.length;null===this.#Oo&&(this.#Oo=new Ir(n,c),this.#Oo.ondecodeditem=e=>{this.#Ho(e),e.itemNumber+1===e.numberOfItems&&(this.onload(e),this.onloadend(e))},this.#Oo.onerror=this.onerror,this.#Oo.onabort=this.onabort);for(let n=0;n<c;++n)this.#Oo.decode(t[n],r,{itemNumber:n,numberOfItems:c,index:e})}#Ho(e){this.onprogress({lengthComputable:!0,loaded:e.itemNumber+1,total:e.numberOfItems,index:e.index,source:origin});const t=e.index,n=e.data[0];if(1!==e.numberOfItems){if(void 0===this.#Mo[t]){this.#Mo[t]=n.length;const i=e.numberOfItems*this.#Mo[t];try{this.#Uo[t]=new n.constructor(i)}catch(e){if(e instanceof RangeError){const e=Math.floor(Math.log(i)/Math.log(2));c.error("Cannot allocate "+n.constructor.name+" of size: "+i+" (>2^"+e+") for decompressed data.")}return this.#Oo.abort(),this.onerror({error:e,source:origin}),void this.onloadend({source:origin})}}n.length!==this.#Mo[t]&&c.warn("Unsupported varying decompressed data size: "+n.length+" != "+this.#Mo[t]),this.#Uo[t].set(n,this.#Mo[t]*e.itemNumber)}else this.#Uo[t]=n;0===e.itemNumber&&this.#No(t,origin)}#zo(e,t){this.#Bo(e,t)}#Wo(e,t){const n=this.#qo[e],i=n.getDicomElements()["7FE00010"].value;n.getDicomElements()["7FE00010"].value=[],this.#Uo[e]=i[0];const r=function(e){let t;return qe(e)?t="jpeg2000":Fe(e)?t="jpeg-baseline":Ee(e)?t="jpeg-lossless":Ue(e)&&(t="rle"),t}(n.getDicomElements()["00020010"].value[0]);void 0!==r?this.#ko(e,i,r):this.#Go(e,t)}convert(e,t,n){this.onloadstart({source:t,index:n});const i=new ke;let r;void 0!==this.#Eo.defaultCharacterSet&&i.setDefaultCharacterSet(this.#Eo.defaultCharacterSet);try{i.parse(e),r=this.#Vo(i.getDicomElements()),void 0!==r&&r.checkElements(i.getDicomElements())}catch(e){return this.onerror({error:e,source:t}),void this.onloadend({source:t})}this.#qo[n]=i,this.#Qo[n]=r,r instanceof io?this.#zo(n,t):this.#Wo(n,t)}abort(){this.#Oo&&this.#Oo.abort()}onloadstart(e){}onloaditem(e){}onprogress(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}}class so{#io=null;#oo=null;#ao=0;#so=0;#E;getDefaultCharacterSet(){return this.#E}setDefaultCharacterSet(e){this.#E=e}#co(e){this.#io=e,this.#ao=0,this.#so=0,this.#do()}#So(e){this.#oo=e}#do(){this.#oo=null}#go=e=>{this.#ao++,this.#ao===this.#io.length&&this.onload({source:this.#io})};#po=e=>{this.#so++,this.#so===this.#io.length&&this.onloadend({source:this.#io})};load(e){if(void 0===e||0===e.length)return;this.#co(e),this.onloadstart({source:e});const t=new dr(this.onprogress);t.setNToLoad(e.length),t.setNumberOfDimensions(1);const n=[];for(let e=0;e<go.length;++e)n.push(new go[e]);let i=e[0],r=null,o=!1;for(let a=0;a<n.length;++a)if(r=n[a],r.canLoadMemory(i)){o=!0,r.setOptions({numberOfFiles:e.length,defaultCharacterSet:this.getDefaultCharacterSet()}),r.onprogress=t.getUndefinedMonoProgressHandler(0),r.onloaditem=this.onloaditem,r.onload=this.#go,r.onloadend=this.#po,r.onerror=this.onerror,r.onabort=this.onabort,this.#So(r);break}if(!o)throw new Error("No loader found for data: "+i.filename);for(let t=0;t<e.length;++t){if(i=e[t],!r.canLoadMemory(i))throw new Error("Input data of different type: "+i.filename);r.load(i.data,i.filename,t)}}abort(){this.#oo&&this.#oo.isLoading()&&this.#oo.abort()}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}}function lo(e){return parseInt(e,36).toString()}function co(e){const t=e.data.length,n=new Uint8Array(t/4*3);let i=0;for(let r=0;r<t;r+=4)n[i]=e.data[r],n[i+1]=e.data[r+1],n[i+2]=e.data[r+2],i+=3;return n}function uo(e,t,n,i,r,o){const a=new Ze([e,t,1]),s=new nt([1,1,1]),l=new F(0,0,n),c=new it([l],a,s),u=new Un(c,i,[o]);u.setPhotometricInterpretation("RGB");const d={BitsStored:8};return void 0!==r&&(d.numberOfFiles=r),u.setMeta(d),u}var ho=o(654),So=o.n(ho);const go=[class{#Eo={};#Yo=!1;setOptions(e){this.#Eo=e}isLoading(){return this.#Yo}#Xo=new ao;load(e,t,n){this.#Yo||(this.#Xo.setOptions(this.#Eo),this.#Xo.onloadstart=this.onloadstart,this.#Xo.onprogress=this.onprogress,this.#Xo.onloaditem=this.onloaditem,this.#Xo.onload=this.onload,this.#Xo.onloadend=e=>{this.#Yo=!1,this.onloadend(e)},this.#Xo.onerror=e=>{e.source=t,this.onerror(e)},this.#Xo.onabort=this.onabort),this.#Yo=!0,this.#Xo.convert(e,t,n)}abort(){this.#Yo=!1,this.#Xo.abort()}canLoadFile(e){const t=V(e.name);return null===t||"dcm"===t}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"dicom"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n){const e="application/dicom";return U(n.value,e)&&"+"!==n.value[e.length]}}}const n=sr(e),i=V(n.pathname),r=null===i,o="dcm"===i,a=n.searchParams.get("contentType");return null!=a?"application/dicom"===a:r||o}canLoadMemory(e){const t=e["Content-Type"];if(void 0!==t&&t.startsWith("application/dicom"))return!0;if(void 0!==e.filename){const t=new File(["from memory"],e.filename);return this.canLoadFile(t)}return!1}loadFileAs(){return po.ArrayBuffer}loadUrlAs(){return 1}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}},class{#Yo=!1;setOptions(e){}isLoading(){return this.#Yo}load(e,t,n){this.#Yo=!0,this.onloadstart({source:t});try{this.onprogress({lengthComputable:!0,loaded:100,total:100,index:n,source:t});const i={data:e,source:t};this.onloaditem(i),this.onload(i)}catch(e){this.onerror({error:e,source:t})}finally{this.#Yo=!1,this.onloadend({source:t})}}abort(){this.#Yo=!1,this.onabort({}),this.onloadend({})}canLoadFile(e){return"json"===V(e.name)}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"json"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n)return U(n.value,"application/json")||U(n.value,"application/dicom+json")}}return"json"===V(sr(e).pathname)}canLoadMemory(e){const t=e["Content-Type"];if(void 0!==t&&t.startsWith("application/json"))return!0;if(void 0!==e.filename){const t=new File(["from memory"],e.filename);return this.canLoadFile(t)}return!1}loadFileAs(){return po.Text}loadUrlAs(){return 0}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}},class{#Yo=!1;setOptions(e){}isLoading(){return this.#Yo}load(e,t,n){this.onloadstart({source:t}),this.#Yo=!0;const i=new so;i.onprogress=e=>{e.loaded=50+e.loaded/2,e.index=n,this.onprogress(e)},i.onloaditem=this.onloaditem,i.onload=this.onload,i.onloadend=e=>{this.#Yo=!1,this.onloadend(e)},i.onerror=this.onerror,i.onabort=this.onabort,i.load(function(e){const t=new Uint8Array(e),n=[];if(0===t.length)return n;const i=Y(new Uint8Array([13,10,13,10]));let r=W(t,i,0);if(void 0===r)throw new Error("Can't find the end of the first multipart header");const o=z(t.slice(0,r)).split("\r\n");let a;for(let e=0;e<o.length;++e)if("-"===o[e][0]&&"-"===o[e][1]){a=o[e];break}if(void 0===a)throw new Error("Can't find the boundary between multi-parts");const s=Y(N(a)),l=a.length;let c=W(t,s,0);for(;void 0!==r;){const e={},o=z(t.slice(c+l,r)).split("\r\n");for(let t=0;t<o.length;++t){const n=o[t],i=n.indexOf(":");if(-1!==i){const t=n.substring(0,i).trim(),r=n.substring(i+1).trim();e[t]=r}}if(c=W(t,s,r),void 0===c)break;const a=r+4,u=c-2;e.data=a<u?t.slice(a,u).buffer:new Uint8Array,n.push(e),r=W(t,i,c+l)}return n}(e))}abort(){this.#Yo=!1,this.onabort({}),this.onloadend({})}canLoadFile(e){return!1}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"multipart"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n)return U(n.value,"multipart/related")}}return!1}canLoadMemory(e){return!1}loadFileAs(){return po.ArrayBuffer}loadUrlAs(){return 1}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}},class{#jo=!1;setOptions(e){}isLoading(){return!0}#Zo(e,t){let n=t;n&&"jpg"!==n||(n="jpeg");const i=new Blob([e],{type:"image/"+n});return window.URL.createObjectURL(i)}load(e,t,n){this.#jo=!1;const i=new Image;if(i.onload=()=>{try{if(!this.#jo){this.onprogress({lengthComputable:!0,loaded:100,total:100,index:n,source:t});const e=function(e,t,n){const i=e.width,r=e.height,o=document.createElement("canvas");o.width=i,o.height=r;const a=o.getContext("2d");a.drawImage(e,0,0);const s=a.getImageData(0,0,i,r),l={};let c;"string"==typeof t?(l.origin={value:t},c=lo(t)):(l.fileName={value:t.name},c=lo(t.name),l.fileType={value:t.type},l.fileLastModifiedDate={value:t.lastModified}),l.imageWidth={value:i},l.imageHeight={value:r};const u=n||0;l.imageUid={value:u},l.seriesUid={value:c};const d=uo(i,r,u,co(s),1,u.toString()),h=d.getMeta();return h.SeriesInstanceUID=c,d.setMeta(h),{data:{image:d,meta:l},source:t}}(i,t,n);this.onloaditem(e),this.onload(e)}}catch(e){this.onerror({error:e,source:t})}finally{this.onloadend({source:t})}},"string"==typeof e)i.src=e;else if("string"==typeof t){const n=t.split(".").pop().toLowerCase();i.src=this.#Zo(e,n)}}abort(){this.#jo=!0,this.onabort({}),this.onloadend({})}canLoadFile(e){return void 0!==e.type&&null!==e.type.match("image.*")}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"rawimage"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n)return U(n.value,"image/")}}const n=sr(e),i=V(n.pathname),r="jpeg"===i||"jpg"===i||"png"===i||"gif"===i,o=n.searchParams.get("contentType");return null!=o?"image/jpeg"===o||"image/png"===o||"image/gif"===o:r}canLoadMemory(e){if(void 0!==e.filename){const t=new File(["from memory"],e.filename);return this.canLoadFile(t)}return!1}loadFileAs(){return po.DataURL}loadUrlAs(){return 1}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}},class{setOptions(e){}isLoading(){return!0}#Zo(e,t){const n=new Uint8Array(e);let i="";for(let e=0;e<n.byteLength;++e)i+=String.fromCharCode(n[e]);return"data:video/"+t+";base64,"+window.btoa(i)}load(e,t,n){const i=document.createElement("video");if("string"==typeof t){const n=t.split(".").pop().toLowerCase();i.src=this.#Zo(e,n)}else i.src=e;i.onloadedmetadata=e=>{try{!function(e,t,n,i,r,o,a){const s=e.videoWidth,l=e.videoHeight,c=Math.ceil(30*e.duration),u={};let d;"string"==typeof o?(u.origin={value:o},d=lo(o)):(u.fileName={value:o.name},d=lo(o.name),u.fileType={value:o.type},u.fileLastModifiedDate={value:o.lastModified}),u.imageWidth={value:s},u.imageHeight={value:l},u.numberOfFrames={value:c},u.imageUid={value:0},u.seriesUid={value:d};const h=document.createElement("canvas");h.width=s,h.height=l;const S=h.getContext("2d");e.addEventListener("seeked",(function h(f){(function(){i({lengthComputable:!0,loaded:g,total:c,index:a,source:o}),S.drawImage(e,0,0);const n=co(S.getImageData(0,0,s,l));if(0===g){p=uo(s,l,1,n,c,a.toString());const e=p.getMeta();e.SeriesInstanceUID=d,p.setMeta(e),t({data:{image:p,meta:u},source:o})}else p.appendFrameBuffer(n,g);++g})(),m+=1/30,m<=f.target.duration?this.currentTime=m:(n({source:o}),r({source:o}),e.removeEventListener("seeked",h))}),!1);let g=0,p=null,m=0;e.currentTime=m}(e.target,this.onloaditem,this.onload,this.onprogress,this.onloadend,t,n)}catch(e){this.onerror({error:e,source:t}),this.onloadend({source:t})}}}abort(){this.onabort({}),this.onloadend({})}canLoadFile(e){return void 0!==e.type&&null!==e.type.match("video.*")}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"rawvideo"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n)return U(n.value,"video/")}}const n=V(sr(e).pathname);return"mp4"===n||"ogg"===n||"webm"===n}canLoadMemory(e){if(void 0!==e.filename){const t=new File(["from memory"],e.filename);return this.canLoadFile(t)}return!1}loadFileAs(){return po.DataURL}loadUrlAs(){return 1}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}},class{#Yo=!1;setOptions(e){}isLoading(){return this.#Yo}#_o="";#Ko=[];#Jo=null;#$o(e,t,n){this.#Ko.push({filename:this.#_o,data:e});const i=100*this.#Ko.length/this.#Jo.length;if(this.onprogress({lengthComputable:!0,loaded:i/2,total:100,index:n,item:{loaded:i,total:100,source:t}}),this.#Ko.length<this.#Jo.length){const e=this.#Ko.length;this.#_o=this.#Jo[e].name,this.#Jo[e].async("arrayBuffer").then((e=>{this.#$o(e,t,n)}))}else{const e=new so;e.onprogress=e=>{e.loaded=50+e.loaded/2,e.index=n,this.onprogress(e)},e.onloaditem=this.onloaditem,e.onload=this.onload,e.onloadend=e=>{this.#Yo=!1,this.onloadend(e)},e.onerror=this.onerror,e.onabort=this.onabort,e.load(this.#Ko)}}load(e,t,n){this.onloadstart({source:t}),this.#Yo=!0,So().loadAsync(e).then((e=>{this.#Ko=[],this.#Jo=e.file(/.*\.dcm/);const i=this.#Ko.length;this.#_o=this.#Jo[i].name,this.#Jo[i].async("arrayBuffer").then((e=>{this.#$o(e,t,n)}))}))}abort(){this.#Yo=!1,this.onabort({}),this.onloadend({})}canLoadFile(e){return"zip"===V(e.name)}canLoadUrl(e,t){if(void 0!==t){if(void 0!==t.forceLoader&&"zip"===t.forceLoader)return!0;if(void 0!==t.requestHeaders){const e=function(e){return"Accept"===e.name},n=t.requestHeaders.find(e);if(void 0!==n)return U(n.value,"application/zip")}}return"zip"===V(sr(e).pathname)}canLoadMemory(e){const t=e["Content-Type"];if(void 0!==t&&t.startsWith("application/zip"))return!0;if(void 0!==e.filename){const t=new File(["from memory"],e.filename);return this.canLoadFile(t)}return!1}loadFileAs(){return po.ArrayBuffer}loadUrlAs(){return 1}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}}],po={Text:0,ArrayBuffer:1,DataURL:2};class mo{#io=null;#ea=[];#oo=null;#ao=0;#so=0;#E;getDefaultCharacterSet(){return this.#E}setDefaultCharacterSet(e){this.#E=e}#co(e){this.#io=e,this.#ao=0,this.#so=0,this.#ta(),this.#do()}#na(e){this.#ea.push(e)}#ta(){this.#ea=[]}#So(e){this.#oo=e}#do(){this.#oo=null}#go=e=>{this.#ao++,this.#ao===this.#io.length&&this.onload({source:this.#io})};#po=e=>{this.#so++,this.#so===this.#io.length&&this.onloadend({source:this.#io})};#mo(e,t){return n=>{n.source=t,e(n)}}#yo(e,t,n){return i=>{e.load(i.target.result,t,n)}}load(e){if(void 0===e||0===e.length)return;this.#co(e),this.onloadstart({source:e});const t=new dr(this.onprogress);t.setNToLoad(e.length);const n=[];for(let e=0;e<go.length;++e)n.push(new go[e]);let i=e[0],r=null,o=!1;for(let a=0;a<n.length;++a)if(r=n[a],r.canLoadFile(i)){o=!0,r.setOptions({numberOfFiles:e.length,defaultCharacterSet:this.getDefaultCharacterSet()}),r.onprogress=t.getUndefinedMonoProgressHandler(1),r.onloaditem=this.onloaditem,r.onload=this.#go,r.onloadend=this.#po,r.onerror=this.onerror,r.onabort=this.onabort,this.#So(r);break}if(!o)throw new Error("No loader found for file: "+i.name);for(let n=0;n<e.length;++n){if(i=e[n],!r.canLoadFile(i))throw new Error("Input file of different type: "+i);const o=new FileReader;this.#na(o),o.onprogress=this.#mo(t.getMonoProgressHandler(n,0),i),o.onload=this.#yo(r,i,n);const a=this.#mo(this.onerror,i);o.onerror=e=>{this.#po(),a(e)};const s=this.#mo(this.onabort,i);o.onabort=e=>{this.#po(),s(e)},r.loadFileAs()===po.Text?o.readAsText(i):r.loadFileAs()===po.DataURL?o.readAsDataURL(i):r.loadFileAs()===po.ArrayBuffer&&o.readAsArrayBuffer(i)}}abort(){for(let e=0;e<this.#ea.length;++e)1===this.#ea[e].readyState&&this.#ea[e].abort();this.#oo&&this.#oo.isLoading()&&this.#oo.abort()}onloadstart(e){}onprogress(e){}onloaditem(e){}onload(e){}onloadend(e){}onerror(e){}onabort(e){}}class fo{#E;#ia={};constructor(e){this.#E=e}loadFiles(e,t){"json"===e[0].name.split(".").pop().toLowerCase()?this.#ra(e[0],t):this.#oa(e,t)}loadURLs(e,t,n){"json"===e[0].split(".").pop().toLowerCase()?this.#aa(e[0],t,n):this.#sa(e,t,n)}loadImageObject(e,t){const n=new so;this.#la(e,n,"image",t)}getLoadingDataIds(){return Object.keys(this.#ia)}abort(e){void 0!==this.#ia[e]&&(this.#ia[e].loader.abort(),delete this.#ia[e])}#oa(e,t){const n=new mo;n.setDefaultCharacterSet(this.#E),this.#la(e,n,"image",t)}#sa(e,t,n){const i=new hr;i.setDefaultCharacterSet(this.#E),this.#la(e,i,"image",t,n)}#ra(e,t){const n=new mo;this.#la([e],n,"state",t)}#aa(e,t,n){const i=new hr;this.#la([e],i,"state",t,n)}#la(e,t,n,i,r){const o={loadtype:n,dataid:i};t.onloadstart=e=>{this.#ia[i]={loader:t,isFirstItem:!0},this.#mo(this.onloadstart,o)(e)},t.onprogress=this.#mo(this.onprogress,o),t.onloaditem=e=>{const t={loadtype:n,dataid:i};void 0!==this.#ia[i]&&(t.isfirstitem=this.#ia[i].isFirstItem),this.#mo(this.onloaditem,t)(e),void 0!==this.#ia[i]&&this.#ia[i].isFirstItem&&(this.#ia[i].isFirstItem=!1)},t.onload=this.#mo(this.onload,o),t.onloadend=e=>{delete this.#ia[i],this.#mo(this.onloadend,o)(e)},t.onerror=this.#mo(this.onerror,o),t.onabort=this.#mo(this.onabort,o),void 0!==t.ontimeout&&(t.ontimeout=this.#mo(this.ontimeout,o));try{t.load(e,r)}catch(e){return this.onerror({error:e,dataid:i}),void this.onloadend({dataid:i})}}#mo(e,t){return function(n){const i=Object.keys(t);for(let e=0;e<i.length;++e){const r=i[e];n[r]=t[r]}e(n)}}onloadstart(e){}onprogress(e){}onload(e){}onloaditem(e){}onloadend(e){}onerror(e){}ontimeout(e){}onabort(e){}}function Do(e){return function(t){return Number(t).toPrecision(e)}}function yo(e){let t="";for(let n=0;n<e;++n)0!==n&&(t+=", "),t+="{v"+n+"}";return t}function Co(e,t){let n=e;for(let e=0;e<t.length;++e)n=n.replace("{v"+e+"}",t[e]);return n}class vo{#Rt;#Ct;#ca;#ua=[];#da;#ha=[];#Sa;#be=new He;constructor(e,t,n){this.#Rt=e,this.#Ct=t,this.#ca=n;const i=Object.keys(this.#ca);for(let e=0;e<i.length;++e){const t=this.#ca[i[e]];for(let e=0;e<t.length;++e){const n=t[e].event;void 0!==n&&(this.#ua.includes(n)||this.#ua.push(n))}}this.addAppListeners()}reset(){this.#ha=[],this.#Sa=void 0}addItemMeta(e){let t;if(void 0!==e["00020010"])t=void 0!==e["00080018"]?e["00080018"].value[0]:e.length,this.#ha[t]=function(e,t){const n=[];let i;const r=e["00080060"];if(void 0===r)return n;i=r.value[0];const o=t[i]||t["*"];if(!o)return n;for(let t=0;t<o.length;++t){const i=JSON.parse(JSON.stringify(o[t])),r=i.tags;if(void 0!==r&&0!==r.length){const t=[];for(let n=0;n<r.length;++n)void 0!==e[r[n]]?t.push(e[r[n]].value):t.push("");void 0!==i.format&&null!==i.format||(i.format=yo(t.length)),i.value=Co(i.format,t).trim()}n.push(i)}const a=e["00200020"];if(void 0!==a&&2===a.value.length){const e=a.value[0],t=a.value[1];n.push({pos:"cr",value:e,format:"{v0}"}),n.push({pos:"cl",value:be(e),format:"{v0}"}),n.push({pos:"bc",value:t,format:"{v0}"}),n.push({pos:"tc",value:be(t),format:"{v0}"})}return n}(e,this.#ca);else{const n=Object.keys(e);for(let i=0;i<n.length;++i){const r=e[n[i]];if("imageUid"===n[i]){t=r.value;break}}this.#ha[t]=function(e,t){const n=[],i=t.DOM;if(!i)return n;const r=Object.keys(e);for(let t=0;t<i.length;++t){const o=JSON.parse(JSON.stringify(i[t])),a=o.tags;if(void 0!==a&&0!==a.length){const t=[];for(let n=0;n<a.length;++n)for(let i=0;i<r.length;++i)a[n]===r[i]&&t.push(e[r[i]].value);void 0!==o.format&&null!==o.format||(o.format=yo(t.length)),o.value=Co(o.format,t).trim()}n.push(o)}return n}(e,this.#ca)}this.#Sa=t}#ga=e=>{e.dataid===this.#Ct&&void 0!==e.data&&void 0!==e.data.imageUid&&this.#Sa!==e.data.imageUid&&(this.#Sa=e.data.imageUid,this.#pa(e))};#pa=e=>{if(e.dataid!==this.#Ct)return;const t=this.#ha[this.#Sa];if(void 0!==t){for(let n=0;n<t.length;++n){let i;if(void 0!==t[n].tags)"positionchange"===e.type&&(i=t[n].value);else if(void 0!==t[n].event&&t[n].event===e.type){const r=t[n].format;let o=e.value;if(void 0!==t[n].precision){let e=null;e="round"===t[n].precision?Math.round:Do(t[n].precision),o=o.map(e)}i=Co(r,o)}void 0!==i&&(t[n].value=i)}this.#Fe({type:"valuechange",data:t})}else console.warn("No slice overlay data for: "+this.#Sa)};isListening(){return this.#da}addAppListeners(){this.#Rt.addEventListener("positionchange",this.#ga);for(let e=0;e<this.#ua.length;++e)this.#Rt.addEventListener(this.#ua[e],this.#pa);this.#da=!0}removeAppListeners(){this.#Rt.removeEventListener("positionchange",this.#ga);for(let e=0;e<this.#ua.length;++e)this.#Rt.removeEventListener(this.#ua[e],this.#pa);this.#da=!1}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}#Fe(e){this.#be.fireEvent(e)}}class Io{divId;orientation;colourMap;opacity;wlPresetName;windowCenter;windowWidth;constructor(e){this.divId=e}}class To{options;constructor(e){this.options=e}}class Lo{dataViewConfigs;tools;binders;viewOnFirstLoadItem;defaultCharacterSet;overlayConfig;rootDocument;constructor(e){this.dataViewConfigs=e}}class Po{#Eo=null;#ma=null;#fa=null;#Da=null;#ya=null;#Ca=null;#Yn=new ui;#va={};#be=new He;getData(e){return this.#ma.get(e)}getImage(e){let t;return void 0!==this.getData(e)&&(t=this.getData(e).image),t}setImage(e,t){this.#ma.setImage(e,t)}addData(e){const t=this.#ma.getNextDataId();return this.#ma.add(t,e),t}getMetaData(e){let t;return void 0!==this.#ma.get(e)&&(t=this.#ma.get(e).meta),t}getDataIds(){return this.#ma.getDataIds()}getDataIdsFromSopUids(e){return this.#ma.getDataIdsFromSopUids(e)}canScroll(){return this.#ya.getActiveLayerGroup().getActiveViewLayer().getViewController().canScroll()}canWindowLevel(){return this.#ya.getActiveLayerGroup().getActiveViewLayer().getViewController().canWindowLevel()}getAddedScale(){return this.#ya.getActiveLayerGroup().getAddedScale()}getBaseScale(){return this.#ya.getActiveLayerGroup().getBaseScale()}getOffset(){return this.#ya.getActiveLayerGroup().getOffset()}getToolboxController(){return this.#fa}getActiveLayerGroup(){return this.#ya.getActiveLayerGroup()}setActiveLayerGroup(e){this.#ya.setActiveLayerGroup(e)}getViewLayersByDataId(e){return this.#ya.getViewLayersByDataId(e)}getViewLayers(e){return this.#ya.getViewLayers(e)}getDrawLayersByDataId(e){return this.#ya.getDrawLayersByDataId(e)}getDrawLayers(e){return this.#ya.getDrawLayers(e)}getLayerGroupByDivId(e){return this.#ya.getLayerGroupByDivId(e)}getNumberOfLayerGroups(){return this.#ya.getNumberOfLayerGroups()}getStyle(){return this.#Yn}addToUndoStack=e=>{null!==this.#Ca&&this.#Ca.add(e)};removeFromUndoStack=e=>{let t=!1;return null!==this.#Ca&&(t=this.#Ca.remove(e)),t};init(e){if(this.#Eo=e,void 0===this.#Eo.viewOnFirstLoadItem&&(this.#Eo.viewOnFirstLoadItem=!0),void 0===this.#Eo.dataViewConfigs&&(this.#Eo.dataViewConfigs={}),void 0===this.#Eo.rootDocument&&(this.#Eo.rootDocument=document),this.#Ca=new cr,this.#Ca.addEventListener("undoadd",this.#Fe),this.#Ca.addEventListener("undo",this.#Fe),this.#Ca.addEventListener("redo",this.#Fe),void 0!==this.#Eo.tools){const e={},t=Object.keys(this.#Eo.tools);for(let n=0;n<t.length;++n){const i=t[n];let r=zi[i];if(void 0===r&&(r=ki[i]),void 0!==r){if(e[i]=new r(this),void 0!==e[i].addEventListener){const t=e[i].getEventNames();for(let n=0;n<t.length;++n)e[i].addEventListener(t[n],this.#Fe)}const t=this.#Eo.tools[i];if(void 0!==t.options&&0!==t.options.length){let n,r="raw";if(void 0!==e[i].getOptionsType&&(r=e[i].getOptionsType()),"instance"===r||"factory"===r){n={};for(let e=0;e<t.options.length;++e){const o=t.options[e];let a=o;"factory"===r&&(a+="Factory");const s=i.charAt(0).toLowerCase()+i.slice(1);let l,u=Hi[s];void 0!==u&&(l=u[a]),void 0===l&&(u=Wi[s],void 0!==u&&(l=u[a])),void 0!==l?n[o]=l:c.warn("Could not find option class for: "+o)}}else n=t.options;e[i].setOptions(n)}}else c.warn("Could not initialise unknown tool: "+i)}this.#fa=new ur(e)}this.#Da=new fo(this.#Eo.defaultCharacterSet),this.#Da.onloadstart=this.#Ia,this.#Da.onprogress=this.#Ta,this.#Da.onloaditem=this.#La,this.#Da.onload=this.#Pa,this.#Da.onloadend=this.#wa,this.#Da.onerror=this.#Oa,this.#Da.ontimeout=this.#Aa,this.#Da.onabort=this.#ba,this.#ma=new oo,this.#ma.addEventListener("dataadd",this.#Fe),this.#ma.addEventListener("dataremove",this.#Fe),this.#ma.addEventListener("dataimageset",this.#Fe),this.#ma.addEventListener("dataupdate",this.#Fe),this.#ma.addEventListener("imagecontentchange",this.#Fe),this.#ma.addEventListener("imagegeometrychange",this.#Fe),this.#ma.addEventListener("annotationadd",this.#Fe),this.#ma.addEventListener("annotationupdate",this.#Fe),this.#ma.addEventListener("annotationremove",this.#Fe),this.#ma.addEventListener("annotationgroupeditablechange",this.#Fe),this.#ya=new tr,void 0!==this.#Eo.binders&&this.#ya.setBinders(this.#Eo.binders)}reset(){this.#ya.empty(),this.#va={},this.#Ca&&(this.#Ca=new cr,this.#Ca.addEventListener("undoadd",this.#Fe),this.#Ca.addEventListener("undo",this.#Fe),this.#Ca.addEventListener("redo",this.#Fe))}resetLayout(){this.#ya.reset(),this.#ya.draw()}addEventListener(e,t){this.#be.add(e,t)}removeEventListener(e,t){this.#be.remove(e,t)}loadFiles=e=>{const t=this.#ma.getNextDataId();0!==e.length?this.#Da.loadFiles(e,t):c.warn("Ignoring empty input file list.")};loadURLs=(e,t)=>{const n=this.#ma.getNextDataId();0!==e.length?this.#Da.loadURLs(e,n,t):c.warn("Ignoring empty input url list.")};loadFromUri=(e,t)=>{const n=function(e){const t=lr(e);return 0===Object.keys(t).length?null:t.query}(e),i=()=>{this.removeEventListener("loadend",i),this.loadURLs([n.state])};n&&void 0!==n.input&&(void 0!==n.state&&this.addEventListener("loadend",i),function(e,t,n){e.type&&"manifest"===e.type?function(e,t){let n="";"/"===e.input[0]&&(n=window.location.protocol+"//"+window.location.host),n+=e.input;const i=new XMLHttpRequest;i.open("GET",decodeURIComponent(n),!0),i.responseType="document",i.onload=function(n){t(function(e,t){const n=[],i=e.getElementsByTagName("wado_query")[0].getAttribute("wadoURL")+"?requestType=WADO&contentType=application/dicom&",r=e.getElementsByTagName("Patient");r.length>1&&c.warn("More than one patient, loading first one.");const o=r[0].getElementsByTagName("Study");o.length>1&&c.warn("More than one study, loading first one.");const a=o[0].getAttribute("StudyInstanceUID"),s=o[0].getElementsByTagName("Series");s.length>1&&c.warn("More than one series, loading first one.");const l=s[0].getAttribute("SeriesInstanceUID"),u=s[0].getElementsByTagName("Instance");let d=u.length;t<d&&(d=t);for(let e=0;e<d;++e){const t=i+"&studyUID="+a+"&seriesUID="+l+"&objectUID="+u[e].getAttribute("SOPInstanceUID");n.push(t)}return n}(n.target.responseXML,e.nslices))},i.onerror=function(e){c.warn("RequestError while receiving manifest: "+e.target.status)},i.send(null)}(e,t):t(function(e,t){const n=[];let i="key";t&&(i=t);const r=decodeURIComponent(e),o=lr(r);if(0===Object.keys(o).length)n.push(r);else{const e=Object.keys(o.query);let t=null;for(let n=0;n<e.length;++n)if(o.query[e[n]]instanceof Array){t=e[n];break}if(t){const r=o.query[t];let a=o.base;""!==a&&"file"!==t&&(a+="?");let s,l=!1;for(let n=0;n<e.length;++n)e[n]!==t&&(l&&(a+="&"),a+=e[n]+"="+o.query[e[n]],l=!0);for(let e=0;e<r.length;++e)s=a,l&&(s+="&"),"key"===i&&(s+=t+"="),s+=r[e],n.push(s)}else n.push(r)}return n}(e.input,e.dwvReplaceMode),n)}(n,this.loadURLs,t))};loadImageObject=e=>{const t=this.#ma.getNextDataId();this.#Da.loadImageObject(e,t)};abortAllLoads(){const e=this.#Da.getLoadingDataIds();for(const t of e)this.abortLoad(t)}abortLoad(e){this.#Da.abort(e),this.#ma.remove(e),this.#ya.removeLayersByDataId(e)}fitToContainer(){this.#ya.fitToContainer()}initWLDisplay(){this.#ya.getActiveLayerGroup().getActiveViewLayer().getViewController().initialise()}setImageSmoothing(e){this.#ya.setImageSmoothing(e),this.#ya.draw()}getViewConfigs(e,t){if(void 0===t&&(t=!1),null===this.#Eo.dataViewConfigs||void 0===this.#Eo.dataViewConfigs)throw new Error("No available data view configuration");let n=[];return void 0!==this.#Eo.dataViewConfigs[e]?n=this.#Eo.dataViewConfigs[e]:t||void 0===this.#Eo.dataViewConfigs["*"]||(n=this.#Eo.dataViewConfigs["*"]),n}getViewConfig(e,t,n){return this.getViewConfigs(e,n).find((function(e){return e.divId===t}))}getDataViewConfigs(){return this.#Eo.dataViewConfigs}setDataViewConfigs(e){this.#ya.empty(),this.#Eo.dataViewConfigs=e,this.#xa(e)}addDataViewConfig(e,t){const n=this.#Eo.dataViewConfigs;if(void 0===n[e]&&(n[e]=[]),-1!==n[e].findIndex((function(e){return e.divId===t.divId})))throw new Error("Duplicate view config for data "+e+" and div "+t.divId);this.#Eo.dataViewConfigs[e].push(t),void 0===this.#ya.getLayerGroupByDivId(t.divId)&&this.#Ra(t),void 0!==this.#ma.get(e)&&this.render(e,[t])}removeDataViewConfig(e,t){const n=this.#Eo.dataViewConfigs;if(void 0===n[e])return;const i=n[e].findIndex((function(e){return e.divId===t}));if(-1!==i&&(n[e].splice(i,1),0===n[e].length&&delete n[e],void 0!==this.#ma.get(e))){const n=this.#ya.getLayerGroupByDivId(t);if(void 0!==n){const t=n.getViewLayersByDataId(e);1===t.length&&n.removeLayer(t[0]);const i=n.getDrawLayersByDataId(e);if(1===i.length&&n.removeLayer(i[0]),0===t.length&&0===i.length)throw new Error("Expected one layer, got none");0===n.getNumberOfLayers()&&this.#ya.removeLayerGroup(n)}}}updateDataViewConfig(e,t,n){const i=this.#Eo.dataViewConfigs;if(void 0===i[e])throw new Error("No config for dataId: "+e);const r=i[e].findIndex((function(e){return e.divId===t}));if(-1===r)throw new Error("No config for dataId: "+e+" and divId: "+t);const o=i[e][r];for(const e in n)o[e]=n[e];const a=this.#ya.getLayerGroupByDivId(o.divId);if(void 0!==a){const t=a.getViewLayersByDataId(e);1===t.length&&a.removeLayer(t[0]);const n=a.getDrawLayersByDataId(e);if(1===n.length&&a.removeLayer(n[0]),0===t.length&&0===n.length)throw new Error("Expected one layer, got none")}void 0!==this.#ma.get(e)&&this.render(e,[o])}#xa(e){const t=Object.keys(e),n=[];for(let i=0;i<t.length;++i){const r=e[t[i]];for(let e=0;e<r.length;++e){const t=r[e];n.includes(t.divId)||(this.#Ra(t),n.push(t.divId))}}}#Ra(e){const t=this.#Eo.rootDocument.getElementById(e.divId),n=this.#ya.addLayerGroup(t);this.#Fa(n)}setLayerGroupsBinders(e){const t=[];for(let n=0;n<e.length;++n)void 0!==er[e[n]]&&t.push(new er[e[n]]);this.#ya.setBinders(t)}render(e,t){if(null==e)throw new Error("Cannot render without data id");const n=void 0!==this.getData(e).image,i=void 0!==this.getData(e).annotationGroup;if(0===this.#ya.getNumberOfLayerGroups()&&this.#xa(this.#Eo.dataViewConfigs),void 0===t&&(t=this.getViewConfigs(e)),0!==t.length)for(let r=0;r<t.length;++r){const o=t[r],a=this.#ya.getLayerGroupByDivId(o.divId);if(!a)throw new Error("No layer group for "+o.divId);void 0!==this.#ma.get(e)&&(n&&0===a.getViewLayersByDataId(e).length?this.#Ea(e,o):i&&0===a.getDrawLayersByDataId(e).length&&this.addDrawLayer(e,o)),a.draw()}else c.info("Not rendering data: "+e+" (no data view config)")}zoom(e,t,n){const i=this.#ya.getActiveLayerGroup(),r=i.getBaseViewLayer().getViewController().getCurrentScrollPosition(),o=new F(t,n,r);i.addScale(e,o),i.draw()}translate(e,t){const n=this.#ya.getActiveLayerGroup();n.addTranslation({x:e,y:t,z:0}),n.draw()}setOpacity(e){const t=this.#ya.getActiveLayerGroup().getActiveViewLayer();t.setOpacity(e),t.draw()}setDrawings(e,t,n){const i=this.#ya.getActiveLayerGroup().getBaseViewLayer(),r=i.getDataId(),o=i.getViewController(),a=function(e,t){const n=[],i=ai().Node.create(e).getChildren(gi);for(let e=0,r=i.length;e<r;++e){const r=i[e].getChildren();for(let e=0,i=r.length;e<i;++e){const e=new Yi,i=r[0];e.id=i.id();const o=i.getChildren(Si)[0];if(e.colour=o.stroke(),"line-group"===i.name()){const t=o.points();e.mathShape=new R(t[0],t[1]),e.referencePoints=[new R(t[2],t[3])]}else if("ruler-group"===i.name()){const t=o.points();e.mathShape=new $n(new R(t[0],t[1]),new R(t[2],t[3]))}else if("rectangle-group"===i.name())e.mathShape=new Mi(new R(o.x(),o.y()),new R(o.x()+o.width(),o.y()+o.height()));else if("roi-group"===i.name()){const t=o.points(),n=[];for(let e=0;e<t.length;e+=2)n.push(new R(t[e],t[e+1]));e.mathShape=new Ti(n)}else if("freeHand-group"===i.name()){c.warn("Converting freehand into ROI shape");const t=o.points(),n=[];for(let e=0;e<t.length;e+=2)n.push(new R(t[e],t[e+1]));e.mathShape=new Ti(n)}else if("protractor-group"===i.name()){const t=o.points();e.mathShape=new Ui([new R(t[0],t[1]),new R(t[2],t[3]),new R(t[4],t[5])])}else if("ellipse-group"===i.name()){const t=o.absolutePosition();e.mathShape=new Ei(new R(t.x,t.y),o.radiusX(),o.radiusY())}else if("circle-group"===i.name()){const t=o.absolutePosition();e.mathShape=new Fi(new R(t.x,t.y),o.radius())}if(t){const n=t[i.id()];e.textExpr=n.meta.textExpr,e.quantification=n.meta.quantification}n.push(e)}}return n}(e,t),s=this.createAnnotationData(r);for(const e of a)e.setViewController(o),s.annotationGroup.add(e);this.#ma.add(n,s),this.render(n)}applyJsonState(e,t){const n=new nr(t);n.apply(this,n.fromJSON(e))}onResize=()=>{this.fitToContainer()};onKeydown=e=>{this.#Fe(e)};defaultOnKeydown=e=>{if(e.ctrlKey)if(e.shiftKey){const t=this.#ya.getActiveLayerGroup(),n=t.getPositionHelper();"ArrowLeft"===e.key?t.moreThanOne(3)&&n.decrementPosition(3):"ArrowUp"===e.key?t.canScroll()&&n.incrementPositionAlongScroll():"ArrowRight"===e.key?t.moreThanOne(3)&&n.incrementPosition(3):"ArrowDown"===e.key&&t.canScroll()&&n.decrementPositionAlongScroll()}else if("y"===e.key)this.#Ca.redo();else if("z"===e.key)this.#Ca.undo();else if(" "===e.key)for(let e=0;e<this.#ya.getNumberOfLayerGroups();++e)this.#ya.getLayerGroup(e).setShowCrosshair(!this.#ya.getLayerGroup(e).getShowCrosshair())};resetDisplay(){this.resetLayout(),this.initWLDisplay()}resetZoom(){this.resetLayout()}setColourMap(e){this.#ya.getActiveLayerGroup().getActiveViewLayer().getViewController().setColourMap(e)}setWindowLevelPreset(e){this.#ya.getActiveLayerGroup().getActiveViewLayer().getViewController().setWindowLevelPreset(e)}setTool(e){for(let e=0;e<this.#ya.getNumberOfLayerGroups();++e){const t=this.#ya.getLayerGroup(e),n=t.getActiveLayer();void 0!==n&&this.#fa.bindLayerGroup(t,n)}this.#fa.setSelectedTool(e)}setToolFeatures(e){this.#fa.setToolFeatures(e)}undo(){this.#Ca.undo()}redo(){this.#Ca.redo()}getStackSize(){return this.#Ca.getStackSize()}getCurrentStackIndex(){return this.#Ca.getCurrentStackIndex()}getOverlayData(e){let t;return void 0!==this.#va&&(t=this.#va[e]),t}toggleOverlayListeners(e){const t=this.getOverlayData(e);void 0!==t&&(t.isListening()?t.removeAppListeners():t.addAppListeners())}createAnnotationData(e){const t=this.getData(e).image.getMeta(),n=new ro({});return n.annotationGroup=new Xi,n.annotationGroup.setMetaValue("Modality","SR"),n.annotationGroup.setMetaValue("PatientID",t.PatientID),n.annotationGroup.setMetaValue("StudyInstanceUID",t.StudyInstanceUID),n.annotationGroup.setMetaValue("ReferencedSeriesSequence",{value:[{SeriesInstanceUID:t.SeriesInstanceUID}]}),n}addAndRenderAnnotationData(e,t,n){const i=this.addData(e),r=this.getViewConfigs(n).find((e=>e.divId===t));if(void 0===r)throw new Error("No reference data view config for draw");const o=new Io(t);o.orientation=r.orientation,this.addDataViewConfig(i,o),this.render(i)}#Fe=e=>{this.#be.fireEvent(e)};#Ia=e=>{void 0!==this.#Eo.overlayConfig&&(this.#va[e.dataid]=new vo(this,e.dataid,this.#Eo.overlayConfig)),e.type="loadstart",this.#Fe(e)};#Ta=e=>{e.type="loadprogress",this.#Fe(e)};#La=e=>{void 0===e.data&&c.error("Missing loaditem event data."),void 0===e.loadtype&&c.error("Missing loaditem event load type.");const t=e.isfirstitem;let n=null;"image"===e.loadtype?(t?this.#ma.add(e.dataid,e.data):this.#ma.update(e.dataid,e.data),n=e.data.meta):"state"===e.loadtype&&(this.applyJsonState(e.data,e.dataid),n="state"),this.#Fe({type:"loaditem",data:n,source:e.source,loadtype:e.loadtype,dataid:e.dataid,isfirstitem:e.isfirstitem,warn:e.warn}),void 0!==this.#va&&void 0!==this.#va[e.dataid]&&this.#va[e.dataid].addItemMeta(n),"image"===e.loadtype&&0!==this.getViewConfigs(e.dataid).length&&t&&this.#Eo.viewOnFirstLoadItem&&this.render(e.dataid)};#Pa=e=>{e.type="load",this.#Fe(e)};#wa=e=>{e.type="loadend",this.#Fe(e)};#Oa=e=>{void 0===e.type&&(e.type="error"),this.#Fe(e)};#Aa=e=>{void 0===e.type&&(e.type="timeout"),this.#Fe(e)};#ba=e=>{void 0===e.type&&(e.type="abort"),this.#Fe(e)};#Fa(e){e.addEventListener("zoomchange",this.#Fe),e.addEventListener("offsetchange",this.#Fe),e.addEventListener("renderstart",this.#Fe),e.addEventListener("renderend",this.#Fe);for(let t=0;t<Vn.length;++t)e.addEventListener(Vn[t],this.#Fe);this.#fa&&this.#fa.hasTool("Draw")&&(e.addEventListener("drawcreate",this.#Fe),e.addEventListener("drawdelete",this.#Fe)),e.addEventListener("wlchange",(e=>{const t=_i(e.srclayerid).groupDivId,n=this.getViewConfig(e.dataid,t,!0);void 0!==n&&(n.windowCenter=void 0,n.windowWidth=void 0,n.wlPresetName=void 0,3===e.value.length&&(n.windowCenter=e.value[0],n.windowWidth=e.value[1],n.wlPresetName=e.value[2]))})),e.addEventListener("opacitychange",(e=>{const t=_i(e.srclayerid).groupDivId,n=this.getViewConfig(e.dataid,t,!0);void 0!==n&&(n.opacity=e.value[0])})),e.addEventListener("colourmapchange",(e=>{const t=_i(e.srclayerid).groupDivId,n=this.getViewConfig(e.dataid,t,!0);void 0!==n&&(n.colourMap=e.value[0])}))}#Ea(e,t){const n=this.#ma.get(e);if(!n)throw new Error("Cannot initialise layer with missing data, id: "+e);const i=this.#ya.getLayerGroupByDivId(t.divId);if(!i)throw new Error("Cannot initialise layer with missing group, id: "+t.divId);const r=n.image.getGeometry();this.#ya.unbindLayerGroups();const o=(new Qn).create(n.meta,n.image),a=Ct(r.getOrientation(),pt(t.orientation));o.setOrientation(a),"SEG"===n.image.getMeta().Modality&&o.setAlphaFunction((function(e){return 0===e?0:255}));const s=0===i.getNumberOfViewLayers();let l=1;void 0!==t.opacity?l=t.opacity:s||(l=.5);const c=i.addViewLayer();c.setView(o,e);const d=r.getSize(a).get2D(),h=r.getSpacing(a).get2D();c.initialise(d,h,l);const S=c.getViewController();if(void 0!==t.wlPresetName)S.setWindowLevelPreset(t.wlPresetName);else if(void 0!==t.windowCenter&&void 0!==t.windowWidth){const e=new u(t.windowCenter,t.windowWidth);S.setWindowLevel(e)}void 0!==t.colourMap?S.setColourMap(t.colourMap):s||("PT"===n.image.getMeta().Modality?S.setColourMap("hot"):S.setColourMap("rainbow")),this.#ma.addEventListener("dataimageset",c.onimageset);const g=[S.getCurrentIndex().getValues(),S.getCurrentPosition().getValues()];i.updateLayersToPositionChange({value:g,srclayerid:c.getId()}),this.#ya.fitToContainer(),c.setOffset(i.getOffset());const p=this.#qa(r.getOrientation(),t.orientation);if(this.#Ua(p,c),s)c.setScale(i.getScale());else{const e=i.getBaseViewLayer();c.initScale(i.getScale(),e.getAbsoluteZoomOffset())}this.#ya.bindLayerGroups(),this.#fa&&this.#fa.bindLayerGroup(i,c),this.#Fe({type:"viewlayeradd",layerid:c.getId(),layergroupid:i.getDivId(),dataid:e}),s&&this.#fa&&this.#fa.init()}addDrawLayer(e,t){const n=this.#ya.getLayerGroupByDivId(t.divId);if(!n)throw new Error("Cannot initialise layer with missing group, id: "+t.divId);const i=this.#ma.get(e);if(!i)throw new Error("Cannot initialise layer with missing data, id: "+e);const r=i.annotationGroup.getMetaValue("ReferencedSeriesSequence").value[0].SeriesInstanceUID,o=n.searchViewLayers({SeriesInstanceUID:r});if(0===o.length)return void console.warn("No loaded data that matches the measurement reference series UID");const a=o[0],s=a.getDataId();this.#ya.unbindLayerGroups();const l=a.getViewController();i.annotationGroup.setViewController(l);const c=this.#ma.get(s);if(!c)throw new Error("Cannot initialise layer without reference data, id: "+s);const u=c.image.getGeometry(),d=Ct(u.getOrientation(),pt(t.orientation)),h=u.getSize(d).get2D(),S=u.getSpacing(d).get2D(),g=n.addDrawLayer();g.initialise(h,S,a.getId());const p=new Gn(u,d);g.setPlaneHelper(p);const m=[l.getCurrentIndex().getValues(),l.getCurrentPosition().getValues()];n.updateLayersToPositionChange({value:m,srclayerid:g.getId()}),this.#ya.fitToContainer(),g.setOffset(n.getOffset());const f=this.#qa(u.getOrientation(),t.orientation);this.#Ua(f,g),g.initScale(n.getScale(),a.getAbsoluteZoomOffset()),g.setAnnotationGroup(i.annotationGroup,e,this.addToUndoStack),g.setCurrentPosition(l.getCurrentPosition(),l.getCurrentIndex()),this.#ya.bindLayerGroups(),this.#fa&&this.#fa.bindLayerGroup(n,g),this.#Fe({type:"drawlayeradd",layerid:g.getId(),layergroupid:n.getDivId(),dataid:e})}#qa(e,t){const n=mt(e.asOneAndZeros());if(void 0===n)throw new Error("Unsupported undefined orientation code");const i=void 0===t,r=!i&&t===gt.Axial,o=!i&&t===gt.Coronal,a=!i&&t===gt.Sagittal,s={x:!1,y:!1},l={x:!1,y:!1,z:!1};return"LPS"===n?(o||a)&&(l.z=!0,s.y=!0):"LAI"===n?i||r?s.y=!0:o?l.z=!0:a&&(l.z=!0,s.x=!0):"RPI"===n?i||r?s.x=!0:o?(l.z=!0,s.x=!0):a&&(l.z=!0):"RAS"===n?(s.x=!0,s.y=!0,(o||a)&&(l.z=!0)):"LSA"===n?(s.y=!0,i||o?l.z=!0:r?l.y=!0:a&&(s.x=!0,l.y=!0,l.z=!0)):"RSP"===n?i||o?(s.x=!0,s.y=!0,l.x=!0,l.z=!0):r?(s.x=!0,l.x=!0):a&&(s.y=!0,l.z=!0):"RIA"===n?(s.x=!0,i||o?l.x=!0:r?(s.y=!0,l.x=!0,l.y=!0):a&&(l.y=!0)):"PSL"===n?(l.z=!0,(i||a||o)&&(s.y=!0)):"PIR"===n?(l.z=!0,(r||o)&&(s.x=!0)):"ASR"===n?(s.x=!0,s.y=!0,(i||a||o)&&(l.z=!0)):"AIL"===n?i||a?(s.x=!0,l.z=!0):r?s.y=!0:o&&(l.z=!0):c.warn("Unsupported orientation code: "+n+", display could be incorrect"),{scale:l,offset:s}}#Ua(e,t){e.offset.x&&t.addFlipOffsetX(),e.offset.y&&t.addFlipOffsetY(),e.scale.x&&t.flipScaleX(),e.scale.y&&t.flipScaleY(),e.scale.z&&t.flipScaleZ()}}class wo{#vi;#Ma;constructor(e){this.#vi=e;const t=e.getMeta();void 0===t.custom&&(t.custom={}),void 0===t.custom.segments&&(t.custom.segments=[]),this.#Ma=t.custom.segments}#Qa(e){return this.#Ma.findIndex((function(t){return t.number===e}))}hasSegment(e){return-1!==this.#Qa(e)}getNumberOfSegments(){return this.#Ma.length}maskHasSegments(e){const t=[],n=[];for(let i=0;i<e.length;++i){const r=this.getSegment(e[i]);void 0!==r?void 0!==r.displayValue?t.push(r.displayValue):t.push(r.number):(c.warn("Unknown segment in maskHasSegments: "+e[i]),n.push(i))}const i=this.#vi.hasValues(t);for(let e=0;e<n.length;++e)i.splice(n[e],0,!1);return i}getSegment(e){let t;const n=this.#Qa(e);return-1!==n&&(t=this.#Ma[n]),t}addSegment(e){-1===this.#Qa(e.number)?(this.#Ma.push(e),void 0!==e.displayRGBValue&&this.#vi.updatePaletteColourMap(e.number,e.displayRGBValue)):c.warn("Not adding segment, it is allready in the segments list: "+e.number)}removeSegment(e){const t=this.#Qa(e);-1!==t?this.#Ma.splice(t,1):c.warn("Cannot remove segment, it is not in the segments list: "+e)}updateSegment(e){const t=this.#Qa(e.number);-1!==t?this.#Ma[t]=e:c.warn("Cannot update segment, it is not in the segments list: "+e.number)}}class Oo{#vi;#Va;#Na;#Ba;constructor(e,t,n){this.#vi=e,this.#Va=t,this.#Na=void 0!==n&&n,void 0!==t.displayRGBValue?this.#Ba=e.getOffsets(t.number):this.#Ba=e.getOffsets(t.displayValue)}getName(){return"Delete-segment"}isValid(){return this.#vi.getMeta().custom.segments.some((e=>e.number===this.#Va.number))}execute(){0!==this.#Ba.length&&this.#vi.setAtOffsets(this.#Ba,0),new wo(this.#vi).removeSegment(this.#Va.number),this.#Na||this.onExecute({type:"masksegmentdelete",segmentnumber:this.#Va.number})}undo(){0!==this.#Ba.length&&(void 0!==this.#Va.displayRGBValue?this.#vi.setAtOffsets(this.#Ba,this.#Va.number):this.#vi.setAtOffsets(this.#Ba,this.#Va.displayValue)),new wo(this.#vi).addSegment(this.#Va),this.onUndo({type:"masksegmentredraw",segmentnumber:this.#Va.number})}onExecute(e){}onUndo(e){}}class Ao{#vi;#Va;#Ga;#ka;#Na;#Ba;constructor(e,t,n,i){this.#vi=e,this.#Va=t,this.#Ga=n,this.#Na=void 0!==i&&i,void 0!==t.displayRGBValue?this.#ka=t.displayRGBValue:(this.#ka=t.displayValue,this.#Ba=e.getOffsets(this.#ka))}getName(){return"Change-segment-colour"}isValid(){let e=!0;return void 0!==this.#Ba&&(e=0!==this.#Ba.length),e}execute(){"number"==typeof this.#Ga?(this.#vi.setAtOffsets(this.#Ba,this.#Ga),this.#Va.displayValue=this.#Ga):(this.#vi.updatePaletteColourMap(this.#Va.number,this.#Ga),this.#Va.displayRGBValue=this.#Ga),this.#Na||this.onExecute({type:"changemasksegmentcolour",segmentnumber:this.#Va.number,value:[this.#Ga]})}undo(){"number"==typeof this.#ka?(this.#vi.setAtOffsets(this.#Ba,this.#ka),this.#Va.displayValue=this.#ka):(this.#vi.updatePaletteColourMap(this.#Va.number,this.#ka),this.#Va.displayRGBValue=this.#ka),this.onUndo({type:"changemasksegmentcolour",segmentnumber:this.#Va.number,value:[this.#ka]})}onExecute(e){}onUndo(e){}}class bo{#Ha=[];#za(e){return this.#Ha.indexOf(e)}isHidden(e){return-1!==this.#za(e)}addToHidden(e){this.isHidden(e)?c.warn("Not hidding segment, it is allready in the hidden list: "+e):this.#Ha.push(e)}removeFromHidden(e){const t=this.#za(e);-1!==t?this.#Ha.splice(t,1):c.warn("Cannot remove segment, it is not in the hidden list: "+e)}getAlphaFunc(){return e=>Array.isArray(e)||0!==e&&!this.#Ha.includes(e)?255:0}}class xo{x;y}class Ro{x;y;z}return a}()}));
 //# sourceMappingURL=dwv.min.js.map
\ No newline at end of file
diff --git a/demo/trunk/dist/dwv.min.js.map b/demo/trunk/dist/dwv.min.js.map
index 82e5d71772..351872dcee 100644
--- a/demo/trunk/dist/dwv.min.js.map
+++ b/demo/trunk/dist/dwv.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"dwv.min.js","mappings":"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AK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAC35BD,MAAO,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,GACllCD,IAAK,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,MAK9lCO,IAAK,CACHP,IAAKN,GAtIT,SAAyBlE,GACvB,MAAMF,EAAU,EAAJE,EACZ,OAAIF,EAAMwE,IACDA,IAEFxE,CACT,IAiII2E,MAAOP,GAvHX,SAA0BlE,GACxB,MAAMgF,EAvCc,IAuCU,EAC9B,IAAIlF,EAAM,EACV,OAAIE,GAAKgF,IACPlF,EAAoB,GAAbE,EAAIgF,GACPlF,EAAMwE,KACDA,IAGJxE,CACT,IA8GI4E,KAAMR,GArGV,SAAyBlE,GACvB,MAAMgF,EA1Dc,IA0DU,EAC9B,IAAIlF,EAAM,EACV,OAAIE,GAAK,EAAIgF,IACXlF,EAAwB,GAAjBE,EAAI,EAAIgF,GACXlF,EAAMwE,KACDA,IAGJxE,CACT,KAgGEmF,SAAU,CACRT,IAAK,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC1sCC,MAAO,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC58BC,KAAM,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,MAM12BQ,IAAK,CACHV,IAAK,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC1kCC,MAAO,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC9lCC,KAAM,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,MAMrpCS,eAAgB,CACdX,IAAK,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC7iCC,MAAO,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC19BC,KAAM,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,MAMxmCU,WAAY,CACVZ,IAAK,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KACpnCC,MAAO,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC3lCC,KAAM,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GA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","sources":["webpack://dwv/webpack/universalModuleDefinition","webpack://dwv/external umd {\"root\":\"JSZip\",\"commonjs\":\"jszip\",\"commonjs2\":\"jszip\",\"amd\":\"jszip\"}","webpack://dwv/external umd {\"root\":\"Konva\",\"commonjs\":\"konva\",\"commonjs2\":\"konva\",\"amd\":\"konva\"}","webpack://dwv/external umd {\"root\":\"MagicWand\",\"commonjs\":\"magic-wand-tool\",\"commonjs2\":\"magic-wand-tool\",\"amd\":\"konmagic-wand-tool\"}","webpack://dwv/webpack/bootstrap","webpack://dwv/webpack/runtime/compat get default export","webpack://dwv/webpack/runtime/define property getters","webpack://dwv/webpack/runtime/hasOwnProperty shorthand","webpack://dwv/webpack/runtime/make namespace object","webpack://dwv/./src/math/index.js","webpack://dwv/./src/image/modalityLut.js","webpack://dwv/./src/utils/logger.js","webpack://dwv/./src/image/windowLevel.js","webpack://dwv/./src/image/voiLut.js","webpack://dwv/./src/image/windowLut.js","webpack://dwv/./src/image/luts.js","webpack://dwv/./src/utils/colour.js","webpack://dwv/./src/app/custom.js","webpack://dwv/./src/math/vector.js","webpack://dwv/./src/math/matrix.js","webpack://dwv/./src/math/point.js","webpack://dwv/./src/utils/i18n.js","webpack://dwv/./src/utils/string.js","webpack://dwv/./src/utils/array.js","webpack://dwv/./src/dicom/dictionary.js","webpack://dwv/./src/dicom/dicomTag.js","webpack://dwv/./src/dicom/dataElement.js","webpack://dwv/./src/dicom/dataReader.js","webpack://dwv/./src/dicom/dicomParser.js","webpack://dwv/./src/utils/listen.js","webpack://dwv/./src/image/iterator.js","webpack://dwv/./src/image/rsi.js","webpack://dwv/./src/image/size.js","webpack://dwv/./src/math/stats.js","webpack://dwv/./src/image/spacing.js","webpack://dwv/./src/image/geometry.js","webpack://dwv/./src/dicom/dicomDate.js","webpack://dwv/./src/math/orientation.js","webpack://dwv/./src/dicom/dicomElementsWrapper.js","webpack://dwv/./src/image/imageFactory.js","webpack://dwv/./src/dicom/dataWriter.js","webpack://dwv/./src/dicom/dicomWriter.js","webpack://dwv/./src/dicom/dicomCode.js","webpack://dwv/./src/dicom/dicomSegment.js","webpack://dwv/./src/dicom/dicomSegmentFrameInfo.js","webpack://dwv/./src/image/maskFactory.js","webpack://dwv/./src/image/image.js","webpack://dwv/./src/image/viewFactory.js","webpack://dwv/./src/image/view.js","webpack://dwv/./src/image/viewMonochrome.js","webpack://dwv/./src/image/viewPaletteColor.js","webpack://dwv/./src/image/viewRgb.js","webpack://dwv/./src/image/viewYbrFull.js","webpack://dwv/./src/image/planeHelper.js","webpack://dwv/./src/image/positionHelper.js","webpack://dwv/./src/app/viewController.js","webpack://dwv/./src/gui/generic.js","webpack://dwv/./src/gui/viewLayer.js","webpack://dwv/./src/tools/scrollWheel.js","webpack://dwv/./src/math/line.js","webpack://dwv/./src/tools/drawCommands.js","webpack://dwv/./src/gui/style.js","webpack://dwv/./src/tools/drawBounds.js","webpack://dwv/./src/tools/drawShapeEditor.js","webpack://dwv/./src/tools/drawTrash.js","webpack://dwv/./src/tools/drawShapeHandler.js","webpack://dwv/./src/math/roi.js","webpack://dwv/./src/math/path.js","webpack://dwv/./src/math/bucketQueue.js","webpack://dwv/./src/math/scissors.js","webpack://dwv/./src/tools/labelFactory.js","webpack://dwv/./src/math/circle.js","webpack://dwv/./src/math/ellipse.js","webpack://dwv/./src/math/protractor.js","webpack://dwv/./src/math/rectangle.js","webpack://dwv/./src/image/filter.js","webpack://dwv/./src/tools/filter.js","webpack://dwv/./src/tools/index.js","webpack://dwv/./src/tools/windowLevel.js","webpack://dwv/./src/tools/scroll.js","webpack://dwv/./src/tools/zoomPan.js","webpack://dwv/./src/tools/opacity.js","webpack://dwv/./src/tools/draw.js","webpack://dwv/./src/tools/floodfill.js","webpack://dwv/./src/tools/livewire.js","webpack://dwv/./src/tools/arrow.js","webpack://dwv/./src/tools/circle.js","webpack://dwv/./src/tools/ellipse.js","webpack://dwv/./src/tools/protractor.js","webpack://dwv/./src/tools/rectangle.js","webpack://dwv/./src/tools/roi.js","webpack://dwv/./src/tools/ruler.js","webpack://dwv/./src/image/annotation.js","webpack://dwv/./src/image/annotationGroup.js","webpack://dwv/./src/app/drawController.js","webpack://dwv/./src/gui/drawLayer.js","webpack://dwv/./src/gui/layerGroup.js","webpack://dwv/./src/gui/stage.js","webpack://dwv/./src/io/state.js","webpack://dwv/./src/utils/uri.js","webpack://dwv/./src/utils/undoStack.js","webpack://dwv/./src/app/toolboxController.js","webpack://dwv/./src/utils/progress.js","webpack://dwv/./src/io/urlsLoader.js","webpack://dwv/./src/utils/thread.js","webpack://dwv/./src/image/decoder.js","webpack://dwv/./src/dicom/dicomMeasuredValue.js","webpack://dwv/./src/dicom/dicomNumericMeasurement.js","webpack://dwv/./src/dicom/dicomSopInstanceReference.js","webpack://dwv/./src/dicom/dicomImageReference.js","webpack://dwv/./src/dicom/dicomSpatialCoordinate.js","webpack://dwv/./src/dicom/dicomSpatialCoordinate3D.js","webpack://dwv/./src/dicom/dicomSRContent.js","webpack://dwv/./src/image/annotationGroupFactory.js","webpack://dwv/./src/app/dataController.js","webpack://dwv/./src/utils/operator.js","webpack://dwv/./src/image/dicomBufferToView.js","webpack://dwv/./src/io/memoryLoader.js","webpack://dwv/./src/image/domReader.js","webpack://dwv/./src/io/loaderList.js","webpack://dwv/./src/io/dicomDataLoader.js","webpack://dwv/./src/io/jsonTextLoader.js","webpack://dwv/./src/io/multipartLoader.js","webpack://dwv/./src/io/rawImageLoader.js","webpack://dwv/./src/io/rawVideoLoader.js","webpack://dwv/./src/io/zipLoader.js","webpack://dwv/./src/io/filesLoader.js","webpack://dwv/./src/app/loadController.js","webpack://dwv/./src/gui/overlayData.js","webpack://dwv/./src/app/application.js","webpack://dwv/./src/image/maskSegmentHelper.js","webpack://dwv/./src/image/deleteSegmentCommand.js","webpack://dwv/./src/image/changeSegmentColourCommand.js","webpack://dwv/./src/image/maskSegmentViewHelper.js","webpack://dwv/./src/math/scalar.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"konva\"), require(\"magic-wand-tool\"), require(\"jszip\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"konva\", \"konmagic-wand-tool\", \"jszip\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"dwv\"] = factory(require(\"konva\"), require(\"magic-wand-tool\"), require(\"jszip\"));\n\telse\n\t\troot[\"dwv\"] = factory(root[\"Konva\"], root[\"MagicWand\"], root[\"JSZip\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE__944__, __WEBPACK_EXTERNAL_MODULE__324__, __WEBPACK_EXTERNAL_MODULE__654__) {\nreturn ","module.exports = __WEBPACK_EXTERNAL_MODULE__654__;","module.exports = __WEBPACK_EXTERNAL_MODULE__944__;","module.exports = __WEBPACK_EXTERNAL_MODULE__324__;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/**\n * Immutable index.\n * Warning: the input array is NOT cloned, modifying it will\n *  modify the index values.\n */\nexport class Index {\n\n  /**\n   * Index values.\n   *\n   * @type {number[]}\n   */\n  #values;\n\n  /**\n   * @param {number[]} values The index values.\n   */\n  constructor(values) {\n    if (!values || typeof values === 'undefined') {\n      throw new Error('Cannot create index with no values.');\n    }\n    if (values.length === 0) {\n      throw new Error('Cannot create index with empty values.');\n    }\n    const valueCheck = function (val) {\n      return !isNaN(val);\n    };\n    if (!values.every(valueCheck)) {\n      throw new Error('Cannot create index with non number values.');\n    }\n    this.#values = values;\n  }\n\n  /**\n   * Get the index value at the given array index.\n   *\n   * @param {number} i The index to get.\n   * @returns {number|undefined} The value or undefined if not in range.\n   */\n  get(i) {\n    return this.#values[i];\n  }\n\n  /**\n   * Get the length of the index.\n   *\n   * @returns {number} The length.\n   */\n  length() {\n    return this.#values.length;\n  }\n\n  /**\n   * Get a string representation of the Index.\n   *\n   * @returns {string} The Index as a string.\n   */\n  toString() {\n    return '(' + this.#values.toString() + ')';\n  }\n\n  /**\n   * Get the values of this index.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return this.#values.slice();\n  }\n\n  /**\n   * Check if the input index can be compared to this one.\n   *\n   * @param {Index} rhs The index to compare to.\n   * @returns {boolean} True if both indices are comparable.\n   */\n  canCompare(rhs) {\n    // check input\n    if (!rhs) {\n      return false;\n    }\n    // check length\n    if (this.length() !== rhs.length()) {\n      return false;\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Check for Index equality.\n   *\n   * @param {Index} rhs The index to compare to.\n   * @returns {boolean} True if both indices are equal.\n   */\n  equals(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return false;\n    }\n    // check values\n    for (let i = 0, leni = this.length(); i < leni; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        return false;\n      }\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Compare indices and return different dimensions.\n   *\n   * @param {Index} rhs The index to compare to.\n   * @returns {number[]} The list of different dimensions.\n   */\n  compare(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return null;\n    }\n    // check values\n    const diffDims = [];\n    for (let i = 0, leni = this.length(); i < leni; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        diffDims.push(i);\n      }\n    }\n    return diffDims;\n  }\n\n  /**\n   * Add another index to this one and return\n   *   the result as a new index.\n   *\n   * @param {Index} rhs The index to add.\n   * @returns {Index} The index representing the sum of both indices.\n   */\n  add(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return null;\n    }\n    // add values\n    const values = [];\n    for (let i = 0, leni = this.length(); i < leni; ++i) {\n      values.push(this.get(i) + rhs.get(i));\n    }\n    // seems ok!\n    return new Index(values);\n  }\n\n  /**\n   * Add the input value to this index at the given\n   *   dimension number and return the result\n   *   as a new index.\n   *\n   * @param {number} dim The dimension number.\n   * @param {number} value The value to add.\n   * @returns {Index} The result index.\n   */\n  #addToDim(dim, value) {\n    const values = this.#values.slice();\n    if (dim < values.length) {\n      values[dim] += value;\n    } else {\n      console.warn('Cannot add to given dimension: ', dim, values.length);\n    }\n    return new Index(values);\n  }\n\n  /**\n   * Increment this index by 1 at the given dimension\n   *   and return the result as a new index.\n   *\n   * @param {number} dim The dimension number.\n   * @returns {Index} The result index.\n   */\n  next(dim) {\n    return this.#addToDim(dim, 1);\n  }\n\n  /**\n   * Decrement this index by 1 at the given dimension\n   *   and return the result as a new index.\n   *\n   * @param {number} dim The dimension number.\n   * @returns {Index} The result index.\n   */\n  previous(dim) {\n    return this.#addToDim(dim, -1);\n  }\n\n  /**\n   * Get the current index with a new 2D base\n   *   and return the result as a new index.\n   *\n   * @param {number} i The new 0 index.\n   * @param {number} j The new 1 index.\n   * @returns {Index} The new index.\n   */\n  getWithNew2D(i, j) {\n    const values = [i, j];\n    for (let l = 2, lenl = this.length(); l < lenl; ++l) {\n      values.push(this.get(l));\n    }\n    return new Index(values);\n  }\n\n} // Index class\n\n/**\n * Get an index with values set to 0 and the input size.\n *\n * @param {number} size The size of the index.\n * @returns {Index} The zero index.\n */\nexport function getZeroIndex(size) {\n  const values = new Array(size);\n  values.fill(0);\n  return new Index(values);\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {RescaleSlopeAndIntercept} from './rsi';\n/* eslint-enable no-unused-vars */\n\n/**\n * Modality LUT class: compensates for any modality-specific presentation.\n * Typically consists of a rescale slope and intercept to\n * rescale the data range.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.11.html}.\n */\nexport class ModalityLut {\n\n  /**\n   * The rescale slope.\n   *\n   * @type {RescaleSlopeAndIntercept}\n   */\n  #rsi;\n\n  /**\n   * Is the RSI an identity one.\n   *\n   * @type {boolean}\n   */\n  #isIdRsi;\n\n  /**\n   * The size of the LUT array.\n   *\n   * @type {number}\n   */\n  #length;\n\n  /**\n   * The internal LUT array.\n   *\n   * @type {Float32Array}\n   */\n  #lut;\n\n  /**\n   * @param {RescaleSlopeAndIntercept} rsi The rescale slope and intercept.\n   * @param {number} bitsStored The number of bits used to store the data.\n   */\n  constructor(rsi, bitsStored) {\n    this.#rsi = rsi;\n    this.#isIdRsi = rsi.isID();\n\n    this.#length = Math.pow(2, bitsStored);\n\n    // create lut if not identity RSI\n    if (!this.#isIdRsi) {\n      this.#lut = new Float32Array(this.#length);\n      for (let i = 0; i < this.#length; ++i) {\n        this.#lut[i] = this.#rsi.apply(i);\n      }\n    }\n  }\n\n  /**\n   * Get the Rescale Slope and Intercept (RSI).\n   *\n   * @returns {RescaleSlopeAndIntercept} The rescale slope and intercept object.\n   */\n  getRSI() {\n    return this.#rsi;\n  }\n\n  /**\n   * Get the length of the LUT array.\n   *\n   * @returns {number} The length of the LUT array.\n   */\n  getLength() {\n    return this.#length;\n  }\n\n  /**\n   * Get the value of the LUT at the given offset.\n   *\n   * @param {number} offset The input offset in [0,2^bitsStored] range\n   *   or full range for ID rescale.\n   * @returns {number} The float32 value of the LUT at the given offset.\n   */\n  getValue(offset) {\n    return this.#isIdRsi ? offset : this.#lut[offset];\n  }\n\n} // class ModalityLut\n","export const logger = {\n  /**\n   * Available log levels.\n   * Note: need to activate verbose level in\n   *   Chrome console to see DEBUG messages.\n   */\n  levels: {\n    TRACE: 0,\n    DEBUG: 1,\n    INFO: 2,\n    WARN: 3,\n    ERROR: 4\n  },\n\n  /**\n   * Logger level: default to WARN.\n   */\n  level: 3,\n\n  /**\n   * Log a trace message.\n   *\n   * @param {string} msg The message to log.\n   */\n  trace: function (msg) {\n    if (this.level <= this.levels.TRACE) {\n      console.trace(msg);\n    }\n  },\n\n  /**\n   * Log a debug message.\n   * Careful: depends on console settings.\n   *\n   * @param {string} msg The message to log.\n   */\n  debug: function (msg) {\n    if (this.level <= this.levels.DEBUG) {\n      console.debug(msg);\n    }\n  },\n\n  /**\n   * Log an info message.\n   *\n   * @param {string} msg The message to log.\n   */\n  info: function (msg) {\n    if (this.level <= this.levels.INFO) {\n      console.info(msg);\n    }\n  },\n\n  /**\n   * Log a warn message.\n   *\n   * @param {string} msg The message to log.\n   */\n  warn: function (msg) {\n    if (this.level <= this.levels.WARN) {\n      console.warn(msg);\n    }\n  },\n\n  /**\n   * Log an error message.\n   *\n   * @param {string} msg The message to log.\n   */\n  error: function (msg) {\n    if (this.level <= this.levels.ERROR) {\n      console.error(msg);\n    }\n  }\n\n}; // logger\n","import {logger} from '../utils/logger';\n\n/**\n * Minimum window width value.\n *\n * Ref: {@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.11.2.html#sect_C.11.2.1.2}.\n */\nconst minWindowWidth = 1;\n\n/**\n * Validate an input window width.\n *\n * @param {number} value The value to test.\n * @returns {number} A valid window width.\n */\nexport function validateWindowWidth(value) {\n  return value < minWindowWidth ? minWindowWidth : value;\n}\n\n/**\n * Window and Level also known as window width and center.\n */\nexport class WindowLevel {\n  /**\n   * The window center.\n   *\n   * @type {number}\n   */\n  center;\n\n  /**\n   * The window width.\n   *\n   * @type {number}\n   */\n  width;\n\n  /**\n   * @param {number} center The window center.\n   * @param {number} width The window width.\n   */\n  constructor(center, width) {\n    // check width\n    if (width < minWindowWidth) {\n      logger.warn('Using minimum window width since input is not valid: ' +\n        width);\n      width = minWindowWidth;\n    }\n    this.center = center;\n    this.width = width;\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {WindowLevel} rhs The other object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      typeof rhs !== 'undefined' &&\n      this.center === rhs.center &&\n      this.width === rhs.width;\n  }\n\n} // WindowLevel class\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {WindowLevel} from './windowLevel';\n/* eslint-enable no-unused-vars */\n\n/**\n * VOI (Values of Interest) LUT class: apply window centre and width.\n *\n * ```\n * if (x <= c - 0.5 - (w-1)/2) then y = ymin\n * else if (x > c - 0.5 + (w-1)/2) then y = ymax\n * else y = ((x - (c - 0.5)) / (w-1) + 0.5) * (ymax - ymin) + ymin\n * ```\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.11.2.html}.\n */\nexport class VoiLut {\n\n  /**\n   * The window and level.\n   *\n   * @type {WindowLevel}\n   */\n  #windowLevel;\n\n  /**\n   * Signed data offset. Defaults to 0.\n   *\n   * @type {number}\n   */\n  #signedOffset = 0;\n\n  /**\n   * Output value minimum. Defaults to 0.\n   *\n   * @type {number}\n   */\n  #ymin = 0;\n\n  /**\n   * Output value maximum. Defaults to 255.\n   *\n   * @type {number}\n   */\n  #ymax = 255;\n\n  /**\n   * Input value minimum (calculated).\n   *\n   * @type {number}\n   */\n  #xmin = null;\n\n  /**\n   * Input value maximum (calculated).\n   *\n   * @type {number}\n   */\n  #xmax = null;\n\n  /**\n   * Window level equation slope (calculated).\n   *\n   * @type {number}\n   */\n  #slope = null;\n\n  /**\n   * Window level equation intercept (calculated).\n   *\n   * @type {number}\n   */\n  #inter = null;\n\n  /**\n   * @param {WindowLevel} wl The window center and width.\n   */\n  constructor(wl) {\n    this.#windowLevel = wl;\n    this.#init();\n  }\n\n  /**\n   * Get the window and level.\n   *\n   * @returns {WindowLevel} The window center and width.\n   */\n  getWindowLevel() {\n    return this.#windowLevel;\n  }\n\n  /**\n   * Initialise members. Called at construction.\n   *\n   */\n  #init() {\n    const center = this.#windowLevel.center;\n    const width = this.#windowLevel.width;\n    const c = center + this.#signedOffset;\n    // from the standard\n    this.#xmin = c - 0.5 - ((width - 1) / 2);\n    this.#xmax = c - 0.5 + ((width - 1) / 2);\n    // develop the equation:\n    // y = ( ( x - (c - 0.5) ) / (w-1) + 0.5 ) * (ymax - ymin) + ymin\n    // y = ( x / (w-1) ) * (ymax - ymin) +\n    //     ( -(c - 0.5) / (w-1) + 0.5 ) * (ymax - ymin) + ymin\n    this.#slope = (this.#ymax - this.#ymin) / (width - 1);\n    this.#inter = (-(c - 0.5) / (width - 1) + 0.5) *\n      (this.#ymax - this.#ymin) + this.#ymin;\n  }\n\n  /**\n   * Set the signed offset.\n   *\n   * @param {number} offset The signed data offset,\n   *   typically: slope * ( size / 2).\n   */\n  setSignedOffset(offset) {\n    this.#signedOffset = offset;\n    // re-initialise\n    this.#init();\n  }\n\n  /**\n   * Apply the window level on an input value.\n   *\n   * @param {number} value The value to rescale as an integer.\n   * @returns {number} The leveled value, in the\n   *  [ymin, ymax] range (default [0,255]).\n   */\n  apply(value) {\n    if (value <= this.#xmin) {\n      return this.#ymin;\n    } else if (value > this.#xmax) {\n      return this.#ymax;\n    } else {\n      return (value * this.#slope) + this.#inter;\n    }\n  }\n\n} // class VoiLut\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {ModalityLut} from './modalityLut';\nimport {VoiLut} from './voiLut';\n/* eslint-enable no-unused-vars */\n\n/**\n * Window LUT class: combines a modality LUT and a VOI LUT.\n */\nexport class WindowLut {\n\n  /**\n   * The modality LUT.\n   *\n   * @type {ModalityLut}\n   */\n  #modalityLut;\n\n  /**\n   * The VOI LUT.\n   *\n   * @type {VoiLut}\n   */\n  #voiLut;\n\n  /**\n   * The internal LUT array: Uint8ClampedArray clamps between 0 and 255.\n   *\n   * @type {Uint8ClampedArray}\n   */\n  #lut;\n\n  /**\n   * Shift for signed data.\n   *\n   * @type {number}\n   */\n  #signedShift = 0;\n\n  /**\n   * Is the RSI discrete.\n   *\n   * @type {boolean}\n   */\n  #isDiscrete = true;\n\n  /**\n   * Construct a window LUT object, VOI LUT is set with\n   *   the 'setVoiLut' method.\n   *\n   * @param {ModalityLut} modalityLut The associated rescale LUT.\n   * @param {boolean} isSigned Flag to know if the data is signed or not.\n   * @param {boolean} isDiscrete Flag to know if the input data is discrete.\n   */\n  constructor(modalityLut, isSigned, isDiscrete) {\n    this.#modalityLut = modalityLut;\n\n    if (isSigned) {\n      const size = this.#modalityLut.getLength();\n      this.#signedShift = size / 2;\n    } else {\n      this.#signedShift = 0;\n    }\n\n    this.#isDiscrete = isDiscrete;\n  }\n\n  /**\n   * Get the VOI LUT.\n   *\n   * @returns {VoiLut} The VOI LUT.\n   */\n  getVoiLut() {\n    return this.#voiLut;\n  }\n\n  /**\n   * Get the modality LUT.\n   *\n   * @returns {ModalityLut} The modality LUT.\n   */\n  getModalityLut() {\n    return this.#modalityLut;\n  }\n\n  /**\n   * Set the VOI LUT.\n   *\n   * @param {VoiLut} lut The VOI LUT.\n   */\n  setVoiLut(lut) {\n    // store the window values\n    this.#voiLut = lut;\n\n    // possible signed shift (LUT indices are positive)\n    this.#voiLut.setSignedOffset(\n      this.#modalityLut.getRSI().getSlope() * this.#signedShift);\n\n    // create lut if not continous\n    if (this.#isDiscrete) {\n      const size = this.#modalityLut.getLength();\n      // use clamped array (polyfilled in env.js)\n      this.#lut = new Uint8ClampedArray(size);\n      // by default WindowLevel returns a value in the [0,255] range\n      // this is ok with regular Arrays and ClampedArray.\n      for (let i = 0; i < size; ++i) {\n        this.#lut[i] = this.#voiLut.apply(this.#modalityLut.getValue(i));\n      }\n    }\n  }\n\n  /**\n   * Get the value of the LUT at the given offset.\n   *\n   * @param {number} offset The input offset in [0,2^bitsStored] range\n   *   for discrete data or full range for non discrete.\n   * @returns {number} The integer value (default [0,255]) of the LUT\n   *   at the given offset.\n   */\n  getValue(offset) {\n    if (this.#isDiscrete) {\n      return this.#lut[offset + this.#signedShift];\n    } else {\n      return Math.floor(this.#voiLut.apply(offset + this.#signedShift));\n    }\n  }\n\n} // class WindowLut\n","/**\n * Lookup tables for image colour display.\n */\n\nconst lut_range_max = 256;\n\n/**\n * Build a LUT of size lut_range_max.\n *\n * @param {Function} func The i to lut function.\n * @returns {number[]} The LUT.\n */\nfunction buildLut(func) {\n  const lut = [];\n  for (let i = 0; i < lut_range_max; ++i) {\n    lut.push(func(i));\n  }\n  return lut;\n}\n\n/**\n * Ramp to lut_range_max minus one on the first third values.\n *\n * @param {number} i The input index.\n * @returns {number} The lut value.\n */\nfunction toMaxFirstThird(i) {\n  const val = i * 3;\n  if (val > lut_range_max - 1) {\n    return lut_range_max - 1;\n  }\n  return val;\n}\n\n/**\n * Ramp to lut_range_max minus one on the second third values,\n *   otherwise return 0 for the first third and\n *   lut_range_max minus one for the last third.\n *\n * @param {number} i The input index.\n * @returns {number} The lut value.\n */\nfunction toMaxSecondThird(i) {\n  const third = lut_range_max / 3;\n  let val = 0;\n  if (i >= third) {\n    val = (i - third) * 3;\n    if (val > lut_range_max - 1) {\n      return lut_range_max - 1;\n    }\n  }\n  return val;\n}\n\n/**\n * Ramp to lut_range_max minus one on the last third values,\n *   otherwise return 0.\n *\n * @param {number} i The input index.\n * @returns {number} The lut value.\n */\nfunction toMaxThirdThird(i) {\n  const third = lut_range_max / 3;\n  let val = 0;\n  if (i >= 2 * third) {\n    val = (i - 2 * third) * 3;\n    if (val > lut_range_max - 1) {\n      return lut_range_max - 1;\n    }\n  }\n  return val;\n}\n\n/**\n * Identity, returns i.\n *\n * @param {number} i The input index.\n * @returns {number} The lut value.\n */\nfunction id(i) {\n  return i;\n}\n\n/**\n * Returns lut_range_max minus one minus i.\n *\n * @param {number} i The input index.\n * @returns {number} The lut value.\n */\nfunction invId(i) {\n  return (lut_range_max - 1) - i;\n}\n\n/**\n * Colour map: red, green and blue components\n *   to associate with intensity values.\n */\nexport class ColourMap {\n  /**\n   * Red component: 256 values in the [0, 255] range.\n   *\n   * @type {number[]}\n   */\n  red;\n  /**\n   * Green component: 256 values in the [0, 255] range.\n   *\n   * @type {number[]}\n   */\n  green;\n  /**\n   * Blue component: 256 values in the [0, 255] range.\n   *\n   * @type {number[]}\n   */\n  blue;\n\n  /**\n   * @param {number[]} red Red component.\n   * @param {number[]} green Green component.\n   * @param {number[]} blue Blue component.\n   */\n  constructor(red, green, blue) {\n    this.red = red;\n    this.green = green;\n    this.blue = blue;\n  }\n}\n\n/**\n * List of available lookup tables (lut).\n *\n * @type {Object<string, ColourMap>}\n */\nexport const luts = {\n  // plain\n  plain: {\n    red: buildLut(id),\n    green: buildLut(id),\n    blue: buildLut(id)\n  },\n\n  // inverse plain\n  invPlain: {\n    red: buildLut(invId),\n    green: buildLut(invId),\n    blue: buildLut(invId)\n  },\n\n  // rainbow\n  /* eslint-disable @stylistic/js/max-len */\n  rainbow: {\n    blue: [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, 252, 255, 247, 239, 231, 223, 215, 207, 199, 191, 183, 175, 167, 159, 151, 143, 135, 127, 119, 111, 103, 95, 87, 79, 71, 63, 55, 47, 39, 31, 23, 15, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n    green: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, 240, 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 251, 249, 247, 245, 243, 241, 239, 237, 235, 233, 231, 229, 227, 225, 223, 221, 219, 217, 215, 213, 211, 209, 207, 205, 203, 201, 199, 197, 195, 193, 192, 189, 186, 183, 180, 177, 174, 171, 168, 165, 162, 159, 156, 153, 150, 147, 144, 141, 138, 135, 132, 129, 126, 123, 120, 117, 114, 111, 108, 105, 102, 99, 96, 93, 90, 87, 84, 81, 78, 75, 72, 69, 66, 63, 60, 57, 54, 51, 48, 45, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3],\n    red: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 62, 60, 58, 56, 54, 52, 50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]\n  },\n  /* eslint-enable @stylistic/js/max-len */\n\n  // hot\n  hot: {\n    red: buildLut(toMaxFirstThird),\n    green: buildLut(toMaxSecondThird),\n    blue: buildLut(toMaxThirdThird)\n  },\n\n  // hot iron\n  /* eslint-disable @stylistic/js/max-len */\n  hot_iron: {\n    red: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],\n    green: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 255],\n    blue: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 252, 255]\n  },\n  /* eslint-enable @stylistic/js/max-len */\n\n  // pet\n  /* eslint-disable @stylistic/js/max-len */\n  pet: {\n    red: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],\n    green: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 128, 126, 124, 122, 120, 118, 116, 114, 112, 110, 108, 106, 104, 102, 100, 98, 96, 94, 92, 90, 88, 86, 84, 82, 80, 78, 76, 74, 72, 70, 68, 66, 64, 63, 61, 59, 57, 55, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 255],\n    blue: [0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 252, 248, 244, 240, 236, 232, 228, 224, 220, 216, 212, 208, 204, 200, 196, 192, 188, 184, 180, 176, 172, 168, 164, 160, 156, 152, 148, 144, 140, 136, 132, 128, 124, 120, 116, 112, 108, 104, 100, 96, 92, 88, 84, 80, 76, 72, 68, 64, 60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 255]\n  },\n  /* eslint-enable @stylistic/js/max-len */\n\n  // hot metal blue\n  /* eslint-disable @stylistic/js/max-len */\n  hot_metal_blue: {\n    red: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 9, 12, 15, 18, 21, 24, 26, 29, 32, 35, 38, 41, 44, 47, 50, 52, 55, 57, 59, 62, 64, 66, 69, 71, 74, 76, 78, 81, 83, 85, 88, 90, 93, 96, 99, 102, 105, 108, 111, 114, 116, 119, 122, 125, 128, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, 166, 169, 172, 175, 178, 181, 184, 187, 190, 194, 198, 201, 205, 209, 213, 217, 221, 224, 228, 232, 236, 240, 244, 247, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],\n    green: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 6, 8, 9, 11, 13, 15, 17, 19, 21, 23, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41, 43, 45, 47, 49, 51, 53, 55, 56, 58, 60, 62, 64, 66, 68, 70, 72, 73, 75, 77, 79, 81, 83, 85, 87, 88, 90, 92, 94, 96, 98, 100, 102, 104, 105, 107, 109, 111, 113, 115, 117, 119, 120, 122, 124, 126, 128, 130, 132, 134, 136, 137, 139, 141, 143, 145, 147, 149, 151, 152, 154, 156, 158, 160, 162, 164, 166, 168, 169, 171, 173, 175, 177, 179, 181, 183, 184, 186, 188, 190, 192, 194, 196, 198, 200, 201, 203, 205, 207, 209, 211, 213, 215, 216, 218, 220, 222, 224, 226, 228, 229, 231, 233, 235, 237, 239, 240, 242, 244, 246, 248, 250, 251, 253, 255],\n    blue: [0, 2, 4, 6, 8, 10, 12, 14, 16, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 184, 186, 188, 190, 192, 194, 196, 198, 200, 197, 194, 191, 188, 185, 182, 179, 176, 174, 171, 168, 165, 162, 159, 156, 153, 150, 144, 138, 132, 126, 121, 115, 109, 103, 97, 91, 85, 79, 74, 68, 62, 56, 50, 47, 44, 41, 38, 35, 32, 29, 26, 24, 21, 18, 15, 12, 9, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 9, 12, 15, 18, 21, 24, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 76, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 126, 129, 132, 135, 138, 141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 176, 179, 182, 185, 188, 191, 194, 197, 200, 203, 206, 210, 213, 216, 219, 223, 226, 229, 232, 236, 239, 242, 245, 249, 252, 255]\n  },\n  /* eslint-enable @stylistic/js/max-len */\n\n  // pet 20 step\n  /* eslint-disable @stylistic/js/max-len */\n  pet_20step: {\n    red: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],\n    green: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],\n    blue: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]\n  }\n  /* eslint-enable @stylistic/js/max-len */\n};\n","// example implementation: dcmtk/dcmiod/libsrc/cielabutil.cc\n// https://github.com/DCMTK/dcmtk/blob/DCMTK-3.6.6/dcmiod/libsrc/cielabutil.cc\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Scalar3D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * RGB colour class.\n */\nexport class RGB {\n  /**\n   * Red component.\n   *\n   * @type {number}\n   */\n  r;\n  /**\n   * Green component.\n   *\n   * @type {number}\n   */\n  g;\n  /**\n   * Blue component.\n   *\n   * @type {number}\n   */\n  b;\n  /**\n   * @param {number} r Red component.\n   * @param {number} g Green component.\n   * @param {number} b Blue component.\n   */\n  constructor(r, g, b) {\n    this.r = r;\n    this.g = g;\n    this.b = b;\n  }\n}\n\n/**\n * Check if two rgb objects are equal.\n *\n * @param {RGB} c1 The first colour.\n * @param {RGB} c2 The second colour.\n * @returns {boolean} True if both colour are equal.\n */\nexport function isEqualRgb(c1, c2) {\n  return c1 !== null &&\n    c2 !== null &&\n    typeof c1 !== 'undefined' &&\n    typeof c2 !== 'undefined' &&\n    c1.r === c2.r &&\n    c1.g === c2.g &&\n    c1.b === c2.b;\n}\n\n/**\n * Convert YBR to RGB.\n *\n * Ref:\n * - {@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2},\n * - {@link https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion}.\n *\n * @param {number} y The Y component.\n * @param {number} cb The Cb component.\n * @param {number} cr The Cr component.\n * @returns {RGB} RGB equivalent as {r,g,b}.\n */\nexport function ybrToRgb(y, cb, cr) {\n  return {\n    r: y + 1.402 * (cr - 128),\n    g: y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128),\n    b: y + 1.772 * (cb - 128)\n  };\n}\n\n/**\n * Convert a hex color into RGB.\n *\n * @param {string} hexStr The hex color as '#ab01ef'.\n * @returns {RGB} The RGB values as {r,g,b}.\n */\nexport function hexToRgb(hexStr) {\n  return {\n    r: parseInt(hexStr.substring(1, 3), 16),\n    g: parseInt(hexStr.substring(3, 5), 16),\n    b: parseInt(hexStr.substring(5, 7), 16)\n  };\n}\n\n/**\n * Convert RGB to its hex equivalent.\n *\n * @param {RGB} rgb The RGB object as {r,g,b}.\n * @returns {string} A string representing the hex color as '#ab01ef'.\n */\nexport function rgbToHex(rgb) {\n  return '#' +\n    ((1 << 24) + (rgb.r << 16) + (rgb.g << 8) + rgb.b).toString(16).slice(1);\n}\n\n/**\n * Get the brightness of a RGB colour: calculates\n * the luma (Y) of the YIQ colour space.\n *\n * Ref: {@link https://en.wikipedia.org/wiki/YIQ#From_RGB_to_YIQ}.\n *\n * @param {RGB} rgb RGB triplet.\n * @returns {number} The brightness ([0,1]).\n */\nexport function getBrightness(rgb) {\n  // 0.001172549 = 0.299 / 255\n  // 0.002301961 = 0.587 / 255\n  // 0.000447059 = 0.114 / 255\n  return rgb.r * 0.001172549 +\n    rgb.g * 0.002301961 +\n    rgb.b * 0.000447059;\n}\n\n/**\n * Check if a colour given in hexadecimal format is dark.\n *\n * @param {string} hexColour The colour (as '#ab01ef').\n * @returns {boolean} True if the colour is dark (brightness < 0.5).\n */\nexport function isDarkColour(hexColour) {\n  return getBrightness(hexToRgb(hexColour)) < 0.5;\n}\n\n/**\n * Get the shadow colour of an input colour.\n *\n * @param {string} hexColour The colour (as '#ab01ef').\n * @returns {string} The shadow colour (white or black).\n */\nexport function getShadowColour(hexColour) {\n  return isDarkColour(hexColour) ? '#fff' : '#000';\n}\n\n/**\n * Unsigned int CIE LAB value ([0, 65535]) to CIE LAB value\n *   (L: [0, 100], a: [-128, 127], b: [-128, 127]).\n *\n * @param {object} triplet CIE LAB triplet as {l,a,b} with unsigned range.\n * @returns {object} CIE LAB triplet as {l,a,b} with CIE LAB range.\n */\nexport function uintLabToLab(triplet) {\n  // 0.001525902 = 100 / 65535\n  // 0.003891051 = 255 / 65535\n  return {\n    l: 0.001525902 * triplet.l,\n    a: 0.003891051 * triplet.a - 128,\n    b: 0.003891051 * triplet.b - 128,\n  };\n}\n\n/**\n * CIE LAB value (L: [0, 100], a: [-128, 127], b: [-128, 127]) to\n *   unsigned int CIE LAB ([0, 65535]).\n *\n * @param {object} triplet CIE XYZ triplet as {l,a,b} with CIE LAB range.\n * @returns {object} CIE LAB triplet as {l,a,b} with unsigned range.\n */\nexport function labToUintLab(triplet) {\n  // 655.35 = 65535 / 100\n  // aUint = (a + 128) * 65535 / 255\n  // 257 = 65535 / 255\n  // 32896 = 257 * 128\n  return {\n    l: 655.35 * triplet.l,\n    a: 257 * triplet.a + 32896,\n    b: 257 * triplet.b + 32896,\n  };\n}\n\n/**\n * CIE Standard Illuminant D65, standard 2° observer.\n *\n * Ref: {@link https://en.wikipedia.org/wiki/Illuminant_D65}.\n */\nconst d65 = {\n  x: 95.0489,\n  y: 100,\n  z: 108.884\n};\n\n/**\n * Convert CIE LAB to CIE XYZ (standard illuminant D65, 2degree 1931).\n *\n * Ref: {@link https://en.wikipedia.org/wiki/CIELAB_color_space#From_CIELAB_to_CIEXYZ}.\n *\n * @param {object} triplet CIE LAB triplet as {l,a,b}.\n * @returns {Scalar3D} CIE XYZ triplet as {x,y,z}.\n */\nexport function cielabToCiexyz(triplet) {\n  /**\n   * Apply the inverse lab function.\n   *\n   * @param {number} x The input value.\n   * @returns {number} The result.\n   */\n  function invLabFunc(x) {\n    let res = null;\n    // delta = 6 / 29 = 0.206896552\n    if (x > 0.206896552) {\n      res = Math.pow(x, 3);\n    } else {\n      // 0.128418549 = 3 * delta^2\n      // 0.017712903 = 3 * delta^2 * (4 / 29)\n      res = 0.128418549 * x - 0.017712903;\n    }\n    return res;\n  }\n\n  const illuminant = d65;\n  const l0 = (triplet.l + 16) / 116;\n\n  return {\n    x: illuminant.x * invLabFunc(l0 + triplet.a / 500),\n    y: illuminant.y * invLabFunc(l0),\n    z: illuminant.z * invLabFunc(l0 - triplet.b / 200)\n  };\n}\n\n/**\n * Convert CIE XYZ to CIE LAB (standard illuminant D65, 2degree 1931).\n *\n * Ref: {@link https://en.wikipedia.org/wiki/CIELAB_color_space#From_CIEXYZ_to_CIELAB}.\n *\n * @param {Scalar3D} triplet CIE XYZ triplet as {x,y,z}.\n * @returns {object} CIE LAB triplet as {l,a,b}.\n */\nexport function ciexyzToCielab(triplet) {\n  /**\n   * Apply the lab function.\n   *\n   * @param {number} x The input value.\n   * @returns {number} The result.\n   */\n  function labFunc(x) {\n    let res = null;\n    // delta = 6 / 29 = 0.206896552\n    // delta^3 = 0.008856452\n    if (x > 0.008856452) {\n      res = Math.pow(x, 0.333333333);\n    } else {\n      // 7.787037037 = 1 / 3 * delta^2\n      // 0.137931034 = 4 / 29\n      res = 7.787037037 * x + 0.137931034;\n    }\n    return res;\n  }\n\n  const illuminant = d65;\n  const fy = labFunc(triplet.y / illuminant.y);\n\n  return {\n    l: 116 * fy - 16,\n    a: 500 * (labFunc(triplet.x / illuminant.x) - fy),\n    b: 200 * (fy - labFunc(triplet.z / illuminant.z))\n  };\n}\n\n/**\n * Convert CIE XYZ to sRGB.\n *\n * Ref: {@link https://en.wikipedia.org/wiki/SRGB#From_CIE_XYZ_to_sRGB}.\n *\n * @param {Scalar3D} triplet CIE XYZ triplet as {x,y,z}.\n * @returns {RGB} 'sRGB' triplet as {r,g,b}.\n */\nexport function ciexyzToSrgb(triplet) {\n  /**\n   * Apply the gamma function.\n   *\n   * @param {number} x The input value.\n   * @returns {number} The result.\n   */\n  function gammaFunc(x) {\n    let res = null;\n    if (x <= 0.0031308) {\n      res = 12.92 * x;\n    } else {\n      // 0.416666667 = 1 / 2.4\n      res = 1.055 * Math.pow(x, 0.416666667) - 0.055;\n    }\n    // clip [0,1]\n    return Math.min(1, Math.max(0, res));\n  }\n\n  const x = triplet.x / 100;\n  const y = triplet.y / 100;\n  const z = triplet.z / 100;\n\n  return {\n    r: Math.round(255 * gammaFunc(3.2406 * x - 1.5372 * y - 0.4986 * z)),\n    g: Math.round(255 * gammaFunc(-0.9689 * x + 1.8758 * y + 0.0415 * z)),\n    b: Math.round(255 * gammaFunc(0.0557 * x - 0.2040 * y + 1.0570 * z))\n  };\n}\n\n/**\n * Convert sRGB to CIE XYZ.\n *\n * Ref: {@link https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ}.\n *\n * @param {RGB} triplet 'sRGB' triplet as {r,g,b}.\n * @returns {Scalar3D} CIE XYZ triplet as {x,y,z}.\n */\nexport function srgbToCiexyz(triplet) {\n  /**\n   * Apply the inverse gamma function.\n   *\n   * @param {number} x The input value.\n   * @returns {number} The result.\n   */\n  function invGammaFunc(x) {\n    let res = null;\n    if (x <= 0.04045) {\n      res = x / 12.92;\n    } else {\n      res = Math.pow((x + 0.055) / 1.055, 2.4);\n    }\n    return res;\n  }\n\n  const rl = invGammaFunc(triplet.r / 255);\n  const gl = invGammaFunc(triplet.g / 255);\n  const bl = invGammaFunc(triplet.b / 255);\n\n  return {\n    x: 100 * (0.4124 * rl + 0.3576 * gl + 0.1805 * bl),\n    y: 100 * (0.2126 * rl + 0.7152 * gl + 0.0722 * bl),\n    z: 100 * (0.0193 * rl + 0.1192 * gl + 0.9505 * bl)\n  };\n}\n\n/**\n * Convert CIE LAB to sRGB (standard illuminant D65).\n *\n * @param {object} triplet CIE LAB triplet as {l,a,b}.\n * @returns {RGB} 'sRGB' triplet as {r,g,b}.\n */\nexport function cielabToSrgb(triplet) {\n  return ciexyzToSrgb(cielabToCiexyz(triplet));\n}\n\n/**\n * Convert sRGB to CIE LAB (standard illuminant D65).\n *\n * @param {RGB} triplet 'sRGB' triplet as {r,g,b}.\n * @returns {object} CIE LAB triplet as {l,a,b}.\n */\nexport function srgbToCielab(triplet) {\n  return ciexyzToCielab(srgbToCiexyz(triplet));\n}\n\n/**\n * Get the hex code of a string colour for a colour used in pre dwv v0.17.\n *\n * @param {string} name The name of a colour.\n * @returns {string} The hex representing the colour.\n */\nexport function colourNameToHex(name) {\n  // default colours used in dwv version < 0.17\n  const dict = {\n    Yellow: '#ffff00',\n    Red: '#ff0000',\n    White: '#ffffff',\n    Green: '#008000',\n    Blue: '#0000ff',\n    Lime: '#00ff00',\n    Fuchsia: '#ff00ff',\n    Black: '#000000'\n  };\n  let res = '#ffff00';\n  if (typeof dict[name] !== 'undefined') {\n    res = dict[name];\n  }\n  return res;\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {WindowLevel} from '../image/windowLevel';\n/* eslint-enable no-unused-vars */\n\n/**\n * Overridalbe custom object for client defined items.\n */\nexport const custom = {\n  /**\n   * List of default window level presets. Indexed bu modality\n   * and then by preset name. For example `wlPresets.MR.mediastimun`.\n   * No need to redefine all, just overrides is enough. Defaults\n   * are used if `custom.wlPresets[modality]` is undefined.\n   *\n   * @type {Object.<string, Object.<string, WindowLevel>>}\n   */\n  wlPresets: undefined,\n\n  /**\n   * List of default shape label texts. Indexed by shape name\n   * and then by modality. For example `labelTexts.arrow.MR`.\n   * No need to redefine all, just overrides is enough. Defaults\n   * are used if `custom.labelTexts[shapeName]` is undefined.\n   *\n   * @type {Object.<string, Object.<string, string>>}\n   */\n  labelTexts: undefined,\n\n  /**\n   * Open a dialogue to edit roi data. Defaults to window.prompt.\n   *\n   * @param {Annotation} annotation The roi data.\n   * @param {Function} callback The callback to launch on dialogue exit.\n   */\n  openRoiDialog: undefined,\n\n  /**\n   * Get the time from a list of dicom tags.\n   *\n   * @param {Object<string, DataElement>} elements The DICOM elements.\n   * @returns {number|undefined} The time value if available.\n   */\n  getTagTime: undefined,\n\n  /**\n   * Get the pixel data unit from a list of dicom tags.\n   * Not used for PET data with SUV values.\n   *\n   * @param {Object<string, DataElement>} elements The DICOM elements.\n   * @returns {string|undefined} The unit value if available.\n   */\n  getTagPixelUnit: undefined,\n\n\n};","/**\n * Immutable 3D vector.\n */\nexport class Vector3D {\n\n  /**\n   * X coordinate.\n   *\n   * @type {number}\n   */\n  #x;\n\n  /**\n   * Y coordinate.\n   *\n   * @type {number}\n   */\n  #y;\n\n  /**\n   * Z coordinate.\n   *\n   * @type {number}\n   */\n  #z;\n\n  /**\n   * @param {number} x The X component of the vector.\n   * @param {number} y The Y component of the vector.\n   * @param {number} z The Z component of the vector.\n   */\n  constructor(x, y, z) {\n    this.#x = x;\n    this.#y = y;\n    this.#z = z;\n  }\n\n  /**\n   * Get the X component of the vector.\n   *\n   * @returns {number} The X component of the vector.\n   */\n  getX() {\n    return this.#x;\n  }\n\n  /**\n   * Get the Y component of the vector.\n   *\n   * @returns {number} The Y component of the vector.\n   */\n  getY() {\n    return this.#y;\n  }\n\n  /**\n   * Get the Z component of the vector.\n   *\n   * @returns {number} The Z component of the vector.\n   */\n  getZ() {\n    return this.#z;\n  }\n\n  /**\n   * Check for Vector3D equality.\n   *\n   * @param {Vector3D} rhs The other vector to compare to.\n   * @returns {boolean} True if both vectors are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.#x === rhs.getX() &&\n      this.#y === rhs.getY() &&\n      this.#z === rhs.getZ();\n  }\n\n  /**\n   * Get a string representation of the Vector3D.\n   *\n   * @returns {string} The vector as a string.\n   */\n  toString() {\n    return '(' + this.#x +\n      ', ' + this.#y +\n      ', ' + this.#z + ')';\n  }\n\n  /**\n   * Get the norm of the vector.\n   *\n   * @returns {number} The norm.\n   */\n  norm() {\n    return Math.sqrt(\n      (this.#x * this.#x) +\n      (this.#y * this.#y) +\n      (this.#z * this.#z)\n    );\n  }\n\n  /**\n   * Get the cross product with another Vector3D, ie the\n   * vector that is perpendicular to both a and b.\n   * If both vectors are parallel, the cross product is a zero vector.\n   *\n   * Ref: {@link https://en.wikipedia.org/wiki/Cross_product}.\n   *\n   * @param {Vector3D} vector3D The input vector.\n   * @returns {Vector3D} The result vector.\n   */\n  crossProduct(vector3D) {\n    return new Vector3D(\n      (this.#y * vector3D.getZ()) - (vector3D.getY() * this.#z),\n      (this.#z * vector3D.getX()) - (vector3D.getZ() * this.#x),\n      (this.#x * vector3D.getY()) - (vector3D.getX() * this.#y));\n  }\n\n  /**\n   * Get the dot product with another Vector3D.\n   *\n   * Ref: {@link https://en.wikipedia.org/wiki/Dot_product}.\n   *\n   * @param {Vector3D} vector3D The input vector.\n   * @returns {number} The dot product.\n   */\n  dotProduct(vector3D) {\n    return (this.#x * vector3D.getX()) +\n      (this.#y * vector3D.getY()) +\n      (this.#z * vector3D.getZ());\n  }\n\n  /**\n   * Is this vector codirectional to an input one.\n   *\n   * @param {Vector3D} vector3D The vector to test.\n   * @returns {boolean} True if codirectional, false is opposite.\n   */\n  isCodirectional(vector3D) {\n    // a.dot(b) = ||a|| * ||b|| * cos(theta)\n    // (https://en.wikipedia.org/wiki/Dot_product#Geometric_definition)\n    // -> the sign of the dot product depends on the cosinus of\n    //    the angle between the vectors\n    //   -> >0 => vectors are codirectional\n    //   -> <0 => vectors are opposite\n    return this.dotProduct(vector3D) > 0;\n  }\n\n} // Vector3D class","import {Vector3D} from './vector';\nimport {Point3D} from './point';\nimport {Index} from './index';\nimport {logger} from '../utils/logger';\n\n// Number.EPSILON is difference between 1 and the smallest\n// floating point number greater than 1\n// -> ~2e-16\n// BIG_EPSILON -> ~2e-12\nexport const BIG_EPSILON = Number.EPSILON * 1e4;\n// 'real world', for example when comparing positions\nexport const REAL_WORLD_EPSILON = 1e-4;\n\n/**\n * Check if two numbers are similar.\n *\n * @param {number} a The first number.\n * @param {number} b The second number.\n * @param {number} tol The comparison tolerance,\n *   default to Number.EPSILON.\n * @returns {boolean} True if similar.\n */\nexport function isSimilar(a, b, tol) {\n  if (typeof tol === 'undefined') {\n    tol = Number.EPSILON;\n  }\n  return Math.abs(a - b) < tol;\n}\n\n/**\n * Immutable 3x3 Matrix.\n */\nexport class Matrix33 {\n\n  /**\n   * Matrix values.\n   *\n   * @type {number[]}\n   */\n  #values;\n\n  /**\n   * Matrix inverse, calculated at first ask.\n   *\n   * @type {Matrix33}\n   */\n  #inverse;\n\n  /**\n   * @param {number[]} values Row-major ordered 9 values.\n   */\n  constructor(values) {\n    this.#values = values;\n  }\n\n  /**\n   * Get a value of the matrix.\n   *\n   * @param {number} row The row at wich to get the value.\n   * @param {number} col The column at wich to get the value.\n   * @returns {number|undefined} The value at the position.\n   */\n  get(row, col) {\n    return this.#values[row * 3 + col];\n  }\n\n  /**\n   * Get the inverse of this matrix.\n   *\n   * @returns {Matrix33|undefined} The inverse matrix or undefined\n   *   if the determinant is zero.\n   */\n  getInverse() {\n    if (typeof this.#inverse === 'undefined') {\n      this.#inverse = getMatrixInverse(this);\n    }\n    return this.#inverse;\n  }\n\n  /**\n   * Check for Matrix33 equality.\n   *\n   * @param {Matrix33} rhs The other matrix to compare to.\n   * @param {number} [p] A numeric expression for the precision to use in check\n   *   (ex: 0.001). Defaults to Number.EPSILON if not provided.\n   * @returns {boolean} True if both matrices are equal.\n   */\n  equals(rhs, p) {\n    // TODO: add type check\n    // check values\n    for (let i = 0; i < 3; ++i) {\n      for (let j = 0; j < 3; ++j) {\n        if (!isSimilar(this.get(i, j), rhs.get(i, j), p)) {\n          return false;\n        }\n      }\n    }\n    return true;\n  }\n\n  /**\n   * Get a string representation of the Matrix33.\n   *\n   * @returns {string} The matrix as a string.\n   */\n  toString() {\n    let str = '[';\n    for (let i = 0; i < 3; ++i) {\n      if (i !== 0) {\n        str += ', \\n ';\n      }\n      for (let j = 0; j < 3; ++j) {\n        if (j !== 0) {\n          str += ', ';\n        }\n        str += this.get(i, j);\n      }\n    }\n    str += ']';\n    return str;\n  }\n\n  /**\n   * Multiply this matrix by another.\n   *\n   * @param {Matrix33} rhs The matrix to multiply by.\n   * @returns {Matrix33} The product matrix.\n   */\n  multiply(rhs) {\n    const values = [];\n    for (let i = 0; i < 3; ++i) {\n      for (let j = 0; j < 3; ++j) {\n        let tmp = 0;\n        for (let k = 0; k < 3; ++k) {\n          tmp += this.get(i, k) * rhs.get(k, j);\n        }\n        values.push(tmp);\n      }\n    }\n    return new Matrix33(values);\n  }\n\n  /**\n   * Get the absolute value of this matrix.\n   *\n   * @returns {Matrix33} The result matrix.\n   */\n  getAbs() {\n    const values = [];\n    for (let i = 0; i < 3; ++i) {\n      for (let j = 0; j < 3; ++j) {\n        values.push(Math.abs(this.get(i, j)));\n      }\n    }\n    return new Matrix33(values);\n  }\n\n  /**\n   * Multiply this matrix by a 3D array.\n   *\n   * @param {number[]} array3D The input 3D array.\n   * @returns {number[]} The result 3D array.\n   */\n  multiplyArray3D(array3D) {\n    if (array3D.length !== 3) {\n      throw new Error('Cannot multiply 3x3 matrix with non 3D array: ' +\n        array3D.length);\n    }\n    const values = [];\n    for (let i = 0; i < 3; ++i) {\n      let tmp = 0;\n      for (let j = 0; j < 3; ++j) {\n        tmp += this.get(i, j) * array3D[j];\n      }\n      values.push(tmp);\n    }\n    return values;\n  }\n\n  /**\n   * Multiply this matrix by a 3D vector.\n   *\n   * @param {Vector3D} vector3D The input 3D vector.\n   * @returns {Vector3D} The result 3D vector.\n   */\n  multiplyVector3D(vector3D) {\n    const array3D = this.multiplyArray3D(\n      [vector3D.getX(), vector3D.getY(), vector3D.getZ()]\n    );\n    return new Vector3D(array3D[0], array3D[1], array3D[2]);\n  }\n\n  /**\n   * Multiply this matrix by a 3D point.\n   *\n   * @param {Point3D} point3D The input 3D point.\n   * @returns {Point3D} The result 3D point.\n   */\n  multiplyPoint3D(point3D) {\n    const array3D = this.multiplyArray3D(\n      [point3D.getX(), point3D.getY(), point3D.getZ()]\n    );\n    return new Point3D(array3D[0], array3D[1], array3D[2]);\n  }\n\n  /**\n   * Multiply this matrix by a 3D index.\n   *\n   * @param {Index} index3D The input 3D index.\n   * @returns {Index} The result 3D index.\n   */\n  multiplyIndex3D(index3D) {\n    const array3D = this.multiplyArray3D(index3D.getValues());\n    return new Index(array3D);\n  }\n\n  /**\n   * Get the index of the maximum in absolute value of a row.\n   *\n   * @param {number} row The row to get the maximum from.\n   * @returns {object} The {value,index} of the maximum.\n   */\n  getRowAbsMax(row) {\n    const values = [\n      Math.abs(this.get(row, 0)),\n      Math.abs(this.get(row, 1)),\n      Math.abs(this.get(row, 2))\n    ];\n    const absMax = Math.max.apply(null, values);\n    const index = values.indexOf(absMax);\n    return {\n      value: this.get(row, index),\n      index: index\n    };\n  }\n\n  /**\n   * Get the index of the maximum in absolute value of a column.\n   *\n   * @param {number} col The column to get the maximum from.\n   * @returns {object} The {value,index} of the maximum.\n   */\n  getColAbsMax(col) {\n    const values = [\n      Math.abs(this.get(0, col)),\n      Math.abs(this.get(1, col)),\n      Math.abs(this.get(2, col))\n    ];\n    const absMax = Math.max.apply(null, values);\n    const index = values.indexOf(absMax);\n    return {\n      value: this.get(index, col),\n      index: index\n    };\n  }\n\n  /**\n   * Get this matrix with only zero and +/- ones instead of the maximum.\n   *\n   * @returns {Matrix33} The simplified matrix.\n   */\n  asOneAndZeros() {\n    const res = [];\n    for (let j = 0; j < 3; ++j) {\n      const max = this.getRowAbsMax(j);\n      const sign = max.value > 0 ? 1 : -1;\n      for (let i = 0; i < 3; ++i) {\n        if (i === max.index) {\n          res.push(1 * sign);\n        } else {\n          res.push(0);\n        }\n      }\n    }\n    return new Matrix33(res);\n  }\n\n  /**\n   * Get the third column direction index of an orientation matrix.\n   *\n   * @returns {number} The index of the absolute maximum of the last column.\n   */\n  getThirdColMajorDirection() {\n    return this.getColAbsMax(2).index;\n  }\n\n} // Matrix33\n\n/**\n * Get the inverse of an input 3*3 matrix.\n *\n * Ref:\n * - {@link https://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_3_%C3%97_3_matrices},\n * - {@link https://github.com/willnode/N-Matrix-Programmer}.\n *\n * @param {Matrix33} m The input matrix.\n * @returns {Matrix33|undefined} The inverse matrix or undefined\n *   if the determinant is zero.\n */\nfunction getMatrixInverse(m) {\n  const m00 = m.get(0, 0);\n  const m01 = m.get(0, 1);\n  const m02 = m.get(0, 2);\n  const m10 = m.get(1, 0);\n  const m11 = m.get(1, 1);\n  const m12 = m.get(1, 2);\n  const m20 = m.get(2, 0);\n  const m21 = m.get(2, 1);\n  const m22 = m.get(2, 2);\n\n  const a1212 = m11 * m22 - m12 * m21;\n  const a2012 = m12 * m20 - m10 * m22;\n  const a0112 = m10 * m21 - m11 * m20;\n\n  let det = m00 * a1212 + m01 * a2012 + m02 * a0112;\n  if (det === 0) {\n    logger.warn('Cannot invert 3*3 matrix with zero determinant.');\n    return undefined;\n  }\n  det = 1 / det;\n\n  const values = [\n    det * a1212,\n    det * (m02 * m21 - m01 * m22),\n    det * (m01 * m12 - m02 * m11),\n    det * a2012,\n    det * (m00 * m22 - m02 * m20),\n    det * (m02 * m10 - m00 * m12),\n    det * a0112,\n    det * (m01 * m20 - m00 * m21),\n    det * (m00 * m11 - m01 * m10)\n  ];\n\n  return new Matrix33(values);\n}\n\n/**\n * Create a 3x3 identity matrix.\n *\n * @returns {Matrix33} The identity matrix.\n */\nexport function getIdentityMat33() {\n  /* eslint-disable @stylistic/js/array-element-newline */\n  return new Matrix33([\n    1, 0, 0,\n    0, 1, 0,\n    0, 0, 1\n  ]);\n  /* eslint-enable @stylistic/js/array-element-newline */\n}\n\n/**\n * Check if a matrix is a 3x3 identity matrix.\n *\n * @param {Matrix33} mat33 The matrix to test.\n * @returns {boolean} True if identity.\n */\nexport function isIdentityMat33(mat33) {\n  return mat33.equals(getIdentityMat33());\n}\n","import {isSimilar} from './matrix';\nimport {Vector3D} from './vector';\n\n/**\n * Immutable 2D point.\n */\nexport class Point2D {\n\n  /**\n   * X position.\n   *\n   * @type {number}\n   */\n  #x;\n\n  /**\n   * Y position.\n   *\n   * @type {number}\n   */\n  #y;\n\n  /**\n   * @param {number} x The X coordinate for the point.\n   * @param {number} y The Y coordinate for the point.\n   */\n  constructor(x, y) {\n    this.#x = x;\n    this.#y = y;\n  }\n\n  /**\n   * Get the X position of the point.\n   *\n   * @returns {number} The X position of the point.\n   */\n  getX() {\n    return this.#x;\n  }\n\n  /**\n   * Get the Y position of the point.\n   *\n   * @returns {number} The Y position of the point.\n   */\n  getY() {\n    return this.#y;\n  }\n\n  /**\n   * Get the values of this point.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return [this.#x, this.#y];\n  }\n\n  /**\n   * Get the centroid of the point, ie itself.\n   *\n   * @returns {Point2D} The centroid point.\n   */\n  getCentroid() {\n    return this;\n  }\n\n  /**\n   * Check for Point2D equality.\n   *\n   * @param {Point2D} rhs The other point to compare to.\n   * @returns {boolean} True if both points are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      typeof rhs !== 'undefined' &&\n      this.#x === rhs.getX() &&\n      this.#y === rhs.getY();\n  }\n\n  /**\n   * Get a string representation of the Point2D.\n   *\n   * @returns {string} The point as a string.\n   */\n  toString() {\n    return '(' + this.#x + ', ' + this.#y + ')';\n  }\n\n  /**\n   * Get the distance to another Point2D.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {number} Ths distance to the input point.\n   */\n  getDistance(point2D) {\n    const dx = this.#x - point2D.getX();\n    const dy = this.#y - point2D.getY();\n    return Math.sqrt(dx * dx + dy * dy);\n  }\n\n} // Point2D class\n\n/**\n * Immutable 3D point.\n */\nexport class Point3D {\n\n  /**\n   * X position.\n   *\n   * @type {number}\n   */\n  #x;\n\n  /**\n   * Y position.\n   *\n   * @type {number}\n   */\n  #y;\n\n  /**\n   * Z position.\n   *\n   * @type {number}\n   */\n  #z;\n\n  /**\n   * @param {number} x The X coordinate for the point.\n   * @param {number} y The Y coordinate for the point.\n   * @param {number} z The Z coordinate for the point.\n   */\n  constructor(x, y, z) {\n    this.#x = x;\n    this.#y = y;\n    this.#z = z;\n  }\n\n  /**\n   * Get the X position of the point.\n   *\n   * @returns {number} The X position of the point.\n   */\n  getX() {\n    return this.#x;\n  }\n\n  /**\n   * Get the Y position of the point.\n   *\n   * @returns {number} The Y position of the point.\n   */\n  getY() {\n    return this.#y;\n  }\n\n  /**\n   * Get the Z position of the point.\n   *\n   * @returns {number} The Z position of the point.\n   */\n  getZ() {\n    return this.#z;\n  }\n\n  /**\n   * Get the values of this point.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return [this.#x, this.#y, this.#z];\n  }\n\n  /**\n   * Check for Point3D equality.\n   *\n   * @param {Point3D} rhs The other point to compare to.\n   * @returns {boolean} True if both points are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.#x === rhs.getX() &&\n      this.#y === rhs.getY() &&\n      this.#z === rhs.getZ();\n  }\n\n  /**\n   * Check for Point3D similarity.\n   *\n   * @param {Point3D} rhs The other point to compare to.\n   * @param {number} tol Optional comparison tolerance,\n   *   default to Number.EPSILON.\n   * @returns {boolean} True if both points are equal.\n   */\n  isSimilar(rhs, tol) {\n    return rhs !== null &&\n      isSimilar(this.#x, rhs.getX(), tol) &&\n      isSimilar(this.#y, rhs.getY(), tol) &&\n      isSimilar(this.#z, rhs.getZ(), tol);\n  }\n\n  /**\n   * Get a string representation of the Point3D.\n   *\n   * @returns {string} The point as a string.\n   */\n  toString() {\n    return '(' + this.#x +\n      ', ' + this.#y +\n      ', ' + this.#z + ')';\n  }\n\n  /**\n   * Get the distance to another Point3D.\n   *\n   * @param {Point3D} point3D The input point.\n   * @returns {number} Ths distance to the input point.\n   */\n  getDistance(point3D) {\n    return Math.sqrt(this.#getSquaredDistance(point3D));\n  }\n\n  /**\n   * Get the square of the distance between this and\n   * an input point. Used for sorting.\n   *\n   * @param {Point3D} point3D The input point.\n   * @returns {number} The square of the distance.\n   */\n  #getSquaredDistance(point3D) {\n    const dx = this.#x - point3D.getX();\n    const dy = this.#y - point3D.getY();\n    const dz = this.#z - point3D.getZ();\n    return dx * dx + dy * dy + dz * dz;\n  }\n\n  /**\n   * Get the closest point to this in a Point3D list.\n   *\n   * @param {Point3D[]} pointList The list to check.\n   * @returns {number} The index of the closest point in the input list.\n   */\n  getClosest(pointList) {\n    let minIndex = 0;\n    // the order between squared distances and distances is the same\n    let minDist = this.#getSquaredDistance(pointList[minIndex]);\n    for (let i = 0; i < pointList.length; ++i) {\n      const dist = this.#getSquaredDistance(pointList[i]);\n      if (dist < minDist) {\n        minIndex = i;\n        minDist = dist;\n      }\n    }\n    return minIndex;\n  }\n\n  /**\n   * Get the difference to another Point3D.\n   *\n   * @param {Point3D} point3D The input point.\n   * @returns {Vector3D} The 3D vector from the input point to this one.\n   */\n  minus(point3D) {\n    return new Vector3D(\n      (this.#x - point3D.getX()),\n      (this.#y - point3D.getY()),\n      (this.#z - point3D.getZ()));\n  }\n\n} // Point3D class\n\n/**\n * Get an array find callback for an equal input point.\n *\n * @param {Point3D} point The point to compare to.\n * @returns {Function} A function that compares, using `equals`,\n *   its input point to the one given as input to this function.\n */\nexport function getEqualPoint3DFunction(point) {\n  return function (element) {\n    return element.equals(point);\n  };\n}\n\n/**\n * Immutable point.\n * Warning: the input array is NOT cloned, modifying it will\n *  modify the point values.\n */\nexport class Point {\n\n  /**\n   * Point values.\n   *\n   * @type {number[]}\n   */\n  #values;\n\n  /**\n   * @param {number[]} values The point values.\n   */\n  constructor(values) {\n    if (!values || typeof values === 'undefined') {\n      throw new Error('Cannot create point with no values.');\n    }\n    if (values.length === 0) {\n      throw new Error('Cannot create point with empty values.');\n    }\n    const valueCheck = function (val) {\n      return !isNaN(val);\n    };\n    if (!values.every(valueCheck)) {\n      throw new Error('Cannot create point with non number values.');\n    }\n    this.#values = values;\n  }\n\n  /**\n   * Get the point value at the given array index.\n   *\n   * @param {number} i The index to get.\n   * @returns {number} The value.\n   */\n  get(i) {\n    return this.#values[i];\n  }\n\n  /**\n   * Get the length of the point.\n   *\n   * @returns {number} The length.\n   */\n  length() {\n    return this.#values.length;\n  }\n\n  /**\n   * Get a string representation of the point.\n   *\n   * @returns {string} The point as a string.\n   */\n  toString() {\n    return '(' + this.#values.toString() + ')';\n  }\n\n  /**\n   * Get the values of this point.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return this.#values.slice();\n  }\n\n  /**\n   * Check if the input point can be compared to this one.\n   *\n   * @param {Point} rhs The point to compare to.\n   * @returns {boolean} True if both points are comparable.\n   */\n  canCompare(rhs) {\n    // check input\n    if (!rhs) {\n      return false;\n    }\n    // check length\n    if (this.length() !== rhs.length()) {\n      return false;\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Check for Point equality.\n   *\n   * @param {Point} rhs The point to compare to.\n   * @returns {boolean} True if both points are equal.\n   */\n  equals(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return false;\n    }\n    // check values\n    for (let i = 0, leni = this.length(); i < leni; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        return false;\n      }\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Compare points and return different dimensions.\n   *\n   * @param {Point} rhs The point to compare to.\n   * @returns {number[]} The list of different dimensions.\n   */\n  compare(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return null;\n    }\n    // check values\n    const diffDims = [];\n    for (let i = 0, leni = this.length(); i < leni; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        diffDims.push(i);\n      }\n    }\n    return diffDims;\n  }\n\n  /**\n   * Get the 3D part of this point.\n   *\n   * @returns {Point3D} The Point3D.\n   */\n  get3D() {\n    return new Point3D(this.get(0), this.get(1), this.get(2));\n  }\n\n  /**\n   * Add another point to this one.\n   *\n   * @param {Point} rhs The point to add.\n   * @returns {Point} The point representing the sum of both points.\n   */\n  add(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return null;\n    }\n    const values = [];\n    const values0 = this.getValues();\n    const values1 = rhs.getValues();\n    for (let i = 0; i < values0.length; ++i) {\n      values.push(values0[i] + values1[i]);\n    }\n    return new Point(values);\n  }\n\n  /**\n   * Merge this point with a Point3D to create a new point.\n   *\n   * @param {Point3D} rhs The Point3D to merge with.\n   * @returns {Point} The merge result.\n   */\n  mergeWith3D(rhs) {\n    const values = this.getValues();\n    values[0] = rhs.getX();\n    values[1] = rhs.getY();\n    values[2] = rhs.getZ();\n    return new Point(values);\n  }\n\n} // Point class\n","/**\n * Namespace for translation function\n *   (in a namespace to allow for override from client).\n */\nexport const i18n = {\n\n  /**\n   * Get the translated text.\n   *\n   * @param {string} key The key to the text entry.\n   * @returns {string|undefined} The translated text.\n   */\n  t(key) {\n    let res = key;\n    const props = key.split('.');\n    // defaut units look like 'unit.cm2'\n    if (props.length === 2 &&\n      props[0] === 'unit') {\n      const units = {\n        mm: 'mm',\n        cm2: 'cm²',\n        degree: '°'\n      };\n      res = units[props[1]];\n    }\n    return res;\n  }\n\n};\n","\nimport {i18n} from './i18n';\n\n/**\n * Capitalise the first letter of a string.\n *\n * @param {string} string The string to capitalise the first letter.\n * @returns {string} The new string.\n */\nexport function capitaliseFirstLetter(string) {\n  let res = string;\n  if (string) {\n    res = string.charAt(0).toUpperCase() + string.slice(1);\n  }\n  return res;\n}\n\n/**\n * Check if a string starts with the input element.\n *\n * @param {string} str The input string.\n * @param {string} search The searched start.\n * @param {number} [rawPos] The position in this string at which to begin\n *  searching for searchString. Defaults to 0.\n * @returns {boolean} True if the input string starts with the searched string.\n */\nexport function startsWith(str, search, rawPos) {\n  if (typeof str === 'undefined' || str === null ||\n    typeof search === 'undefined' || search === null) {\n    return false;\n  }\n  const pos = rawPos > 0 ? rawPos | 0 : 0;\n  return str.substring(pos, pos + search.length) === search;\n}\n\n/**\n * Check if a string ends with the input element.\n *\n * @param {string} str The input string.\n * @param {string} search The searched ending.\n * @returns {boolean} True if the input string ends with the searched string.\n */\nexport function endsWith(str, search) {\n  if (typeof str === 'undefined' || str === null ||\n    typeof search === 'undefined' || search === null) {\n    return false;\n  }\n  return str.substring(str.length - search.length) === search;\n}\n\n/**\n * Split key/value string: `key0=val00&key0=val01&key1=val10\n *   will return `{key0 : [val00, val01], key1 : val1}`.\n *\n * @param {string} inputStr The string to split.\n * @returns {object} The split string.\n */\nexport function splitKeyValueString(inputStr) {\n  // result\n  const result = {};\n  // check input string\n  if (inputStr) {\n    // split key/value pairs\n    const pairs = inputStr.split('&');\n    for (let i = 0; i < pairs.length; ++i) {\n      const pair = pairs[i].split('=');\n      // if the key does not exist, create it\n      if (!result[pair[0]]) {\n        result[pair[0]] = pair[1];\n      } else {\n        // make it an array\n        if (!(result[pair[0]] instanceof Array)) {\n          result[pair[0]] = [result[pair[0]]];\n        }\n        result[pair[0]].push(pair[1]);\n      }\n    }\n  }\n  return result;\n}\n\n/**\n * Get flags from an input string. Flags are words surrounded with curly\n * braces.\n *\n * @param {string} inputStr The input string.\n * @returns {string[]} An array of found flags.\n */\nexport function getFlags(inputStr) {\n  const flags = [];\n  // check input string\n  if (inputStr === null || typeof inputStr === 'undefined') {\n    return flags;\n  }\n\n  // word surrounded by curly braces\n  const regex = /{(\\w+)}/g;\n\n  let match = regex.exec(inputStr);\n  while (match) {\n    flags.push(match[1]); // first matching group\n    match = regex.exec(inputStr);\n  }\n  return flags;\n}\n\n/**\n * Replace flags in a input string. Flags are keywords surrounded with curly\n * braces.\n *\n * @param {string} inputStr The input string.\n * @param {object} values A object of {value, unit}.\n * @returns {string} The result string.\n */\nexport function replaceFlags(inputStr, values) {\n  let res = '';\n  // check input string\n  if (inputStr === null || typeof inputStr === 'undefined') {\n    return res;\n  }\n  res = inputStr;\n  // check values\n  if (values === null || typeof values === 'undefined') {\n    return res;\n  }\n\n  // loop through flags\n  const keys = getFlags(inputStr);\n  for (let i = 0; i < keys.length; ++i) {\n    const valueObj = values[keys[i]];\n    if (valueObj !== null && typeof valueObj !== 'undefined' &&\n      valueObj.value !== null && typeof valueObj.value !== 'undefined') {\n      // value string\n      let valueStr = valueObj.value.toPrecision(4);\n      // add unit if available\n      // space or no space? Yes apart from degree...\n      // check: https://en.wikipedia.org/wiki/Space_(punctuation)#Spaces_and_unit_symbols\n      if (valueObj.unit !== null &&\n        typeof valueObj.unit !== 'undefined' &&\n        valueObj.unit.length !== 0) {\n        if (valueObj.unit !== 'unit.degree') {\n          valueStr += ' ';\n        }\n        valueStr += i18n.t(valueObj.unit);\n      }\n      // flag to replace\n      const flag = '{' + keys[i] + '}';\n      // replace\n      res = res.replace(flag, valueStr);\n    }\n  }\n  // return\n  return res;\n}\n\n/**\n * Get the root of an input path.\n * Splits using `/` as separator.\n *\n * @param {string} path The input path.\n * @returns {string} The input path without its last part.\n */\nexport function getRootPath(path) {\n  return path.split('/').slice(0, -1).join('/');\n}\n\n/**\n * Get a file extension: anything after the last dot.\n * File name starting with a dot are discarded.\n * Extensions are expected to contain at least one letter.\n *\n * @param {string} filePath The file path containing the file name.\n * @returns {string} The lower case file extension or null for none.\n */\nexport function getFileExtension(filePath) {\n  let ext = null;\n  if (typeof filePath !== 'undefined' &&\n    filePath !== null &&\n    filePath[0] !== '.') {\n    const pathSplit = filePath.toLowerCase().split('.');\n    if (pathSplit.length !== 1) {\n      ext = pathSplit.pop();\n      // extension should contain at least one letter and no slash\n      const regExp = /[a-z]/;\n      if (!regExp.test(ext) || ext.includes('/')) {\n        ext = null;\n      }\n    }\n  }\n  return ext;\n}\n\n/**\n * Convert a string to a Uint8Array.\n *\n * @param {string} str The string to convert.\n * @returns {Uint8Array} The Uint8Array.\n */\nexport function stringToUint8Array(str) {\n  const arr = new Uint8Array(str.length);\n  for (let i = 0, leni = str.length; i < leni; i++) {\n    arr[i] = str.charCodeAt(i);\n  }\n  return arr;\n}\n\n/**\n * Round a float number to a given precision.\n *\n * Inspired from {@link https://stackoverflow.com/a/49729715/3639892}.\n *\n * Can be a solution to not have trailing zero as when\n *   using toFixed or toPrecision.\n * '+number.toFixed(precision)' does not pass all the tests...\n *\n * @param {number} number The number to round.\n * @param {number} precision The rounding precision.\n * @returns {number} The rounded number.\n */\nexport function precisionRound(number, precision) {\n  const factor = Math.pow(10, precision);\n  const delta = 0.01 / factor; // fixes precisionRound(1.005, 2)\n  return Math.round(number * factor + delta) / factor;\n}\n","import {stringToUint8Array} from './string';\n\n/**\n * Get a string id from array values in the form of: '#0-1_#1-2'.\n *\n * @param {Array} arr The input array.\n * @param {number[]} [dims] Optional list of dimensions to use.\n * @returns {string} The string id.\n */\nexport function toStringId(arr, dims) {\n  // use all dims if not as input\n  if (typeof dims === 'undefined') {\n    dims = [];\n    for (let i = 0; i < arr.length; ++i) {\n      dims.push(i);\n    }\n  }\n  // check dims\n  for (let i = 0; i < dims.length; ++i) {\n    if (dims[i] >= arr.length) {\n      throw new Error('Non valid dimension for toStringId');\n    }\n  }\n  // build string\n  let res = '';\n  for (let i = 0; i < dims.length; ++i) {\n    if (i !== 0) {\n      res += '_';\n    }\n    res += '#' + dims[i] + '-' + arr[dims[i]];\n  }\n  return res;\n}\n\n/**\n * Get an array from an id string in the form of: '#0-1_#1-2'\n * (result of toStringId).\n *\n * @param {string} inputStr The input string.\n * @returns {Array} The corresponding array (minimum size is 3D).\n */\nexport function getArrayFromStringId(inputStr) {\n  // split ids\n  const strIds = inputStr.split('_');\n  // get the size of the index (minimum 3)\n  let numberOfDims = 3;\n  let dim;\n  for (let i = 0; i < strIds.length; ++i) {\n    // expecting dim < 10\n    dim = parseInt(strIds[i].substring(1, 2), 10);\n    // dim is zero based\n    if (dim + 1 > numberOfDims) {\n      numberOfDims = dim + 1;\n    }\n  }\n  // default values\n  const values = new Array(numberOfDims);\n  values.fill(0);\n  // get other values from the input string\n  for (let j = 0; j < strIds.length; ++j) {\n    // expecting dim < 10\n    dim = parseInt(strIds[j].substring(1, 2), 10);\n    const value = parseInt(strIds[j].substring(3), 10);\n    values[dim] = value;\n  }\n\n  return values;\n}\n\n/**\n * Check if the first input array contains all the\n * elements of the second input array.\n *\n * @param {string[]} arr0 The test array.\n * @param {string[]} arr1 The elements to check in the first array.\n * @returns {boolean} True if all the elements of arr1 are included in arr0.\n */\nexport function arrayContains(arr0, arr1) {\n  // check input\n  if (arr0 === null ||\n    arr1 === null ||\n    typeof arr0 === 'undefined' ||\n    typeof arr1 === 'undefined') {\n    return false;\n  }\n  if (arr0.length === 0 ||\n    arr1.length === 0 ||\n    arr1.length > arr0.length) {\n    return false;\n  }\n  // check values\n  for (const itemArr1 of arr1) {\n    if (!arr0.includes(itemArr1)) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * Check for array equality after sorting.\n *\n * @param {Array} arr0 First array.\n * @param {Array} arr1 Second array.\n * @returns {boolean} True if both array are defined and contain same values.\n */\nexport function arraySortEquals(arr0, arr1) {\n  if (arr0 === null ||\n    arr1 === null ||\n    typeof arr0 === 'undefined' ||\n    typeof arr1 === 'undefined') {\n    return false;\n  }\n  const arr0sorted = arr0.slice().sort();\n  const arr1sorted = arr1.slice().sort();\n  return arrayEquals(arr0sorted, arr1sorted);\n}\n\n/**\n * Check for array equality.\n *\n * @param {Array} arr0 First array.\n * @param {Array} arr1 Second array.\n * @returns {boolean} True if both array are defined and contain same values.\n */\nexport function arrayEquals(arr0, arr1) {\n  if (arr0 === null ||\n    arr1 === null ||\n    typeof arr0 === 'undefined' ||\n    typeof arr1 === 'undefined') {\n    return false;\n  }\n  if (arr0.length !== arr1.length) {\n    return false;\n  }\n  return arr0.every(function (element, index) {\n    return element === arr1[index];\n  });\n}\n\n/**\n * Convert a Uint8Array to a string.\n *\n * @param {Uint8Array} arr The array to convert.\n * @returns {string} The array as string.\n */\nexport function uint8ArrayToString(arr) {\n  return String.fromCharCode.apply(String, arr);\n}\n\n/**\n * Array find in a subset of the input array.\n * Equivalent to: `arr.slice(start, end).find(callbackFn)`.\n *\n * @param {Uint8Array} arr The input array to search.\n * @param {Function} callbackFn The find function.\n * @param {number|undefined} start The array start index.\n * @param {number|undefined} [end] The array end index.\n * @returns {number|undefined} The index where the element was found.\n */\nexport function findInArraySubset(arr, callbackFn, start, end) {\n  // check inputs\n  if (typeof start === 'undefined' ||\n    start < 0 ||\n    start >= arr.length\n  ) {\n    start = 0;\n  }\n  if (typeof end === 'undefined' ||\n    end <= start ||\n    end > arr.length) {\n    end = arr.length;\n  }\n  // run\n  for (let i = start; i < end; ++i) {\n    if (callbackFn(arr[i], i, arr)) {\n      return i;\n    }\n  }\n  return undefined;\n}\n\n/**\n * Get a find in array callback.\n *\n * @param {Uint8Array} arr1 The array to find.\n * @returns {Function} The find callback function.\n */\nexport function getFindArrayInArrayCallback(arr1) {\n  return function (element, index, arr0) {\n    for (let i = 0; i < arr1.length; ++i) {\n      if (arr0[index + i] !== arr1[i]) {\n        return false;\n      }\n    }\n    return true;\n  };\n}\n\n/**\n * Extract each element of a multipart ArrayBuffer.\n *\n * Ref: {@link https://en.wikipedia.org/wiki/MIME#Multipart_messages}.\n *\n * @param {ArrayBuffer} arr The multipart array.\n * @returns {Array} The multipart parts as an array of object as\n *   {'Content-Type', ..., data} (depending on header tags).\n */\nexport function parseMultipart(arr) {\n  const u8Array = new Uint8Array(arr);\n\n  const parts = [];\n  // check input\n  if (u8Array.length === 0) {\n    return parts;\n  }\n\n  // \\r\\n\\r\\n\n  const doubleReturnNew = new Uint8Array([0x0d, 0x0a, 0x0d, 0x0a]);\n  const partHeaderEndCb = getFindArrayInArrayCallback(doubleReturnNew);\n\n  // look for boundary in first part header\n  let partHeaderEndIndex = findInArraySubset(\n    u8Array, partHeaderEndCb, 0\n  );\n  if (typeof partHeaderEndIndex === 'undefined') {\n    throw new Error('Can\\'t find the end of the first multipart header');\n  }\n  const firstPartHeader = u8Array.slice(0, partHeaderEndIndex);\n  // switch to string to use split\n  const lines = uint8ArrayToString(firstPartHeader).split('\\r\\n');\n  // boundary should start with '--'\n  let boundaryStr;\n  for (let i = 0; i < lines.length; ++i) {\n    if (lines[i][0] === '-' && lines[i][1] === '-') {\n      boundaryStr = lines[i];\n      break;\n    }\n  }\n  if (typeof boundaryStr === 'undefined') {\n    throw new Error('Can\\'t find the boundary between multi-parts');\n  }\n  const boundary = stringToUint8Array(boundaryStr);\n  const boundaryCb = getFindArrayInArrayCallback(boundary);\n  const boundaryLen = boundaryStr.length;\n\n  // skip mime header\n  let nextBoundaryIndex = findInArraySubset(\n    u8Array, boundaryCb, 0\n  );\n\n  // loop through content\n  while (typeof partHeaderEndIndex !== 'undefined') {\n    const part = {};\n\n    // header\n    const partHeader = u8Array.slice(\n      nextBoundaryIndex + boundaryLen, partHeaderEndIndex);\n    // split into object\n    const partHeaderLines =\n      uint8ArrayToString(partHeader).split('\\r\\n');\n    for (let l = 0; l < partHeaderLines.length; ++l) {\n      const line = partHeaderLines[l];\n      const semiColonIndex = line.indexOf(':');\n      if (semiColonIndex !== -1) {\n        const key = line.substring(0, semiColonIndex).trim();\n        const val = line.substring(semiColonIndex + 1).trim();\n        part[key] = val;\n      }\n    }\n\n    // find next boundary\n    nextBoundaryIndex = findInArraySubset(\n      u8Array, boundaryCb, partHeaderEndIndex\n    );\n    // exit if none\n    if (typeof nextBoundaryIndex === 'undefined') {\n      break;\n    }\n\n    // get part\n    // partHeaderEndIndex plus the size of the '\\r\\n\\r\\n' separator\n    const dataBeginIndex = partHeaderEndIndex + 4;\n    // nextBoundaryIndex minus the previous '\\r\\n'\n    const dataEndIndex = nextBoundaryIndex - 2;\n    if (dataBeginIndex < dataEndIndex) {\n      part.data = u8Array.slice(dataBeginIndex, dataEndIndex).buffer;\n    } else {\n      part.data = new Uint8Array();\n    }\n\n    // store part\n    parts.push(part);\n\n    // find next part header end\n    partHeaderEndIndex = findInArraySubset(\n      u8Array, partHeaderEndCb,\n      nextBoundaryIndex + boundaryLen\n    );\n  }\n\n  return parts;\n}\n\n/**\n * Build a multipart message.\n *\n * Ref:\n * - {@link https://en.wikipedia.org/wiki/MIME#Multipart_messages},\n * - {@link https://hg.orthanc-server.com/orthanc-dicomweb/file/tip/Resources/Samples/JavaScript/stow-rs.js}.\n *\n * @param {Array} parts The message parts as an array of object containing\n *   content headers and messages as the data property (as returned by parse).\n * @param {string} boundary The message boundary.\n * @returns {Uint8Array} The full multipart message.\n */\nexport function buildMultipart(parts, boundary) {\n  const lineBreak = '\\r\\n';\n  // build headers and calculate size\n  let partsSize = 0;\n  const headers = [];\n  for (let i = 0; i < parts.length; ++i) {\n    let headerStr = '';\n    if (i !== 0) {\n      headerStr += lineBreak;\n    }\n    headerStr += '--' + boundary + lineBreak;\n    const partKeys = Object.keys(parts[i]);\n    for (let k = 0; k < partKeys.length; ++k) {\n      const key = partKeys[k];\n      if (key !== 'data') {\n        headerStr += key + ': ' + parts[i][key] + lineBreak;\n      }\n    }\n    headerStr += lineBreak;\n    const header = stringToUint8Array(headerStr);\n    headers.push(header);\n    partsSize += header.byteLength + parts[i].data.byteLength;\n  }\n  // build trailer\n  const trailerStr = lineBreak + '--' + boundary + '--' + lineBreak;\n  const trailer = stringToUint8Array(trailerStr);\n\n  // final buffer\n  const buffer = new Uint8Array(partsSize + trailer.byteLength);\n  let offset = 0;\n  // concatenate parts\n  for (let j = 0; j < parts.length; ++j) {\n    buffer.set(headers[j], offset);\n    offset += headers[j].byteLength;\n    buffer.set(new Uint8Array(parts[j].data), offset);\n    offset += parts[j].data.byteLength;\n  }\n  // end buffer with trailer\n  buffer.set(trailer, offset);\n\n  // return\n  return buffer;\n}\n","/* eslint-disable @stylistic/js/quote-props */\n/* eslint @stylistic/js/max-len:0 */\n\n/**\n * DICOM tag dictionary 2022a.\n * Generated using xml standard conversion from {@link https://github.com/ivmartel/dcmStdToJs} v0.1.0.\n *\n * Conversion changes:\n * - (vr) 'See Note' -> 'NONE',\n * - (vr) 'OB or OW' -> 'ox',\n * - (vr) 'US or SS' -> 'xs',\n * - (vr) 'US or OW' -> 'xx',\n * - (vr) 'US or SS or OW' -> 'xs',\n * - added 'GenericGroupLength' element to each group.\n *\n * Local changes:\n * - tag numbers with 'xx' were replaced with '00', 'xxx' with '001' and\n *  'xxxx' with '0004'.\n *\n * @type {Object<string, Object<string, string[]>>}\n */\nexport const dictionary = {\n  '0000': {\n    '0000': ['UL', '1', 'CommandGroupLength'],\n    '0001': ['UL', '1', 'CommandLengthToEnd'],\n    '0002': ['UI', '1', 'AffectedSOPClassUID'],\n    '0003': ['UI', '1', 'RequestedSOPClassUID'],\n    '0010': ['SH', '1', 'CommandRecognitionCode'],\n    '0100': ['US', '1', 'CommandField'],\n    '0110': ['US', '1', 'MessageID'],\n    '0120': ['US', '1', 'MessageIDBeingRespondedTo'],\n    '0200': ['AE', '1', 'Initiator'],\n    '0300': ['AE', '1', 'Receiver'],\n    '0400': ['AE', '1', 'FindLocation'],\n    '0600': ['AE', '1', 'MoveDestination'],\n    '0700': ['US', '1', 'Priority'],\n    '0800': ['US', '1', 'CommandDataSetType'],\n    '0850': ['US', '1', 'NumberOfMatches'],\n    '0860': ['US', '1', 'ResponseSequenceNumber'],\n    '0900': ['US', '1', 'Status'],\n    '0901': ['AT', '1-n', 'OffendingElement'],\n    '0902': ['LO', '1', 'ErrorComment'],\n    '0903': ['US', '1', 'ErrorID'],\n    '1000': ['UI', '1', 'AffectedSOPInstanceUID'],\n    '1001': ['UI', '1', 'RequestedSOPInstanceUID'],\n    '1002': ['US', '1', 'EventTypeID'],\n    '1005': ['AT', '1-n', 'AttributeIdentifierList'],\n    '1008': ['US', '1', 'ActionTypeID'],\n    '1020': ['US', '1', 'NumberOfRemainingSuboperations'],\n    '1021': ['US', '1', 'NumberOfCompletedSuboperations'],\n    '1022': ['US', '1', 'NumberOfFailedSuboperations'],\n    '1023': ['US', '1', 'NumberOfWarningSuboperations'],\n    '1030': ['AE', '1', 'MoveOriginatorApplicationEntityTitle'],\n    '1031': ['US', '1', 'MoveOriginatorMessageID'],\n    '4000': ['LT', '1', 'DialogReceiver'],\n    '4010': ['LT', '1', 'TerminalType'],\n    '5010': ['SH', '1', 'MessageSetID'],\n    '5020': ['SH', '1', 'EndMessageID'],\n    '5110': ['LT', '1', 'DisplayFormat'],\n    '5120': ['LT', '1', 'PagePositionID'],\n    '5130': ['CS', '1', 'TextFormatID'],\n    '5140': ['CS', '1', 'NormalReverse'],\n    '5150': ['CS', '1', 'AddGrayScale'],\n    '5160': ['CS', '1', 'Borders'],\n    '5170': ['IS', '1', 'Copies'],\n    '5180': ['CS', '1', 'CommandMagnificationType'],\n    '5190': ['CS', '1', 'Erase'],\n    '51A0': ['CS', '1', 'Print'],\n    '51B0': ['US', '1-n', 'Overlays']\n  },\n  '0002': {\n    '0000': ['UL', '1', 'FileMetaInformationGroupLength'],\n    '0001': ['OB', '1', 'FileMetaInformationVersion'],\n    '0002': ['UI', '1', 'MediaStorageSOPClassUID'],\n    '0003': ['UI', '1', 'MediaStorageSOPInstanceUID'],\n    '0010': ['UI', '1', 'TransferSyntaxUID'],\n    '0012': ['UI', '1', 'ImplementationClassUID'],\n    '0013': ['SH', '1', 'ImplementationVersionName'],\n    '0016': ['AE', '1', 'SourceApplicationEntityTitle'],\n    '0017': ['AE', '1', 'SendingApplicationEntityTitle'],\n    '0018': ['AE', '1', 'ReceivingApplicationEntityTitle'],\n    '0026': ['UR', '1', 'SourcePresentationAddress'],\n    '0027': ['UR', '1', 'SendingPresentationAddress'],\n    '0028': ['UR', '1', 'ReceivingPresentationAddress'],\n    '0031': ['OB', '1', 'RTVMetaInformationVersion'],\n    '0032': ['UI', '1', 'RTVCommunicationSOPClassUID'],\n    '0033': ['UI', '1', 'RTVCommunicationSOPInstanceUID'],\n    '0035': ['OB', '1', 'RTVSourceIdentifier'],\n    '0036': ['OB', '1', 'RTVFlowIdentifier'],\n    '0037': ['UL', '1', 'RTVFlowRTPSamplingRate'],\n    '0038': ['FD', '1', 'RTVFlowActualFrameDuration'],\n    '0100': ['UI', '1', 'PrivateInformationCreatorUID'],\n    '0102': ['OB', '1', 'PrivateInformation']\n  },\n  '0004': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '1130': ['CS', '1', 'FileSetID'],\n    '1141': ['CS', '1-8', 'FileSetDescriptorFileID'],\n    '1142': ['CS', '1', 'SpecificCharacterSetOfFileSetDescriptorFile'],\n    '1200': ['UL', '1', 'OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity'],\n    '1202': ['UL', '1', 'OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity'],\n    '1212': ['US', '1', 'FileSetConsistencyFlag'],\n    '1220': ['SQ', '1', 'DirectoryRecordSequence'],\n    '1400': ['UL', '1', 'OffsetOfTheNextDirectoryRecord'],\n    '1410': ['US', '1', 'RecordInUseFlag'],\n    '1420': ['UL', '1', 'OffsetOfReferencedLowerLevelDirectoryEntity'],\n    '1430': ['CS', '1', 'DirectoryRecordType'],\n    '1432': ['UI', '1', 'PrivateRecordUID'],\n    '1500': ['CS', '1-8', 'ReferencedFileID'],\n    '1504': ['UL', '1', 'MRDRDirectoryRecordOffset'],\n    '1510': ['UI', '1', 'ReferencedSOPClassUIDInFile'],\n    '1511': ['UI', '1', 'ReferencedSOPInstanceUIDInFile'],\n    '1512': ['UI', '1', 'ReferencedTransferSyntaxUIDInFile'],\n    '151A': ['UI', '1-n', 'ReferencedRelatedGeneralSOPClassUIDInFile'],\n    '1600': ['UL', '1', 'NumberOfReferences']\n  },\n  '0008': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['UL', '1', 'LengthToEnd'],\n    '0005': ['CS', '1-n', 'SpecificCharacterSet'],\n    '0006': ['SQ', '1', 'LanguageCodeSequence'],\n    '0008': ['CS', '2-n', 'ImageType'],\n    '0010': ['SH', '1', 'RecognitionCode'],\n    '0012': ['DA', '1', 'InstanceCreationDate'],\n    '0013': ['TM', '1', 'InstanceCreationTime'],\n    '0014': ['UI', '1', 'InstanceCreatorUID'],\n    '0015': ['DT', '1', 'InstanceCoercionDateTime'],\n    '0016': ['UI', '1', 'SOPClassUID'],\n    '0018': ['UI', '1', 'SOPInstanceUID'],\n    '001A': ['UI', '1-n', 'RelatedGeneralSOPClassUID'],\n    '001B': ['UI', '1', 'OriginalSpecializedSOPClassUID'],\n    '0020': ['DA', '1', 'StudyDate'],\n    '0021': ['DA', '1', 'SeriesDate'],\n    '0022': ['DA', '1', 'AcquisitionDate'],\n    '0023': ['DA', '1', 'ContentDate'],\n    '0024': ['DA', '1', 'OverlayDate'],\n    '0025': ['DA', '1', 'CurveDate'],\n    '002A': ['DT', '1', 'AcquisitionDateTime'],\n    '0030': ['TM', '1', 'StudyTime'],\n    '0031': ['TM', '1', 'SeriesTime'],\n    '0032': ['TM', '1', 'AcquisitionTime'],\n    '0033': ['TM', '1', 'ContentTime'],\n    '0034': ['TM', '1', 'OverlayTime'],\n    '0035': ['TM', '1', 'CurveTime'],\n    '0040': ['US', '1', 'DataSetType'],\n    '0041': ['LO', '1', 'DataSetSubtype'],\n    '0042': ['CS', '1', 'NuclearMedicineSeriesType'],\n    '0050': ['SH', '1', 'AccessionNumber'],\n    '0051': ['SQ', '1', 'IssuerOfAccessionNumberSequence'],\n    '0052': ['CS', '1', 'QueryRetrieveLevel'],\n    '0053': ['CS', '1', 'QueryRetrieveView'],\n    '0054': ['AE', '1-n', 'RetrieveAETitle'],\n    '0055': ['AE', '1', 'StationAETitle'],\n    '0056': ['CS', '1', 'InstanceAvailability'],\n    '0058': ['UI', '1-n', 'FailedSOPInstanceUIDList'],\n    '0060': ['CS', '1', 'Modality'],\n    '0061': ['CS', '1-n', 'ModalitiesInStudy'],\n    '0062': ['UI', '1-n', 'SOPClassesInStudy'],\n    '0063': ['SQ', '1', 'AnatomicRegionsInStudyCodeSequence'],\n    '0064': ['CS', '1', 'ConversionType'],\n    '0068': ['CS', '1', 'PresentationIntentType'],\n    '0070': ['LO', '1', 'Manufacturer'],\n    '0080': ['LO', '1', 'InstitutionName'],\n    '0081': ['ST', '1', 'InstitutionAddress'],\n    '0082': ['SQ', '1', 'InstitutionCodeSequence'],\n    '0090': ['PN', '1', 'ReferringPhysicianName'],\n    '0092': ['ST', '1', 'ReferringPhysicianAddress'],\n    '0094': ['SH', '1-n', 'ReferringPhysicianTelephoneNumbers'],\n    '0096': ['SQ', '1', 'ReferringPhysicianIdentificationSequence'],\n    '009C': ['PN', '1-n', 'ConsultingPhysicianName'],\n    '009D': ['SQ', '1', 'ConsultingPhysicianIdentificationSequence'],\n    '0100': ['SH', '1', 'CodeValue'],\n    '0101': ['LO', '1', 'ExtendedCodeValue'],\n    '0102': ['SH', '1', 'CodingSchemeDesignator'],\n    '0103': ['SH', '1', 'CodingSchemeVersion'],\n    '0104': ['LO', '1', 'CodeMeaning'],\n    '0105': ['CS', '1', 'MappingResource'],\n    '0106': ['DT', '1', 'ContextGroupVersion'],\n    '0107': ['DT', '1', 'ContextGroupLocalVersion'],\n    '0108': ['LT', '1', 'ExtendedCodeMeaning'],\n    '0109': ['SQ', '1', 'CodingSchemeResourcesSequence'],\n    '010A': ['CS', '1', 'CodingSchemeURLType'],\n    '010B': ['CS', '1', 'ContextGroupExtensionFlag'],\n    '010C': ['UI', '1', 'CodingSchemeUID'],\n    '010D': ['UI', '1', 'ContextGroupExtensionCreatorUID'],\n    '010E': ['UR', '1', 'CodingSchemeURL'],\n    '010F': ['CS', '1', 'ContextIdentifier'],\n    '0110': ['SQ', '1', 'CodingSchemeIdentificationSequence'],\n    '0112': ['LO', '1', 'CodingSchemeRegistry'],\n    '0114': ['ST', '1', 'CodingSchemeExternalID'],\n    '0115': ['ST', '1', 'CodingSchemeName'],\n    '0116': ['ST', '1', 'CodingSchemeResponsibleOrganization'],\n    '0117': ['UI', '1', 'ContextUID'],\n    '0118': ['UI', '1', 'MappingResourceUID'],\n    '0119': ['UC', '1', 'LongCodeValue'],\n    '0120': ['UR', '1', 'URNCodeValue'],\n    '0121': ['SQ', '1', 'EquivalentCodeSequence'],\n    '0122': ['LO', '1', 'MappingResourceName'],\n    '0123': ['SQ', '1', 'ContextGroupIdentificationSequence'],\n    '0124': ['SQ', '1', 'MappingResourceIdentificationSequence'],\n    '0201': ['SH', '1', 'TimezoneOffsetFromUTC'],\n    '0202': ['', '', ''],\n    '0220': ['SQ', '1', 'ResponsibleGroupCodeSequence'],\n    '0221': ['CS', '1', 'EquipmentModality'],\n    '0222': ['LO', '1', 'ManufacturerRelatedModelGroup'],\n    '0300': ['SQ', '1', 'PrivateDataElementCharacteristicsSequence'],\n    '0301': ['US', '1', 'PrivateGroupReference'],\n    '0302': ['LO', '1', 'PrivateCreatorReference'],\n    '0303': ['CS', '1', 'BlockIdentifyingInformationStatus'],\n    '0304': ['US', '1-n', 'NonidentifyingPrivateElements'],\n    '0305': ['SQ', '1', 'DeidentificationActionSequence'],\n    '0306': ['US', '1-n', 'IdentifyingPrivateElements'],\n    '0307': ['CS', '1', 'DeidentificationAction'],\n    '0308': ['US', '1', 'PrivateDataElement'],\n    '0309': ['UL', '1-3', 'PrivateDataElementValueMultiplicity'],\n    '030A': ['CS', '1', 'PrivateDataElementValueRepresentation'],\n    '030B': ['UL', '1-2', 'PrivateDataElementNumberOfItems'],\n    '030C': ['UC', '1', 'PrivateDataElementName'],\n    '030D': ['UC', '1', 'PrivateDataElementKeyword'],\n    '030E': ['UT', '1', 'PrivateDataElementDescription'],\n    '030F': ['UT', '1', 'PrivateDataElementEncoding'],\n    '0310': ['SQ', '1', 'PrivateDataElementDefinitionSequence'],\n    '1000': ['AE', '1', 'NetworkID'],\n    '1010': ['SH', '1', 'StationName'],\n    '1030': ['LO', '1', 'StudyDescription'],\n    '1032': ['SQ', '1', 'ProcedureCodeSequence'],\n    '103E': ['LO', '1', 'SeriesDescription'],\n    '103F': ['SQ', '1', 'SeriesDescriptionCodeSequence'],\n    '1040': ['LO', '1', 'InstitutionalDepartmentName'],\n    '1041': ['SQ', '1', 'InstitutionalDepartmentTypeCodeSequence'],\n    '1048': ['PN', '1-n', 'PhysiciansOfRecord'],\n    '1049': ['SQ', '1', 'PhysiciansOfRecordIdentificationSequence'],\n    '1050': ['PN', '1-n', 'PerformingPhysicianName'],\n    '1052': ['SQ', '1', 'PerformingPhysicianIdentificationSequence'],\n    '1060': ['PN', '1-n', 'NameOfPhysiciansReadingStudy'],\n    '1062': ['SQ', '1', 'PhysiciansReadingStudyIdentificationSequence'],\n    '1070': ['PN', '1-n', 'OperatorsName'],\n    '1072': ['SQ', '1', 'OperatorIdentificationSequence'],\n    '1080': ['LO', '1-n', 'AdmittingDiagnosesDescription'],\n    '1084': ['SQ', '1', 'AdmittingDiagnosesCodeSequence'],\n    '1090': ['LO', '1', 'ManufacturerModelName'],\n    '1100': ['SQ', '1', 'ReferencedResultsSequence'],\n    '1110': ['SQ', '1', 'ReferencedStudySequence'],\n    '1111': ['SQ', '1', 'ReferencedPerformedProcedureStepSequence'],\n    '1115': ['SQ', '1', 'ReferencedSeriesSequence'],\n    '1120': ['SQ', '1', 'ReferencedPatientSequence'],\n    '1125': ['SQ', '1', 'ReferencedVisitSequence'],\n    '1130': ['SQ', '1', 'ReferencedOverlaySequence'],\n    '1134': ['SQ', '1', 'ReferencedStereometricInstanceSequence'],\n    '113A': ['SQ', '1', 'ReferencedWaveformSequence'],\n    '1140': ['SQ', '1', 'ReferencedImageSequence'],\n    '1145': ['SQ', '1', 'ReferencedCurveSequence'],\n    '114A': ['SQ', '1', 'ReferencedInstanceSequence'],\n    '114B': ['SQ', '1', 'ReferencedRealWorldValueMappingInstanceSequence'],\n    '1150': ['UI', '1', 'ReferencedSOPClassUID'],\n    '1155': ['UI', '1', 'ReferencedSOPInstanceUID'],\n    '1156': ['SQ', '1', 'DefinitionSourceSequence'],\n    '115A': ['UI', '1-n', 'SOPClassesSupported'],\n    '1160': ['IS', '1-n', 'ReferencedFrameNumber'],\n    '1161': ['UL', '1-n', 'SimpleFrameList'],\n    '1162': ['UL', '3-3n', 'CalculatedFrameList'],\n    '1163': ['FD', '2', 'TimeRange'],\n    '1164': ['SQ', '1', 'FrameExtractionSequence'],\n    '1167': ['UI', '1', 'MultiFrameSourceSOPInstanceUID'],\n    '1190': ['UR', '1', 'RetrieveURL'],\n    '1195': ['UI', '1', 'TransactionUID'],\n    '1196': ['US', '1', 'WarningReason'],\n    '1197': ['US', '1', 'FailureReason'],\n    '1198': ['SQ', '1', 'FailedSOPSequence'],\n    '1199': ['SQ', '1', 'ReferencedSOPSequence'],\n    '119A': ['SQ', '1', 'OtherFailuresSequence'],\n    '1200': ['SQ', '1', 'StudiesContainingOtherReferencedInstancesSequence'],\n    '1250': ['SQ', '1', 'RelatedSeriesSequence'],\n    '2110': ['CS', '1', 'LossyImageCompressionRetired'],\n    '2111': ['ST', '1', 'DerivationDescription'],\n    '2112': ['SQ', '1', 'SourceImageSequence'],\n    '2120': ['SH', '1', 'StageName'],\n    '2122': ['IS', '1', 'StageNumber'],\n    '2124': ['IS', '1', 'NumberOfStages'],\n    '2127': ['SH', '1', 'ViewName'],\n    '2128': ['IS', '1', 'ViewNumber'],\n    '2129': ['IS', '1', 'NumberOfEventTimers'],\n    '212A': ['IS', '1', 'NumberOfViewsInStage'],\n    '2130': ['DS', '1-n', 'EventElapsedTimes'],\n    '2132': ['LO', '1-n', 'EventTimerNames'],\n    '2133': ['SQ', '1', 'EventTimerSequence'],\n    '2134': ['FD', '1', 'EventTimeOffset'],\n    '2135': ['SQ', '1', 'EventCodeSequence'],\n    '2142': ['IS', '1', 'StartTrim'],\n    '2143': ['IS', '1', 'StopTrim'],\n    '2144': ['IS', '1', 'RecommendedDisplayFrameRate'],\n    '2200': ['CS', '1', 'TransducerPosition'],\n    '2204': ['CS', '1', 'TransducerOrientation'],\n    '2208': ['CS', '1', 'AnatomicStructure'],\n    '2218': ['SQ', '1', 'AnatomicRegionSequence'],\n    '2220': ['SQ', '1', 'AnatomicRegionModifierSequence'],\n    '2228': ['SQ', '1', 'PrimaryAnatomicStructureSequence'],\n    '2229': ['SQ', '1', 'AnatomicStructureSpaceOrRegionSequence'],\n    '2230': ['SQ', '1', 'PrimaryAnatomicStructureModifierSequence'],\n    '2240': ['SQ', '1', 'TransducerPositionSequence'],\n    '2242': ['SQ', '1', 'TransducerPositionModifierSequence'],\n    '2244': ['SQ', '1', 'TransducerOrientationSequence'],\n    '2246': ['SQ', '1', 'TransducerOrientationModifierSequence'],\n    '2251': ['SQ', '1', 'AnatomicStructureSpaceOrRegionCodeSequenceTrial'],\n    '2253': ['SQ', '1', 'AnatomicPortalOfEntranceCodeSequenceTrial'],\n    '2255': ['SQ', '1', 'AnatomicApproachDirectionCodeSequenceTrial'],\n    '2256': ['ST', '1', 'AnatomicPerspectiveDescriptionTrial'],\n    '2257': ['SQ', '1', 'AnatomicPerspectiveCodeSequenceTrial'],\n    '2258': ['ST', '1', 'AnatomicLocationOfExaminingInstrumentDescriptionTrial'],\n    '2259': ['SQ', '1', 'AnatomicLocationOfExaminingInstrumentCodeSequenceTrial'],\n    '225A': ['SQ', '1', 'AnatomicStructureSpaceOrRegionModifierCodeSequenceTrial'],\n    '225C': ['SQ', '1', 'OnAxisBackgroundAnatomicStructureCodeSequenceTrial'],\n    '3001': ['SQ', '1', 'AlternateRepresentationSequence'],\n    '3002': ['UI', '1-n', 'AvailableTransferSyntaxUID'],\n    '3010': ['UI', '1-n', 'IrradiationEventUID'],\n    '3011': ['SQ', '1', 'SourceIrradiationEventSequence'],\n    '3012': ['UI', '1', 'RadiopharmaceuticalAdministrationEventUID'],\n    '4000': ['LT', '1', 'IdentifyingComments'],\n    '9007': ['CS', '4', 'FrameType'],\n    '9092': ['SQ', '1', 'ReferencedImageEvidenceSequence'],\n    '9121': ['SQ', '1', 'ReferencedRawDataSequence'],\n    '9123': ['UI', '1', 'CreatorVersionUID'],\n    '9124': ['SQ', '1', 'DerivationImageSequence'],\n    '9154': ['SQ', '1', 'SourceImageEvidenceSequence'],\n    '9205': ['CS', '1', 'PixelPresentation'],\n    '9206': ['CS', '1', 'VolumetricProperties'],\n    '9207': ['CS', '1', 'VolumeBasedCalculationTechnique'],\n    '9208': ['CS', '1', 'ComplexImageComponent'],\n    '9209': ['CS', '1', 'AcquisitionContrast'],\n    '9215': ['SQ', '1', 'DerivationCodeSequence'],\n    '9237': ['SQ', '1', 'ReferencedPresentationStateSequence'],\n    '9410': ['SQ', '1', 'ReferencedOtherPlaneSequence'],\n    '9458': ['SQ', '1', 'FrameDisplaySequence'],\n    '9459': ['FL', '1', 'RecommendedDisplayFrameRateInFloat'],\n    '9460': ['CS', '1', 'SkipFrameRangeFlag']\n  },\n  '0010': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['PN', '1', 'PatientName'],\n    '0020': ['LO', '1', 'PatientID'],\n    '0021': ['LO', '1', 'IssuerOfPatientID'],\n    '0022': ['CS', '1', 'TypeOfPatientID'],\n    '0024': ['SQ', '1', 'IssuerOfPatientIDQualifiersSequence'],\n    '0026': ['SQ', '1', 'SourcePatientGroupIdentificationSequence'],\n    '0027': ['SQ', '1', 'GroupOfPatientsIdentificationSequence'],\n    '0028': ['US', '3', 'SubjectRelativePositionInImage'],\n    '0030': ['DA', '1', 'PatientBirthDate'],\n    '0032': ['TM', '1', 'PatientBirthTime'],\n    '0033': ['LO', '1', 'PatientBirthDateInAlternativeCalendar'],\n    '0034': ['LO', '1', 'PatientDeathDateInAlternativeCalendar'],\n    '0035': ['CS', '1', 'PatientAlternativeCalendar'],\n    '0040': ['CS', '1', 'PatientSex'],\n    '0050': ['SQ', '1', 'PatientInsurancePlanCodeSequence'],\n    '0101': ['SQ', '1', 'PatientPrimaryLanguageCodeSequence'],\n    '0102': ['SQ', '1', 'PatientPrimaryLanguageModifierCodeSequence'],\n    '0200': ['CS', '1', 'QualityControlSubject'],\n    '0201': ['SQ', '1', 'QualityControlSubjectTypeCodeSequence'],\n    '0212': ['UC', '1', 'StrainDescription'],\n    '0213': ['LO', '1', 'StrainNomenclature'],\n    '0214': ['LO', '1', 'StrainStockNumber'],\n    '0215': ['SQ', '1', 'StrainSourceRegistryCodeSequence'],\n    '0216': ['SQ', '1', 'StrainStockSequence'],\n    '0217': ['LO', '1', 'StrainSource'],\n    '0218': ['UT', '1', 'StrainAdditionalInformation'],\n    '0219': ['SQ', '1', 'StrainCodeSequence'],\n    '0221': ['SQ', '1', 'GeneticModificationsSequence'],\n    '0222': ['UC', '1', 'GeneticModificationsDescription'],\n    '0223': ['LO', '1', 'GeneticModificationsNomenclature'],\n    '0229': ['SQ', '1', 'GeneticModificationsCodeSequence'],\n    '1000': ['LO', '1-n', 'OtherPatientIDs'],\n    '1001': ['PN', '1-n', 'OtherPatientNames'],\n    '1002': ['SQ', '1', 'OtherPatientIDsSequence'],\n    '1005': ['PN', '1', 'PatientBirthName'],\n    '1010': ['AS', '1', 'PatientAge'],\n    '1020': ['DS', '1', 'PatientSize'],\n    '1021': ['SQ', '1', 'PatientSizeCodeSequence'],\n    '1022': ['DS', '1', 'PatientBodyMassIndex'],\n    '1023': ['DS', '1', 'MeasuredAPDimension'],\n    '1024': ['DS', '1', 'MeasuredLateralDimension'],\n    '1030': ['DS', '1', 'PatientWeight'],\n    '1040': ['LO', '1', 'PatientAddress'],\n    '1050': ['LO', '1-n', 'InsurancePlanIdentification'],\n    '1060': ['PN', '1', 'PatientMotherBirthName'],\n    '1080': ['LO', '1', 'MilitaryRank'],\n    '1081': ['LO', '1', 'BranchOfService'],\n    '1090': ['LO', '1', 'MedicalRecordLocator'],\n    '1100': ['SQ', '1', 'ReferencedPatientPhotoSequence'],\n    '2000': ['LO', '1-n', 'MedicalAlerts'],\n    '2110': ['LO', '1-n', 'Allergies'],\n    '2150': ['LO', '1', 'CountryOfResidence'],\n    '2152': ['LO', '1', 'RegionOfResidence'],\n    '2154': ['SH', '1-n', 'PatientTelephoneNumbers'],\n    '2155': ['LT', '1', 'PatientTelecomInformation'],\n    '2160': ['SH', '1', 'EthnicGroup'],\n    '2180': ['SH', '1', 'Occupation'],\n    '21A0': ['CS', '1', 'SmokingStatus'],\n    '21B0': ['LT', '1', 'AdditionalPatientHistory'],\n    '21C0': ['US', '1', 'PregnancyStatus'],\n    '21D0': ['DA', '1', 'LastMenstrualDate'],\n    '21F0': ['LO', '1', 'PatientReligiousPreference'],\n    '2201': ['LO', '1', 'PatientSpeciesDescription'],\n    '2202': ['SQ', '1', 'PatientSpeciesCodeSequence'],\n    '2203': ['CS', '1', 'PatientSexNeutered'],\n    '2210': ['CS', '1', 'AnatomicalOrientationType'],\n    '2292': ['LO', '1', 'PatientBreedDescription'],\n    '2293': ['SQ', '1', 'PatientBreedCodeSequence'],\n    '2294': ['SQ', '1', 'BreedRegistrationSequence'],\n    '2295': ['LO', '1', 'BreedRegistrationNumber'],\n    '2296': ['SQ', '1', 'BreedRegistryCodeSequence'],\n    '2297': ['PN', '1', 'ResponsiblePerson'],\n    '2298': ['CS', '1', 'ResponsiblePersonRole'],\n    '2299': ['LO', '1', 'ResponsibleOrganization'],\n    '4000': ['LT', '1', 'PatientComments'],\n    '9431': ['FL', '1', 'ExaminedBodyThickness']\n  },\n  '0012': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['LO', '1', 'ClinicalTrialSponsorName'],\n    '0020': ['LO', '1', 'ClinicalTrialProtocolID'],\n    '0021': ['LO', '1', 'ClinicalTrialProtocolName'],\n    '0030': ['LO', '1', 'ClinicalTrialSiteID'],\n    '0031': ['LO', '1', 'ClinicalTrialSiteName'],\n    '0040': ['LO', '1', 'ClinicalTrialSubjectID'],\n    '0042': ['LO', '1', 'ClinicalTrialSubjectReadingID'],\n    '0050': ['LO', '1', 'ClinicalTrialTimePointID'],\n    '0051': ['ST', '1', 'ClinicalTrialTimePointDescription'],\n    '0052': ['FD', '1', 'LongitudinalTemporalOffsetFromEvent'],\n    '0053': ['CS', '1', 'LongitudinalTemporalEventType'],\n    '0060': ['LO', '1', 'ClinicalTrialCoordinatingCenterName'],\n    '0062': ['CS', '1', 'PatientIdentityRemoved'],\n    '0063': ['LO', '1-n', 'DeidentificationMethod'],\n    '0064': ['SQ', '1', 'DeidentificationMethodCodeSequence'],\n    '0071': ['LO', '1', 'ClinicalTrialSeriesID'],\n    '0072': ['LO', '1', 'ClinicalTrialSeriesDescription'],\n    '0081': ['LO', '1', 'ClinicalTrialProtocolEthicsCommitteeName'],\n    '0082': ['LO', '1', 'ClinicalTrialProtocolEthicsCommitteeApprovalNumber'],\n    '0083': ['SQ', '1', 'ConsentForClinicalTrialUseSequence'],\n    '0084': ['CS', '1', 'DistributionType'],\n    '0085': ['CS', '1', 'ConsentForDistributionFlag'],\n    '0086': ['DA', '1', 'EthicsCommitteeApprovalEffectivenessStartDate'],\n    '0087': ['DA', '1', 'EthicsCommitteeApprovalEffectivenessEndDate']\n  },\n  '0014': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0023': ['ST', '1', 'CADFileFormat'],\n    '0024': ['ST', '1', 'ComponentReferenceSystem'],\n    '0025': ['ST', '1', 'ComponentManufacturingProcedure'],\n    '0028': ['ST', '1', 'ComponentManufacturer'],\n    '0030': ['DS', '1-n', 'MaterialThickness'],\n    '0032': ['DS', '1-n', 'MaterialPipeDiameter'],\n    '0034': ['DS', '1-n', 'MaterialIsolationDiameter'],\n    '0042': ['ST', '1', 'MaterialGrade'],\n    '0044': ['ST', '1', 'MaterialPropertiesDescription'],\n    '0045': ['ST', '1', 'MaterialPropertiesFileFormatRetired'],\n    '0046': ['LT', '1', 'MaterialNotes'],\n    '0050': ['CS', '1', 'ComponentShape'],\n    '0052': ['CS', '1', 'CurvatureType'],\n    '0054': ['DS', '1', 'OuterDiameter'],\n    '0056': ['DS', '1', 'InnerDiameter'],\n    '0100': ['LO', '1-n', 'ComponentWelderIDs'],\n    '0101': ['CS', '1', 'SecondaryApprovalStatus'],\n    '0102': ['DA', '1', 'SecondaryReviewDate'],\n    '0103': ['TM', '1', 'SecondaryReviewTime'],\n    '0104': ['PN', '1', 'SecondaryReviewerName'],\n    '0105': ['ST', '1', 'RepairID'],\n    '0106': ['SQ', '1', 'MultipleComponentApprovalSequence'],\n    '0107': ['CS', '1-n', 'OtherApprovalStatus'],\n    '0108': ['CS', '1-n', 'OtherSecondaryApprovalStatus'],\n    '1010': ['ST', '1', 'ActualEnvironmentalConditions'],\n    '1020': ['DA', '1', 'ExpiryDate'],\n    '1040': ['ST', '1', 'EnvironmentalConditions'],\n    '2002': ['SQ', '1', 'EvaluatorSequence'],\n    '2004': ['IS', '1', 'EvaluatorNumber'],\n    '2006': ['PN', '1', 'EvaluatorName'],\n    '2008': ['IS', '1', 'EvaluationAttempt'],\n    '2012': ['SQ', '1', 'IndicationSequence'],\n    '2014': ['IS', '1', 'IndicationNumber'],\n    '2016': ['SH', '1', 'IndicationLabel'],\n    '2018': ['ST', '1', 'IndicationDescription'],\n    '201A': ['CS', '1-n', 'IndicationType'],\n    '201C': ['CS', '1', 'IndicationDisposition'],\n    '201E': ['SQ', '1', 'IndicationROISequence'],\n    '2030': ['SQ', '1', 'IndicationPhysicalPropertySequence'],\n    '2032': ['SH', '1', 'PropertyLabel'],\n    '2202': ['IS', '1', 'CoordinateSystemNumberOfAxes'],\n    '2204': ['SQ', '1', 'CoordinateSystemAxesSequence'],\n    '2206': ['ST', '1', 'CoordinateSystemAxisDescription'],\n    '2208': ['CS', '1', 'CoordinateSystemDataSetMapping'],\n    '220A': ['IS', '1', 'CoordinateSystemAxisNumber'],\n    '220C': ['CS', '1', 'CoordinateSystemAxisType'],\n    '220E': ['CS', '1', 'CoordinateSystemAxisUnits'],\n    '2210': ['OB', '1', 'CoordinateSystemAxisValues'],\n    '2220': ['SQ', '1', 'CoordinateSystemTransformSequence'],\n    '2222': ['ST', '1', 'TransformDescription'],\n    '2224': ['IS', '1', 'TransformNumberOfAxes'],\n    '2226': ['IS', '1-n', 'TransformOrderOfAxes'],\n    '2228': ['CS', '1', 'TransformedAxisUnits'],\n    '222A': ['DS', '1-n', 'CoordinateSystemTransformRotationAndScaleMatrix'],\n    '222C': ['DS', '1-n', 'CoordinateSystemTransformTranslationMatrix'],\n    '3011': ['DS', '1', 'InternalDetectorFrameTime'],\n    '3012': ['DS', '1', 'NumberOfFramesIntegrated'],\n    '3020': ['SQ', '1', 'DetectorTemperatureSequence'],\n    '3022': ['ST', '1', 'SensorName'],\n    '3024': ['DS', '1', 'HorizontalOffsetOfSensor'],\n    '3026': ['DS', '1', 'VerticalOffsetOfSensor'],\n    '3028': ['DS', '1', 'SensorTemperature'],\n    '3040': ['SQ', '1', 'DarkCurrentSequence'],\n    '3050': ['ox', '1', 'DarkCurrentCounts'],\n    '3060': ['SQ', '1', 'GainCorrectionReferenceSequence'],\n    '3070': ['ox', '1', 'AirCounts'],\n    '3071': ['DS', '1', 'KVUsedInGainCalibration'],\n    '3072': ['DS', '1', 'MAUsedInGainCalibration'],\n    '3073': ['DS', '1', 'NumberOfFramesUsedForIntegration'],\n    '3074': ['LO', '1', 'FilterMaterialUsedInGainCalibration'],\n    '3075': ['DS', '1', 'FilterThicknessUsedInGainCalibration'],\n    '3076': ['DA', '1', 'DateOfGainCalibration'],\n    '3077': ['TM', '1', 'TimeOfGainCalibration'],\n    '3080': ['OB', '1', 'BadPixelImage'],\n    '3099': ['LT', '1', 'CalibrationNotes'],\n    '3100': ['LT', '1', 'LinearityCorrectionTechnique'],\n    '3101': ['LT', '1', 'BeamHardeningCorrectionTechnique'],\n    '4002': ['SQ', '1', 'PulserEquipmentSequence'],\n    '4004': ['CS', '1', 'PulserType'],\n    '4006': ['LT', '1', 'PulserNotes'],\n    '4008': ['SQ', '1', 'ReceiverEquipmentSequence'],\n    '400A': ['CS', '1', 'AmplifierType'],\n    '400C': ['LT', '1', 'ReceiverNotes'],\n    '400E': ['SQ', '1', 'PreAmplifierEquipmentSequence'],\n    '400F': ['LT', '1', 'PreAmplifierNotes'],\n    '4010': ['SQ', '1', 'TransmitTransducerSequence'],\n    '4011': ['SQ', '1', 'ReceiveTransducerSequence'],\n    '4012': ['US', '1', 'NumberOfElements'],\n    '4013': ['CS', '1', 'ElementShape'],\n    '4014': ['DS', '1', 'ElementDimensionA'],\n    '4015': ['DS', '1', 'ElementDimensionB'],\n    '4016': ['DS', '1', 'ElementPitchA'],\n    '4017': ['DS', '1', 'MeasuredBeamDimensionA'],\n    '4018': ['DS', '1', 'MeasuredBeamDimensionB'],\n    '4019': ['DS', '1', 'LocationOfMeasuredBeamDiameter'],\n    '401A': ['DS', '1', 'NominalFrequency'],\n    '401B': ['DS', '1', 'MeasuredCenterFrequency'],\n    '401C': ['DS', '1', 'MeasuredBandwidth'],\n    '401D': ['DS', '1', 'ElementPitchB'],\n    '4020': ['SQ', '1', 'PulserSettingsSequence'],\n    '4022': ['DS', '1', 'PulseWidth'],\n    '4024': ['DS', '1', 'ExcitationFrequency'],\n    '4026': ['CS', '1', 'ModulationType'],\n    '4028': ['DS', '1', 'Damping'],\n    '4030': ['SQ', '1', 'ReceiverSettingsSequence'],\n    '4031': ['DS', '1', 'AcquiredSoundpathLength'],\n    '4032': ['CS', '1', 'AcquisitionCompressionType'],\n    '4033': ['IS', '1', 'AcquisitionSampleSize'],\n    '4034': ['DS', '1', 'RectifierSmoothing'],\n    '4035': ['SQ', '1', 'DACSequence'],\n    '4036': ['CS', '1', 'DACType'],\n    '4038': ['DS', '1-n', 'DACGainPoints'],\n    '403A': ['DS', '1-n', 'DACTimePoints'],\n    '403C': ['DS', '1-n', 'DACAmplitude'],\n    '4040': ['SQ', '1', 'PreAmplifierSettingsSequence'],\n    '4050': ['SQ', '1', 'TransmitTransducerSettingsSequence'],\n    '4051': ['SQ', '1', 'ReceiveTransducerSettingsSequence'],\n    '4052': ['DS', '1', 'IncidentAngle'],\n    '4054': ['ST', '1', 'CouplingTechnique'],\n    '4056': ['ST', '1', 'CouplingMedium'],\n    '4057': ['DS', '1', 'CouplingVelocity'],\n    '4058': ['DS', '1', 'ProbeCenterLocationX'],\n    '4059': ['DS', '1', 'ProbeCenterLocationZ'],\n    '405A': ['DS', '1', 'SoundPathLength'],\n    '405C': ['ST', '1', 'DelayLawIdentifier'],\n    '4060': ['SQ', '1', 'GateSettingsSequence'],\n    '4062': ['DS', '1', 'GateThreshold'],\n    '4064': ['DS', '1', 'VelocityOfSound'],\n    '4070': ['SQ', '1', 'CalibrationSettingsSequence'],\n    '4072': ['ST', '1', 'CalibrationProcedure'],\n    '4074': ['SH', '1', 'ProcedureVersion'],\n    '4076': ['DA', '1', 'ProcedureCreationDate'],\n    '4078': ['DA', '1', 'ProcedureExpirationDate'],\n    '407A': ['DA', '1', 'ProcedureLastModifiedDate'],\n    '407C': ['TM', '1-n', 'CalibrationTime'],\n    '407E': ['DA', '1-n', 'CalibrationDate'],\n    '4080': ['SQ', '1', 'ProbeDriveEquipmentSequence'],\n    '4081': ['CS', '1', 'DriveType'],\n    '4082': ['LT', '1', 'ProbeDriveNotes'],\n    '4083': ['SQ', '1', 'DriveProbeSequence'],\n    '4084': ['DS', '1', 'ProbeInductance'],\n    '4085': ['DS', '1', 'ProbeResistance'],\n    '4086': ['SQ', '1', 'ReceiveProbeSequence'],\n    '4087': ['SQ', '1', 'ProbeDriveSettingsSequence'],\n    '4088': ['DS', '1', 'BridgeResistors'],\n    '4089': ['DS', '1', 'ProbeOrientationAngle'],\n    '408B': ['DS', '1', 'UserSelectedGainY'],\n    '408C': ['DS', '1', 'UserSelectedPhase'],\n    '408D': ['DS', '1', 'UserSelectedOffsetX'],\n    '408E': ['DS', '1', 'UserSelectedOffsetY'],\n    '4091': ['SQ', '1', 'ChannelSettingsSequence'],\n    '4092': ['DS', '1', 'ChannelThreshold'],\n    '409A': ['SQ', '1', 'ScannerSettingsSequence'],\n    '409B': ['ST', '1', 'ScanProcedure'],\n    '409C': ['DS', '1', 'TranslationRateX'],\n    '409D': ['DS', '1', 'TranslationRateY'],\n    '409F': ['DS', '1', 'ChannelOverlap'],\n    '40A0': ['LO', '1-n', 'ImageQualityIndicatorType'],\n    '40A1': ['LO', '1-n', 'ImageQualityIndicatorMaterial'],\n    '40A2': ['LO', '1-n', 'ImageQualityIndicatorSize'],\n    '5002': ['IS', '1', 'LINACEnergy'],\n    '5004': ['IS', '1', 'LINACOutput'],\n    '5100': ['US', '1', 'ActiveAperture'],\n    '5101': ['DS', '1', 'TotalAperture'],\n    '5102': ['DS', '1', 'ApertureElevation'],\n    '5103': ['DS', '1', 'MainLobeAngle'],\n    '5104': ['DS', '1', 'MainRoofAngle'],\n    '5105': ['CS', '1', 'ConnectorType'],\n    '5106': ['SH', '1', 'WedgeModelNumber'],\n    '5107': ['DS', '1', 'WedgeAngleFloat'],\n    '5108': ['DS', '1', 'WedgeRoofAngle'],\n    '5109': ['CS', '1', 'WedgeElement1Position'],\n    '510A': ['DS', '1', 'WedgeMaterialVelocity'],\n    '510B': ['SH', '1', 'WedgeMaterial'],\n    '510C': ['DS', '1', 'WedgeOffsetZ'],\n    '510D': ['DS', '1', 'WedgeOriginOffsetX'],\n    '510E': ['DS', '1', 'WedgeTimeDelay'],\n    '510F': ['SH', '1', 'WedgeName'],\n    '5110': ['SH', '1', 'WedgeManufacturerName'],\n    '5111': ['LO', '1', 'WedgeDescription'],\n    '5112': ['DS', '1', 'NominalBeamAngle'],\n    '5113': ['DS', '1', 'WedgeOffsetX'],\n    '5114': ['DS', '1', 'WedgeOffsetY'],\n    '5115': ['DS', '1', 'WedgeTotalLength'],\n    '5116': ['DS', '1', 'WedgeInContactLength'],\n    '5117': ['DS', '1', 'WedgeFrontGap'],\n    '5118': ['DS', '1', 'WedgeTotalHeight'],\n    '5119': ['DS', '1', 'WedgeFrontHeight'],\n    '511A': ['DS', '1', 'WedgeRearHeight'],\n    '511B': ['DS', '1', 'WedgeTotalWidth'],\n    '511C': ['DS', '1', 'WedgeInContactWidth'],\n    '511D': ['DS', '1', 'WedgeChamferHeight'],\n    '511E': ['CS', '1', 'WedgeCurve'],\n    '511F': ['DS', '1', 'RadiusAlongWedge']\n  },\n  '0016': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['DS', '1', 'WhitePoint'],\n    '0002': ['DS', '3', 'PrimaryChromaticities'],\n    '0003': ['UT', '1', 'BatteryLevel'],\n    '0004': ['DS', '1', 'ExposureTimeInSeconds'],\n    '0005': ['DS', '1', 'FNumber'],\n    '0006': ['IS', '1', 'OECFRows'],\n    '0007': ['IS', '1', 'OECFColumns'],\n    '0008': ['UC', '1-n', 'OECFColumnNames'],\n    '0009': ['DS', '1-n', 'OECFValues'],\n    '000A': ['IS', '1', 'SpatialFrequencyResponseRows'],\n    '000B': ['IS', '1', 'SpatialFrequencyResponseColumns'],\n    '000C': ['UC', '1-n', 'SpatialFrequencyResponseColumnNames'],\n    '000D': ['DS', '1-n', 'SpatialFrequencyResponseValues'],\n    '000E': ['IS', '1', 'ColorFilterArrayPatternRows'],\n    '000F': ['IS', '1', 'ColorFilterArrayPatternColumns'],\n    '0010': ['DS', '1-n', 'ColorFilterArrayPatternValues'],\n    '0011': ['US', '1', 'FlashFiringStatus'],\n    '0012': ['US', '1', 'FlashReturnStatus'],\n    '0013': ['US', '1', 'FlashMode'],\n    '0014': ['US', '1', 'FlashFunctionPresent'],\n    '0015': ['US', '1', 'FlashRedEyeMode'],\n    '0016': ['US', '1', 'ExposureProgram'],\n    '0017': ['UT', '1', 'SpectralSensitivity'],\n    '0018': ['IS', '1', 'PhotographicSensitivity'],\n    '0019': ['IS', '1', 'SelfTimerMode'],\n    '001A': ['US', '1', 'SensitivityType'],\n    '001B': ['IS', '1', 'StandardOutputSensitivity'],\n    '001C': ['IS', '1', 'RecommendedExposureIndex'],\n    '001D': ['IS', '1', 'ISOSpeed'],\n    '001E': ['IS', '1', 'ISOSpeedLatitudeyyy'],\n    '001F': ['IS', '1', 'ISOSpeedLatitudezzz'],\n    '0020': ['UT', '1', 'EXIFVersion'],\n    '0021': ['DS', '1', 'ShutterSpeedValue'],\n    '0022': ['DS', '1', 'ApertureValue'],\n    '0023': ['DS', '1', 'BrightnessValue'],\n    '0024': ['DS', '1', 'ExposureBiasValue'],\n    '0025': ['DS', '1', 'MaxApertureValue'],\n    '0026': ['DS', '1', 'SubjectDistance'],\n    '0027': ['US', '1', 'MeteringMode'],\n    '0028': ['US', '1', 'LightSource'],\n    '0029': ['DS', '1', 'FocalLength'],\n    '002A': ['IS', '2-4', 'SubjectArea'],\n    '002B': ['OB', '1', 'MakerNote'],\n    '0030': ['DS', '1', 'Temperature'],\n    '0031': ['DS', '1', 'Humidity'],\n    '0032': ['DS', '1', 'Pressure'],\n    '0033': ['DS', '1', 'WaterDepth'],\n    '0034': ['DS', '1', 'Acceleration'],\n    '0035': ['DS', '1', 'CameraElevationAngle'],\n    '0036': ['DS', '1-2', 'FlashEnergy'],\n    '0037': ['IS', '2', 'SubjectLocation'],\n    '0038': ['DS', '1', 'PhotographicExposureIndex'],\n    '0039': ['US', '1', 'SensingMethod'],\n    '003A': ['US', '1', 'FileSource'],\n    '003B': ['US', '1', 'SceneType'],\n    '0041': ['US', '1', 'CustomRendered'],\n    '0042': ['US', '1', 'ExposureMode'],\n    '0043': ['US', '1', 'WhiteBalance'],\n    '0044': ['DS', '1', 'DigitalZoomRatio'],\n    '0045': ['IS', '1', 'FocalLengthIn35mmFilm'],\n    '0046': ['US', '1', 'SceneCaptureType'],\n    '0047': ['US', '1', 'GainControl'],\n    '0048': ['US', '1', 'Contrast'],\n    '0049': ['US', '1', 'Saturation'],\n    '004A': ['US', '1', 'Sharpness'],\n    '004B': ['OB', '1', 'DeviceSettingDescription'],\n    '004C': ['US', '1', 'SubjectDistanceRange'],\n    '004D': ['UT', '1', 'CameraOwnerName'],\n    '004E': ['DS', '4', 'LensSpecification'],\n    '004F': ['UT', '1', 'LensMake'],\n    '0050': ['UT', '1', 'LensModel'],\n    '0051': ['UT', '1', 'LensSerialNumber'],\n    '0061': ['CS', '1', 'InteroperabilityIndex'],\n    '0062': ['OB', '1', 'InteroperabilityVersion'],\n    '0070': ['OB', '1', 'GPSVersionID'],\n    '0071': ['CS', '1', 'GPSLatitudeRef'],\n    '0072': ['DS', '3', 'GPSLatitude'],\n    '0073': ['CS', '1', 'GPSLongitudeRef'],\n    '0074': ['DS', '3', 'GPSLongitude'],\n    '0075': ['US', '1', 'GPSAltitudeRef'],\n    '0076': ['DS', '1', 'GPSAltitude'],\n    '0077': ['DT', '1', 'GPSTimeStamp'],\n    '0078': ['UT', '1', 'GPSSatellites'],\n    '0079': ['CS', '1', 'GPSStatus'],\n    '007A': ['CS', '1', 'GPSMeasureMode'],\n    '007B': ['DS', '1', 'GPSDOP'],\n    '007C': ['CS', '1', 'GPSSpeedRef'],\n    '007D': ['DS', '1', 'GPSSpeed'],\n    '007E': ['CS', '1', 'GPSTrackRef'],\n    '007F': ['DS', '1', 'GPSTrack'],\n    '0080': ['CS', '1', 'GPSImgDirectionRef'],\n    '0081': ['DS', '1', 'GPSImgDirection'],\n    '0082': ['UT', '1', 'GPSMapDatum'],\n    '0083': ['CS', '1', 'GPSDestLatitudeRef'],\n    '0084': ['DS', '3', 'GPSDestLatitude'],\n    '0085': ['CS', '1', 'GPSDestLongitudeRef'],\n    '0086': ['DS', '3', 'GPSDestLongitude'],\n    '0087': ['CS', '1', 'GPSDestBearingRef'],\n    '0088': ['DS', '1', 'GPSDestBearing'],\n    '0089': ['CS', '1', 'GPSDestDistanceRef'],\n    '008A': ['DS', '1', 'GPSDestDistance'],\n    '008B': ['OB', '1', 'GPSProcessingMethod'],\n    '008C': ['OB', '1', 'GPSAreaInformation'],\n    '008D': ['DT', '1', 'GPSDateStamp'],\n    '008E': ['IS', '1', 'GPSDifferential'],\n    '1001': ['CS', '1', 'LightSourcePolarization'],\n    '1002': ['DS', '1', 'EmitterColorTemperature'],\n    '1003': ['CS', '1', 'ContactMethod'],\n    '1004': ['CS', '1-n', 'ImmersionMedia'],\n    '1005': ['DS', '1', 'OpticalMagnificationFactor']\n  },\n  '0018': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['LO', '1', 'ContrastBolusAgent'],\n    '0012': ['SQ', '1', 'ContrastBolusAgentSequence'],\n    '0013': ['FL', '1', 'ContrastBolusT1Relaxivity'],\n    '0014': ['SQ', '1', 'ContrastBolusAdministrationRouteSequence'],\n    '0015': ['CS', '1', 'BodyPartExamined'],\n    '0020': ['CS', '1-n', 'ScanningSequence'],\n    '0021': ['CS', '1-n', 'SequenceVariant'],\n    '0022': ['CS', '1-n', 'ScanOptions'],\n    '0023': ['CS', '1', 'MRAcquisitionType'],\n    '0024': ['SH', '1', 'SequenceName'],\n    '0025': ['CS', '1', 'AngioFlag'],\n    '0026': ['SQ', '1', 'InterventionDrugInformationSequence'],\n    '0027': ['TM', '1', 'InterventionDrugStopTime'],\n    '0028': ['DS', '1', 'InterventionDrugDose'],\n    '0029': ['SQ', '1', 'InterventionDrugCodeSequence'],\n    '002A': ['SQ', '1', 'AdditionalDrugSequence'],\n    '0030': ['LO', '1-n', 'Radionuclide'],\n    '0031': ['LO', '1', 'Radiopharmaceutical'],\n    '0032': ['DS', '1', 'EnergyWindowCenterline'],\n    '0033': ['DS', '1-n', 'EnergyWindowTotalWidth'],\n    '0034': ['LO', '1', 'InterventionDrugName'],\n    '0035': ['TM', '1', 'InterventionDrugStartTime'],\n    '0036': ['SQ', '1', 'InterventionSequence'],\n    '0037': ['CS', '1', 'TherapyType'],\n    '0038': ['CS', '1', 'InterventionStatus'],\n    '0039': ['CS', '1', 'TherapyDescription'],\n    '003A': ['ST', '1', 'InterventionDescription'],\n    '0040': ['IS', '1', 'CineRate'],\n    '0042': ['CS', '1', 'InitialCineRunState'],\n    '0050': ['DS', '1', 'SliceThickness'],\n    '0060': ['DS', '1', 'KVP'],\n    '0061': ['DS', '1', ''],\n    '0070': ['IS', '1', 'CountsAccumulated'],\n    '0071': ['CS', '1', 'AcquisitionTerminationCondition'],\n    '0072': ['DS', '1', 'EffectiveDuration'],\n    '0073': ['CS', '1', 'AcquisitionStartCondition'],\n    '0074': ['IS', '1', 'AcquisitionStartConditionData'],\n    '0075': ['IS', '1', 'AcquisitionTerminationConditionData'],\n    '0080': ['DS', '1', 'RepetitionTime'],\n    '0081': ['DS', '1', 'EchoTime'],\n    '0082': ['DS', '1', 'InversionTime'],\n    '0083': ['DS', '1', 'NumberOfAverages'],\n    '0084': ['DS', '1', 'ImagingFrequency'],\n    '0085': ['SH', '1', 'ImagedNucleus'],\n    '0086': ['IS', '1-n', 'EchoNumbers'],\n    '0087': ['DS', '1', 'MagneticFieldStrength'],\n    '0088': ['DS', '1', 'SpacingBetweenSlices'],\n    '0089': ['IS', '1', 'NumberOfPhaseEncodingSteps'],\n    '0090': ['DS', '1', 'DataCollectionDiameter'],\n    '0091': ['IS', '1', 'EchoTrainLength'],\n    '0093': ['DS', '1', 'PercentSampling'],\n    '0094': ['DS', '1', 'PercentPhaseFieldOfView'],\n    '0095': ['DS', '1', 'PixelBandwidth'],\n    '1000': ['LO', '1', 'DeviceSerialNumber'],\n    '1002': ['UI', '1', 'DeviceUID'],\n    '1003': ['LO', '1', 'DeviceID'],\n    '1004': ['LO', '1', 'PlateID'],\n    '1005': ['LO', '1', 'GeneratorID'],\n    '1006': ['LO', '1', 'GridID'],\n    '1007': ['LO', '1', 'CassetteID'],\n    '1008': ['LO', '1', 'GantryID'],\n    '1009': ['UT', '1', 'UniqueDeviceIdentifier'],\n    '100A': ['SQ', '1', 'UDISequence'],\n    '100B': ['UI', '1-n', 'ManufacturerDeviceClassUID'],\n    '1010': ['LO', '1', 'SecondaryCaptureDeviceID'],\n    '1011': ['LO', '1', 'HardcopyCreationDeviceID'],\n    '1012': ['DA', '1', 'DateOfSecondaryCapture'],\n    '1014': ['TM', '1', 'TimeOfSecondaryCapture'],\n    '1016': ['LO', '1', 'SecondaryCaptureDeviceManufacturer'],\n    '1017': ['LO', '1', 'HardcopyDeviceManufacturer'],\n    '1018': ['LO', '1', 'SecondaryCaptureDeviceManufacturerModelName'],\n    '1019': ['LO', '1-n', 'SecondaryCaptureDeviceSoftwareVersions'],\n    '101A': ['LO', '1-n', 'HardcopyDeviceSoftwareVersion'],\n    '101B': ['LO', '1', 'HardcopyDeviceManufacturerModelName'],\n    '1020': ['LO', '1-n', 'SoftwareVersions'],\n    '1022': ['SH', '1', 'VideoImageFormatAcquired'],\n    '1023': ['LO', '1', 'DigitalImageFormatAcquired'],\n    '1030': ['LO', '1', 'ProtocolName'],\n    '1040': ['LO', '1', 'ContrastBolusRoute'],\n    '1041': ['DS', '1', 'ContrastBolusVolume'],\n    '1042': ['TM', '1', 'ContrastBolusStartTime'],\n    '1043': ['TM', '1', 'ContrastBolusStopTime'],\n    '1044': ['DS', '1', 'ContrastBolusTotalDose'],\n    '1045': ['IS', '1', 'SyringeCounts'],\n    '1046': ['DS', '1-n', 'ContrastFlowRate'],\n    '1047': ['DS', '1-n', 'ContrastFlowDuration'],\n    '1048': ['CS', '1', 'ContrastBolusIngredient'],\n    '1049': ['DS', '1', 'ContrastBolusIngredientConcentration'],\n    '1050': ['DS', '1', 'SpatialResolution'],\n    '1060': ['DS', '1', 'TriggerTime'],\n    '1061': ['LO', '1', 'TriggerSourceOrType'],\n    '1062': ['IS', '1', 'NominalInterval'],\n    '1063': ['DS', '1', 'FrameTime'],\n    '1064': ['LO', '1', 'CardiacFramingType'],\n    '1065': ['DS', '1-n', 'FrameTimeVector'],\n    '1066': ['DS', '1', 'FrameDelay'],\n    '1067': ['DS', '1', 'ImageTriggerDelay'],\n    '1068': ['DS', '1', 'MultiplexGroupTimeOffset'],\n    '1069': ['DS', '1', 'TriggerTimeOffset'],\n    '106A': ['CS', '1', 'SynchronizationTrigger'],\n    '106C': ['US', '2', 'SynchronizationChannel'],\n    '106E': ['UL', '1', 'TriggerSamplePosition'],\n    '1070': ['LO', '1', 'RadiopharmaceuticalRoute'],\n    '1071': ['DS', '1', 'RadiopharmaceuticalVolume'],\n    '1072': ['TM', '1', 'RadiopharmaceuticalStartTime'],\n    '1073': ['TM', '1', 'RadiopharmaceuticalStopTime'],\n    '1074': ['DS', '1', 'RadionuclideTotalDose'],\n    '1075': ['DS', '1', 'RadionuclideHalfLife'],\n    '1076': ['DS', '1', 'RadionuclidePositronFraction'],\n    '1077': ['DS', '1', 'RadiopharmaceuticalSpecificActivity'],\n    '1078': ['DT', '1', 'RadiopharmaceuticalStartDateTime'],\n    '1079': ['DT', '1', 'RadiopharmaceuticalStopDateTime'],\n    '1080': ['CS', '1', 'BeatRejectionFlag'],\n    '1081': ['IS', '1', 'LowRRValue'],\n    '1082': ['IS', '1', 'HighRRValue'],\n    '1083': ['IS', '1', 'IntervalsAcquired'],\n    '1084': ['IS', '1', 'IntervalsRejected'],\n    '1085': ['LO', '1', 'PVCRejection'],\n    '1086': ['IS', '1', 'SkipBeats'],\n    '1088': ['IS', '1', 'HeartRate'],\n    '1090': ['IS', '1', 'CardiacNumberOfImages'],\n    '1094': ['IS', '1', 'TriggerWindow'],\n    '1100': ['DS', '1', 'ReconstructionDiameter'],\n    '1110': ['DS', '1', 'DistanceSourceToDetector'],\n    '1111': ['DS', '1', 'DistanceSourceToPatient'],\n    '1114': ['DS', '1', 'EstimatedRadiographicMagnificationFactor'],\n    '1120': ['DS', '1', 'GantryDetectorTilt'],\n    '1121': ['DS', '1', 'GantryDetectorSlew'],\n    '1130': ['DS', '1', 'TableHeight'],\n    '1131': ['DS', '1', 'TableTraverse'],\n    '1134': ['CS', '1', 'TableMotion'],\n    '1135': ['DS', '1-n', 'TableVerticalIncrement'],\n    '1136': ['DS', '1-n', 'TableLateralIncrement'],\n    '1137': ['DS', '1-n', 'TableLongitudinalIncrement'],\n    '1138': ['DS', '1', 'TableAngle'],\n    '113A': ['CS', '1', 'TableType'],\n    '1140': ['CS', '1', 'RotationDirection'],\n    '1141': ['DS', '1', 'AngularPosition'],\n    '1142': ['DS', '1-n', 'RadialPosition'],\n    '1143': ['DS', '1', 'ScanArc'],\n    '1144': ['DS', '1', 'AngularStep'],\n    '1145': ['DS', '1', 'CenterOfRotationOffset'],\n    '1146': ['DS', '1-n', 'RotationOffset'],\n    '1147': ['CS', '1', 'FieldOfViewShape'],\n    '1149': ['IS', '1-2', 'FieldOfViewDimensions'],\n    '1150': ['IS', '1', 'ExposureTime'],\n    '1151': ['IS', '1', 'XRayTubeCurrent'],\n    '1152': ['IS', '1', 'Exposure'],\n    '1153': ['IS', '1', 'ExposureInuAs'],\n    '1154': ['DS', '1', 'AveragePulseWidth'],\n    '1155': ['CS', '1', 'RadiationSetting'],\n    '1156': ['CS', '1', 'RectificationType'],\n    '115A': ['CS', '1', 'RadiationMode'],\n    '115E': ['DS', '1', 'ImageAndFluoroscopyAreaDoseProduct'],\n    '1160': ['SH', '1', 'FilterType'],\n    '1161': ['LO', '1-n', 'TypeOfFilters'],\n    '1162': ['DS', '1', 'IntensifierSize'],\n    '1164': ['DS', '2', 'ImagerPixelSpacing'],\n    '1166': ['CS', '1-n', 'Grid'],\n    '1170': ['IS', '1', 'GeneratorPower'],\n    '1180': ['SH', '1', 'CollimatorGridName'],\n    '1181': ['CS', '1', 'CollimatorType'],\n    '1182': ['IS', '1-2', 'FocalDistance'],\n    '1183': ['DS', '1-2', 'XFocusCenter'],\n    '1184': ['DS', '1-2', 'YFocusCenter'],\n    '1190': ['DS', '1-n', 'FocalSpots'],\n    '1191': ['CS', '1', 'AnodeTargetMaterial'],\n    '11A0': ['DS', '1', 'BodyPartThickness'],\n    '11A2': ['DS', '1', 'CompressionForce'],\n    '11A3': ['DS', '1', 'CompressionPressure'],\n    '11A4': ['LO', '1', 'PaddleDescription'],\n    '11A5': ['DS', '1', 'CompressionContactArea'],\n    '11B0': ['LO', '1', 'AcquisitionMode'],\n    '11B1': ['LO', '1', 'DoseModeName'],\n    '11B2': ['CS', '1', 'AcquiredSubtractionMaskFlag'],\n    '11B3': ['CS', '1', 'FluoroscopyPersistenceFlag'],\n    '11B4': ['CS', '1', 'FluoroscopyLastImageHoldPersistenceFlag'],\n    '11B5': ['IS', '1', 'UpperLimitNumberOfPersistentFluoroscopyFrames'],\n    '11B6': ['CS', '1', 'ContrastBolusAutoInjectionTriggerFlag'],\n    '11B7': ['FD', '1', 'ContrastBolusInjectionDelay'],\n    '11B8': ['SQ', '1', 'XAAcquisitionPhaseDetailsSequence'],\n    '11B9': ['FD', '1', 'XAAcquisitionFrameRate'],\n    '11BA': ['SQ', '1', 'XAPlaneDetailsSequence'],\n    '11BB': ['LO', '1', 'AcquisitionFieldOfViewLabel'],\n    '11BC': ['SQ', '1', 'XRayFilterDetailsSequence'],\n    '11BD': ['FD', '1', 'XAAcquisitionDuration'],\n    '11BE': ['CS', '1', 'ReconstructionPipelineType'],\n    '11BF': ['SQ', '1', 'ImageFilterDetailsSequence'],\n    '11C0': ['CS', '1', 'AppliedMaskSubtractionFlag'],\n    '11C1': ['SQ', '1', 'RequestedSeriesDescriptionCodeSequence'],\n    '1200': ['DA', '1-n', 'DateOfLastCalibration'],\n    '1201': ['TM', '1-n', 'TimeOfLastCalibration'],\n    '1202': ['DT', '1', 'DateTimeOfLastCalibration'],\n    '1203': ['DT', '1', 'CalibrationDateTime'],\n    '1210': ['SH', '1-n', 'ConvolutionKernel'],\n    '1240': ['IS', '1-n', 'UpperLowerPixelValues'],\n    '1242': ['IS', '1', 'ActualFrameDuration'],\n    '1243': ['IS', '1', 'CountRate'],\n    '1244': ['US', '1', 'PreferredPlaybackSequencing'],\n    '1250': ['SH', '1', 'ReceiveCoilName'],\n    '1251': ['SH', '1', 'TransmitCoilName'],\n    '1260': ['SH', '1', 'PlateType'],\n    '1261': ['LO', '1', 'PhosphorType'],\n    '1271': ['FD', '1', 'WaterEquivalentDiameter'],\n    '1272': ['SQ', '1', 'WaterEquivalentDiameterCalculationMethodCodeSequence'],\n    '1300': ['DS', '1', 'ScanVelocity'],\n    '1301': ['CS', '1-n', 'WholeBodyTechnique'],\n    '1302': ['IS', '1', 'ScanLength'],\n    '1310': ['US', '4', 'AcquisitionMatrix'],\n    '1312': ['CS', '1', 'InPlanePhaseEncodingDirection'],\n    '1314': ['DS', '1', 'FlipAngle'],\n    '1315': ['CS', '1', 'VariableFlipAngleFlag'],\n    '1316': ['DS', '1', 'SAR'],\n    '1318': ['DS', '1', 'dBdt'],\n    '1320': ['FL', '1', 'B1rms'],\n    '1400': ['LO', '1', 'AcquisitionDeviceProcessingDescription'],\n    '1401': ['LO', '1', 'AcquisitionDeviceProcessingCode'],\n    '1402': ['CS', '1', 'CassetteOrientation'],\n    '1403': ['CS', '1', 'CassetteSize'],\n    '1404': ['US', '1', 'ExposuresOnPlate'],\n    '1405': ['IS', '1', 'RelativeXRayExposure'],\n    '1411': ['DS', '1', 'ExposureIndex'],\n    '1412': ['DS', '1', 'TargetExposureIndex'],\n    '1413': ['DS', '1', 'DeviationIndex'],\n    '1450': ['DS', '1', 'ColumnAngulation'],\n    '1460': ['DS', '1', 'TomoLayerHeight'],\n    '1470': ['DS', '1', 'TomoAngle'],\n    '1480': ['DS', '1', 'TomoTime'],\n    '1490': ['CS', '1', 'TomoType'],\n    '1491': ['CS', '1', 'TomoClass'],\n    '1495': ['IS', '1', 'NumberOfTomosynthesisSourceImages'],\n    '1500': ['CS', '1', 'PositionerMotion'],\n    '1508': ['CS', '1', 'PositionerType'],\n    '1510': ['DS', '1', 'PositionerPrimaryAngle'],\n    '1511': ['DS', '1', 'PositionerSecondaryAngle'],\n    '1520': ['DS', '1-n', 'PositionerPrimaryAngleIncrement'],\n    '1521': ['DS', '1-n', 'PositionerSecondaryAngleIncrement'],\n    '1530': ['DS', '1', 'DetectorPrimaryAngle'],\n    '1531': ['DS', '1', 'DetectorSecondaryAngle'],\n    '1600': ['CS', '1-3', 'ShutterShape'],\n    '1602': ['IS', '1', 'ShutterLeftVerticalEdge'],\n    '1604': ['IS', '1', 'ShutterRightVerticalEdge'],\n    '1606': ['IS', '1', 'ShutterUpperHorizontalEdge'],\n    '1608': ['IS', '1', 'ShutterLowerHorizontalEdge'],\n    '1610': ['IS', '2', 'CenterOfCircularShutter'],\n    '1612': ['IS', '1', 'RadiusOfCircularShutter'],\n    '1620': ['IS', '2-2n', 'VerticesOfThePolygonalShutter'],\n    '1622': ['US', '1', 'ShutterPresentationValue'],\n    '1623': ['US', '1', 'ShutterOverlayGroup'],\n    '1624': ['US', '3', 'ShutterPresentationColorCIELabValue'],\n    '1630': ['CS', '1', 'OutlineShapeType'],\n    '1631': ['FD', '1', 'OutlineLeftVerticalEdge'],\n    '1632': ['FD', '1', 'OutlineRightVerticalEdge'],\n    '1633': ['FD', '1', 'OutlineUpperHorizontalEdge'],\n    '1634': ['FD', '1', 'OutlineLowerHorizontalEdge'],\n    '1635': ['FD', '2', 'CenterOfCircularOutline'],\n    '1636': ['FD', '1', 'DiameterOfCircularOutline'],\n    '1637': ['UL', '1', 'NumberOfPolygonalVertices'],\n    '1638': ['OF', '1', 'VerticesOfThePolygonalOutline'],\n    '1700': ['CS', '1-3', 'CollimatorShape'],\n    '1702': ['IS', '1', 'CollimatorLeftVerticalEdge'],\n    '1704': ['IS', '1', 'CollimatorRightVerticalEdge'],\n    '1706': ['IS', '1', 'CollimatorUpperHorizontalEdge'],\n    '1708': ['IS', '1', 'CollimatorLowerHorizontalEdge'],\n    '1710': ['IS', '2', 'CenterOfCircularCollimator'],\n    '1712': ['IS', '1', 'RadiusOfCircularCollimator'],\n    '1720': ['IS', '2-2n', 'VerticesOfThePolygonalCollimator'],\n    '1800': ['CS', '1', 'AcquisitionTimeSynchronized'],\n    '1801': ['SH', '1', 'TimeSource'],\n    '1802': ['CS', '1', 'TimeDistributionProtocol'],\n    '1803': ['LO', '1', 'NTPSourceAddress'],\n    '2001': ['IS', '1-n', 'PageNumberVector'],\n    '2002': ['SH', '1-n', 'FrameLabelVector'],\n    '2003': ['DS', '1-n', 'FramePrimaryAngleVector'],\n    '2004': ['DS', '1-n', 'FrameSecondaryAngleVector'],\n    '2005': ['DS', '1-n', 'SliceLocationVector'],\n    '2006': ['SH', '1-n', 'DisplayWindowLabelVector'],\n    '2010': ['DS', '2', 'NominalScannedPixelSpacing'],\n    '2020': ['CS', '1', 'DigitizingDeviceTransportDirection'],\n    '2030': ['DS', '1', 'RotationOfScannedFilm'],\n    '2041': ['SQ', '1', 'BiopsyTargetSequence'],\n    '2042': ['UI', '1', 'TargetUID'],\n    '2043': ['FL', '2', 'LocalizingCursorPosition'],\n    '2044': ['FL', '3', 'CalculatedTargetPosition'],\n    '2045': ['SH', '1', 'TargetLabel'],\n    '2046': ['FL', '1', 'DisplayedZValue'],\n    '3100': ['CS', '1', 'IVUSAcquisition'],\n    '3101': ['DS', '1', 'IVUSPullbackRate'],\n    '3102': ['DS', '1', 'IVUSGatedRate'],\n    '3103': ['IS', '1', 'IVUSPullbackStartFrameNumber'],\n    '3104': ['IS', '1', 'IVUSPullbackStopFrameNumber'],\n    '3105': ['IS', '1-n', 'LesionNumber'],\n    '4000': ['LT', '1', 'AcquisitionComments'],\n    '5000': ['SH', '1-n', 'OutputPower'],\n    '5010': ['LO', '1-n', 'TransducerData'],\n    '5011': ['SQ', '1', 'TransducerIdentificationSequence'],\n    '5012': ['DS', '1', 'FocusDepth'],\n    '5020': ['LO', '1', 'ProcessingFunction'],\n    '5021': ['LO', '1', 'PostprocessingFunction'],\n    '5022': ['DS', '1', 'MechanicalIndex'],\n    '5024': ['DS', '1', 'BoneThermalIndex'],\n    '5026': ['DS', '1', 'CranialThermalIndex'],\n    '5027': ['DS', '1', 'SoftTissueThermalIndex'],\n    '5028': ['DS', '1', 'SoftTissueFocusThermalIndex'],\n    '5029': ['DS', '1', 'SoftTissueSurfaceThermalIndex'],\n    '5030': ['DS', '1', 'DynamicRange'],\n    '5040': ['DS', '1', 'TotalGain'],\n    '5050': ['IS', '1', 'DepthOfScanField'],\n    '5100': ['CS', '1', 'PatientPosition'],\n    '5101': ['CS', '1', 'ViewPosition'],\n    '5104': ['SQ', '1', 'ProjectionEponymousNameCodeSequence'],\n    '5210': ['DS', '6', 'ImageTransformationMatrix'],\n    '5212': ['DS', '3', 'ImageTranslationVector'],\n    '6000': ['DS', '1', 'Sensitivity'],\n    '6011': ['SQ', '1', 'SequenceOfUltrasoundRegions'],\n    '6012': ['US', '1', 'RegionSpatialFormat'],\n    '6014': ['US', '1', 'RegionDataType'],\n    '6016': ['UL', '1', 'RegionFlags'],\n    '6018': ['UL', '1', 'RegionLocationMinX0'],\n    '601A': ['UL', '1', 'RegionLocationMinY0'],\n    '601C': ['UL', '1', 'RegionLocationMaxX1'],\n    '601E': ['UL', '1', 'RegionLocationMaxY1'],\n    '6020': ['SL', '1', 'ReferencePixelX0'],\n    '6022': ['SL', '1', 'ReferencePixelY0'],\n    '6024': ['US', '1', 'PhysicalUnitsXDirection'],\n    '6026': ['US', '1', 'PhysicalUnitsYDirection'],\n    '6028': ['FD', '1', 'ReferencePixelPhysicalValueX'],\n    '602A': ['FD', '1', 'ReferencePixelPhysicalValueY'],\n    '602C': ['FD', '1', 'PhysicalDeltaX'],\n    '602E': ['FD', '1', 'PhysicalDeltaY'],\n    '6030': ['UL', '1', 'TransducerFrequency'],\n    '6031': ['CS', '1', 'TransducerType'],\n    '6032': ['UL', '1', 'PulseRepetitionFrequency'],\n    '6034': ['FD', '1', 'DopplerCorrectionAngle'],\n    '6036': ['FD', '1', 'SteeringAngle'],\n    '6038': ['UL', '1', 'DopplerSampleVolumeXPositionRetired'],\n    '6039': ['SL', '1', 'DopplerSampleVolumeXPosition'],\n    '603A': ['UL', '1', 'DopplerSampleVolumeYPositionRetired'],\n    '603B': ['SL', '1', 'DopplerSampleVolumeYPosition'],\n    '603C': ['UL', '1', 'TMLinePositionX0Retired'],\n    '603D': ['SL', '1', 'TMLinePositionX0'],\n    '603E': ['UL', '1', 'TMLinePositionY0Retired'],\n    '603F': ['SL', '1', 'TMLinePositionY0'],\n    '6040': ['UL', '1', 'TMLinePositionX1Retired'],\n    '6041': ['SL', '1', 'TMLinePositionX1'],\n    '6042': ['UL', '1', 'TMLinePositionY1Retired'],\n    '6043': ['SL', '1', 'TMLinePositionY1'],\n    '6044': ['US', '1', 'PixelComponentOrganization'],\n    '6046': ['UL', '1', 'PixelComponentMask'],\n    '6048': ['UL', '1', 'PixelComponentRangeStart'],\n    '604A': ['UL', '1', 'PixelComponentRangeStop'],\n    '604C': ['US', '1', 'PixelComponentPhysicalUnits'],\n    '604E': ['US', '1', 'PixelComponentDataType'],\n    '6050': ['UL', '1', 'NumberOfTableBreakPoints'],\n    '6052': ['UL', '1-n', 'TableOfXBreakPoints'],\n    '6054': ['FD', '1-n', 'TableOfYBreakPoints'],\n    '6056': ['UL', '1', 'NumberOfTableEntries'],\n    '6058': ['UL', '1-n', 'TableOfPixelValues'],\n    '605A': ['FL', '1-n', 'TableOfParameterValues'],\n    '6060': ['FL', '1-n', 'RWaveTimeVector'],\n    '6070': ['US', '1', 'ActiveImageAreaOverlayGroup'],\n    '7000': ['CS', '1', 'DetectorConditionsNominalFlag'],\n    '7001': ['DS', '1', 'DetectorTemperature'],\n    '7004': ['CS', '1', 'DetectorType'],\n    '7005': ['CS', '1', 'DetectorConfiguration'],\n    '7006': ['LT', '1', 'DetectorDescription'],\n    '7008': ['LT', '1', 'DetectorMode'],\n    '700A': ['SH', '1', 'DetectorID'],\n    '700C': ['DA', '1', 'DateOfLastDetectorCalibration'],\n    '700E': ['TM', '1', 'TimeOfLastDetectorCalibration'],\n    '7010': ['IS', '1', 'ExposuresOnDetectorSinceLastCalibration'],\n    '7011': ['IS', '1', 'ExposuresOnDetectorSinceManufactured'],\n    '7012': ['DS', '1', 'DetectorTimeSinceLastExposure'],\n    '7014': ['DS', '1', 'DetectorActiveTime'],\n    '7016': ['DS', '1', 'DetectorActivationOffsetFromExposure'],\n    '701A': ['DS', '2', 'DetectorBinning'],\n    '7020': ['DS', '2', 'DetectorElementPhysicalSize'],\n    '7022': ['DS', '2', 'DetectorElementSpacing'],\n    '7024': ['CS', '1', 'DetectorActiveShape'],\n    '7026': ['DS', '1-2', 'DetectorActiveDimensions'],\n    '7028': ['DS', '2', 'DetectorActiveOrigin'],\n    '702A': ['LO', '1', 'DetectorManufacturerName'],\n    '702B': ['LO', '1', 'DetectorManufacturerModelName'],\n    '7030': ['DS', '2', 'FieldOfViewOrigin'],\n    '7032': ['DS', '1', 'FieldOfViewRotation'],\n    '7034': ['CS', '1', 'FieldOfViewHorizontalFlip'],\n    '7036': ['FL', '2', 'PixelDataAreaOriginRelativeToFOV'],\n    '7038': ['FL', '1', 'PixelDataAreaRotationAngleRelativeToFOV'],\n    '7040': ['LT', '1', 'GridAbsorbingMaterial'],\n    '7041': ['LT', '1', 'GridSpacingMaterial'],\n    '7042': ['DS', '1', 'GridThickness'],\n    '7044': ['DS', '1', 'GridPitch'],\n    '7046': ['IS', '2', 'GridAspectRatio'],\n    '7048': ['DS', '1', 'GridPeriod'],\n    '704C': ['DS', '1', 'GridFocalDistance'],\n    '7050': ['CS', '1-n', 'FilterMaterial'],\n    '7052': ['DS', '1-n', 'FilterThicknessMinimum'],\n    '7054': ['DS', '1-n', 'FilterThicknessMaximum'],\n    '7056': ['FL', '1-n', 'FilterBeamPathLengthMinimum'],\n    '7058': ['FL', '1-n', 'FilterBeamPathLengthMaximum'],\n    '7060': ['CS', '1', 'ExposureControlMode'],\n    '7062': ['LT', '1', 'ExposureControlModeDescription'],\n    '7064': ['CS', '1', 'ExposureStatus'],\n    '7065': ['DS', '1', 'PhototimerSetting'],\n    '8150': ['DS', '1', 'ExposureTimeInuS'],\n    '8151': ['DS', '1', 'XRayTubeCurrentInuA'],\n    '9004': ['CS', '1', 'ContentQualification'],\n    '9005': ['SH', '1', 'PulseSequenceName'],\n    '9006': ['SQ', '1', 'MRImagingModifierSequence'],\n    '9008': ['CS', '1', 'EchoPulseSequence'],\n    '9009': ['CS', '1', 'InversionRecovery'],\n    '9010': ['CS', '1', 'FlowCompensation'],\n    '9011': ['CS', '1', 'MultipleSpinEcho'],\n    '9012': ['CS', '1', 'MultiPlanarExcitation'],\n    '9014': ['CS', '1', 'PhaseContrast'],\n    '9015': ['CS', '1', 'TimeOfFlightContrast'],\n    '9016': ['CS', '1', 'Spoiling'],\n    '9017': ['CS', '1', 'SteadyStatePulseSequence'],\n    '9018': ['CS', '1', 'EchoPlanarPulseSequence'],\n    '9019': ['FD', '1', 'TagAngleFirstAxis'],\n    '9020': ['CS', '1', 'MagnetizationTransfer'],\n    '9021': ['CS', '1', 'T2Preparation'],\n    '9022': ['CS', '1', 'BloodSignalNulling'],\n    '9024': ['CS', '1', 'SaturationRecovery'],\n    '9025': ['CS', '1', 'SpectrallySelectedSuppression'],\n    '9026': ['CS', '1', 'SpectrallySelectedExcitation'],\n    '9027': ['CS', '1', 'SpatialPresaturation'],\n    '9028': ['CS', '1', 'Tagging'],\n    '9029': ['CS', '1', 'OversamplingPhase'],\n    '9030': ['FD', '1', 'TagSpacingFirstDimension'],\n    '9032': ['CS', '1', 'GeometryOfKSpaceTraversal'],\n    '9033': ['CS', '1', 'SegmentedKSpaceTraversal'],\n    '9034': ['CS', '1', 'RectilinearPhaseEncodeReordering'],\n    '9035': ['FD', '1', 'TagThickness'],\n    '9036': ['CS', '1', 'PartialFourierDirection'],\n    '9037': ['CS', '1', 'CardiacSynchronizationTechnique'],\n    '9041': ['LO', '1', 'ReceiveCoilManufacturerName'],\n    '9042': ['SQ', '1', 'MRReceiveCoilSequence'],\n    '9043': ['CS', '1', 'ReceiveCoilType'],\n    '9044': ['CS', '1', 'QuadratureReceiveCoil'],\n    '9045': ['SQ', '1', 'MultiCoilDefinitionSequence'],\n    '9046': ['LO', '1', 'MultiCoilConfiguration'],\n    '9047': ['SH', '1', 'MultiCoilElementName'],\n    '9048': ['CS', '1', 'MultiCoilElementUsed'],\n    '9049': ['SQ', '1', 'MRTransmitCoilSequence'],\n    '9050': ['LO', '1', 'TransmitCoilManufacturerName'],\n    '9051': ['CS', '1', 'TransmitCoilType'],\n    '9052': ['FD', '1-2', 'SpectralWidth'],\n    '9053': ['FD', '1-2', 'ChemicalShiftReference'],\n    '9054': ['CS', '1', 'VolumeLocalizationTechnique'],\n    '9058': ['US', '1', 'MRAcquisitionFrequencyEncodingSteps'],\n    '9059': ['CS', '1', 'Decoupling'],\n    '9060': ['CS', '1-2', 'DecoupledNucleus'],\n    '9061': ['FD', '1-2', 'DecouplingFrequency'],\n    '9062': ['CS', '1', 'DecouplingMethod'],\n    '9063': ['FD', '1-2', 'DecouplingChemicalShiftReference'],\n    '9064': ['CS', '1', 'KSpaceFiltering'],\n    '9065': ['CS', '1-2', 'TimeDomainFiltering'],\n    '9066': ['US', '1-2', 'NumberOfZeroFills'],\n    '9067': ['CS', '1', 'BaselineCorrection'],\n    '9069': ['FD', '1', 'ParallelReductionFactorInPlane'],\n    '9070': ['FD', '1', 'CardiacRRIntervalSpecified'],\n    '9073': ['FD', '1', 'AcquisitionDuration'],\n    '9074': ['DT', '1', 'FrameAcquisitionDateTime'],\n    '9075': ['CS', '1', 'DiffusionDirectionality'],\n    '9076': ['SQ', '1', 'DiffusionGradientDirectionSequence'],\n    '9077': ['CS', '1', 'ParallelAcquisition'],\n    '9078': ['CS', '1', 'ParallelAcquisitionTechnique'],\n    '9079': ['FD', '1-n', 'InversionTimes'],\n    '9080': ['ST', '1', 'MetaboliteMapDescription'],\n    '9081': ['CS', '1', 'PartialFourier'],\n    '9082': ['FD', '1', 'EffectiveEchoTime'],\n    '9083': ['SQ', '1', 'MetaboliteMapCodeSequence'],\n    '9084': ['SQ', '1', 'ChemicalShiftSequence'],\n    '9085': ['CS', '1', 'CardiacSignalSource'],\n    '9087': ['FD', '1', 'DiffusionBValue'],\n    '9089': ['FD', '3', 'DiffusionGradientOrientation'],\n    '9090': ['FD', '3', 'VelocityEncodingDirection'],\n    '9091': ['FD', '1', 'VelocityEncodingMinimumValue'],\n    '9092': ['SQ', '1', 'VelocityEncodingAcquisitionSequence'],\n    '9093': ['US', '1', 'NumberOfKSpaceTrajectories'],\n    '9094': ['CS', '1', 'CoverageOfKSpace'],\n    '9095': ['UL', '1', 'SpectroscopyAcquisitionPhaseRows'],\n    '9096': ['FD', '1', 'ParallelReductionFactorInPlaneRetired'],\n    '9098': ['FD', '1-2', 'TransmitterFrequency'],\n    '9100': ['CS', '1-2', 'ResonantNucleus'],\n    '9101': ['CS', '1', 'FrequencyCorrection'],\n    '9103': ['SQ', '1', 'MRSpectroscopyFOVGeometrySequence'],\n    '9104': ['FD', '1', 'SlabThickness'],\n    '9105': ['FD', '3', 'SlabOrientation'],\n    '9106': ['FD', '3', 'MidSlabPosition'],\n    '9107': ['SQ', '1', 'MRSpatialSaturationSequence'],\n    '9112': ['SQ', '1', 'MRTimingAndRelatedParametersSequence'],\n    '9114': ['SQ', '1', 'MREchoSequence'],\n    '9115': ['SQ', '1', 'MRModifierSequence'],\n    '9117': ['SQ', '1', 'MRDiffusionSequence'],\n    '9118': ['SQ', '1', 'CardiacSynchronizationSequence'],\n    '9119': ['SQ', '1', 'MRAveragesSequence'],\n    '9125': ['SQ', '1', 'MRFOVGeometrySequence'],\n    '9126': ['SQ', '1', 'VolumeLocalizationSequence'],\n    '9127': ['UL', '1', 'SpectroscopyAcquisitionDataColumns'],\n    '9147': ['CS', '1', 'DiffusionAnisotropyType'],\n    '9151': ['DT', '1', 'FrameReferenceDateTime'],\n    '9152': ['SQ', '1', 'MRMetaboliteMapSequence'],\n    '9155': ['FD', '1', 'ParallelReductionFactorOutOfPlane'],\n    '9159': ['UL', '1', 'SpectroscopyAcquisitionOutOfPlanePhaseSteps'],\n    '9166': ['CS', '1', 'BulkMotionStatus'],\n    '9168': ['FD', '1', 'ParallelReductionFactorSecondInPlane'],\n    '9169': ['CS', '1', 'CardiacBeatRejectionTechnique'],\n    '9170': ['CS', '1', 'RespiratoryMotionCompensationTechnique'],\n    '9171': ['CS', '1', 'RespiratorySignalSource'],\n    '9172': ['CS', '1', 'BulkMotionCompensationTechnique'],\n    '9173': ['CS', '1', 'BulkMotionSignalSource'],\n    '9174': ['CS', '1', 'ApplicableSafetyStandardAgency'],\n    '9175': ['LO', '1', 'ApplicableSafetyStandardDescription'],\n    '9176': ['SQ', '1', 'OperatingModeSequence'],\n    '9177': ['CS', '1', 'OperatingModeType'],\n    '9178': ['CS', '1', 'OperatingMode'],\n    '9179': ['CS', '1', 'SpecificAbsorptionRateDefinition'],\n    '9180': ['CS', '1', 'GradientOutputType'],\n    '9181': ['FD', '1', 'SpecificAbsorptionRateValue'],\n    '9182': ['FD', '1', 'GradientOutput'],\n    '9183': ['CS', '1', 'FlowCompensationDirection'],\n    '9184': ['FD', '1', 'TaggingDelay'],\n    '9185': ['ST', '1', 'RespiratoryMotionCompensationTechniqueDescription'],\n    '9186': ['SH', '1', 'RespiratorySignalSourceID'],\n    '9195': ['FD', '1', 'ChemicalShiftMinimumIntegrationLimitInHz'],\n    '9196': ['FD', '1', 'ChemicalShiftMaximumIntegrationLimitInHz'],\n    '9197': ['SQ', '1', 'MRVelocityEncodingSequence'],\n    '9198': ['CS', '1', 'FirstOrderPhaseCorrection'],\n    '9199': ['CS', '1', 'WaterReferencedPhaseCorrection'],\n    '9200': ['CS', '1', 'MRSpectroscopyAcquisitionType'],\n    '9214': ['CS', '1', 'RespiratoryCyclePosition'],\n    '9217': ['FD', '1', 'VelocityEncodingMaximumValue'],\n    '9218': ['FD', '1', 'TagSpacingSecondDimension'],\n    '9219': ['SS', '1', 'TagAngleSecondAxis'],\n    '9220': ['FD', '1', 'FrameAcquisitionDuration'],\n    '9226': ['SQ', '1', 'MRImageFrameTypeSequence'],\n    '9227': ['SQ', '1', 'MRSpectroscopyFrameTypeSequence'],\n    '9231': ['US', '1', 'MRAcquisitionPhaseEncodingStepsInPlane'],\n    '9232': ['US', '1', 'MRAcquisitionPhaseEncodingStepsOutOfPlane'],\n    '9234': ['UL', '1', 'SpectroscopyAcquisitionPhaseColumns'],\n    '9236': ['CS', '1', 'CardiacCyclePosition'],\n    '9239': ['SQ', '1', 'SpecificAbsorptionRateSequence'],\n    '9240': ['US', '1', 'RFEchoTrainLength'],\n    '9241': ['US', '1', 'GradientEchoTrainLength'],\n    '9250': ['CS', '1', 'ArterialSpinLabelingContrast'],\n    '9251': ['SQ', '1', 'MRArterialSpinLabelingSequence'],\n    '9252': ['LO', '1', 'ASLTechniqueDescription'],\n    '9253': ['US', '1', 'ASLSlabNumber'],\n    '9254': ['FD', '1', 'ASLSlabThickness'],\n    '9255': ['FD', '3', 'ASLSlabOrientation'],\n    '9256': ['FD', '3', 'ASLMidSlabPosition'],\n    '9257': ['CS', '1', 'ASLContext'],\n    '9258': ['UL', '1', 'ASLPulseTrainDuration'],\n    '9259': ['CS', '1', 'ASLCrusherFlag'],\n    '925A': ['FD', '1', 'ASLCrusherFlowLimit'],\n    '925B': ['LO', '1', 'ASLCrusherDescription'],\n    '925C': ['CS', '1', 'ASLBolusCutoffFlag'],\n    '925D': ['SQ', '1', 'ASLBolusCutoffTimingSequence'],\n    '925E': ['LO', '1', 'ASLBolusCutoffTechnique'],\n    '925F': ['UL', '1', 'ASLBolusCutoffDelayTime'],\n    '9260': ['SQ', '1', 'ASLSlabSequence'],\n    '9295': ['FD', '1', 'ChemicalShiftMinimumIntegrationLimitInppm'],\n    '9296': ['FD', '1', 'ChemicalShiftMaximumIntegrationLimitInppm'],\n    '9297': ['CS', '1', 'WaterReferenceAcquisition'],\n    '9298': ['IS', '1', 'EchoPeakPosition'],\n    '9301': ['SQ', '1', 'CTAcquisitionTypeSequence'],\n    '9302': ['CS', '1', 'AcquisitionType'],\n    '9303': ['FD', '1', 'TubeAngle'],\n    '9304': ['SQ', '1', 'CTAcquisitionDetailsSequence'],\n    '9305': ['FD', '1', 'RevolutionTime'],\n    '9306': ['FD', '1', 'SingleCollimationWidth'],\n    '9307': ['FD', '1', 'TotalCollimationWidth'],\n    '9308': ['SQ', '1', 'CTTableDynamicsSequence'],\n    '9309': ['FD', '1', 'TableSpeed'],\n    '9310': ['FD', '1', 'TableFeedPerRotation'],\n    '9311': ['FD', '1', 'SpiralPitchFactor'],\n    '9312': ['SQ', '1', 'CTGeometrySequence'],\n    '9313': ['FD', '3', 'DataCollectionCenterPatient'],\n    '9314': ['SQ', '1', 'CTReconstructionSequence'],\n    '9315': ['CS', '1', 'ReconstructionAlgorithm'],\n    '9316': ['CS', '1', 'ConvolutionKernelGroup'],\n    '9317': ['FD', '2', 'ReconstructionFieldOfView'],\n    '9318': ['FD', '3', 'ReconstructionTargetCenterPatient'],\n    '9319': ['FD', '1', 'ReconstructionAngle'],\n    '9320': ['SH', '1', 'ImageFilter'],\n    '9321': ['SQ', '1', 'CTExposureSequence'],\n    '9322': ['FD', '2', 'ReconstructionPixelSpacing'],\n    '9323': ['CS', '1-n', 'ExposureModulationType'],\n    '9324': ['FD', '1', 'EstimatedDoseSaving'],\n    '9325': ['SQ', '1', 'CTXRayDetailsSequence'],\n    '9326': ['SQ', '1', 'CTPositionSequence'],\n    '9327': ['FD', '1', 'TablePosition'],\n    '9328': ['FD', '1', 'ExposureTimeInms'],\n    '9329': ['SQ', '1', 'CTImageFrameTypeSequence'],\n    '9330': ['FD', '1', 'XRayTubeCurrentInmA'],\n    '9332': ['FD', '1', 'ExposureInmAs'],\n    '9333': ['CS', '1', 'ConstantVolumeFlag'],\n    '9334': ['CS', '1', 'FluoroscopyFlag'],\n    '9335': ['FD', '1', 'DistanceSourceToDataCollectionCenter'],\n    '9337': ['US', '1', 'ContrastBolusAgentNumber'],\n    '9338': ['SQ', '1', 'ContrastBolusIngredientCodeSequence'],\n    '9340': ['SQ', '1', 'ContrastAdministrationProfileSequence'],\n    '9341': ['SQ', '1', 'ContrastBolusUsageSequence'],\n    '9342': ['CS', '1', 'ContrastBolusAgentAdministered'],\n    '9343': ['CS', '1', 'ContrastBolusAgentDetected'],\n    '9344': ['CS', '1', 'ContrastBolusAgentPhase'],\n    '9345': ['FD', '1', 'CTDIvol'],\n    '9346': ['SQ', '1', 'CTDIPhantomTypeCodeSequence'],\n    '9351': ['FL', '1', 'CalciumScoringMassFactorPatient'],\n    '9352': ['FL', '3', 'CalciumScoringMassFactorDevice'],\n    '9353': ['FL', '1', 'EnergyWeightingFactor'],\n    '9360': ['SQ', '1', 'CTAdditionalXRaySourceSequence'],\n    '9361': ['CS', '1', 'MultienergyCTAcquisition'],\n    '9362': ['SQ', '1', 'MultienergyCTAcquisitionSequence'],\n    '9363': ['SQ', '1', 'MultienergyCTProcessingSequence'],\n    '9364': ['SQ', '1', 'MultienergyCTCharacteristicsSequence'],\n    '9365': ['SQ', '1', 'MultienergyCTXRaySourceSequence'],\n    '9366': ['US', '1', 'XRaySourceIndex'],\n    '9367': ['UC', '1', 'XRaySourceID'],\n    '9368': ['CS', '1', 'MultienergySourceTechnique'],\n    '9369': ['DT', '1', 'SourceStartDateTime'],\n    '936A': ['DT', '1', 'SourceEndDateTime'],\n    '936B': ['US', '1', 'SwitchingPhaseNumber'],\n    '936C': ['DS', '1', 'SwitchingPhaseNominalDuration'],\n    '936D': ['DS', '1', 'SwitchingPhaseTransitionDuration'],\n    '936E': ['DS', '1', 'EffectiveBinEnergy'],\n    '936F': ['SQ', '1', 'MultienergyCTXRayDetectorSequence'],\n    '9370': ['US', '1', 'XRayDetectorIndex'],\n    '9371': ['UC', '1', 'XRayDetectorID'],\n    '9372': ['CS', '1', 'MultienergyDetectorType'],\n    '9373': ['ST', '1', 'XRayDetectorLabel'],\n    '9374': ['DS', '1', 'NominalMaxEnergy'],\n    '9375': ['DS', '1', 'NominalMinEnergy'],\n    '9376': ['US', '1-n', 'ReferencedXRayDetectorIndex'],\n    '9377': ['US', '1-n', 'ReferencedXRaySourceIndex'],\n    '9378': ['US', '1-n', 'ReferencedPathIndex'],\n    '9379': ['SQ', '1', 'MultienergyCTPathSequence'],\n    '937A': ['US', '1', 'MultienergyCTPathIndex'],\n    '937B': ['UT', '1', 'MultienergyAcquisitionDescription'],\n    '937C': ['FD', '1', 'MonoenergeticEnergyEquivalent'],\n    '937D': ['SQ', '1', 'MaterialCodeSequence'],\n    '937E': ['CS', '1', 'DecompositionMethod'],\n    '937F': ['UT', '1', 'DecompositionDescription'],\n    '9380': ['SQ', '1', 'DecompositionAlgorithmIdentificationSequence'],\n    '9381': ['SQ', '1', 'DecompositionMaterialSequence'],\n    '9382': ['SQ', '1', 'MaterialAttenuationSequence'],\n    '9383': ['DS', '1', 'PhotonEnergy'],\n    '9384': ['DS', '1', 'XRayMassAttenuationCoefficient'],\n    '9401': ['SQ', '1', 'ProjectionPixelCalibrationSequence'],\n    '9402': ['FL', '1', 'DistanceSourceToIsocenter'],\n    '9403': ['FL', '1', 'DistanceObjectToTableTop'],\n    '9404': ['FL', '2', 'ObjectPixelSpacingInCenterOfBeam'],\n    '9405': ['SQ', '1', 'PositionerPositionSequence'],\n    '9406': ['SQ', '1', 'TablePositionSequence'],\n    '9407': ['SQ', '1', 'CollimatorShapeSequence'],\n    '9410': ['CS', '1', 'PlanesInAcquisition'],\n    '9412': ['SQ', '1', 'XAXRFFrameCharacteristicsSequence'],\n    '9417': ['SQ', '1', 'FrameAcquisitionSequence'],\n    '9420': ['CS', '1', 'XRayReceptorType'],\n    '9423': ['LO', '1', 'AcquisitionProtocolName'],\n    '9424': ['LT', '1', 'AcquisitionProtocolDescription'],\n    '9425': ['CS', '1', 'ContrastBolusIngredientOpaque'],\n    '9426': ['FL', '1', 'DistanceReceptorPlaneToDetectorHousing'],\n    '9427': ['CS', '1', 'IntensifierActiveShape'],\n    '9428': ['FL', '1-2', 'IntensifierActiveDimensions'],\n    '9429': ['FL', '2', 'PhysicalDetectorSize'],\n    '9430': ['FL', '2', 'PositionOfIsocenterProjection'],\n    '9432': ['SQ', '1', 'FieldOfViewSequence'],\n    '9433': ['LO', '1', 'FieldOfViewDescription'],\n    '9434': ['SQ', '1', 'ExposureControlSensingRegionsSequence'],\n    '9435': ['CS', '1', 'ExposureControlSensingRegionShape'],\n    '9436': ['SS', '1', 'ExposureControlSensingRegionLeftVerticalEdge'],\n    '9437': ['SS', '1', 'ExposureControlSensingRegionRightVerticalEdge'],\n    '9438': ['SS', '1', 'ExposureControlSensingRegionUpperHorizontalEdge'],\n    '9439': ['SS', '1', 'ExposureControlSensingRegionLowerHorizontalEdge'],\n    '9440': ['SS', '2', 'CenterOfCircularExposureControlSensingRegion'],\n    '9441': ['US', '1', 'RadiusOfCircularExposureControlSensingRegion'],\n    '9442': ['SS', '2-n', 'VerticesOfThePolygonalExposureControlSensingRegion'],\n    '9445': ['', '', ''],\n    '9447': ['FL', '1', 'ColumnAngulationPatient'],\n    '9449': ['FL', '1', 'BeamAngle'],\n    '9451': ['SQ', '1', 'FrameDetectorParametersSequence'],\n    '9452': ['FL', '1', 'CalculatedAnatomyThickness'],\n    '9455': ['SQ', '1', 'CalibrationSequence'],\n    '9456': ['SQ', '1', 'ObjectThicknessSequence'],\n    '9457': ['CS', '1', 'PlaneIdentification'],\n    '9461': ['FL', '1-2', 'FieldOfViewDimensionsInFloat'],\n    '9462': ['SQ', '1', 'IsocenterReferenceSystemSequence'],\n    '9463': ['FL', '1', 'PositionerIsocenterPrimaryAngle'],\n    '9464': ['FL', '1', 'PositionerIsocenterSecondaryAngle'],\n    '9465': ['FL', '1', 'PositionerIsocenterDetectorRotationAngle'],\n    '9466': ['FL', '1', 'TableXPositionToIsocenter'],\n    '9467': ['FL', '1', 'TableYPositionToIsocenter'],\n    '9468': ['FL', '1', 'TableZPositionToIsocenter'],\n    '9469': ['FL', '1', 'TableHorizontalRotationAngle'],\n    '9470': ['FL', '1', 'TableHeadTiltAngle'],\n    '9471': ['FL', '1', 'TableCradleTiltAngle'],\n    '9472': ['SQ', '1', 'FrameDisplayShutterSequence'],\n    '9473': ['FL', '1', 'AcquiredImageAreaDoseProduct'],\n    '9474': ['CS', '1', 'CArmPositionerTabletopRelationship'],\n    '9476': ['SQ', '1', 'XRayGeometrySequence'],\n    '9477': ['SQ', '1', 'IrradiationEventIdentificationSequence'],\n    '9504': ['SQ', '1', 'XRay3DFrameTypeSequence'],\n    '9506': ['SQ', '1', 'ContributingSourcesSequence'],\n    '9507': ['SQ', '1', 'XRay3DAcquisitionSequence'],\n    '9508': ['FL', '1', 'PrimaryPositionerScanArc'],\n    '9509': ['FL', '1', 'SecondaryPositionerScanArc'],\n    '9510': ['FL', '1', 'PrimaryPositionerScanStartAngle'],\n    '9511': ['FL', '1', 'SecondaryPositionerScanStartAngle'],\n    '9514': ['FL', '1', 'PrimaryPositionerIncrement'],\n    '9515': ['FL', '1', 'SecondaryPositionerIncrement'],\n    '9516': ['DT', '1', 'StartAcquisitionDateTime'],\n    '9517': ['DT', '1', 'EndAcquisitionDateTime'],\n    '9518': ['SS', '1', 'PrimaryPositionerIncrementSign'],\n    '9519': ['SS', '1', 'SecondaryPositionerIncrementSign'],\n    '9524': ['LO', '1', 'ApplicationName'],\n    '9525': ['LO', '1', 'ApplicationVersion'],\n    '9526': ['LO', '1', 'ApplicationManufacturer'],\n    '9527': ['CS', '1', 'AlgorithmType'],\n    '9528': ['LO', '1', 'AlgorithmDescription'],\n    '9530': ['SQ', '1', 'XRay3DReconstructionSequence'],\n    '9531': ['LO', '1', 'ReconstructionDescription'],\n    '9538': ['SQ', '1', 'PerProjectionAcquisitionSequence'],\n    '9541': ['SQ', '1', 'DetectorPositionSequence'],\n    '9542': ['SQ', '1', 'XRayAcquisitionDoseSequence'],\n    '9543': ['FD', '1', 'XRaySourceIsocenterPrimaryAngle'],\n    '9544': ['FD', '1', 'XRaySourceIsocenterSecondaryAngle'],\n    '9545': ['FD', '1', 'BreastSupportIsocenterPrimaryAngle'],\n    '9546': ['FD', '1', 'BreastSupportIsocenterSecondaryAngle'],\n    '9547': ['FD', '1', 'BreastSupportXPositionToIsocenter'],\n    '9548': ['FD', '1', 'BreastSupportYPositionToIsocenter'],\n    '9549': ['FD', '1', 'BreastSupportZPositionToIsocenter'],\n    '9550': ['FD', '1', 'DetectorIsocenterPrimaryAngle'],\n    '9551': ['FD', '1', 'DetectorIsocenterSecondaryAngle'],\n    '9552': ['FD', '1', 'DetectorXPositionToIsocenter'],\n    '9553': ['FD', '1', 'DetectorYPositionToIsocenter'],\n    '9554': ['FD', '1', 'DetectorZPositionToIsocenter'],\n    '9555': ['SQ', '1', 'XRayGridSequence'],\n    '9556': ['SQ', '1', 'XRayFilterSequence'],\n    '9557': ['FD', '3', 'DetectorActiveAreaTLHCPosition'],\n    '9558': ['FD', '6', 'DetectorActiveAreaOrientation'],\n    '9559': ['CS', '1', 'PositionerPrimaryAngleDirection'],\n    '9601': ['SQ', '1', 'DiffusionBMatrixSequence'],\n    '9602': ['FD', '1', 'DiffusionBValueXX'],\n    '9603': ['FD', '1', 'DiffusionBValueXY'],\n    '9604': ['FD', '1', 'DiffusionBValueXZ'],\n    '9605': ['FD', '1', 'DiffusionBValueYY'],\n    '9606': ['FD', '1', 'DiffusionBValueYZ'],\n    '9607': ['FD', '1', 'DiffusionBValueZZ'],\n    '9621': ['SQ', '1', 'FunctionalMRSequence'],\n    '9622': ['CS', '1', 'FunctionalSettlingPhaseFramesPresent'],\n    '9623': ['DT', '1', 'FunctionalSyncPulse'],\n    '9624': ['CS', '1', 'SettlingPhaseFrame'],\n    '9701': ['DT', '1', 'DecayCorrectionDateTime'],\n    '9715': ['FD', '1', 'StartDensityThreshold'],\n    '9716': ['FD', '1', 'StartRelativeDensityDifferenceThreshold'],\n    '9717': ['FD', '1', 'StartCardiacTriggerCountThreshold'],\n    '9718': ['FD', '1', 'StartRespiratoryTriggerCountThreshold'],\n    '9719': ['FD', '1', 'TerminationCountsThreshold'],\n    '9720': ['FD', '1', 'TerminationDensityThreshold'],\n    '9721': ['FD', '1', 'TerminationRelativeDensityThreshold'],\n    '9722': ['FD', '1', 'TerminationTimeThreshold'],\n    '9723': ['FD', '1', 'TerminationCardiacTriggerCountThreshold'],\n    '9724': ['FD', '1', 'TerminationRespiratoryTriggerCountThreshold'],\n    '9725': ['CS', '1', 'DetectorGeometry'],\n    '9726': ['FD', '1', 'TransverseDetectorSeparation'],\n    '9727': ['FD', '1', 'AxialDetectorDimension'],\n    '9729': ['US', '1', 'RadiopharmaceuticalAgentNumber'],\n    '9732': ['SQ', '1', 'PETFrameAcquisitionSequence'],\n    '9733': ['SQ', '1', 'PETDetectorMotionDetailsSequence'],\n    '9734': ['SQ', '1', 'PETTableDynamicsSequence'],\n    '9735': ['SQ', '1', 'PETPositionSequence'],\n    '9736': ['SQ', '1', 'PETFrameCorrectionFactorsSequence'],\n    '9737': ['SQ', '1', 'RadiopharmaceuticalUsageSequence'],\n    '9738': ['CS', '1', 'AttenuationCorrectionSource'],\n    '9739': ['US', '1', 'NumberOfIterations'],\n    '9740': ['US', '1', 'NumberOfSubsets'],\n    '9749': ['SQ', '1', 'PETReconstructionSequence'],\n    '9751': ['SQ', '1', 'PETFrameTypeSequence'],\n    '9755': ['CS', '1', 'TimeOfFlightInformationUsed'],\n    '9756': ['CS', '1', 'ReconstructionType'],\n    '9758': ['CS', '1', 'DecayCorrected'],\n    '9759': ['CS', '1', 'AttenuationCorrected'],\n    '9760': ['CS', '1', 'ScatterCorrected'],\n    '9761': ['CS', '1', 'DeadTimeCorrected'],\n    '9762': ['CS', '1', 'GantryMotionCorrected'],\n    '9763': ['CS', '1', 'PatientMotionCorrected'],\n    '9764': ['CS', '1', 'CountLossNormalizationCorrected'],\n    '9765': ['CS', '1', 'RandomsCorrected'],\n    '9766': ['CS', '1', 'NonUniformRadialSamplingCorrected'],\n    '9767': ['CS', '1', 'SensitivityCalibrated'],\n    '9768': ['CS', '1', 'DetectorNormalizationCorrection'],\n    '9769': ['CS', '1', 'IterativeReconstructionMethod'],\n    '9770': ['CS', '1', 'AttenuationCorrectionTemporalRelationship'],\n    '9771': ['SQ', '1', 'PatientPhysiologicalStateSequence'],\n    '9772': ['SQ', '1', 'PatientPhysiologicalStateCodeSequence'],\n    '9801': ['FD', '1-n', 'DepthsOfFocus'],\n    '9803': ['SQ', '1', 'ExcludedIntervalsSequence'],\n    '9804': ['DT', '1', 'ExclusionStartDateTime'],\n    '9805': ['FD', '1', 'ExclusionDuration'],\n    '9806': ['SQ', '1', 'USImageDescriptionSequence'],\n    '9807': ['SQ', '1', 'ImageDataTypeSequence'],\n    '9808': ['CS', '1', 'DataType'],\n    '9809': ['SQ', '1', 'TransducerScanPatternCodeSequence'],\n    '980B': ['CS', '1', 'AliasedDataType'],\n    '980C': ['CS', '1', 'PositionMeasuringDeviceUsed'],\n    '980D': ['SQ', '1', 'TransducerGeometryCodeSequence'],\n    '980E': ['SQ', '1', 'TransducerBeamSteeringCodeSequence'],\n    '980F': ['SQ', '1', 'TransducerApplicationCodeSequence'],\n    '9810': ['xs', '1', 'ZeroVelocityPixelValue'],\n    '9900': ['LO', '1', 'ReferenceLocationLabel'],\n    '9901': ['UT', '1', 'ReferenceLocationDescription'],\n    '9902': ['SQ', '1', 'ReferenceBasisCodeSequence'],\n    '9903': ['SQ', '1', 'ReferenceGeometryCodeSequence'],\n    '9904': ['DS', '1', 'OffsetDistance'],\n    '9905': ['CS', '1', 'OffsetDirection'],\n    '9906': ['SQ', '1', 'PotentialScheduledProtocolCodeSequence'],\n    '9907': ['SQ', '1', 'PotentialRequestedProcedureCodeSequence'],\n    '9908': ['UC', '1-n', 'PotentialReasonsForProcedure'],\n    '9909': ['SQ', '1', 'PotentialReasonsForProcedureCodeSequence'],\n    '990A': ['UC', '1-n', 'PotentialDiagnosticTasks'],\n    '990B': ['SQ', '1', 'ContraindicationsCodeSequence'],\n    '990C': ['SQ', '1', 'ReferencedDefinedProtocolSequence'],\n    '990D': ['SQ', '1', 'ReferencedPerformedProtocolSequence'],\n    '990E': ['SQ', '1', 'PredecessorProtocolSequence'],\n    '990F': ['UT', '1', 'ProtocolPlanningInformation'],\n    '9910': ['UT', '1', 'ProtocolDesignRationale'],\n    '9911': ['SQ', '1', 'PatientSpecificationSequence'],\n    '9912': ['SQ', '1', 'ModelSpecificationSequence'],\n    '9913': ['SQ', '1', 'ParametersSpecificationSequence'],\n    '9914': ['SQ', '1', 'InstructionSequence'],\n    '9915': ['US', '1', 'InstructionIndex'],\n    '9916': ['LO', '1', 'InstructionText'],\n    '9917': ['UT', '1', 'InstructionDescription'],\n    '9918': ['CS', '1', 'InstructionPerformedFlag'],\n    '9919': ['DT', '1', 'InstructionPerformedDateTime'],\n    '991A': ['UT', '1', 'InstructionPerformanceComment'],\n    '991B': ['SQ', '1', 'PatientPositioningInstructionSequence'],\n    '991C': ['SQ', '1', 'PositioningMethodCodeSequence'],\n    '991D': ['SQ', '1', 'PositioningLandmarkSequence'],\n    '991E': ['UI', '1', 'TargetFrameOfReferenceUID'],\n    '991F': ['SQ', '1', 'AcquisitionProtocolElementSpecificationSequence'],\n    '9920': ['SQ', '1', 'AcquisitionProtocolElementSequence'],\n    '9921': ['US', '1', 'ProtocolElementNumber'],\n    '9922': ['LO', '1', 'ProtocolElementName'],\n    '9923': ['UT', '1', 'ProtocolElementCharacteristicsSummary'],\n    '9924': ['UT', '1', 'ProtocolElementPurpose'],\n    '9930': ['CS', '1', 'AcquisitionMotion'],\n    '9931': ['SQ', '1', 'AcquisitionStartLocationSequence'],\n    '9932': ['SQ', '1', 'AcquisitionEndLocationSequence'],\n    '9933': ['SQ', '1', 'ReconstructionProtocolElementSpecificationSequence'],\n    '9934': ['SQ', '1', 'ReconstructionProtocolElementSequence'],\n    '9935': ['SQ', '1', 'StorageProtocolElementSpecificationSequence'],\n    '9936': ['SQ', '1', 'StorageProtocolElementSequence'],\n    '9937': ['LO', '1', 'RequestedSeriesDescription'],\n    '9938': ['US', '1-n', 'SourceAcquisitionProtocolElementNumber'],\n    '9939': ['US', '1-n', 'SourceAcquisitionBeamNumber'],\n    '993A': ['US', '1-n', 'SourceReconstructionProtocolElementNumber'],\n    '993B': ['SQ', '1', 'ReconstructionStartLocationSequence'],\n    '993C': ['SQ', '1', 'ReconstructionEndLocationSequence'],\n    '993D': ['SQ', '1', 'ReconstructionAlgorithmSequence'],\n    '993E': ['SQ', '1', 'ReconstructionTargetCenterLocationSequence'],\n    '9941': ['UT', '1', 'ImageFilterDescription'],\n    '9942': ['FD', '1', 'CTDIvolNotificationTrigger'],\n    '9943': ['FD', '1', 'DLPNotificationTrigger'],\n    '9944': ['CS', '1', 'AutoKVPSelectionType'],\n    '9945': ['FD', '1', 'AutoKVPUpperBound'],\n    '9946': ['FD', '1', 'AutoKVPLowerBound'],\n    '9947': ['CS', '1', 'ProtocolDefinedPatientPosition'],\n    'A001': ['SQ', '1', 'ContributingEquipmentSequence'],\n    'A002': ['DT', '1', 'ContributionDateTime'],\n    'A003': ['ST', '1', 'ContributionDescription']\n  },\n  '0020': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '000D': ['UI', '1', 'StudyInstanceUID'],\n    '000E': ['UI', '1', 'SeriesInstanceUID'],\n    '0010': ['SH', '1', 'StudyID'],\n    '0011': ['IS', '1', 'SeriesNumber'],\n    '0012': ['IS', '1', 'AcquisitionNumber'],\n    '0013': ['IS', '1', 'InstanceNumber'],\n    '0014': ['IS', '1', 'IsotopeNumber'],\n    '0015': ['IS', '1', 'PhaseNumber'],\n    '0016': ['IS', '1', 'IntervalNumber'],\n    '0017': ['IS', '1', 'TimeSlotNumber'],\n    '0018': ['IS', '1', 'AngleNumber'],\n    '0019': ['IS', '1', 'ItemNumber'],\n    '0020': ['CS', '2', 'PatientOrientation'],\n    '0022': ['IS', '1', 'OverlayNumber'],\n    '0024': ['IS', '1', 'CurveNumber'],\n    '0026': ['IS', '1', 'LUTNumber'],\n    '0030': ['DS', '3', 'ImagePosition'],\n    '0032': ['DS', '3', 'ImagePositionPatient'],\n    '0035': ['DS', '6', 'ImageOrientation'],\n    '0037': ['DS', '6', 'ImageOrientationPatient'],\n    '0050': ['DS', '1', 'Location'],\n    '0052': ['UI', '1', 'FrameOfReferenceUID'],\n    '0060': ['CS', '1', 'Laterality'],\n    '0062': ['CS', '1', 'ImageLaterality'],\n    '0070': ['LO', '1', 'ImageGeometryType'],\n    '0080': ['CS', '1-n', 'MaskingImage'],\n    '00AA': ['IS', '1', 'ReportNumber'],\n    '0100': ['IS', '1', 'TemporalPositionIdentifier'],\n    '0105': ['IS', '1', 'NumberOfTemporalPositions'],\n    '0110': ['DS', '1', 'TemporalResolution'],\n    '0200': ['UI', '1', 'SynchronizationFrameOfReferenceUID'],\n    '0242': ['UI', '1', 'SOPInstanceUIDOfConcatenationSource'],\n    '1000': ['IS', '1', 'SeriesInStudy'],\n    '1001': ['IS', '1', 'AcquisitionsInSeries'],\n    '1002': ['IS', '1', 'ImagesInAcquisition'],\n    '1003': ['IS', '1', 'ImagesInSeries'],\n    '1004': ['IS', '1', 'AcquisitionsInStudy'],\n    '1005': ['IS', '1', 'ImagesInStudy'],\n    '1020': ['LO', '1-n', 'Reference'],\n    '103F': ['LO', '1', 'TargetPositionReferenceIndicator'],\n    '1040': ['LO', '1', 'PositionReferenceIndicator'],\n    '1041': ['DS', '1', 'SliceLocation'],\n    '1070': ['IS', '1-n', 'OtherStudyNumbers'],\n    '1200': ['IS', '1', 'NumberOfPatientRelatedStudies'],\n    '1202': ['IS', '1', 'NumberOfPatientRelatedSeries'],\n    '1204': ['IS', '1', 'NumberOfPatientRelatedInstances'],\n    '1206': ['IS', '1', 'NumberOfStudyRelatedSeries'],\n    '1208': ['IS', '1', 'NumberOfStudyRelatedInstances'],\n    '1209': ['IS', '1', 'NumberOfSeriesRelatedInstances'],\n    '3100': ['CS', '1-n', 'SourceImageIDs'],\n    '3401': ['CS', '1', 'ModifyingDeviceID'],\n    '3402': ['CS', '1', 'ModifiedImageID'],\n    '3403': ['DA', '1', 'ModifiedImageDate'],\n    '3404': ['LO', '1', 'ModifyingDeviceManufacturer'],\n    '3405': ['TM', '1', 'ModifiedImageTime'],\n    '3406': ['LO', '1', 'ModifiedImageDescription'],\n    '4000': ['LT', '1', 'ImageComments'],\n    '5000': ['AT', '1-n', 'OriginalImageIdentification'],\n    '5002': ['LO', '1-n', 'OriginalImageIdentificationNomenclature'],\n    '9056': ['SH', '1', 'StackID'],\n    '9057': ['UL', '1', 'InStackPositionNumber'],\n    '9071': ['SQ', '1', 'FrameAnatomySequence'],\n    '9072': ['CS', '1', 'FrameLaterality'],\n    '9111': ['SQ', '1', 'FrameContentSequence'],\n    '9113': ['SQ', '1', 'PlanePositionSequence'],\n    '9116': ['SQ', '1', 'PlaneOrientationSequence'],\n    '9128': ['UL', '1', 'TemporalPositionIndex'],\n    '9153': ['FD', '1', 'NominalCardiacTriggerDelayTime'],\n    '9154': ['FL', '1', 'NominalCardiacTriggerTimePriorToRPeak'],\n    '9155': ['FL', '1', 'ActualCardiacTriggerTimePriorToRPeak'],\n    '9156': ['US', '1', 'FrameAcquisitionNumber'],\n    '9157': ['UL', '1-n', 'DimensionIndexValues'],\n    '9158': ['LT', '1', 'FrameComments'],\n    '9161': ['UI', '1', 'ConcatenationUID'],\n    '9162': ['US', '1', 'InConcatenationNumber'],\n    '9163': ['US', '1', 'InConcatenationTotalNumber'],\n    '9164': ['UI', '1', 'DimensionOrganizationUID'],\n    '9165': ['AT', '1', 'DimensionIndexPointer'],\n    '9167': ['AT', '1', 'FunctionalGroupPointer'],\n    '9170': ['SQ', '1', 'UnassignedSharedConvertedAttributesSequence'],\n    '9171': ['SQ', '1', 'UnassignedPerFrameConvertedAttributesSequence'],\n    '9172': ['SQ', '1', 'ConversionSourceAttributesSequence'],\n    '9213': ['LO', '1', 'DimensionIndexPrivateCreator'],\n    '9221': ['SQ', '1', 'DimensionOrganizationSequence'],\n    '9222': ['SQ', '1', 'DimensionIndexSequence'],\n    '9228': ['UL', '1', 'ConcatenationFrameOffsetNumber'],\n    '9238': ['LO', '1', 'FunctionalGroupPrivateCreator'],\n    '9241': ['FL', '1', 'NominalPercentageOfCardiacPhase'],\n    '9245': ['FL', '1', 'NominalPercentageOfRespiratoryPhase'],\n    '9246': ['FL', '1', 'StartingRespiratoryAmplitude'],\n    '9247': ['CS', '1', 'StartingRespiratoryPhase'],\n    '9248': ['FL', '1', 'EndingRespiratoryAmplitude'],\n    '9249': ['CS', '1', 'EndingRespiratoryPhase'],\n    '9250': ['CS', '1', 'RespiratoryTriggerType'],\n    '9251': ['FD', '1', 'RRIntervalTimeNominal'],\n    '9252': ['FD', '1', 'ActualCardiacTriggerDelayTime'],\n    '9253': ['SQ', '1', 'RespiratorySynchronizationSequence'],\n    '9254': ['FD', '1', 'RespiratoryIntervalTime'],\n    '9255': ['FD', '1', 'NominalRespiratoryTriggerDelayTime'],\n    '9256': ['FD', '1', 'RespiratoryTriggerDelayThreshold'],\n    '9257': ['FD', '1', 'ActualRespiratoryTriggerDelayTime'],\n    '9301': ['FD', '3', 'ImagePositionVolume'],\n    '9302': ['FD', '6', 'ImageOrientationVolume'],\n    '9307': ['CS', '1', 'UltrasoundAcquisitionGeometry'],\n    '9308': ['FD', '3', 'ApexPosition'],\n    '9309': ['FD', '16', 'VolumeToTransducerMappingMatrix'],\n    '930A': ['FD', '16', 'VolumeToTableMappingMatrix'],\n    '930B': ['CS', '1', 'VolumeToTransducerRelationship'],\n    '930C': ['CS', '1', 'PatientFrameOfReferenceSource'],\n    '930D': ['FD', '1', 'TemporalPositionTimeOffset'],\n    '930E': ['SQ', '1', 'PlanePositionVolumeSequence'],\n    '930F': ['SQ', '1', 'PlaneOrientationVolumeSequence'],\n    '9310': ['SQ', '1', 'TemporalPositionSequence'],\n    '9311': ['CS', '1', 'DimensionOrganizationType'],\n    '9312': ['UI', '1', 'VolumeFrameOfReferenceUID'],\n    '9313': ['UI', '1', 'TableFrameOfReferenceUID'],\n    '9421': ['LO', '1', 'DimensionDescriptionLabel'],\n    '9450': ['SQ', '1', 'PatientOrientationInFrameSequence'],\n    '9453': ['LO', '1', 'FrameLabel'],\n    '9518': ['US', '1-n', 'AcquisitionIndex'],\n    '9529': ['SQ', '1', 'ContributingSOPInstancesReferenceSequence'],\n    '9536': ['US', '1', 'ReconstructionIndex']\n  },\n  '0022': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['US', '1', 'LightPathFilterPassThroughWavelength'],\n    '0002': ['US', '2', 'LightPathFilterPassBand'],\n    '0003': ['US', '1', 'ImagePathFilterPassThroughWavelength'],\n    '0004': ['US', '2', 'ImagePathFilterPassBand'],\n    '0005': ['CS', '1', 'PatientEyeMovementCommanded'],\n    '0006': ['SQ', '1', 'PatientEyeMovementCommandCodeSequence'],\n    '0007': ['FL', '1', 'SphericalLensPower'],\n    '0008': ['FL', '1', 'CylinderLensPower'],\n    '0009': ['FL', '1', 'CylinderAxis'],\n    '000A': ['FL', '1', 'EmmetropicMagnification'],\n    '000B': ['FL', '1', 'IntraOcularPressure'],\n    '000C': ['FL', '1', 'HorizontalFieldOfView'],\n    '000D': ['CS', '1', 'PupilDilated'],\n    '000E': ['FL', '1', 'DegreeOfDilation'],\n    '0010': ['FL', '1', 'StereoBaselineAngle'],\n    '0011': ['FL', '1', 'StereoBaselineDisplacement'],\n    '0012': ['FL', '1', 'StereoHorizontalPixelOffset'],\n    '0013': ['FL', '1', 'StereoVerticalPixelOffset'],\n    '0014': ['FL', '1', 'StereoRotation'],\n    '0015': ['SQ', '1', 'AcquisitionDeviceTypeCodeSequence'],\n    '0016': ['SQ', '1', 'IlluminationTypeCodeSequence'],\n    '0017': ['SQ', '1', 'LightPathFilterTypeStackCodeSequence'],\n    '0018': ['SQ', '1', 'ImagePathFilterTypeStackCodeSequence'],\n    '0019': ['SQ', '1', 'LensesCodeSequence'],\n    '001A': ['SQ', '1', 'ChannelDescriptionCodeSequence'],\n    '001B': ['SQ', '1', 'RefractiveStateSequence'],\n    '001C': ['SQ', '1', 'MydriaticAgentCodeSequence'],\n    '001D': ['SQ', '1', 'RelativeImagePositionCodeSequence'],\n    '001E': ['FL', '1', 'CameraAngleOfView'],\n    '0020': ['SQ', '1', 'StereoPairsSequence'],\n    '0021': ['SQ', '1', 'LeftImageSequence'],\n    '0022': ['SQ', '1', 'RightImageSequence'],\n    '0028': ['CS', '1', 'StereoPairsPresent'],\n    '0030': ['FL', '1', 'AxialLengthOfTheEye'],\n    '0031': ['SQ', '1', 'OphthalmicFrameLocationSequence'],\n    '0032': ['FL', '2-2n', 'ReferenceCoordinates'],\n    '0035': ['FL', '1', 'DepthSpatialResolution'],\n    '0036': ['FL', '1', 'MaximumDepthDistortion'],\n    '0037': ['FL', '1', 'AlongScanSpatialResolution'],\n    '0038': ['FL', '1', 'MaximumAlongScanDistortion'],\n    '0039': ['CS', '1', 'OphthalmicImageOrientation'],\n    '0041': ['FL', '1', 'DepthOfTransverseImage'],\n    '0042': ['SQ', '1', 'MydriaticAgentConcentrationUnitsSequence'],\n    '0048': ['FL', '1', 'AcrossScanSpatialResolution'],\n    '0049': ['FL', '1', 'MaximumAcrossScanDistortion'],\n    '004E': ['DS', '1', 'MydriaticAgentConcentration'],\n    '0055': ['FL', '1', 'IlluminationWaveLength'],\n    '0056': ['FL', '1', 'IlluminationPower'],\n    '0057': ['FL', '1', 'IlluminationBandwidth'],\n    '0058': ['SQ', '1', 'MydriaticAgentSequence'],\n    '1007': ['SQ', '1', 'OphthalmicAxialMeasurementsRightEyeSequence'],\n    '1008': ['SQ', '1', 'OphthalmicAxialMeasurementsLeftEyeSequence'],\n    '1009': ['CS', '1', 'OphthalmicAxialMeasurementsDeviceType'],\n    '1010': ['CS', '1', 'OphthalmicAxialLengthMeasurementsType'],\n    '1012': ['SQ', '1', 'OphthalmicAxialLengthSequence'],\n    '1019': ['FL', '1', 'OphthalmicAxialLength'],\n    '1024': ['SQ', '1', 'LensStatusCodeSequence'],\n    '1025': ['SQ', '1', 'VitreousStatusCodeSequence'],\n    '1028': ['SQ', '1', 'IOLFormulaCodeSequence'],\n    '1029': ['LO', '1', 'IOLFormulaDetail'],\n    '1033': ['FL', '1', 'KeratometerIndex'],\n    '1035': ['SQ', '1', 'SourceOfOphthalmicAxialLengthCodeSequence'],\n    '1036': ['SQ', '1', 'SourceOfCornealSizeDataCodeSequence'],\n    '1037': ['FL', '1', 'TargetRefraction'],\n    '1039': ['CS', '1', 'RefractiveProcedureOccurred'],\n    '1040': ['SQ', '1', 'RefractiveSurgeryTypeCodeSequence'],\n    '1044': ['SQ', '1', 'OphthalmicUltrasoundMethodCodeSequence'],\n    '1045': ['SQ', '1', 'SurgicallyInducedAstigmatismSequence'],\n    '1046': ['CS', '1', 'TypeOfOpticalCorrection'],\n    '1047': ['SQ', '1', 'ToricIOLPowerSequence'],\n    '1048': ['SQ', '1', 'PredictedToricErrorSequence'],\n    '1049': ['CS', '1', 'PreSelectedForImplantation'],\n    '104A': ['SQ', '1', 'ToricIOLPowerForExactEmmetropiaSequence'],\n    '104B': ['SQ', '1', 'ToricIOLPowerForExactTargetRefractionSequence'],\n    '1050': ['SQ', '1', 'OphthalmicAxialLengthMeasurementsSequence'],\n    '1053': ['FL', '1', 'IOLPower'],\n    '1054': ['FL', '1', 'PredictedRefractiveError'],\n    '1059': ['FL', '1', 'OphthalmicAxialLengthVelocity'],\n    '1065': ['LO', '1', 'LensStatusDescription'],\n    '1066': ['LO', '1', 'VitreousStatusDescription'],\n    '1090': ['SQ', '1', 'IOLPowerSequence'],\n    '1092': ['SQ', '1', 'LensConstantSequence'],\n    '1093': ['LO', '1', 'IOLManufacturer'],\n    '1094': ['LO', '1', 'LensConstantDescription'],\n    '1095': ['LO', '1', 'ImplantName'],\n    '1096': ['SQ', '1', 'KeratometryMeasurementTypeCodeSequence'],\n    '1097': ['LO', '1', 'ImplantPartNumber'],\n    '1100': ['SQ', '1', 'ReferencedOphthalmicAxialMeasurementsSequence'],\n    '1101': ['SQ', '1', 'OphthalmicAxialLengthMeasurementsSegmentNameCodeSequence'],\n    '1103': ['SQ', '1', 'RefractiveErrorBeforeRefractiveSurgeryCodeSequence'],\n    '1121': ['FL', '1', 'IOLPowerForExactEmmetropia'],\n    '1122': ['FL', '1', 'IOLPowerForExactTargetRefraction'],\n    '1125': ['SQ', '1', 'AnteriorChamberDepthDefinitionCodeSequence'],\n    '1127': ['SQ', '1', 'LensThicknessSequence'],\n    '1128': ['SQ', '1', 'AnteriorChamberDepthSequence'],\n    '112A': ['SQ', '1', 'CalculationCommentSequence'],\n    '112B': ['CS', '1', 'CalculationCommentType'],\n    '112C': ['LT', '1', 'CalculationComment'],\n    '1130': ['FL', '1', 'LensThickness'],\n    '1131': ['FL', '1', 'AnteriorChamberDepth'],\n    '1132': ['SQ', '1', 'SourceOfLensThicknessDataCodeSequence'],\n    '1133': ['SQ', '1', 'SourceOfAnteriorChamberDepthDataCodeSequence'],\n    '1134': ['SQ', '1', 'SourceOfRefractiveMeasurementsSequence'],\n    '1135': ['SQ', '1', 'SourceOfRefractiveMeasurementsCodeSequence'],\n    '1140': ['CS', '1', 'OphthalmicAxialLengthMeasurementModified'],\n    '1150': ['SQ', '1', 'OphthalmicAxialLengthDataSourceCodeSequence'],\n    '1153': ['SQ', '1', 'OphthalmicAxialLengthAcquisitionMethodCodeSequence'],\n    '1155': ['FL', '1', 'SignalToNoiseRatio'],\n    '1159': ['LO', '1', 'OphthalmicAxialLengthDataSourceDescription'],\n    '1210': ['SQ', '1', 'OphthalmicAxialLengthMeasurementsTotalLengthSequence'],\n    '1211': ['SQ', '1', 'OphthalmicAxialLengthMeasurementsSegmentalLengthSequence'],\n    '1212': ['SQ', '1', 'OphthalmicAxialLengthMeasurementsLengthSummationSequence'],\n    '1220': ['SQ', '1', 'UltrasoundOphthalmicAxialLengthMeasurementsSequence'],\n    '1225': ['SQ', '1', 'OpticalOphthalmicAxialLengthMeasurementsSequence'],\n    '1230': ['SQ', '1', 'UltrasoundSelectedOphthalmicAxialLengthSequence'],\n    '1250': ['SQ', '1', 'OphthalmicAxialLengthSelectionMethodCodeSequence'],\n    '1255': ['SQ', '1', 'OpticalSelectedOphthalmicAxialLengthSequence'],\n    '1257': ['SQ', '1', 'SelectedSegmentalOphthalmicAxialLengthSequence'],\n    '1260': ['SQ', '1', 'SelectedTotalOphthalmicAxialLengthSequence'],\n    '1262': ['SQ', '1', 'OphthalmicAxialLengthQualityMetricSequence'],\n    '1265': ['SQ', '1', 'OphthalmicAxialLengthQualityMetricTypeCodeSequence'],\n    '1273': ['LO', '1', 'OphthalmicAxialLengthQualityMetricTypeDescription'],\n    '1300': ['SQ', '1', 'IntraocularLensCalculationsRightEyeSequence'],\n    '1310': ['SQ', '1', 'IntraocularLensCalculationsLeftEyeSequence'],\n    '1330': ['SQ', '1', 'ReferencedOphthalmicAxialLengthMeasurementQCImageSequence'],\n    '1415': ['CS', '1', 'OphthalmicMappingDeviceType'],\n    '1420': ['SQ', '1', 'AcquisitionMethodCodeSequence'],\n    '1423': ['SQ', '1', 'AcquisitionMethodAlgorithmSequence'],\n    '1436': ['SQ', '1', 'OphthalmicThicknessMapTypeCodeSequence'],\n    '1443': ['SQ', '1', 'OphthalmicThicknessMappingNormalsSequence'],\n    '1445': ['SQ', '1', 'RetinalThicknessDefinitionCodeSequence'],\n    '1450': ['SQ', '1', 'PixelValueMappingToCodedConceptSequence'],\n    '1452': ['xs', '1', 'MappedPixelValue'],\n    '1454': ['LO', '1', 'PixelValueMappingExplanation'],\n    '1458': ['SQ', '1', 'OphthalmicThicknessMapQualityThresholdSequence'],\n    '1460': ['FL', '1', 'OphthalmicThicknessMapThresholdQualityRating'],\n    '1463': ['FL', '2', 'AnatomicStructureReferencePoint'],\n    '1465': ['SQ', '1', 'RegistrationToLocalizerSequence'],\n    '1466': ['CS', '1', 'RegisteredLocalizerUnits'],\n    '1467': ['FL', '2', 'RegisteredLocalizerTopLeftHandCorner'],\n    '1468': ['FL', '2', 'RegisteredLocalizerBottomRightHandCorner'],\n    '1470': ['SQ', '1', 'OphthalmicThicknessMapQualityRatingSequence'],\n    '1472': ['SQ', '1', 'RelevantOPTAttributesSequence'],\n    '1512': ['SQ', '1', 'TransformationMethodCodeSequence'],\n    '1513': ['SQ', '1', 'TransformationAlgorithmSequence'],\n    '1515': ['CS', '1', 'OphthalmicAxialLengthMethod'],\n    '1517': ['FL', '1', 'OphthalmicFOV'],\n    '1518': ['SQ', '1', 'TwoDimensionalToThreeDimensionalMapSequence'],\n    '1525': ['SQ', '1', 'WideFieldOphthalmicPhotographyQualityRatingSequence'],\n    '1526': ['SQ', '1', 'WideFieldOphthalmicPhotographyQualityThresholdSequence'],\n    '1527': ['FL', '1', 'WideFieldOphthalmicPhotographyThresholdQualityRating'],\n    '1528': ['FL', '1', 'XCoordinatesCenterPixelViewAngle'],\n    '1529': ['FL', '1', 'YCoordinatesCenterPixelViewAngle'],\n    '1530': ['UL', '1', 'NumberOfMapPoints'],\n    '1531': ['OF', '1', 'TwoDimensionalToThreeDimensionalMapData'],\n    '1612': ['SQ', '1', 'DerivationAlgorithmSequence'],\n    '1615': ['SQ', '1', 'OphthalmicImageTypeCodeSequence'],\n    '1616': ['LO', '1', 'OphthalmicImageTypeDescription'],\n    '1618': ['SQ', '1', 'ScanPatternTypeCodeSequence'],\n    '1620': ['SQ', '1', 'ReferencedSurfaceMeshIdentificationSequence'],\n    '1622': ['CS', '1', 'OphthalmicVolumetricPropertiesFlag'],\n    '1624': ['FL', '1', 'OphthalmicAnatomicReferencePointXCoordinate'],\n    '1626': ['FL', '1', 'OphthalmicAnatomicReferencePointYCoordinate'],\n    '1628': ['SQ', '1', 'OphthalmicEnFaceImageQualityRatingSequence'],\n    '1630': ['DS', '1', 'QualityThreshold'],\n    '1640': ['SQ', '1', 'OCTBscanAnalysisAcquisitionParametersSequence'],\n    '1642': ['UL', '1', 'NumberOfBscansPerFrame'],\n    '1643': ['FL', '1', 'BscanSlabThickness'],\n    '1644': ['FL', '1', 'DistanceBetweenBscanSlabs'],\n    '1645': ['FL', '1', 'BscanCycleTime'],\n    '1646': ['FL', '1-n', 'BscanCycleTimeVector'],\n    '1649': ['FL', '1', 'AscanRate'],\n    '1650': ['FL', '1', 'BscanRate'],\n    '1658': ['UL', '1', 'SurfaceMeshZPixelOffset']\n  },\n  '0024': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['FL', '1', 'VisualFieldHorizontalExtent'],\n    '0011': ['FL', '1', 'VisualFieldVerticalExtent'],\n    '0012': ['CS', '1', 'VisualFieldShape'],\n    '0016': ['SQ', '1', 'ScreeningTestModeCodeSequence'],\n    '0018': ['FL', '1', 'MaximumStimulusLuminance'],\n    '0020': ['FL', '1', 'BackgroundLuminance'],\n    '0021': ['SQ', '1', 'StimulusColorCodeSequence'],\n    '0024': ['SQ', '1', 'BackgroundIlluminationColorCodeSequence'],\n    '0025': ['FL', '1', 'StimulusArea'],\n    '0028': ['FL', '1', 'StimulusPresentationTime'],\n    '0032': ['SQ', '1', 'FixationSequence'],\n    '0033': ['SQ', '1', 'FixationMonitoringCodeSequence'],\n    '0034': ['SQ', '1', 'VisualFieldCatchTrialSequence'],\n    '0035': ['US', '1', 'FixationCheckedQuantity'],\n    '0036': ['US', '1', 'PatientNotProperlyFixatedQuantity'],\n    '0037': ['CS', '1', 'PresentedVisualStimuliDataFlag'],\n    '0038': ['US', '1', 'NumberOfVisualStimuli'],\n    '0039': ['CS', '1', 'ExcessiveFixationLossesDataFlag'],\n    '0040': ['CS', '1', 'ExcessiveFixationLosses'],\n    '0042': ['US', '1', 'StimuliRetestingQuantity'],\n    '0044': ['LT', '1', 'CommentsOnPatientPerformanceOfVisualField'],\n    '0045': ['CS', '1', 'FalseNegativesEstimateFlag'],\n    '0046': ['FL', '1', 'FalseNegativesEstimate'],\n    '0048': ['US', '1', 'NegativeCatchTrialsQuantity'],\n    '0050': ['US', '1', 'FalseNegativesQuantity'],\n    '0051': ['CS', '1', 'ExcessiveFalseNegativesDataFlag'],\n    '0052': ['CS', '1', 'ExcessiveFalseNegatives'],\n    '0053': ['CS', '1', 'FalsePositivesEstimateFlag'],\n    '0054': ['FL', '1', 'FalsePositivesEstimate'],\n    '0055': ['CS', '1', 'CatchTrialsDataFlag'],\n    '0056': ['US', '1', 'PositiveCatchTrialsQuantity'],\n    '0057': ['CS', '1', 'TestPointNormalsDataFlag'],\n    '0058': ['SQ', '1', 'TestPointNormalsSequence'],\n    '0059': ['CS', '1', 'GlobalDeviationProbabilityNormalsFlag'],\n    '0060': ['US', '1', 'FalsePositivesQuantity'],\n    '0061': ['CS', '1', 'ExcessiveFalsePositivesDataFlag'],\n    '0062': ['CS', '1', 'ExcessiveFalsePositives'],\n    '0063': ['CS', '1', 'VisualFieldTestNormalsFlag'],\n    '0064': ['SQ', '1', 'ResultsNormalsSequence'],\n    '0065': ['SQ', '1', 'AgeCorrectedSensitivityDeviationAlgorithmSequence'],\n    '0066': ['FL', '1', 'GlobalDeviationFromNormal'],\n    '0067': ['SQ', '1', 'GeneralizedDefectSensitivityDeviationAlgorithmSequence'],\n    '0068': ['FL', '1', 'LocalizedDeviationFromNormal'],\n    '0069': ['LO', '1', 'PatientReliabilityIndicator'],\n    '0070': ['FL', '1', 'VisualFieldMeanSensitivity'],\n    '0071': ['FL', '1', 'GlobalDeviationProbability'],\n    '0072': ['CS', '1', 'LocalDeviationProbabilityNormalsFlag'],\n    '0073': ['FL', '1', 'LocalizedDeviationProbability'],\n    '0074': ['CS', '1', 'ShortTermFluctuationCalculated'],\n    '0075': ['FL', '1', 'ShortTermFluctuation'],\n    '0076': ['CS', '1', 'ShortTermFluctuationProbabilityCalculated'],\n    '0077': ['FL', '1', 'ShortTermFluctuationProbability'],\n    '0078': ['CS', '1', 'CorrectedLocalizedDeviationFromNormalCalculated'],\n    '0079': ['FL', '1', 'CorrectedLocalizedDeviationFromNormal'],\n    '0080': ['CS', '1', 'CorrectedLocalizedDeviationFromNormalProbabilityCalculated'],\n    '0081': ['FL', '1', 'CorrectedLocalizedDeviationFromNormalProbability'],\n    '0083': ['SQ', '1', 'GlobalDeviationProbabilitySequence'],\n    '0085': ['SQ', '1', 'LocalizedDeviationProbabilitySequence'],\n    '0086': ['CS', '1', 'FovealSensitivityMeasured'],\n    '0087': ['FL', '1', 'FovealSensitivity'],\n    '0088': ['FL', '1', 'VisualFieldTestDuration'],\n    '0089': ['SQ', '1', 'VisualFieldTestPointSequence'],\n    '0090': ['FL', '1', 'VisualFieldTestPointXCoordinate'],\n    '0091': ['FL', '1', 'VisualFieldTestPointYCoordinate'],\n    '0092': ['FL', '1', 'AgeCorrectedSensitivityDeviationValue'],\n    '0093': ['CS', '1', 'StimulusResults'],\n    '0094': ['FL', '1', 'SensitivityValue'],\n    '0095': ['CS', '1', 'RetestStimulusSeen'],\n    '0096': ['FL', '1', 'RetestSensitivityValue'],\n    '0097': ['SQ', '1', 'VisualFieldTestPointNormalsSequence'],\n    '0098': ['FL', '1', 'QuantifiedDefect'],\n    '0100': ['FL', '1', 'AgeCorrectedSensitivityDeviationProbabilityValue'],\n    '0102': ['CS', '1', 'GeneralizedDefectCorrectedSensitivityDeviationFlag'],\n    '0103': ['FL', '1', 'GeneralizedDefectCorrectedSensitivityDeviationValue'],\n    '0104': ['FL', '1', 'GeneralizedDefectCorrectedSensitivityDeviationProbabilityValue'],\n    '0105': ['FL', '1', 'MinimumSensitivityValue'],\n    '0106': ['CS', '1', 'BlindSpotLocalized'],\n    '0107': ['FL', '1', 'BlindSpotXCoordinate'],\n    '0108': ['FL', '1', 'BlindSpotYCoordinate'],\n    '0110': ['SQ', '1', 'VisualAcuityMeasurementSequence'],\n    '0112': ['SQ', '1', 'RefractiveParametersUsedOnPatientSequence'],\n    '0113': ['CS', '1', 'MeasurementLaterality'],\n    '0114': ['SQ', '1', 'OphthalmicPatientClinicalInformationLeftEyeSequence'],\n    '0115': ['SQ', '1', 'OphthalmicPatientClinicalInformationRightEyeSequence'],\n    '0117': ['CS', '1', 'FovealPointNormativeDataFlag'],\n    '0118': ['FL', '1', 'FovealPointProbabilityValue'],\n    '0120': ['CS', '1', 'ScreeningBaselineMeasured'],\n    '0122': ['SQ', '1', 'ScreeningBaselineMeasuredSequence'],\n    '0124': ['CS', '1', 'ScreeningBaselineType'],\n    '0126': ['FL', '1', 'ScreeningBaselineValue'],\n    '0202': ['LO', '1', 'AlgorithmSource'],\n    '0306': ['LO', '1', 'DataSetName'],\n    '0307': ['LO', '1', 'DataSetVersion'],\n    '0308': ['LO', '1', 'DataSetSource'],\n    '0309': ['LO', '1', 'DataSetDescription'],\n    '0317': ['SQ', '1', 'VisualFieldTestReliabilityGlobalIndexSequence'],\n    '0320': ['SQ', '1', 'VisualFieldGlobalResultsIndexSequence'],\n    '0325': ['SQ', '1', 'DataObservationSequence'],\n    '0338': ['CS', '1', 'IndexNormalsFlag'],\n    '0341': ['FL', '1', 'IndexProbability'],\n    '0344': ['SQ', '1', 'IndexProbabilitySequence']\n  },\n  '0028': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['US', '1', 'SamplesPerPixel'],\n    '0003': ['US', '1', 'SamplesPerPixelUsed'],\n    '0004': ['CS', '1', 'PhotometricInterpretation'],\n    '0005': ['US', '1', 'ImageDimensions'],\n    '0006': ['US', '1', 'PlanarConfiguration'],\n    '0008': ['IS', '1', 'NumberOfFrames'],\n    '0009': ['AT', '1-n', 'FrameIncrementPointer'],\n    '000A': ['AT', '1-n', 'FrameDimensionPointer'],\n    '0010': ['US', '1', 'Rows'],\n    '0011': ['US', '1', 'Columns'],\n    '0012': ['US', '1', 'Planes'],\n    '0014': ['US', '1', 'UltrasoundColorDataPresent'],\n    '0020': ['', '', ''],\n    '0030': ['DS', '2', 'PixelSpacing'],\n    '0031': ['DS', '2', 'ZoomFactor'],\n    '0032': ['DS', '2', 'ZoomCenter'],\n    '0034': ['IS', '2', 'PixelAspectRatio'],\n    '0040': ['CS', '1', 'ImageFormat'],\n    '0050': ['LO', '1-n', 'ManipulatedImage'],\n    '0051': ['CS', '1-n', 'CorrectedImage'],\n    '005F': ['LO', '1', 'CompressionRecognitionCode'],\n    '0060': ['CS', '1', 'CompressionCode'],\n    '0061': ['SH', '1', 'CompressionOriginator'],\n    '0062': ['LO', '1', 'CompressionLabel'],\n    '0063': ['SH', '1', 'CompressionDescription'],\n    '0065': ['CS', '1-n', 'CompressionSequence'],\n    '0066': ['AT', '1-n', 'CompressionStepPointers'],\n    '0068': ['US', '1', 'RepeatInterval'],\n    '0069': ['US', '1', 'BitsGrouped'],\n    '0070': ['US', '1-n', 'PerimeterTable'],\n    '0071': ['xs', '1', 'PerimeterValue'],\n    '0080': ['US', '1', 'PredictorRows'],\n    '0081': ['US', '1', 'PredictorColumns'],\n    '0082': ['US', '1-n', 'PredictorConstants'],\n    '0090': ['CS', '1', 'BlockedPixels'],\n    '0091': ['US', '1', 'BlockRows'],\n    '0092': ['US', '1', 'BlockColumns'],\n    '0093': ['US', '1', 'RowOverlap'],\n    '0094': ['US', '1', 'ColumnOverlap'],\n    '0100': ['US', '1', 'BitsAllocated'],\n    '0101': ['US', '1', 'BitsStored'],\n    '0102': ['US', '1', 'HighBit'],\n    '0103': ['US', '1', 'PixelRepresentation'],\n    '0104': ['xs', '1', 'SmallestValidPixelValue'],\n    '0105': ['xs', '1', 'LargestValidPixelValue'],\n    '0106': ['xs', '1', 'SmallestImagePixelValue'],\n    '0107': ['xs', '1', 'LargestImagePixelValue'],\n    '0108': ['xs', '1', 'SmallestPixelValueInSeries'],\n    '0109': ['xs', '1', 'LargestPixelValueInSeries'],\n    '0110': ['xs', '1', 'SmallestImagePixelValueInPlane'],\n    '0111': ['xs', '1', 'LargestImagePixelValueInPlane'],\n    '0120': ['xs', '1', 'PixelPaddingValue'],\n    '0121': ['xs', '1', 'PixelPaddingRangeLimit'],\n    '0122': ['FL', '1', 'FloatPixelPaddingValue'],\n    '0123': ['FD', '1', 'DoubleFloatPixelPaddingValue'],\n    '0124': ['FL', '1', 'FloatPixelPaddingRangeLimit'],\n    '0125': ['FD', '1', 'DoubleFloatPixelPaddingRangeLimit'],\n    '0200': ['US', '1', 'ImageLocation'],\n    '0300': ['CS', '1', 'QualityControlImage'],\n    '0301': ['CS', '1', 'BurnedInAnnotation'],\n    '0302': ['CS', '1', 'RecognizableVisualFeatures'],\n    '0303': ['CS', '1', 'LongitudinalTemporalInformationModified'],\n    '0304': ['UI', '1', 'ReferencedColorPaletteInstanceUID'],\n    '0400': ['LO', '1', 'TransformLabel'],\n    '0401': ['LO', '1', 'TransformVersionNumber'],\n    '0402': ['US', '1', 'NumberOfTransformSteps'],\n    '0403': ['LO', '1-n', 'SequenceOfCompressedData'],\n    '0404': ['AT', '1-n', 'DetailsOfCoefficients'],\n    '04x0': ['US', '1', 'RowsForNthOrderCoefficients'],\n    '04x1': ['US', '1', 'ColumnsForNthOrderCoefficients'],\n    '04x2': ['LO', '1-n', 'CoefficientCoding'],\n    '04x3': ['AT', '1-n', 'CoefficientCodingPointers'],\n    '0700': ['LO', '1', 'DCTLabel'],\n    '0701': ['CS', '1-n', 'DataBlockDescription'],\n    '0702': ['AT', '1-n', 'DataBlock'],\n    '0710': ['US', '1', 'NormalizationFactorFormat'],\n    '0720': ['US', '1', 'ZonalMapNumberFormat'],\n    '0721': ['AT', '1-n', 'ZonalMapLocation'],\n    '0722': ['US', '1', 'ZonalMapFormat'],\n    '0730': ['US', '1', 'AdaptiveMapFormat'],\n    '0740': ['US', '1', 'CodeNumberFormat'],\n    '08x0': ['CS', '1-n', 'CodeLabel'],\n    '08x2': ['US', '1', 'NumberOfTables'],\n    '08x3': ['AT', '1-n', 'CodeTableLocation'],\n    '08x4': ['US', '1', 'BitsForCodeWord'],\n    '08x8': ['AT', '1-n', 'ImageDataLocation'],\n    '0A02': ['CS', '1', 'PixelSpacingCalibrationType'],\n    '0A04': ['LO', '1', 'PixelSpacingCalibrationDescription'],\n    '1040': ['CS', '1', 'PixelIntensityRelationship'],\n    '1041': ['SS', '1', 'PixelIntensityRelationshipSign'],\n    '1050': ['DS', '1-n', 'WindowCenter'],\n    '1051': ['DS', '1-n', 'WindowWidth'],\n    '1052': ['DS', '1', 'RescaleIntercept'],\n    '1053': ['DS', '1', 'RescaleSlope'],\n    '1054': ['LO', '1', 'RescaleType'],\n    '1055': ['LO', '1-n', 'WindowCenterWidthExplanation'],\n    '1056': ['CS', '1', 'VOILUTFunction'],\n    '1080': ['CS', '1', 'GrayScale'],\n    '1090': ['CS', '1', 'RecommendedViewingMode'],\n    '1100': ['xs', '3', 'GrayLookupTableDescriptor'],\n    '1101': ['xs', '3', 'RedPaletteColorLookupTableDescriptor'],\n    '1102': ['xs', '3', 'GreenPaletteColorLookupTableDescriptor'],\n    '1103': ['xs', '3', 'BluePaletteColorLookupTableDescriptor'],\n    '1104': ['US', '3', 'AlphaPaletteColorLookupTableDescriptor'],\n    '1111': ['xs', '4', 'LargeRedPaletteColorLookupTableDescriptor'],\n    '1112': ['xs', '4', 'LargeGreenPaletteColorLookupTableDescriptor'],\n    '1113': ['xs', '4', 'LargeBluePaletteColorLookupTableDescriptor'],\n    '1199': ['UI', '1', 'PaletteColorLookupTableUID'],\n    '1200': ['xs', '1-n or 1', 'GrayLookupTableData'],\n    '1201': ['OW', '1', 'RedPaletteColorLookupTableData'],\n    '1202': ['OW', '1', 'GreenPaletteColorLookupTableData'],\n    '1203': ['OW', '1', 'BluePaletteColorLookupTableData'],\n    '1204': ['OW', '1', 'AlphaPaletteColorLookupTableData'],\n    '1211': ['OW', '1', 'LargeRedPaletteColorLookupTableData'],\n    '1212': ['OW', '1', 'LargeGreenPaletteColorLookupTableData'],\n    '1213': ['OW', '1', 'LargeBluePaletteColorLookupTableData'],\n    '1214': ['UI', '1', 'LargePaletteColorLookupTableUID'],\n    '1221': ['OW', '1', 'SegmentedRedPaletteColorLookupTableData'],\n    '1222': ['OW', '1', 'SegmentedGreenPaletteColorLookupTableData'],\n    '1223': ['OW', '1', 'SegmentedBluePaletteColorLookupTableData'],\n    '1224': ['OW', '1', 'SegmentedAlphaPaletteColorLookupTableData'],\n    '1230': ['SQ', '1', 'StoredValueColorRangeSequence'],\n    '1231': ['FD', '1', 'MinimumStoredValueMapped'],\n    '1232': ['FD', '1', 'MaximumStoredValueMapped'],\n    '1300': ['CS', '1', 'BreastImplantPresent'],\n    '1350': ['CS', '1', 'PartialView'],\n    '1351': ['ST', '1', 'PartialViewDescription'],\n    '1352': ['SQ', '1', 'PartialViewCodeSequence'],\n    '135A': ['CS', '1', 'SpatialLocationsPreserved'],\n    '1401': ['SQ', '1', 'DataFrameAssignmentSequence'],\n    '1402': ['CS', '1', 'DataPathAssignment'],\n    '1403': ['US', '1', 'BitsMappedToColorLookupTable'],\n    '1404': ['SQ', '1', 'BlendingLUT1Sequence'],\n    '1405': ['CS', '1', 'BlendingLUT1TransferFunction'],\n    '1406': ['FD', '1', 'BlendingWeightConstant'],\n    '1407': ['US', '3', 'BlendingLookupTableDescriptor'],\n    '1408': ['OW', '1', 'BlendingLookupTableData'],\n    '140B': ['SQ', '1', 'EnhancedPaletteColorLookupTableSequence'],\n    '140C': ['SQ', '1', 'BlendingLUT2Sequence'],\n    '140D': ['CS', '1', 'BlendingLUT2TransferFunction'],\n    '140E': ['CS', '1', 'DataPathID'],\n    '140F': ['CS', '1', 'RGBLUTTransferFunction'],\n    '1410': ['CS', '1', 'AlphaLUTTransferFunction'],\n    '2000': ['OB', '1', 'ICCProfile'],\n    '2002': ['CS', '1', 'ColorSpace'],\n    '2110': ['CS', '1', 'LossyImageCompression'],\n    '2112': ['DS', '1-n', 'LossyImageCompressionRatio'],\n    '2114': ['CS', '1-n', 'LossyImageCompressionMethod'],\n    '3000': ['SQ', '1', 'ModalityLUTSequence'],\n    '3002': ['xs', '3', 'LUTDescriptor'],\n    '3003': ['LO', '1', 'LUTExplanation'],\n    '3004': ['LO', '1', 'ModalityLUTType'],\n    '3006': ['xx', '1-n or 1', 'LUTData'],\n    '3010': ['SQ', '1', 'VOILUTSequence'],\n    '3110': ['SQ', '1', 'SoftcopyVOILUTSequence'],\n    '4000': ['LT', '1', 'ImagePresentationComments'],\n    '5000': ['SQ', '1', 'BiPlaneAcquisitionSequence'],\n    '6010': ['US', '1', 'RepresentativeFrameNumber'],\n    '6020': ['US', '1-n', 'FrameNumbersOfInterest'],\n    '6022': ['LO', '1-n', 'FrameOfInterestDescription'],\n    '6023': ['CS', '1-n', 'FrameOfInterestType'],\n    '6030': ['US', '1-n', 'MaskPointers'],\n    '6040': ['US', '1-n', 'RWavePointer'],\n    '6100': ['SQ', '1', 'MaskSubtractionSequence'],\n    '6101': ['CS', '1', 'MaskOperation'],\n    '6102': ['US', '2-2n', 'ApplicableFrameRange'],\n    '6110': ['US', '1-n', 'MaskFrameNumbers'],\n    '6112': ['US', '1', 'ContrastFrameAveraging'],\n    '6114': ['FL', '2', 'MaskSubPixelShift'],\n    '6120': ['SS', '1', 'TIDOffset'],\n    '6190': ['ST', '1', 'MaskOperationExplanation'],\n    '7000': ['SQ', '1', 'EquipmentAdministratorSequence'],\n    '7001': ['US', '1', 'NumberOfDisplaySubsystems'],\n    '7002': ['US', '1', 'CurrentConfigurationID'],\n    '7003': ['US', '1', 'DisplaySubsystemID'],\n    '7004': ['SH', '1', 'DisplaySubsystemName'],\n    '7005': ['LO', '1', 'DisplaySubsystemDescription'],\n    '7006': ['CS', '1', 'SystemStatus'],\n    '7007': ['LO', '1', 'SystemStatusComment'],\n    '7008': ['SQ', '1', 'TargetLuminanceCharacteristicsSequence'],\n    '7009': ['US', '1', 'LuminanceCharacteristicsID'],\n    '700A': ['SQ', '1', 'DisplaySubsystemConfigurationSequence'],\n    '700B': ['US', '1', 'ConfigurationID'],\n    '700C': ['SH', '1', 'ConfigurationName'],\n    '700D': ['LO', '1', 'ConfigurationDescription'],\n    '700E': ['US', '1', 'ReferencedTargetLuminanceCharacteristicsID'],\n    '700F': ['SQ', '1', 'QAResultsSequence'],\n    '7010': ['SQ', '1', 'DisplaySubsystemQAResultsSequence'],\n    '7011': ['SQ', '1', 'ConfigurationQAResultsSequence'],\n    '7012': ['SQ', '1', 'MeasurementEquipmentSequence'],\n    '7013': ['CS', '1-n', 'MeasurementFunctions'],\n    '7014': ['CS', '1', 'MeasurementEquipmentType'],\n    '7015': ['SQ', '1', 'VisualEvaluationResultSequence'],\n    '7016': ['SQ', '1', 'DisplayCalibrationResultSequence'],\n    '7017': ['US', '1', 'DDLValue'],\n    '7018': ['FL', '2', 'CIExyWhitePoint'],\n    '7019': ['CS', '1', 'DisplayFunctionType'],\n    '701A': ['FL', '1', 'GammaValue'],\n    '701B': ['US', '1', 'NumberOfLuminancePoints'],\n    '701C': ['SQ', '1', 'LuminanceResponseSequence'],\n    '701D': ['FL', '1', 'TargetMinimumLuminance'],\n    '701E': ['FL', '1', 'TargetMaximumLuminance'],\n    '701F': ['FL', '1', 'LuminanceValue'],\n    '7020': ['LO', '1', 'LuminanceResponseDescription'],\n    '7021': ['CS', '1', 'WhitePointFlag'],\n    '7022': ['SQ', '1', 'DisplayDeviceTypeCodeSequence'],\n    '7023': ['SQ', '1', 'DisplaySubsystemSequence'],\n    '7024': ['SQ', '1', 'LuminanceResultSequence'],\n    '7025': ['CS', '1', 'AmbientLightValueSource'],\n    '7026': ['CS', '1-n', 'MeasuredCharacteristics'],\n    '7027': ['SQ', '1', 'LuminanceUniformityResultSequence'],\n    '7028': ['SQ', '1', 'VisualEvaluationTestSequence'],\n    '7029': ['CS', '1', 'TestResult'],\n    '702A': ['LO', '1', 'TestResultComment'],\n    '702B': ['CS', '1', 'TestImageValidation'],\n    '702C': ['SQ', '1', 'TestPatternCodeSequence'],\n    '702D': ['SQ', '1', 'MeasurementPatternCodeSequence'],\n    '702E': ['SQ', '1', 'VisualEvaluationMethodCodeSequence'],\n    '7FE0': ['UR', '1', 'PixelDataProviderURL'],\n    '9001': ['UL', '1', 'DataPointRows'],\n    '9002': ['UL', '1', 'DataPointColumns'],\n    '9003': ['CS', '1', 'SignalDomainColumns'],\n    '9099': ['US', '1', 'LargestMonochromePixelValue'],\n    '9108': ['CS', '1', 'DataRepresentation'],\n    '9110': ['SQ', '1', 'PixelMeasuresSequence'],\n    '9132': ['SQ', '1', 'FrameVOILUTSequence'],\n    '9145': ['SQ', '1', 'PixelValueTransformationSequence'],\n    '9235': ['CS', '1', 'SignalDomainRows'],\n    '9411': ['FL', '1', 'DisplayFilterPercentage'],\n    '9415': ['SQ', '1', 'FramePixelShiftSequence'],\n    '9416': ['US', '1', 'SubtractionItemID'],\n    '9422': ['SQ', '1', 'PixelIntensityRelationshipLUTSequence'],\n    '9443': ['SQ', '1', 'FramePixelDataPropertiesSequence'],\n    '9444': ['CS', '1', 'GeometricalProperties'],\n    '9445': ['FL', '1', 'GeometricMaximumDistortion'],\n    '9446': ['CS', '1-n', 'ImageProcessingApplied'],\n    '9454': ['CS', '1', 'MaskSelectionMode'],\n    '9474': ['CS', '1', 'LUTFunction'],\n    '9478': ['FL', '1', 'MaskVisibilityPercentage'],\n    '9501': ['SQ', '1', 'PixelShiftSequence'],\n    '9502': ['SQ', '1', 'RegionPixelShiftSequence'],\n    '9503': ['SS', '2-2n', 'VerticesOfTheRegion'],\n    '9505': ['SQ', '1', 'MultiFramePresentationSequence'],\n    '9506': ['US', '2-2n', 'PixelShiftFrameRange'],\n    '9507': ['US', '2-2n', 'LUTFrameRange'],\n    '9520': ['DS', '16', 'ImageToEquipmentMappingMatrix'],\n    '9537': ['CS', '1', 'EquipmentCoordinateSystemIdentification']\n  },\n  '0032': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '000A': ['CS', '1', 'StudyStatusID'],\n    '000C': ['CS', '1', 'StudyPriorityID'],\n    '0012': ['LO', '1', 'StudyIDIssuer'],\n    '0032': ['DA', '1', 'StudyVerifiedDate'],\n    '0033': ['TM', '1', 'StudyVerifiedTime'],\n    '0034': ['DA', '1', 'StudyReadDate'],\n    '0035': ['TM', '1', 'StudyReadTime'],\n    '1000': ['DA', '1', 'ScheduledStudyStartDate'],\n    '1001': ['TM', '1', 'ScheduledStudyStartTime'],\n    '1010': ['DA', '1', 'ScheduledStudyStopDate'],\n    '1011': ['TM', '1', 'ScheduledStudyStopTime'],\n    '1020': ['LO', '1', 'ScheduledStudyLocation'],\n    '1021': ['AE', '1-n', 'ScheduledStudyLocationAETitle'],\n    '1030': ['LO', '1', 'ReasonForStudy'],\n    '1031': ['SQ', '1', 'RequestingPhysicianIdentificationSequence'],\n    '1032': ['PN', '1', 'RequestingPhysician'],\n    '1033': ['LO', '1', 'RequestingService'],\n    '1034': ['SQ', '1', 'RequestingServiceCodeSequence'],\n    '1040': ['DA', '1', 'StudyArrivalDate'],\n    '1041': ['TM', '1', 'StudyArrivalTime'],\n    '1050': ['DA', '1', 'StudyCompletionDate'],\n    '1051': ['TM', '1', 'StudyCompletionTime'],\n    '1055': ['CS', '1', 'StudyComponentStatusID'],\n    '1060': ['LO', '1', 'RequestedProcedureDescription'],\n    '1064': ['SQ', '1', 'RequestedProcedureCodeSequence'],\n    '1065': ['SQ', '1', 'RequestedLateralityCodeSequence'],\n    '1066': ['UT', '1', 'ReasonForVisit'],\n    '1067': ['SQ', '1', 'ReasonForVisitCodeSequence'],\n    '1070': ['LO', '1', 'RequestedContrastAgent'],\n    '4000': ['LT', '1', 'StudyComments']\n  },\n  '0034': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['SQ', '1', 'FlowIdentifierSequence'],\n    '0002': ['OB', '1', 'FlowIdentifier'],\n    '0003': ['UI', '1', 'FlowTransferSyntaxUID'],\n    '0004': ['UL', '1', 'FlowRTPSamplingRate'],\n    '0005': ['OB', '1', 'SourceIdentifier'],\n    '0007': ['OB', '1', 'FrameOriginTimestamp'],\n    '0008': ['CS', '1', 'IncludesImagingSubject'],\n    '0009': ['SQ', '1', 'FrameUsefulnessGroupSequence'],\n    '000A': ['SQ', '1', 'RealTimeBulkDataFlowSequence'],\n    '000B': ['SQ', '1', 'CameraPositionGroupSequence'],\n    '000C': ['CS', '1', 'IncludesInformation'],\n    '000D': ['SQ', '1', 'TimeOfFrameGroupSequence']\n  },\n  '0038': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0004': ['SQ', '1', 'ReferencedPatientAliasSequence'],\n    '0008': ['CS', '1', 'VisitStatusID'],\n    '0010': ['LO', '1', 'AdmissionID'],\n    '0011': ['LO', '1', 'IssuerOfAdmissionID'],\n    '0014': ['SQ', '1', 'IssuerOfAdmissionIDSequence'],\n    '0016': ['LO', '1', 'RouteOfAdmissions'],\n    '001A': ['DA', '1', 'ScheduledAdmissionDate'],\n    '001B': ['TM', '1', 'ScheduledAdmissionTime'],\n    '001C': ['DA', '1', 'ScheduledDischargeDate'],\n    '001D': ['TM', '1', 'ScheduledDischargeTime'],\n    '001E': ['LO', '1', 'ScheduledPatientInstitutionResidence'],\n    '0020': ['DA', '1', 'AdmittingDate'],\n    '0021': ['TM', '1', 'AdmittingTime'],\n    '0030': ['DA', '1', 'DischargeDate'],\n    '0032': ['TM', '1', 'DischargeTime'],\n    '0040': ['LO', '1', 'DischargeDiagnosisDescription'],\n    '0044': ['SQ', '1', 'DischargeDiagnosisCodeSequence'],\n    '0050': ['LO', '1', 'SpecialNeeds'],\n    '0060': ['LO', '1', 'ServiceEpisodeID'],\n    '0061': ['LO', '1', 'IssuerOfServiceEpisodeID'],\n    '0062': ['LO', '1', 'ServiceEpisodeDescription'],\n    '0064': ['SQ', '1', 'IssuerOfServiceEpisodeIDSequence'],\n    '0100': ['SQ', '1', 'PertinentDocumentsSequence'],\n    '0101': ['SQ', '1', 'PertinentResourcesSequence'],\n    '0102': ['LO', '1', 'ResourceDescription'],\n    '0300': ['LO', '1', 'CurrentPatientLocation'],\n    '0400': ['LO', '1', 'PatientInstitutionResidence'],\n    '0500': ['LO', '1', 'PatientState'],\n    '0502': ['SQ', '1', 'PatientClinicalTrialParticipationSequence'],\n    '4000': ['LT', '1', 'VisitComments']\n  },\n  '003A': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0004': ['CS', '1', 'WaveformOriginality'],\n    '0005': ['US', '1', 'NumberOfWaveformChannels'],\n    '0010': ['UL', '1', 'NumberOfWaveformSamples'],\n    '001A': ['DS', '1', 'SamplingFrequency'],\n    '0020': ['SH', '1', 'MultiplexGroupLabel'],\n    '0200': ['SQ', '1', 'ChannelDefinitionSequence'],\n    '0202': ['IS', '1', 'WaveformChannelNumber'],\n    '0203': ['SH', '1', 'ChannelLabel'],\n    '0205': ['CS', '1-n', 'ChannelStatus'],\n    '0208': ['SQ', '1', 'ChannelSourceSequence'],\n    '0209': ['SQ', '1', 'ChannelSourceModifiersSequence'],\n    '020A': ['SQ', '1', 'SourceWaveformSequence'],\n    '020C': ['LO', '1', 'ChannelDerivationDescription'],\n    '0210': ['DS', '1', 'ChannelSensitivity'],\n    '0211': ['SQ', '1', 'ChannelSensitivityUnitsSequence'],\n    '0212': ['DS', '1', 'ChannelSensitivityCorrectionFactor'],\n    '0213': ['DS', '1', 'ChannelBaseline'],\n    '0214': ['DS', '1', 'ChannelTimeSkew'],\n    '0215': ['DS', '1', 'ChannelSampleSkew'],\n    '0218': ['DS', '1', 'ChannelOffset'],\n    '021A': ['US', '1', 'WaveformBitsStored'],\n    '0220': ['DS', '1', 'FilterLowFrequency'],\n    '0221': ['DS', '1', 'FilterHighFrequency'],\n    '0222': ['DS', '1', 'NotchFilterFrequency'],\n    '0223': ['DS', '1', 'NotchFilterBandwidth'],\n    '0230': ['FL', '1', 'WaveformDataDisplayScale'],\n    '0231': ['US', '3', 'WaveformDisplayBackgroundCIELabValue'],\n    '0240': ['SQ', '1', 'WaveformPresentationGroupSequence'],\n    '0241': ['US', '1', 'PresentationGroupNumber'],\n    '0242': ['SQ', '1', 'ChannelDisplaySequence'],\n    '0244': ['US', '3', 'ChannelRecommendedDisplayCIELabValue'],\n    '0245': ['FL', '1', 'ChannelPosition'],\n    '0246': ['CS', '1', 'DisplayShadingFlag'],\n    '0247': ['FL', '1', 'FractionalChannelDisplayScale'],\n    '0248': ['FL', '1', 'AbsoluteChannelDisplayScale'],\n    '0300': ['SQ', '1', 'MultiplexedAudioChannelsDescriptionCodeSequence'],\n    '0301': ['IS', '1', 'ChannelIdentificationCode'],\n    '0302': ['CS', '1', 'ChannelMode'],\n    '0310': ['UI', '1', 'MultiplexGroupUID'],\n    '0311': ['DS', '1', 'PowerlineFrequency'],\n    '0312': ['SQ', '1', 'ChannelImpedanceSequence'],\n    '0313': ['DS', '1', 'ImpedanceValue'],\n    '0314': ['DT', '1', 'ImpedanceMeasurementDateTime'],\n    '0315': ['DS', '1', 'ImpedanceMeasurementFrequency'],\n    '0316': ['CS', '1', 'ImpedanceMeasurementCurrentType']\n  },\n  '0040': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['AE', '1-n', 'ScheduledStationAETitle'],\n    '0002': ['DA', '1', 'ScheduledProcedureStepStartDate'],\n    '0003': ['TM', '1', 'ScheduledProcedureStepStartTime'],\n    '0004': ['DA', '1', 'ScheduledProcedureStepEndDate'],\n    '0005': ['TM', '1', 'ScheduledProcedureStepEndTime'],\n    '0006': ['PN', '1', 'ScheduledPerformingPhysicianName'],\n    '0007': ['LO', '1', 'ScheduledProcedureStepDescription'],\n    '0008': ['SQ', '1', 'ScheduledProtocolCodeSequence'],\n    '0009': ['SH', '1', 'ScheduledProcedureStepID'],\n    '000A': ['SQ', '1', 'StageCodeSequence'],\n    '000B': ['SQ', '1', 'ScheduledPerformingPhysicianIdentificationSequence'],\n    '0010': ['SH', '1-n', 'ScheduledStationName'],\n    '0011': ['SH', '1', 'ScheduledProcedureStepLocation'],\n    '0012': ['LO', '1', 'PreMedication'],\n    '0020': ['CS', '1', 'ScheduledProcedureStepStatus'],\n    '0026': ['SQ', '1', 'OrderPlacerIdentifierSequence'],\n    '0027': ['SQ', '1', 'OrderFillerIdentifierSequence'],\n    '0031': ['UT', '1', 'LocalNamespaceEntityID'],\n    '0032': ['UT', '1', 'UniversalEntityID'],\n    '0033': ['CS', '1', 'UniversalEntityIDType'],\n    '0035': ['CS', '1', 'IdentifierTypeCode'],\n    '0036': ['SQ', '1', 'AssigningFacilitySequence'],\n    '0039': ['SQ', '1', 'AssigningJurisdictionCodeSequence'],\n    '003A': ['SQ', '1', 'AssigningAgencyOrDepartmentCodeSequence'],\n    '0100': ['SQ', '1', 'ScheduledProcedureStepSequence'],\n    '0220': ['SQ', '1', 'ReferencedNonImageCompositeSOPInstanceSequence'],\n    '0241': ['AE', '1', 'PerformedStationAETitle'],\n    '0242': ['SH', '1', 'PerformedStationName'],\n    '0243': ['SH', '1', 'PerformedLocation'],\n    '0244': ['DA', '1', 'PerformedProcedureStepStartDate'],\n    '0245': ['TM', '1', 'PerformedProcedureStepStartTime'],\n    '0250': ['DA', '1', 'PerformedProcedureStepEndDate'],\n    '0251': ['TM', '1', 'PerformedProcedureStepEndTime'],\n    '0252': ['CS', '1', 'PerformedProcedureStepStatus'],\n    '0253': ['SH', '1', 'PerformedProcedureStepID'],\n    '0254': ['LO', '1', 'PerformedProcedureStepDescription'],\n    '0255': ['LO', '1', 'PerformedProcedureTypeDescription'],\n    '0260': ['SQ', '1', 'PerformedProtocolCodeSequence'],\n    '0261': ['CS', '1', 'PerformedProtocolType'],\n    '0270': ['SQ', '1', 'ScheduledStepAttributesSequence'],\n    '0275': ['SQ', '1', 'RequestAttributesSequence'],\n    '0280': ['ST', '1', 'CommentsOnThePerformedProcedureStep'],\n    '0281': ['SQ', '1', 'PerformedProcedureStepDiscontinuationReasonCodeSequence'],\n    '0293': ['SQ', '1', 'QuantitySequence'],\n    '0294': ['DS', '1', 'Quantity'],\n    '0295': ['SQ', '1', 'MeasuringUnitsSequence'],\n    '0296': ['SQ', '1', 'BillingItemSequence'],\n    '0300': ['US', '1', 'TotalTimeOfFluoroscopy'],\n    '0301': ['US', '1', 'TotalNumberOfExposures'],\n    '0302': ['US', '1', 'EntranceDose'],\n    '0303': ['US', '1-2', 'ExposedArea'],\n    '0306': ['DS', '1', 'DistanceSourceToEntrance'],\n    '0307': ['DS', '1', 'DistanceSourceToSupport'],\n    '030E': ['SQ', '1', 'ExposureDoseSequence'],\n    '0310': ['ST', '1', 'CommentsOnRadiationDose'],\n    '0312': ['DS', '1', 'XRayOutput'],\n    '0314': ['DS', '1', 'HalfValueLayer'],\n    '0316': ['DS', '1', 'OrganDose'],\n    '0318': ['CS', '1', 'OrganExposed'],\n    '0320': ['SQ', '1', 'BillingProcedureStepSequence'],\n    '0321': ['SQ', '1', 'FilmConsumptionSequence'],\n    '0324': ['SQ', '1', 'BillingSuppliesAndDevicesSequence'],\n    '0330': ['SQ', '1', 'ReferencedProcedureStepSequence'],\n    '0340': ['SQ', '1', 'PerformedSeriesSequence'],\n    '0400': ['LT', '1', 'CommentsOnTheScheduledProcedureStep'],\n    '0440': ['SQ', '1', 'ProtocolContextSequence'],\n    '0441': ['SQ', '1', 'ContentItemModifierSequence'],\n    '0500': ['SQ', '1', 'ScheduledSpecimenSequence'],\n    '050A': ['LO', '1', 'SpecimenAccessionNumber'],\n    '0512': ['LO', '1', 'ContainerIdentifier'],\n    '0513': ['SQ', '1', 'IssuerOfTheContainerIdentifierSequence'],\n    '0515': ['SQ', '1', 'AlternateContainerIdentifierSequence'],\n    '0518': ['SQ', '1', 'ContainerTypeCodeSequence'],\n    '051A': ['LO', '1', 'ContainerDescription'],\n    '0520': ['SQ', '1', 'ContainerComponentSequence'],\n    '0550': ['SQ', '1', 'SpecimenSequence'],\n    '0551': ['LO', '1', 'SpecimenIdentifier'],\n    '0552': ['SQ', '1', 'SpecimenDescriptionSequenceTrial'],\n    '0553': ['ST', '1', 'SpecimenDescriptionTrial'],\n    '0554': ['UI', '1', 'SpecimenUID'],\n    '0555': ['SQ', '1', 'AcquisitionContextSequence'],\n    '0556': ['ST', '1', 'AcquisitionContextDescription'],\n    '0560': ['SQ', '1', 'SpecimenDescriptionSequence'],\n    '0562': ['SQ', '1', 'IssuerOfTheSpecimenIdentifierSequence'],\n    '059A': ['SQ', '1', 'SpecimenTypeCodeSequence'],\n    '0600': ['LO', '1', 'SpecimenShortDescription'],\n    '0602': ['UT', '1', 'SpecimenDetailedDescription'],\n    '0610': ['SQ', '1', 'SpecimenPreparationSequence'],\n    '0612': ['SQ', '1', 'SpecimenPreparationStepContentItemSequence'],\n    '0620': ['SQ', '1', 'SpecimenLocalizationContentItemSequence'],\n    '06FA': ['LO', '1', 'SlideIdentifier'],\n    '0710': ['SQ', '1', 'WholeSlideMicroscopyImageFrameTypeSequence'],\n    '071A': ['SQ', '1', 'ImageCenterPointCoordinatesSequence'],\n    '072A': ['DS', '1', 'XOffsetInSlideCoordinateSystem'],\n    '073A': ['DS', '1', 'YOffsetInSlideCoordinateSystem'],\n    '074A': ['DS', '1', 'ZOffsetInSlideCoordinateSystem'],\n    '08D8': ['SQ', '1', 'PixelSpacingSequence'],\n    '08DA': ['SQ', '1', 'CoordinateSystemAxisCodeSequence'],\n    '08EA': ['SQ', '1', 'MeasurementUnitsCodeSequence'],\n    '09F8': ['SQ', '1', 'VitalStainCodeSequenceTrial'],\n    '1001': ['SH', '1', 'RequestedProcedureID'],\n    '1002': ['LO', '1', 'ReasonForTheRequestedProcedure'],\n    '1003': ['SH', '1', 'RequestedProcedurePriority'],\n    '1004': ['LO', '1', 'PatientTransportArrangements'],\n    '1005': ['LO', '1', 'RequestedProcedureLocation'],\n    '1006': ['SH', '1', 'PlacerOrderNumberProcedure'],\n    '1007': ['SH', '1', 'FillerOrderNumberProcedure'],\n    '1008': ['LO', '1', 'ConfidentialityCode'],\n    '1009': ['SH', '1', 'ReportingPriority'],\n    '100A': ['SQ', '1', 'ReasonForRequestedProcedureCodeSequence'],\n    '1010': ['PN', '1-n', 'NamesOfIntendedRecipientsOfResults'],\n    '1011': ['SQ', '1', 'IntendedRecipientsOfResultsIdentificationSequence'],\n    '1012': ['SQ', '1', 'ReasonForPerformedProcedureCodeSequence'],\n    '1060': ['LO', '1', 'RequestedProcedureDescriptionTrial'],\n    '1101': ['SQ', '1', 'PersonIdentificationCodeSequence'],\n    '1102': ['ST', '1', 'PersonAddress'],\n    '1103': ['LO', '1-n', 'PersonTelephoneNumbers'],\n    '1104': ['LT', '1', 'PersonTelecomInformation'],\n    '1400': ['LT', '1', 'RequestedProcedureComments'],\n    '2001': ['LO', '1', 'ReasonForTheImagingServiceRequest'],\n    '2004': ['DA', '1', 'IssueDateOfImagingServiceRequest'],\n    '2005': ['TM', '1', 'IssueTimeOfImagingServiceRequest'],\n    '2006': ['SH', '1', 'PlacerOrderNumberImagingServiceRequestRetired'],\n    '2007': ['SH', '1', 'FillerOrderNumberImagingServiceRequestRetired'],\n    '2008': ['PN', '1', 'OrderEnteredBy'],\n    '2009': ['SH', '1', 'OrderEntererLocation'],\n    '2010': ['SH', '1', 'OrderCallbackPhoneNumber'],\n    '2011': ['LT', '1', 'OrderCallbackTelecomInformation'],\n    '2016': ['LO', '1', 'PlacerOrderNumberImagingServiceRequest'],\n    '2017': ['LO', '1', 'FillerOrderNumberImagingServiceRequest'],\n    '2400': ['LT', '1', 'ImagingServiceRequestComments'],\n    '3001': ['LO', '1', 'ConfidentialityConstraintOnPatientDataDescription'],\n    '4001': ['CS', '1', 'GeneralPurposeScheduledProcedureStepStatus'],\n    '4002': ['CS', '1', 'GeneralPurposePerformedProcedureStepStatus'],\n    '4003': ['CS', '1', 'GeneralPurposeScheduledProcedureStepPriority'],\n    '4004': ['SQ', '1', 'ScheduledProcessingApplicationsCodeSequence'],\n    '4005': ['DT', '1', 'ScheduledProcedureStepStartDateTime'],\n    '4006': ['CS', '1', 'MultipleCopiesFlag'],\n    '4007': ['SQ', '1', 'PerformedProcessingApplicationsCodeSequence'],\n    '4008': ['DT', '1', 'ScheduledProcedureStepExpirationDateTime'],\n    '4009': ['SQ', '1', 'HumanPerformerCodeSequence'],\n    '4010': ['DT', '1', 'ScheduledProcedureStepModificationDateTime'],\n    '4011': ['DT', '1', 'ExpectedCompletionDateTime'],\n    '4015': ['SQ', '1', 'ResultingGeneralPurposePerformedProcedureStepsSequence'],\n    '4016': ['SQ', '1', 'ReferencedGeneralPurposeScheduledProcedureStepSequence'],\n    '4018': ['SQ', '1', 'ScheduledWorkitemCodeSequence'],\n    '4019': ['SQ', '1', 'PerformedWorkitemCodeSequence'],\n    '4020': ['CS', '1', 'InputAvailabilityFlag'],\n    '4021': ['SQ', '1', 'InputInformationSequence'],\n    '4022': ['SQ', '1', 'RelevantInformationSequence'],\n    '4023': ['UI', '1', 'ReferencedGeneralPurposeScheduledProcedureStepTransactionUID'],\n    '4025': ['SQ', '1', 'ScheduledStationNameCodeSequence'],\n    '4026': ['SQ', '1', 'ScheduledStationClassCodeSequence'],\n    '4027': ['SQ', '1', 'ScheduledStationGeographicLocationCodeSequence'],\n    '4028': ['SQ', '1', 'PerformedStationNameCodeSequence'],\n    '4029': ['SQ', '1', 'PerformedStationClassCodeSequence'],\n    '4030': ['SQ', '1', 'PerformedStationGeographicLocationCodeSequence'],\n    '4031': ['SQ', '1', 'RequestedSubsequentWorkitemCodeSequence'],\n    '4032': ['SQ', '1', 'NonDICOMOutputCodeSequence'],\n    '4033': ['SQ', '1', 'OutputInformationSequence'],\n    '4034': ['SQ', '1', 'ScheduledHumanPerformersSequence'],\n    '4035': ['SQ', '1', 'ActualHumanPerformersSequence'],\n    '4036': ['LO', '1', 'HumanPerformerOrganization'],\n    '4037': ['PN', '1', 'HumanPerformerName'],\n    '4040': ['CS', '1', 'RawDataHandling'],\n    '4041': ['CS', '1', 'InputReadinessState'],\n    '4050': ['DT', '1', 'PerformedProcedureStepStartDateTime'],\n    '4051': ['DT', '1', 'PerformedProcedureStepEndDateTime'],\n    '4052': ['DT', '1', 'ProcedureStepCancellationDateTime'],\n    '4070': ['SQ', '1', 'OutputDestinationSequence'],\n    '4071': ['SQ', '1', 'DICOMStorageSequence'],\n    '4072': ['SQ', '1', 'STOWRSStorageSequence'],\n    '4073': ['UR', '1', 'StorageURL'],\n    '4074': ['SQ', '1', 'XDSStorageSequence'],\n    '8302': ['DS', '1', 'EntranceDoseInmGy'],\n    '8303': ['CS', '1', 'EntranceDoseDerivation'],\n    '9092': ['SQ', '1', 'ParametricMapFrameTypeSequence'],\n    '9094': ['SQ', '1', 'ReferencedImageRealWorldValueMappingSequence'],\n    '9096': ['SQ', '1', 'RealWorldValueMappingSequence'],\n    '9098': ['SQ', '1', 'PixelValueMappingCodeSequence'],\n    '9210': ['SH', '1', 'LUTLabel'],\n    '9211': ['xs', '1', 'RealWorldValueLastValueMapped'],\n    '9212': ['FD', '1-n', 'RealWorldValueLUTData'],\n    '9213': ['FD', '1', 'DoubleFloatRealWorldValueLastValueMapped'],\n    '9214': ['FD', '1', 'DoubleFloatRealWorldValueFirstValueMapped'],\n    '9216': ['xs', '1', 'RealWorldValueFirstValueMapped'],\n    '9220': ['SQ', '1', 'QuantityDefinitionSequence'],\n    '9224': ['FD', '1', 'RealWorldValueIntercept'],\n    '9225': ['FD', '1', 'RealWorldValueSlope'],\n    'A007': ['CS', '1', 'FindingsFlagTrial'],\n    'A010': ['CS', '1', 'RelationshipType'],\n    'A020': ['SQ', '1', 'FindingsSequenceTrial'],\n    'A021': ['UI', '1', 'FindingsGroupUIDTrial'],\n    'A022': ['UI', '1', 'ReferencedFindingsGroupUIDTrial'],\n    'A023': ['DA', '1', 'FindingsGroupRecordingDateTrial'],\n    'A024': ['TM', '1', 'FindingsGroupRecordingTimeTrial'],\n    'A026': ['SQ', '1', 'FindingsSourceCategoryCodeSequenceTrial'],\n    'A027': ['LO', '1', 'VerifyingOrganization'],\n    'A028': ['SQ', '1', 'DocumentingOrganizationIdentifierCodeSequenceTrial'],\n    'A030': ['DT', '1', 'VerificationDateTime'],\n    'A032': ['DT', '1', 'ObservationDateTime'],\n    'A033': ['DT', '1', 'ObservationStartDateTime'],\n    'A040': ['CS', '1', 'ValueType'],\n    'A043': ['SQ', '1', 'ConceptNameCodeSequence'],\n    'A047': ['LO', '1', 'MeasurementPrecisionDescriptionTrial'],\n    'A050': ['CS', '1', 'ContinuityOfContent'],\n    'A057': ['CS', '1-n', 'UrgencyOrPriorityAlertsTrial'],\n    'A060': ['LO', '1', 'SequencingIndicatorTrial'],\n    'A066': ['SQ', '1', 'DocumentIdentifierCodeSequenceTrial'],\n    'A067': ['PN', '1', 'DocumentAuthorTrial'],\n    'A068': ['SQ', '1', 'DocumentAuthorIdentifierCodeSequenceTrial'],\n    'A070': ['SQ', '1', 'IdentifierCodeSequenceTrial'],\n    'A073': ['SQ', '1', 'VerifyingObserverSequence'],\n    'A074': ['OB', '1', 'ObjectBinaryIdentifierTrial'],\n    'A075': ['PN', '1', 'VerifyingObserverName'],\n    'A076': ['SQ', '1', 'DocumentingObserverIdentifierCodeSequenceTrial'],\n    'A078': ['SQ', '1', 'AuthorObserverSequence'],\n    'A07A': ['SQ', '1', 'ParticipantSequence'],\n    'A07C': ['SQ', '1', 'CustodialOrganizationSequence'],\n    'A080': ['CS', '1', 'ParticipationType'],\n    'A082': ['DT', '1', 'ParticipationDateTime'],\n    'A084': ['CS', '1', 'ObserverType'],\n    'A085': ['SQ', '1', 'ProcedureIdentifierCodeSequenceTrial'],\n    'A088': ['SQ', '1', 'VerifyingObserverIdentificationCodeSequence'],\n    'A089': ['OB', '1', 'ObjectDirectoryBinaryIdentifierTrial'],\n    'A090': ['SQ', '1', 'EquivalentCDADocumentSequence'],\n    'A0B0': ['US', '2-2n', 'ReferencedWaveformChannels'],\n    'A110': ['DA', '1', 'DateOfDocumentOrVerbalTransactionTrial'],\n    'A112': ['TM', '1', 'TimeOfDocumentCreationOrVerbalTransactionTrial'],\n    'A120': ['DT', '1', 'DateTime'],\n    'A121': ['DA', '1', 'Date'],\n    'A122': ['TM', '1', 'Time'],\n    'A123': ['PN', '1', 'PersonName'],\n    'A124': ['UI', '1', 'UID'],\n    'A125': ['CS', '2', 'ReportStatusIDTrial'],\n    'A130': ['CS', '1', 'TemporalRangeType'],\n    'A132': ['UL', '1-n', 'ReferencedSamplePositions'],\n    'A136': ['US', '1-n', 'ReferencedFrameNumbers'],\n    'A138': ['DS', '1-n', 'ReferencedTimeOffsets'],\n    'A13A': ['DT', '1-n', 'ReferencedDateTime'],\n    'A160': ['UT', '1', 'TextValue'],\n    'A161': ['FD', '1-n', 'FloatingPointValue'],\n    'A162': ['SL', '1-n', 'RationalNumeratorValue'],\n    'A163': ['UL', '1-n', 'RationalDenominatorValue'],\n    'A167': ['SQ', '1', 'ObservationCategoryCodeSequenceTrial'],\n    'A168': ['SQ', '1', 'ConceptCodeSequence'],\n    'A16A': ['ST', '1', 'BibliographicCitationTrial'],\n    'A170': ['SQ', '1', 'PurposeOfReferenceCodeSequence'],\n    'A171': ['UI', '1', 'ObservationUID'],\n    'A172': ['UI', '1', 'ReferencedObservationUIDTrial'],\n    'A173': ['CS', '1', 'ReferencedObservationClassTrial'],\n    'A174': ['CS', '1', 'ReferencedObjectObservationClassTrial'],\n    'A180': ['US', '1', 'AnnotationGroupNumber'],\n    'A192': ['DA', '1', 'ObservationDateTrial'],\n    'A193': ['TM', '1', 'ObservationTimeTrial'],\n    'A194': ['CS', '1', 'MeasurementAutomationTrial'],\n    'A195': ['SQ', '1', 'ModifierCodeSequence'],\n    'A224': ['ST', '1', 'IdentificationDescriptionTrial'],\n    'A290': ['CS', '1', 'CoordinatesSetGeometricTypeTrial'],\n    'A296': ['SQ', '1', 'AlgorithmCodeSequenceTrial'],\n    'A297': ['ST', '1', 'AlgorithmDescriptionTrial'],\n    'A29A': ['SL', '2-2n', 'PixelCoordinatesSetTrial'],\n    'A300': ['SQ', '1', 'MeasuredValueSequence'],\n    'A301': ['SQ', '1', 'NumericValueQualifierCodeSequence'],\n    'A307': ['PN', '1', 'CurrentObserverTrial'],\n    'A30A': ['DS', '1-n', 'NumericValue'],\n    'A313': ['SQ', '1', 'ReferencedAccessionSequenceTrial'],\n    'A33A': ['ST', '1', 'ReportStatusCommentTrial'],\n    'A340': ['SQ', '1', 'ProcedureContextSequenceTrial'],\n    'A352': ['PN', '1', 'VerbalSourceTrial'],\n    'A353': ['ST', '1', 'AddressTrial'],\n    'A354': ['LO', '1', 'TelephoneNumberTrial'],\n    'A358': ['SQ', '1', 'VerbalSourceIdentifierCodeSequenceTrial'],\n    'A360': ['SQ', '1', 'PredecessorDocumentsSequence'],\n    'A370': ['SQ', '1', 'ReferencedRequestSequence'],\n    'A372': ['SQ', '1', 'PerformedProcedureCodeSequence'],\n    'A375': ['SQ', '1', 'CurrentRequestedProcedureEvidenceSequence'],\n    'A380': ['SQ', '1', 'ReportDetailSequenceTrial'],\n    'A385': ['SQ', '1', 'PertinentOtherEvidenceSequence'],\n    'A390': ['SQ', '1', 'HL7StructuredDocumentReferenceSequence'],\n    'A402': ['UI', '1', 'ObservationSubjectUIDTrial'],\n    'A403': ['CS', '1', 'ObservationSubjectClassTrial'],\n    'A404': ['SQ', '1', 'ObservationSubjectTypeCodeSequenceTrial'],\n    'A491': ['CS', '1', 'CompletionFlag'],\n    'A492': ['LO', '1', 'CompletionFlagDescription'],\n    'A493': ['CS', '1', 'VerificationFlag'],\n    'A494': ['CS', '1', 'ArchiveRequested'],\n    'A496': ['CS', '1', 'PreliminaryFlag'],\n    'A504': ['SQ', '1', 'ContentTemplateSequence'],\n    'A525': ['SQ', '1', 'IdenticalDocumentsSequence'],\n    'A600': ['CS', '1', 'ObservationSubjectContextFlagTrial'],\n    'A601': ['CS', '1', 'ObserverContextFlagTrial'],\n    'A603': ['CS', '1', 'ProcedureContextFlagTrial'],\n    'A730': ['SQ', '1', 'ContentSequence'],\n    'A731': ['SQ', '1', 'RelationshipSequenceTrial'],\n    'A732': ['SQ', '1', 'RelationshipTypeCodeSequenceTrial'],\n    'A744': ['SQ', '1', 'LanguageCodeSequenceTrial'],\n    'A801': ['SQ', '1', 'TabulatedValuesSequence'],\n    'A802': ['UL', '1', 'NumberOfTableRows'],\n    'A803': ['UL', '1', 'NumberOfTableColumns'],\n    'A804': ['UL', '1', 'TableRowNumber'],\n    'A805': ['UL', '1', 'TableColumnNumber'],\n    'A806': ['SQ', '1', 'TableRowDefinitionSequence'],\n    'A807': ['SQ', '1', 'TableColumnDefinitionSequence'],\n    'A808': ['SQ', '1', 'CellValuesSequence'],\n    'A992': ['ST', '1', 'UniformResourceLocatorTrial'],\n    'B020': ['SQ', '1', 'WaveformAnnotationSequence'],\n    'DB00': ['CS', '1', 'TemplateIdentifier'],\n    'DB06': ['DT', '1', 'TemplateVersion'],\n    'DB07': ['DT', '1', 'TemplateLocalVersion'],\n    'DB0B': ['CS', '1', 'TemplateExtensionFlag'],\n    'DB0C': ['UI', '1', 'TemplateExtensionOrganizationUID'],\n    'DB0D': ['UI', '1', 'TemplateExtensionCreatorUID'],\n    'DB73': ['UL', '1-n', 'ReferencedContentItemIdentifier'],\n    'E001': ['ST', '1', 'HL7InstanceIdentifier'],\n    'E004': ['DT', '1', 'HL7DocumentEffectiveTime'],\n    'E006': ['SQ', '1', 'HL7DocumentTypeCodeSequence'],\n    'E008': ['SQ', '1', 'DocumentClassCodeSequence'],\n    'E010': ['UR', '1', 'RetrieveURI'],\n    'E011': ['UI', '1', 'RetrieveLocationUID'],\n    'E020': ['CS', '1', 'TypeOfInstances'],\n    'E021': ['SQ', '1', 'DICOMRetrievalSequence'],\n    'E022': ['SQ', '1', 'DICOMMediaRetrievalSequence'],\n    'E023': ['SQ', '1', 'WADORetrievalSequence'],\n    'E024': ['SQ', '1', 'XDSRetrievalSequence'],\n    'E025': ['SQ', '1', 'WADORSRetrievalSequence'],\n    'E030': ['UI', '1', 'RepositoryUniqueID'],\n    'E031': ['UI', '1', 'HomeCommunityID']\n  },\n  '0042': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['ST', '1', 'DocumentTitle'],\n    '0011': ['OB', '1', 'EncapsulatedDocument'],\n    '0012': ['LO', '1', 'MIMETypeOfEncapsulatedDocument'],\n    '0013': ['SQ', '1', 'SourceInstanceSequence'],\n    '0014': ['LO', '1-n', 'ListOfMIMETypes'],\n    '0015': ['UL', '1', 'EncapsulatedDocumentLength']\n  },\n  '0044': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['ST', '1', 'ProductPackageIdentifier'],\n    '0002': ['CS', '1', 'SubstanceAdministrationApproval'],\n    '0003': ['LT', '1', 'ApprovalStatusFurtherDescription'],\n    '0004': ['DT', '1', 'ApprovalStatusDateTime'],\n    '0007': ['SQ', '1', 'ProductTypeCodeSequence'],\n    '0008': ['LO', '1-n', 'ProductName'],\n    '0009': ['LT', '1', 'ProductDescription'],\n    '000A': ['LO', '1', 'ProductLotIdentifier'],\n    '000B': ['DT', '1', 'ProductExpirationDateTime'],\n    '0010': ['DT', '1', 'SubstanceAdministrationDateTime'],\n    '0011': ['LO', '1', 'SubstanceAdministrationNotes'],\n    '0012': ['LO', '1', 'SubstanceAdministrationDeviceID'],\n    '0013': ['SQ', '1', 'ProductParameterSequence'],\n    '0019': ['SQ', '1', 'SubstanceAdministrationParameterSequence'],\n    '0100': ['SQ', '1', 'ApprovalSequence'],\n    '0101': ['SQ', '1', 'AssertionCodeSequence'],\n    '0102': ['UI', '1', 'AssertionUID'],\n    '0103': ['SQ', '1', 'AsserterIdentificationSequence'],\n    '0104': ['DT', '1', 'AssertionDateTime'],\n    '0105': ['DT', '1', 'AssertionExpirationDateTime'],\n    '0106': ['UT', '1', 'AssertionComments'],\n    '0107': ['SQ', '1', 'RelatedAssertionSequence'],\n    '0108': ['UI', '1', 'ReferencedAssertionUID'],\n    '0109': ['SQ', '1', 'ApprovalSubjectSequence'],\n    '010A': ['SQ', '1', 'OrganizationalRoleCodeSequence']\n  },\n  '0046': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0012': ['LO', '1', 'LensDescription'],\n    '0014': ['SQ', '1', 'RightLensSequence'],\n    '0015': ['SQ', '1', 'LeftLensSequence'],\n    '0016': ['SQ', '1', 'UnspecifiedLateralityLensSequence'],\n    '0018': ['SQ', '1', 'CylinderSequence'],\n    '0028': ['SQ', '1', 'PrismSequence'],\n    '0030': ['FD', '1', 'HorizontalPrismPower'],\n    '0032': ['CS', '1', 'HorizontalPrismBase'],\n    '0034': ['FD', '1', 'VerticalPrismPower'],\n    '0036': ['CS', '1', 'VerticalPrismBase'],\n    '0038': ['CS', '1', 'LensSegmentType'],\n    '0040': ['FD', '1', 'OpticalTransmittance'],\n    '0042': ['FD', '1', 'ChannelWidth'],\n    '0044': ['FD', '1', 'PupilSize'],\n    '0046': ['FD', '1', 'CornealSize'],\n    '0047': ['SQ', '1', 'CornealSizeSequence'],\n    '0050': ['SQ', '1', 'AutorefractionRightEyeSequence'],\n    '0052': ['SQ', '1', 'AutorefractionLeftEyeSequence'],\n    '0060': ['FD', '1', 'DistancePupillaryDistance'],\n    '0062': ['FD', '1', 'NearPupillaryDistance'],\n    '0063': ['FD', '1', 'IntermediatePupillaryDistance'],\n    '0064': ['FD', '1', 'OtherPupillaryDistance'],\n    '0070': ['SQ', '1', 'KeratometryRightEyeSequence'],\n    '0071': ['SQ', '1', 'KeratometryLeftEyeSequence'],\n    '0074': ['SQ', '1', 'SteepKeratometricAxisSequence'],\n    '0075': ['FD', '1', 'RadiusOfCurvature'],\n    '0076': ['FD', '1', 'KeratometricPower'],\n    '0077': ['FD', '1', 'KeratometricAxis'],\n    '0080': ['SQ', '1', 'FlatKeratometricAxisSequence'],\n    '0092': ['CS', '1', 'BackgroundColor'],\n    '0094': ['CS', '1', 'Optotype'],\n    '0095': ['CS', '1', 'OptotypePresentation'],\n    '0097': ['SQ', '1', 'SubjectiveRefractionRightEyeSequence'],\n    '0098': ['SQ', '1', 'SubjectiveRefractionLeftEyeSequence'],\n    '0100': ['SQ', '1', 'AddNearSequence'],\n    '0101': ['SQ', '1', 'AddIntermediateSequence'],\n    '0102': ['SQ', '1', 'AddOtherSequence'],\n    '0104': ['FD', '1', 'AddPower'],\n    '0106': ['FD', '1', 'ViewingDistance'],\n    '0110': ['SQ', '1', 'CorneaMeasurementsSequence'],\n    '0111': ['SQ', '1', 'SourceOfCorneaMeasurementDataCodeSequence'],\n    '0112': ['SQ', '1', 'SteepCornealAxisSequence'],\n    '0113': ['SQ', '1', 'FlatCornealAxisSequence'],\n    '0114': ['FD', '1', 'CornealPower'],\n    '0115': ['FD', '1', 'CornealAxis'],\n    '0116': ['SQ', '1', 'CorneaMeasurementMethodCodeSequence'],\n    '0117': ['FL', '1', 'RefractiveIndexOfCornea'],\n    '0118': ['FL', '1', 'RefractiveIndexOfAqueousHumor'],\n    '0121': ['SQ', '1', 'VisualAcuityTypeCodeSequence'],\n    '0122': ['SQ', '1', 'VisualAcuityRightEyeSequence'],\n    '0123': ['SQ', '1', 'VisualAcuityLeftEyeSequence'],\n    '0124': ['SQ', '1', 'VisualAcuityBothEyesOpenSequence'],\n    '0125': ['CS', '1', 'ViewingDistanceType'],\n    '0135': ['SS', '2', 'VisualAcuityModifiers'],\n    '0137': ['FD', '1', 'DecimalVisualAcuity'],\n    '0139': ['LO', '1', 'OptotypeDetailedDefinition'],\n    '0145': ['SQ', '1', 'ReferencedRefractiveMeasurementsSequence'],\n    '0146': ['FD', '1', 'SpherePower'],\n    '0147': ['FD', '1', 'CylinderPower'],\n    '0201': ['CS', '1', 'CornealTopographySurface'],\n    '0202': ['FL', '2', 'CornealVertexLocation'],\n    '0203': ['FL', '1', 'PupilCentroidXCoordinate'],\n    '0204': ['FL', '1', 'PupilCentroidYCoordinate'],\n    '0205': ['FL', '1', 'EquivalentPupilRadius'],\n    '0207': ['SQ', '1', 'CornealTopographyMapTypeCodeSequence'],\n    '0208': ['IS', '2-2n', 'VerticesOfTheOutlineOfPupil'],\n    '0210': ['SQ', '1', 'CornealTopographyMappingNormalsSequence'],\n    '0211': ['SQ', '1', 'MaximumCornealCurvatureSequence'],\n    '0212': ['FL', '1', 'MaximumCornealCurvature'],\n    '0213': ['FL', '2', 'MaximumCornealCurvatureLocation'],\n    '0215': ['SQ', '1', 'MinimumKeratometricSequence'],\n    '0218': ['SQ', '1', 'SimulatedKeratometricCylinderSequence'],\n    '0220': ['FL', '1', 'AverageCornealPower'],\n    '0224': ['FL', '1', 'CornealISValue'],\n    '0227': ['FL', '1', 'AnalyzedArea'],\n    '0230': ['FL', '1', 'SurfaceRegularityIndex'],\n    '0232': ['FL', '1', 'SurfaceAsymmetryIndex'],\n    '0234': ['FL', '1', 'CornealEccentricityIndex'],\n    '0236': ['FL', '1', 'KeratoconusPredictionIndex'],\n    '0238': ['FL', '1', 'DecimalPotentialVisualAcuity'],\n    '0242': ['CS', '1', 'CornealTopographyMapQualityEvaluation'],\n    '0244': ['SQ', '1', 'SourceImageCornealProcessedDataSequence'],\n    '0247': ['FL', '3', 'CornealPointLocation'],\n    '0248': ['CS', '1', 'CornealPointEstimated'],\n    '0249': ['FL', '1', 'AxialPower'],\n    '0250': ['FL', '1', 'TangentialPower'],\n    '0251': ['FL', '1', 'RefractivePower'],\n    '0252': ['FL', '1', 'RelativeElevation'],\n    '0253': ['FL', '1', 'CornealWavefront']\n  },\n  '0048': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['FL', '1', 'ImagedVolumeWidth'],\n    '0002': ['FL', '1', 'ImagedVolumeHeight'],\n    '0003': ['FL', '1', 'ImagedVolumeDepth'],\n    '0006': ['UL', '1', 'TotalPixelMatrixColumns'],\n    '0007': ['UL', '1', 'TotalPixelMatrixRows'],\n    '0008': ['SQ', '1', 'TotalPixelMatrixOriginSequence'],\n    '0010': ['CS', '1', 'SpecimenLabelInImage'],\n    '0011': ['CS', '1', 'FocusMethod'],\n    '0012': ['CS', '1', 'ExtendedDepthOfField'],\n    '0013': ['US', '1', 'NumberOfFocalPlanes'],\n    '0014': ['FL', '1', 'DistanceBetweenFocalPlanes'],\n    '0015': ['US', '3', 'RecommendedAbsentPixelCIELabValue'],\n    '0100': ['SQ', '1', 'IlluminatorTypeCodeSequence'],\n    '0102': ['DS', '6', 'ImageOrientationSlide'],\n    '0105': ['SQ', '1', 'OpticalPathSequence'],\n    '0106': ['SH', '1', 'OpticalPathIdentifier'],\n    '0107': ['ST', '1', 'OpticalPathDescription'],\n    '0108': ['SQ', '1', 'IlluminationColorCodeSequence'],\n    '0110': ['SQ', '1', 'SpecimenReferenceSequence'],\n    '0111': ['DS', '1', 'CondenserLensPower'],\n    '0112': ['DS', '1', 'ObjectiveLensPower'],\n    '0113': ['DS', '1', 'ObjectiveLensNumericalAperture'],\n    '0120': ['SQ', '1', 'PaletteColorLookupTableSequence'],\n    '0200': ['SQ', '1', 'ReferencedImageNavigationSequence'],\n    '0201': ['US', '2', 'TopLeftHandCornerOfLocalizerArea'],\n    '0202': ['US', '2', 'BottomRightHandCornerOfLocalizerArea'],\n    '0207': ['SQ', '1', 'OpticalPathIdentificationSequence'],\n    '021A': ['SQ', '1', 'PlanePositionSlideSequence'],\n    '021E': ['SL', '1', 'ColumnPositionInTotalImagePixelMatrix'],\n    '021F': ['SL', '1', 'RowPositionInTotalImagePixelMatrix'],\n    '0301': ['CS', '1', 'PixelOriginInterpretation'],\n    '0302': ['UL', '1', 'NumberOfOpticalPaths'],\n    '0303': ['UL', '1', 'TotalPixelMatrixFocalPlanes']\n  },\n  '0050': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0004': ['CS', '1', 'CalibrationImage'],\n    '0010': ['SQ', '1', 'DeviceSequence'],\n    '0012': ['SQ', '1', 'ContainerComponentTypeCodeSequence'],\n    '0013': ['FD', '1', 'ContainerComponentThickness'],\n    '0014': ['DS', '1', 'DeviceLength'],\n    '0015': ['FD', '1', 'ContainerComponentWidth'],\n    '0016': ['DS', '1', 'DeviceDiameter'],\n    '0017': ['CS', '1', 'DeviceDiameterUnits'],\n    '0018': ['DS', '1', 'DeviceVolume'],\n    '0019': ['DS', '1', 'InterMarkerDistance'],\n    '001A': ['CS', '1', 'ContainerComponentMaterial'],\n    '001B': ['LO', '1', 'ContainerComponentID'],\n    '001C': ['FD', '1', 'ContainerComponentLength'],\n    '001D': ['FD', '1', 'ContainerComponentDiameter'],\n    '001E': ['LO', '1', 'ContainerComponentDescription'],\n    '0020': ['LO', '1', 'DeviceDescription'],\n    '0021': ['ST', '1', 'LongDeviceDescription']\n  },\n  '0052': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['FL', '1', 'ContrastBolusIngredientPercentByVolume'],\n    '0002': ['FD', '1', 'OCTFocalDistance'],\n    '0003': ['FD', '1', 'BeamSpotSize'],\n    '0004': ['FD', '1', 'EffectiveRefractiveIndex'],\n    '0006': ['CS', '1', 'OCTAcquisitionDomain'],\n    '0007': ['FD', '1', 'OCTOpticalCenterWavelength'],\n    '0008': ['FD', '1', 'AxialResolution'],\n    '0009': ['FD', '1', 'RangingDepth'],\n    '0011': ['FD', '1', 'ALineRate'],\n    '0012': ['US', '1', 'ALinesPerFrame'],\n    '0013': ['FD', '1', 'CatheterRotationalRate'],\n    '0014': ['FD', '1', 'ALinePixelSpacing'],\n    '0016': ['SQ', '1', 'ModeOfPercutaneousAccessSequence'],\n    '0025': ['SQ', '1', 'IntravascularOCTFrameTypeSequence'],\n    '0026': ['CS', '1', 'OCTZOffsetApplied'],\n    '0027': ['SQ', '1', 'IntravascularFrameContentSequence'],\n    '0028': ['FD', '1', 'IntravascularLongitudinalDistance'],\n    '0029': ['SQ', '1', 'IntravascularOCTFrameContentSequence'],\n    '0030': ['SS', '1', 'OCTZOffsetCorrection'],\n    '0031': ['CS', '1', 'CatheterDirectionOfRotation'],\n    '0033': ['FD', '1', 'SeamLineLocation'],\n    '0034': ['FD', '1', 'FirstALineLocation'],\n    '0036': ['US', '1', 'SeamLineIndex'],\n    '0038': ['US', '1', 'NumberOfPaddedALines'],\n    '0039': ['CS', '1', 'InterpolationType'],\n    '003A': ['CS', '1', 'RefractiveIndexApplied']\n  },\n  '0054': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['US', '1-n', 'EnergyWindowVector'],\n    '0011': ['US', '1', 'NumberOfEnergyWindows'],\n    '0012': ['SQ', '1', 'EnergyWindowInformationSequence'],\n    '0013': ['SQ', '1', 'EnergyWindowRangeSequence'],\n    '0014': ['DS', '1', 'EnergyWindowLowerLimit'],\n    '0015': ['DS', '1', 'EnergyWindowUpperLimit'],\n    '0016': ['SQ', '1', 'RadiopharmaceuticalInformationSequence'],\n    '0017': ['IS', '1', 'ResidualSyringeCounts'],\n    '0018': ['SH', '1', 'EnergyWindowName'],\n    '0020': ['US', '1-n', 'DetectorVector'],\n    '0021': ['US', '1', 'NumberOfDetectors'],\n    '0022': ['SQ', '1', 'DetectorInformationSequence'],\n    '0030': ['US', '1-n', 'PhaseVector'],\n    '0031': ['US', '1', 'NumberOfPhases'],\n    '0032': ['SQ', '1', 'PhaseInformationSequence'],\n    '0033': ['US', '1', 'NumberOfFramesInPhase'],\n    '0036': ['IS', '1', 'PhaseDelay'],\n    '0038': ['IS', '1', 'PauseBetweenFrames'],\n    '0039': ['CS', '1', 'PhaseDescription'],\n    '0050': ['US', '1-n', 'RotationVector'],\n    '0051': ['US', '1', 'NumberOfRotations'],\n    '0052': ['SQ', '1', 'RotationInformationSequence'],\n    '0053': ['US', '1', 'NumberOfFramesInRotation'],\n    '0060': ['US', '1-n', 'RRIntervalVector'],\n    '0061': ['US', '1', 'NumberOfRRIntervals'],\n    '0062': ['SQ', '1', 'GatedInformationSequence'],\n    '0063': ['SQ', '1', 'DataInformationSequence'],\n    '0070': ['US', '1-n', 'TimeSlotVector'],\n    '0071': ['US', '1', 'NumberOfTimeSlots'],\n    '0072': ['SQ', '1', 'TimeSlotInformationSequence'],\n    '0073': ['DS', '1', 'TimeSlotTime'],\n    '0080': ['US', '1-n', 'SliceVector'],\n    '0081': ['US', '1', 'NumberOfSlices'],\n    '0090': ['US', '1-n', 'AngularViewVector'],\n    '0100': ['US', '1-n', 'TimeSliceVector'],\n    '0101': ['US', '1', 'NumberOfTimeSlices'],\n    '0200': ['DS', '1', 'StartAngle'],\n    '0202': ['CS', '1', 'TypeOfDetectorMotion'],\n    '0210': ['IS', '1-n', 'TriggerVector'],\n    '0211': ['US', '1', 'NumberOfTriggersInPhase'],\n    '0220': ['SQ', '1', 'ViewCodeSequence'],\n    '0222': ['SQ', '1', 'ViewModifierCodeSequence'],\n    '0300': ['SQ', '1', 'RadionuclideCodeSequence'],\n    '0302': ['SQ', '1', 'AdministrationRouteCodeSequence'],\n    '0304': ['SQ', '1', 'RadiopharmaceuticalCodeSequence'],\n    '0306': ['SQ', '1', 'CalibrationDataSequence'],\n    '0308': ['US', '1', 'EnergyWindowNumber'],\n    '0400': ['SH', '1', 'ImageID'],\n    '0410': ['SQ', '1', 'PatientOrientationCodeSequence'],\n    '0412': ['SQ', '1', 'PatientOrientationModifierCodeSequence'],\n    '0414': ['SQ', '1', 'PatientGantryRelationshipCodeSequence'],\n    '0500': ['CS', '1', 'SliceProgressionDirection'],\n    '0501': ['CS', '1', 'ScanProgressionDirection'],\n    '1000': ['CS', '2', 'SeriesType'],\n    '1001': ['CS', '1', 'Units'],\n    '1002': ['CS', '1', 'CountsSource'],\n    '1004': ['CS', '1', 'ReprojectionMethod'],\n    '1006': ['CS', '1', 'SUVType'],\n    '1100': ['CS', '1', 'RandomsCorrectionMethod'],\n    '1101': ['LO', '1', 'AttenuationCorrectionMethod'],\n    '1102': ['CS', '1', 'DecayCorrection'],\n    '1103': ['LO', '1', 'ReconstructionMethod'],\n    '1104': ['LO', '1', 'DetectorLinesOfResponseUsed'],\n    '1105': ['LO', '1', 'ScatterCorrectionMethod'],\n    '1200': ['DS', '1', 'AxialAcceptance'],\n    '1201': ['IS', '2', 'AxialMash'],\n    '1202': ['IS', '1', 'TransverseMash'],\n    '1203': ['DS', '2', 'DetectorElementSize'],\n    '1210': ['DS', '1', 'CoincidenceWindowWidth'],\n    '1220': ['CS', '1-n', 'SecondaryCountsType'],\n    '1300': ['DS', '1', 'FrameReferenceTime'],\n    '1310': ['IS', '1', 'PrimaryPromptsCountsAccumulated'],\n    '1311': ['IS', '1-n', 'SecondaryCountsAccumulated'],\n    '1320': ['DS', '1', 'SliceSensitivityFactor'],\n    '1321': ['DS', '1', 'DecayFactor'],\n    '1322': ['DS', '1', 'DoseCalibrationFactor'],\n    '1323': ['DS', '1', 'ScatterFractionFactor'],\n    '1324': ['DS', '1', 'DeadTimeFactor'],\n    '1330': ['US', '1', 'ImageIndex'],\n    '1400': ['CS', '1-n', 'CountsIncluded'],\n    '1401': ['CS', '1', 'DeadTimeCorrectionFlag']\n  },\n  '0060': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '3000': ['SQ', '1', 'HistogramSequence'],\n    '3002': ['US', '1', 'HistogramNumberOfBins'],\n    '3004': ['xs', '1', 'HistogramFirstBinValue'],\n    '3006': ['xs', '1', 'HistogramLastBinValue'],\n    '3008': ['US', '1', 'HistogramBinWidth'],\n    '3010': ['LO', '1', 'HistogramExplanation'],\n    '3020': ['UL', '1-n', 'HistogramData']\n  },\n  '0062': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'SegmentationType'],\n    '0002': ['SQ', '1', 'SegmentSequence'],\n    '0003': ['SQ', '1', 'SegmentedPropertyCategoryCodeSequence'],\n    '0004': ['US', '1', 'SegmentNumber'],\n    '0005': ['LO', '1', 'SegmentLabel'],\n    '0006': ['ST', '1', 'SegmentDescription'],\n    '0007': ['SQ', '1', 'SegmentationAlgorithmIdentificationSequence'],\n    '0008': ['CS', '1', 'SegmentAlgorithmType'],\n    '0009': ['LO', '1-n', 'SegmentAlgorithmName'],\n    '000A': ['SQ', '1', 'SegmentIdentificationSequence'],\n    '000B': ['US', '1-n', 'ReferencedSegmentNumber'],\n    '000C': ['US', '1', 'RecommendedDisplayGrayscaleValue'],\n    '000D': ['US', '3', 'RecommendedDisplayCIELabValue'],\n    '000E': ['US', '1', 'MaximumFractionalValue'],\n    '000F': ['SQ', '1', 'SegmentedPropertyTypeCodeSequence'],\n    '0010': ['CS', '1', 'SegmentationFractionalType'],\n    '0011': ['SQ', '1', 'SegmentedPropertyTypeModifierCodeSequence'],\n    '0012': ['SQ', '1', 'UsedSegmentsSequence'],\n    '0013': ['CS', '1', 'SegmentsOverlap'],\n    '0020': ['UT', '1', 'TrackingID'],\n    '0021': ['UI', '1', 'TrackingUID']\n  },\n  '0064': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SQ', '1', 'DeformableRegistrationSequence'],\n    '0003': ['UI', '1', 'SourceFrameOfReferenceUID'],\n    '0005': ['SQ', '1', 'DeformableRegistrationGridSequence'],\n    '0007': ['UL', '3', 'GridDimensions'],\n    '0008': ['FD', '3', 'GridResolution'],\n    '0009': ['OF', '1', 'VectorGridData'],\n    '000F': ['SQ', '1', 'PreDeformationMatrixRegistrationSequence'],\n    '0010': ['SQ', '1', 'PostDeformationMatrixRegistrationSequence']\n  },\n  '0066': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['UL', '1', 'NumberOfSurfaces'],\n    '0002': ['SQ', '1', 'SurfaceSequence'],\n    '0003': ['UL', '1', 'SurfaceNumber'],\n    '0004': ['LT', '1', 'SurfaceComments'],\n    '0009': ['CS', '1', 'SurfaceProcessing'],\n    '000A': ['FL', '1', 'SurfaceProcessingRatio'],\n    '000B': ['LO', '1', 'SurfaceProcessingDescription'],\n    '000C': ['FL', '1', 'RecommendedPresentationOpacity'],\n    '000D': ['CS', '1', 'RecommendedPresentationType'],\n    '000E': ['CS', '1', 'FiniteVolume'],\n    '0010': ['CS', '1', 'Manifold'],\n    '0011': ['SQ', '1', 'SurfacePointsSequence'],\n    '0012': ['SQ', '1', 'SurfacePointsNormalsSequence'],\n    '0013': ['SQ', '1', 'SurfaceMeshPrimitivesSequence'],\n    '0015': ['UL', '1', 'NumberOfSurfacePoints'],\n    '0016': ['OF', '1', 'PointCoordinatesData'],\n    '0017': ['FL', '3', 'PointPositionAccuracy'],\n    '0018': ['FL', '1', 'MeanPointDistance'],\n    '0019': ['FL', '1', 'MaximumPointDistance'],\n    '001A': ['FL', '6', 'PointsBoundingBoxCoordinates'],\n    '001B': ['FL', '3', 'AxisOfRotation'],\n    '001C': ['FL', '3', 'CenterOfRotation'],\n    '001E': ['UL', '1', 'NumberOfVectors'],\n    '001F': ['US', '1', 'VectorDimensionality'],\n    '0020': ['FL', '1-n', 'VectorAccuracy'],\n    '0021': ['OF', '1', 'VectorCoordinateData'],\n    '0022': ['OD', '1', 'DoublePointCoordinatesData'],\n    '0023': ['OW', '1', 'TrianglePointIndexList'],\n    '0024': ['OW', '1', 'EdgePointIndexList'],\n    '0025': ['OW', '1', 'VertexPointIndexList'],\n    '0026': ['SQ', '1', 'TriangleStripSequence'],\n    '0027': ['SQ', '1', 'TriangleFanSequence'],\n    '0028': ['SQ', '1', 'LineSequence'],\n    '0029': ['OW', '1', 'PrimitivePointIndexList'],\n    '002A': ['UL', '1', 'SurfaceCount'],\n    '002B': ['SQ', '1', 'ReferencedSurfaceSequence'],\n    '002C': ['UL', '1', 'ReferencedSurfaceNumber'],\n    '002D': ['SQ', '1', 'SegmentSurfaceGenerationAlgorithmIdentificationSequence'],\n    '002E': ['SQ', '1', 'SegmentSurfaceSourceInstanceSequence'],\n    '002F': ['SQ', '1', 'AlgorithmFamilyCodeSequence'],\n    '0030': ['SQ', '1', 'AlgorithmNameCodeSequence'],\n    '0031': ['LO', '1', 'AlgorithmVersion'],\n    '0032': ['LT', '1', 'AlgorithmParameters'],\n    '0034': ['SQ', '1', 'FacetSequence'],\n    '0035': ['SQ', '1', 'SurfaceProcessingAlgorithmIdentificationSequence'],\n    '0036': ['LO', '1', 'AlgorithmName'],\n    '0037': ['FL', '1', 'RecommendedPointRadius'],\n    '0038': ['FL', '1', 'RecommendedLineThickness'],\n    '0040': ['OL', '1', 'LongPrimitivePointIndexList'],\n    '0041': ['OL', '1', 'LongTrianglePointIndexList'],\n    '0042': ['OL', '1', 'LongEdgePointIndexList'],\n    '0043': ['OL', '1', 'LongVertexPointIndexList'],\n    '0101': ['SQ', '1', 'TrackSetSequence'],\n    '0102': ['SQ', '1', 'TrackSequence'],\n    '0103': ['OW', '1', 'RecommendedDisplayCIELabValueList'],\n    '0104': ['SQ', '1', 'TrackingAlgorithmIdentificationSequence'],\n    '0105': ['UL', '1', 'TrackSetNumber'],\n    '0106': ['LO', '1', 'TrackSetLabel'],\n    '0107': ['UT', '1', 'TrackSetDescription'],\n    '0108': ['SQ', '1', 'TrackSetAnatomicalTypeCodeSequence'],\n    '0121': ['SQ', '1', 'MeasurementsSequence'],\n    '0124': ['SQ', '1', 'TrackSetStatisticsSequence'],\n    '0125': ['OF', '1', 'FloatingPointValues'],\n    '0129': ['OL', '1', 'TrackPointIndexList'],\n    '0130': ['SQ', '1', 'TrackStatisticsSequence'],\n    '0132': ['SQ', '1', 'MeasurementValuesSequence'],\n    '0133': ['SQ', '1', 'DiffusionAcquisitionCodeSequence'],\n    '0134': ['SQ', '1', 'DiffusionModelCodeSequence']\n  },\n  '0068': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '6210': ['LO', '1', 'ImplantSize'],\n    '6221': ['LO', '1', 'ImplantTemplateVersion'],\n    '6222': ['SQ', '1', 'ReplacedImplantTemplateSequence'],\n    '6223': ['CS', '1', 'ImplantType'],\n    '6224': ['SQ', '1', 'DerivationImplantTemplateSequence'],\n    '6225': ['SQ', '1', 'OriginalImplantTemplateSequence'],\n    '6226': ['DT', '1', 'EffectiveDateTime'],\n    '6230': ['SQ', '1', 'ImplantTargetAnatomySequence'],\n    '6260': ['SQ', '1', 'InformationFromManufacturerSequence'],\n    '6265': ['SQ', '1', 'NotificationFromManufacturerSequence'],\n    '6270': ['DT', '1', 'InformationIssueDateTime'],\n    '6280': ['ST', '1', 'InformationSummary'],\n    '62A0': ['SQ', '1', 'ImplantRegulatoryDisapprovalCodeSequence'],\n    '62A5': ['FD', '1', 'OverallTemplateSpatialTolerance'],\n    '62C0': ['SQ', '1', 'HPGLDocumentSequence'],\n    '62D0': ['US', '1', 'HPGLDocumentID'],\n    '62D5': ['LO', '1', 'HPGLDocumentLabel'],\n    '62E0': ['SQ', '1', 'ViewOrientationCodeSequence'],\n    '62F0': ['SQ', '1', 'ViewOrientationModifierCodeSequence'],\n    '62F2': ['FD', '1', 'HPGLDocumentScaling'],\n    '6300': ['OB', '1', 'HPGLDocument'],\n    '6310': ['US', '1', 'HPGLContourPenNumber'],\n    '6320': ['SQ', '1', 'HPGLPenSequence'],\n    '6330': ['US', '1', 'HPGLPenNumber'],\n    '6340': ['LO', '1', 'HPGLPenLabel'],\n    '6345': ['ST', '1', 'HPGLPenDescription'],\n    '6346': ['FD', '2', 'RecommendedRotationPoint'],\n    '6347': ['FD', '4', 'BoundingRectangle'],\n    '6350': ['US', '1-n', 'ImplantTemplate3DModelSurfaceNumber'],\n    '6360': ['SQ', '1', 'SurfaceModelDescriptionSequence'],\n    '6380': ['LO', '1', 'SurfaceModelLabel'],\n    '6390': ['FD', '1', 'SurfaceModelScalingFactor'],\n    '63A0': ['SQ', '1', 'MaterialsCodeSequence'],\n    '63A4': ['SQ', '1', 'CoatingMaterialsCodeSequence'],\n    '63A8': ['SQ', '1', 'ImplantTypeCodeSequence'],\n    '63AC': ['SQ', '1', 'FixationMethodCodeSequence'],\n    '63B0': ['SQ', '1', 'MatingFeatureSetsSequence'],\n    '63C0': ['US', '1', 'MatingFeatureSetID'],\n    '63D0': ['LO', '1', 'MatingFeatureSetLabel'],\n    '63E0': ['SQ', '1', 'MatingFeatureSequence'],\n    '63F0': ['US', '1', 'MatingFeatureID'],\n    '6400': ['SQ', '1', 'MatingFeatureDegreeOfFreedomSequence'],\n    '6410': ['US', '1', 'DegreeOfFreedomID'],\n    '6420': ['CS', '1', 'DegreeOfFreedomType'],\n    '6430': ['SQ', '1', 'TwoDMatingFeatureCoordinatesSequence'],\n    '6440': ['US', '1', 'ReferencedHPGLDocumentID'],\n    '6450': ['FD', '2', 'TwoDMatingPoint'],\n    '6460': ['FD', '4', 'TwoDMatingAxes'],\n    '6470': ['SQ', '1', 'TwoDDegreeOfFreedomSequence'],\n    '6490': ['FD', '3', 'ThreeDDegreeOfFreedomAxis'],\n    '64A0': ['FD', '2', 'RangeOfFreedom'],\n    '64C0': ['FD', '3', 'ThreeDMatingPoint'],\n    '64D0': ['FD', '9', 'ThreeDMatingAxes'],\n    '64F0': ['FD', '3', 'TwoDDegreeOfFreedomAxis'],\n    '6500': ['SQ', '1', 'PlanningLandmarkPointSequence'],\n    '6510': ['SQ', '1', 'PlanningLandmarkLineSequence'],\n    '6520': ['SQ', '1', 'PlanningLandmarkPlaneSequence'],\n    '6530': ['US', '1', 'PlanningLandmarkID'],\n    '6540': ['LO', '1', 'PlanningLandmarkDescription'],\n    '6545': ['SQ', '1', 'PlanningLandmarkIdentificationCodeSequence'],\n    '6550': ['SQ', '1', 'TwoDPointCoordinatesSequence'],\n    '6560': ['FD', '2', 'TwoDPointCoordinates'],\n    '6590': ['FD', '3', 'ThreeDPointCoordinates'],\n    '65A0': ['SQ', '1', 'TwoDLineCoordinatesSequence'],\n    '65B0': ['FD', '4', 'TwoDLineCoordinates'],\n    '65D0': ['FD', '6', 'ThreeDLineCoordinates'],\n    '65E0': ['SQ', '1', 'TwoDPlaneCoordinatesSequence'],\n    '65F0': ['FD', '4', 'TwoDPlaneIntersection'],\n    '6610': ['FD', '3', 'ThreeDPlaneOrigin'],\n    '6620': ['FD', '3', 'ThreeDPlaneNormal'],\n    '7001': ['CS', '1', 'ModelModification'],\n    '7002': ['CS', '1', 'ModelMirroring'],\n    '7003': ['SQ', '1', 'ModelUsageCodeSequence'],\n    '7004': ['UI', '1', 'ModelGroupUID'],\n    '7005': ['UR', '1', 'RelativeURIReferenceWithinEncapsulatedDocument']\n  },\n  '006A': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'AnnotationCoordinateType'],\n    '0002': ['SQ', '1', 'AnnotationGroupSequence'],\n    '0003': ['UI', '1', 'AnnotationGroupUID'],\n    '0005': ['LO', '1', 'AnnotationGroupLabel'],\n    '0006': ['UT', '1', 'AnnotationGroupDescription'],\n    '0007': ['CS', '1', 'AnnotationGroupGenerationType'],\n    '0008': ['SQ', '1', 'AnnotationGroupAlgorithmIdentificationSequence'],\n    '0009': ['SQ', '1', 'AnnotationPropertyCategoryCodeSequence'],\n    '000A': ['SQ', '1', 'AnnotationPropertyTypeCodeSequence'],\n    '000B': ['SQ', '1', 'AnnotationPropertyTypeModifierCodeSequence'],\n    '000C': ['UL', '1', 'NumberOfAnnotations'],\n    '000D': ['CS', '1', 'AnnotationAppliesToAllOpticalPaths'],\n    '000E': ['SH', '1-n', 'ReferencedOpticalPathIdentifier'],\n    '000F': ['CS', '1', 'AnnotationAppliesToAllZPlanes'],\n    '0010': ['FD', '1-n', 'CommonZCoordinateValue'],\n    '0011': ['OL', '1', 'AnnotationIndexList']\n  },\n  '0070': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['SQ', '1', 'GraphicAnnotationSequence'],\n    '0002': ['CS', '1', 'GraphicLayer'],\n    '0003': ['CS', '1', 'BoundingBoxAnnotationUnits'],\n    '0004': ['CS', '1', 'AnchorPointAnnotationUnits'],\n    '0005': ['CS', '1', 'GraphicAnnotationUnits'],\n    '0006': ['ST', '1', 'UnformattedTextValue'],\n    '0008': ['SQ', '1', 'TextObjectSequence'],\n    '0009': ['SQ', '1', 'GraphicObjectSequence'],\n    '0010': ['FL', '2', 'BoundingBoxTopLeftHandCorner'],\n    '0011': ['FL', '2', 'BoundingBoxBottomRightHandCorner'],\n    '0012': ['CS', '1', 'BoundingBoxTextHorizontalJustification'],\n    '0014': ['FL', '2', 'AnchorPoint'],\n    '0015': ['CS', '1', 'AnchorPointVisibility'],\n    '0020': ['US', '1', 'GraphicDimensions'],\n    '0021': ['US', '1', 'NumberOfGraphicPoints'],\n    '0022': ['FL', '2-n', 'GraphicData'],\n    '0023': ['CS', '1', 'GraphicType'],\n    '0024': ['CS', '1', 'GraphicFilled'],\n    '0040': ['IS', '1', 'ImageRotationRetired'],\n    '0041': ['CS', '1', 'ImageHorizontalFlip'],\n    '0042': ['US', '1', 'ImageRotation'],\n    '0050': ['US', '2', 'DisplayedAreaTopLeftHandCornerTrial'],\n    '0051': ['US', '2', 'DisplayedAreaBottomRightHandCornerTrial'],\n    '0052': ['SL', '2', 'DisplayedAreaTopLeftHandCorner'],\n    '0053': ['SL', '2', 'DisplayedAreaBottomRightHandCorner'],\n    '005A': ['SQ', '1', 'DisplayedAreaSelectionSequence'],\n    '0060': ['SQ', '1', 'GraphicLayerSequence'],\n    '0062': ['IS', '1', 'GraphicLayerOrder'],\n    '0066': ['US', '1', 'GraphicLayerRecommendedDisplayGrayscaleValue'],\n    '0067': ['US', '3', 'GraphicLayerRecommendedDisplayRGBValue'],\n    '0068': ['LO', '1', 'GraphicLayerDescription'],\n    '0080': ['CS', '1', 'ContentLabel'],\n    '0081': ['LO', '1', 'ContentDescription'],\n    '0082': ['DA', '1', 'PresentationCreationDate'],\n    '0083': ['TM', '1', 'PresentationCreationTime'],\n    '0084': ['PN', '1', 'ContentCreatorName'],\n    '0086': ['SQ', '1', 'ContentCreatorIdentificationCodeSequence'],\n    '0087': ['SQ', '1', 'AlternateContentDescriptionSequence'],\n    '0100': ['CS', '1', 'PresentationSizeMode'],\n    '0101': ['DS', '2', 'PresentationPixelSpacing'],\n    '0102': ['IS', '2', 'PresentationPixelAspectRatio'],\n    '0103': ['FL', '1', 'PresentationPixelMagnificationRatio'],\n    '0207': ['LO', '1', 'GraphicGroupLabel'],\n    '0208': ['ST', '1', 'GraphicGroupDescription'],\n    '0209': ['SQ', '1', 'CompoundGraphicSequence'],\n    '0226': ['UL', '1', 'CompoundGraphicInstanceID'],\n    '0227': ['LO', '1', 'FontName'],\n    '0228': ['CS', '1', 'FontNameType'],\n    '0229': ['LO', '1', 'CSSFontName'],\n    '0230': ['FD', '1', 'RotationAngle'],\n    '0231': ['SQ', '1', 'TextStyleSequence'],\n    '0232': ['SQ', '1', 'LineStyleSequence'],\n    '0233': ['SQ', '1', 'FillStyleSequence'],\n    '0234': ['SQ', '1', 'GraphicGroupSequence'],\n    '0241': ['US', '3', 'TextColorCIELabValue'],\n    '0242': ['CS', '1', 'HorizontalAlignment'],\n    '0243': ['CS', '1', 'VerticalAlignment'],\n    '0244': ['CS', '1', 'ShadowStyle'],\n    '0245': ['FL', '1', 'ShadowOffsetX'],\n    '0246': ['FL', '1', 'ShadowOffsetY'],\n    '0247': ['US', '3', 'ShadowColorCIELabValue'],\n    '0248': ['CS', '1', 'Underlined'],\n    '0249': ['CS', '1', 'Bold'],\n    '0250': ['CS', '1', 'Italic'],\n    '0251': ['US', '3', 'PatternOnColorCIELabValue'],\n    '0252': ['US', '3', 'PatternOffColorCIELabValue'],\n    '0253': ['FL', '1', 'LineThickness'],\n    '0254': ['CS', '1', 'LineDashingStyle'],\n    '0255': ['UL', '1', 'LinePattern'],\n    '0256': ['OB', '1', 'FillPattern'],\n    '0257': ['CS', '1', 'FillMode'],\n    '0258': ['FL', '1', 'ShadowOpacity'],\n    '0261': ['FL', '1', 'GapLength'],\n    '0262': ['FL', '1', 'DiameterOfVisibility'],\n    '0273': ['FL', '2', 'RotationPoint'],\n    '0274': ['CS', '1', 'TickAlignment'],\n    '0278': ['CS', '1', 'ShowTickLabel'],\n    '0279': ['CS', '1', 'TickLabelAlignment'],\n    '0282': ['CS', '1', 'CompoundGraphicUnits'],\n    '0284': ['FL', '1', 'PatternOnOpacity'],\n    '0285': ['FL', '1', 'PatternOffOpacity'],\n    '0287': ['SQ', '1', 'MajorTicksSequence'],\n    '0288': ['FL', '1', 'TickPosition'],\n    '0289': ['SH', '1', 'TickLabel'],\n    '0294': ['CS', '1', 'CompoundGraphicType'],\n    '0295': ['UL', '1', 'GraphicGroupID'],\n    '0306': ['CS', '1', 'ShapeType'],\n    '0308': ['SQ', '1', 'RegistrationSequence'],\n    '0309': ['SQ', '1', 'MatrixRegistrationSequence'],\n    '030A': ['SQ', '1', 'MatrixSequence'],\n    '030B': ['FD', '16', 'FrameOfReferenceToDisplayedCoordinateSystemTransformationMatrix'],\n    '030C': ['CS', '1', 'FrameOfReferenceTransformationMatrixType'],\n    '030D': ['SQ', '1', 'RegistrationTypeCodeSequence'],\n    '030F': ['ST', '1', 'FiducialDescription'],\n    '0310': ['SH', '1', 'FiducialIdentifier'],\n    '0311': ['SQ', '1', 'FiducialIdentifierCodeSequence'],\n    '0312': ['FD', '1', 'ContourUncertaintyRadius'],\n    '0314': ['SQ', '1', 'UsedFiducialsSequence'],\n    '0318': ['SQ', '1', 'GraphicCoordinatesDataSequence'],\n    '031A': ['UI', '1', 'FiducialUID'],\n    '031B': ['UI', '1', 'ReferencedFiducialUID'],\n    '031C': ['SQ', '1', 'FiducialSetSequence'],\n    '031E': ['SQ', '1', 'FiducialSequence'],\n    '031F': ['SQ', '1', 'FiducialsPropertyCategoryCodeSequence'],\n    '0401': ['US', '3', 'GraphicLayerRecommendedDisplayCIELabValue'],\n    '0402': ['SQ', '1', 'BlendingSequence'],\n    '0403': ['FL', '1', 'RelativeOpacity'],\n    '0404': ['SQ', '1', 'ReferencedSpatialRegistrationSequence'],\n    '0405': ['CS', '1', 'BlendingPosition'],\n    '1101': ['UI', '1', 'PresentationDisplayCollectionUID'],\n    '1102': ['UI', '1', 'PresentationSequenceCollectionUID'],\n    '1103': ['US', '1', 'PresentationSequencePositionIndex'],\n    '1104': ['SQ', '1', 'RenderedImageReferenceSequence'],\n    '1201': ['SQ', '1', 'VolumetricPresentationStateInputSequence'],\n    '1202': ['CS', '1', 'PresentationInputType'],\n    '1203': ['US', '1', 'InputSequencePositionIndex'],\n    '1204': ['CS', '1', 'Crop'],\n    '1205': ['US', '1-n', 'CroppingSpecificationIndex'],\n    '1206': ['CS', '1', 'CompositingMethod'],\n    '1207': ['US', '1', 'VolumetricPresentationInputNumber'],\n    '1208': ['CS', '1', 'ImageVolumeGeometry'],\n    '1209': ['UI', '1', 'VolumetricPresentationInputSetUID'],\n    '120A': ['SQ', '1', 'VolumetricPresentationInputSetSequence'],\n    '120B': ['CS', '1', 'GlobalCrop'],\n    '120C': ['US', '1-n', 'GlobalCroppingSpecificationIndex'],\n    '120D': ['CS', '1', 'RenderingMethod'],\n    '1301': ['SQ', '1', 'VolumeCroppingSequence'],\n    '1302': ['CS', '1', 'VolumeCroppingMethod'],\n    '1303': ['FD', '6', 'BoundingBoxCrop'],\n    '1304': ['SQ', '1', 'ObliqueCroppingPlaneSequence'],\n    '1305': ['FD', '4', 'Plane'],\n    '1306': ['FD', '3', 'PlaneNormal'],\n    '1309': ['US', '1', 'CroppingSpecificationNumber'],\n    '1501': ['CS', '1', 'MultiPlanarReconstructionStyle'],\n    '1502': ['CS', '1', 'MPRThicknessType'],\n    '1503': ['FD', '1', 'MPRSlabThickness'],\n    '1505': ['FD', '3', 'MPRTopLeftHandCorner'],\n    '1507': ['FD', '3', 'MPRViewWidthDirection'],\n    '1508': ['FD', '1', 'MPRViewWidth'],\n    '150C': ['UL', '1', 'NumberOfVolumetricCurvePoints'],\n    '150D': ['OD', '1', 'VolumetricCurvePoints'],\n    '1511': ['FD', '3', 'MPRViewHeightDirection'],\n    '1512': ['FD', '1', 'MPRViewHeight'],\n    '1602': ['CS', '1', 'RenderProjection'],\n    '1603': ['FD', '3', 'ViewpointPosition'],\n    '1604': ['FD', '3', 'ViewpointLookAtPoint'],\n    '1605': ['FD', '3', 'ViewpointUpDirection'],\n    '1606': ['FD', '6', 'RenderFieldOfView'],\n    '1607': ['FD', '1', 'SamplingStepSize'],\n    '1701': ['CS', '1', 'ShadingStyle'],\n    '1702': ['FD', '1', 'AmbientReflectionIntensity'],\n    '1703': ['FD', '3', 'LightDirection'],\n    '1704': ['FD', '1', 'DiffuseReflectionIntensity'],\n    '1705': ['FD', '1', 'SpecularReflectionIntensity'],\n    '1706': ['FD', '1', 'Shininess'],\n    '1801': ['SQ', '1', 'PresentationStateClassificationComponentSequence'],\n    '1802': ['CS', '1', 'ComponentType'],\n    '1803': ['SQ', '1', 'ComponentInputSequence'],\n    '1804': ['US', '1', 'VolumetricPresentationInputIndex'],\n    '1805': ['SQ', '1', 'PresentationStateCompositorComponentSequence'],\n    '1806': ['SQ', '1', 'WeightingTransferFunctionSequence'],\n    '1807': ['US', '3', 'WeightingLookupTableDescriptor'],\n    '1808': ['OB', '1', 'WeightingLookupTableData'],\n    '1901': ['SQ', '1', 'VolumetricAnnotationSequence'],\n    '1903': ['SQ', '1', 'ReferencedStructuredContextSequence'],\n    '1904': ['UI', '1', 'ReferencedContentItem'],\n    '1905': ['SQ', '1', 'VolumetricPresentationInputAnnotationSequence'],\n    '1907': ['CS', '1', 'AnnotationClipping'],\n    '1A01': ['CS', '1', 'PresentationAnimationStyle'],\n    '1A03': ['FD', '1', 'RecommendedAnimationRate'],\n    '1A04': ['SQ', '1', 'AnimationCurveSequence'],\n    '1A05': ['FD', '1', 'AnimationStepSize'],\n    '1A06': ['FD', '1', 'SwivelRange'],\n    '1A07': ['OD', '1', 'VolumetricCurveUpDirections'],\n    '1A08': ['SQ', '1', 'VolumeStreamSequence'],\n    '1A09': ['LO', '1', 'RGBATransferFunctionDescription'],\n    '1B01': ['SQ', '1', 'AdvancedBlendingSequence'],\n    '1B02': ['US', '1', 'BlendingInputNumber'],\n    '1B03': ['SQ', '1', 'BlendingDisplayInputSequence'],\n    '1B04': ['SQ', '1', 'BlendingDisplaySequence'],\n    '1B06': ['CS', '1', 'BlendingMode'],\n    '1B07': ['CS', '1', 'TimeSeriesBlending'],\n    '1B08': ['CS', '1', 'GeometryForDisplay'],\n    '1B11': ['SQ', '1', 'ThresholdSequence'],\n    '1B12': ['SQ', '1', 'ThresholdValueSequence'],\n    '1B13': ['CS', '1', 'ThresholdType'],\n    '1B14': ['FD', '1', 'ThresholdValue']\n  },\n  '0072': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SH', '1', 'HangingProtocolName'],\n    '0004': ['LO', '1', 'HangingProtocolDescription'],\n    '0006': ['CS', '1', 'HangingProtocolLevel'],\n    '0008': ['LO', '1', 'HangingProtocolCreator'],\n    '000A': ['DT', '1', 'HangingProtocolCreationDateTime'],\n    '000C': ['SQ', '1', 'HangingProtocolDefinitionSequence'],\n    '000E': ['SQ', '1', 'HangingProtocolUserIdentificationCodeSequence'],\n    '0010': ['LO', '1', 'HangingProtocolUserGroupName'],\n    '0012': ['SQ', '1', 'SourceHangingProtocolSequence'],\n    '0014': ['US', '1', 'NumberOfPriorsReferenced'],\n    '0020': ['SQ', '1', 'ImageSetsSequence'],\n    '0022': ['SQ', '1', 'ImageSetSelectorSequence'],\n    '0024': ['CS', '1', 'ImageSetSelectorUsageFlag'],\n    '0026': ['AT', '1', 'SelectorAttribute'],\n    '0028': ['US', '1', 'SelectorValueNumber'],\n    '0030': ['SQ', '1', 'TimeBasedImageSetsSequence'],\n    '0032': ['US', '1', 'ImageSetNumber'],\n    '0034': ['CS', '1', 'ImageSetSelectorCategory'],\n    '0038': ['US', '2', 'RelativeTime'],\n    '003A': ['CS', '1', 'RelativeTimeUnits'],\n    '003C': ['SS', '2', 'AbstractPriorValue'],\n    '003E': ['SQ', '1', 'AbstractPriorCodeSequence'],\n    '0040': ['LO', '1', 'ImageSetLabel'],\n    '0050': ['CS', '1', 'SelectorAttributeVR'],\n    '0052': ['AT', '1-n', 'SelectorSequencePointer'],\n    '0054': ['LO', '1-n', 'SelectorSequencePointerPrivateCreator'],\n    '0056': ['LO', '1', 'SelectorAttributePrivateCreator'],\n    '005E': ['AE', '1-n', 'SelectorAEValue'],\n    '005F': ['AS', '1-n', 'SelectorASValue'],\n    '0060': ['AT', '1-n', 'SelectorATValue'],\n    '0061': ['DA', '1-n', 'SelectorDAValue'],\n    '0062': ['CS', '1-n', 'SelectorCSValue'],\n    '0063': ['DT', '1-n', 'SelectorDTValue'],\n    '0064': ['IS', '1-n', 'SelectorISValue'],\n    '0065': ['OB', '1', 'SelectorOBValue'],\n    '0066': ['LO', '1-n', 'SelectorLOValue'],\n    '0067': ['OF', '1', 'SelectorOFValue'],\n    '0068': ['LT', '1', 'SelectorLTValue'],\n    '0069': ['OW', '1', 'SelectorOWValue'],\n    '006A': ['PN', '1-n', 'SelectorPNValue'],\n    '006B': ['TM', '1-n', 'SelectorTMValue'],\n    '006C': ['SH', '1-n', 'SelectorSHValue'],\n    '006D': ['UN', '1', 'SelectorUNValue'],\n    '006E': ['ST', '1', 'SelectorSTValue'],\n    '006F': ['UC', '1-n', 'SelectorUCValue'],\n    '0070': ['UT', '1', 'SelectorUTValue'],\n    '0071': ['UR', '1', 'SelectorURValue'],\n    '0072': ['DS', '1-n', 'SelectorDSValue'],\n    '0073': ['OD', '1', 'SelectorODValue'],\n    '0074': ['FD', '1-n', 'SelectorFDValue'],\n    '0075': ['OL', '1', 'SelectorOLValue'],\n    '0076': ['FL', '1-n', 'SelectorFLValue'],\n    '0078': ['UL', '1-n', 'SelectorULValue'],\n    '007A': ['US', '1-n', 'SelectorUSValue'],\n    '007C': ['SL', '1-n', 'SelectorSLValue'],\n    '007E': ['SS', '1-n', 'SelectorSSValue'],\n    '007F': ['UI', '1-n', 'SelectorUIValue'],\n    '0080': ['SQ', '1', 'SelectorCodeSequenceValue'],\n    '0081': ['OV', '1', 'SelectorOVValue'],\n    '0082': ['SV', '1-n', 'SelectorSVValue'],\n    '0083': ['UV', '1-n', 'SelectorUVValue'],\n    '0100': ['US', '1', 'NumberOfScreens'],\n    '0102': ['SQ', '1', 'NominalScreenDefinitionSequence'],\n    '0104': ['US', '1', 'NumberOfVerticalPixels'],\n    '0106': ['US', '1', 'NumberOfHorizontalPixels'],\n    '0108': ['FD', '4', 'DisplayEnvironmentSpatialPosition'],\n    '010A': ['US', '1', 'ScreenMinimumGrayscaleBitDepth'],\n    '010C': ['US', '1', 'ScreenMinimumColorBitDepth'],\n    '010E': ['US', '1', 'ApplicationMaximumRepaintTime'],\n    '0200': ['SQ', '1', 'DisplaySetsSequence'],\n    '0202': ['US', '1', 'DisplaySetNumber'],\n    '0203': ['LO', '1', 'DisplaySetLabel'],\n    '0204': ['US', '1', 'DisplaySetPresentationGroup'],\n    '0206': ['LO', '1', 'DisplaySetPresentationGroupDescription'],\n    '0208': ['CS', '1', 'PartialDataDisplayHandling'],\n    '0210': ['SQ', '1', 'SynchronizedScrollingSequence'],\n    '0212': ['US', '2-n', 'DisplaySetScrollingGroup'],\n    '0214': ['SQ', '1', 'NavigationIndicatorSequence'],\n    '0216': ['US', '1', 'NavigationDisplaySet'],\n    '0218': ['US', '1-n', 'ReferenceDisplaySets'],\n    '0300': ['SQ', '1', 'ImageBoxesSequence'],\n    '0302': ['US', '1', 'ImageBoxNumber'],\n    '0304': ['CS', '1', 'ImageBoxLayoutType'],\n    '0306': ['US', '1', 'ImageBoxTileHorizontalDimension'],\n    '0308': ['US', '1', 'ImageBoxTileVerticalDimension'],\n    '0310': ['CS', '1', 'ImageBoxScrollDirection'],\n    '0312': ['CS', '1', 'ImageBoxSmallScrollType'],\n    '0314': ['US', '1', 'ImageBoxSmallScrollAmount'],\n    '0316': ['CS', '1', 'ImageBoxLargeScrollType'],\n    '0318': ['US', '1', 'ImageBoxLargeScrollAmount'],\n    '0320': ['US', '1', 'ImageBoxOverlapPriority'],\n    '0330': ['FD', '1', 'CineRelativeToRealTime'],\n    '0400': ['SQ', '1', 'FilterOperationsSequence'],\n    '0402': ['CS', '1', 'FilterByCategory'],\n    '0404': ['CS', '1', 'FilterByAttributePresence'],\n    '0406': ['CS', '1', 'FilterByOperator'],\n    '0420': ['US', '3', 'StructuredDisplayBackgroundCIELabValue'],\n    '0421': ['US', '3', 'EmptyImageBoxCIELabValue'],\n    '0422': ['SQ', '1', 'StructuredDisplayImageBoxSequence'],\n    '0424': ['SQ', '1', 'StructuredDisplayTextBoxSequence'],\n    '0427': ['SQ', '1', 'ReferencedFirstFrameSequence'],\n    '0430': ['SQ', '1', 'ImageBoxSynchronizationSequence'],\n    '0432': ['US', '2-n', 'SynchronizedImageBoxList'],\n    '0434': ['CS', '1', 'TypeOfSynchronization'],\n    '0500': ['CS', '1', 'BlendingOperationType'],\n    '0510': ['CS', '1', 'ReformattingOperationType'],\n    '0512': ['FD', '1', 'ReformattingThickness'],\n    '0514': ['FD', '1', 'ReformattingInterval'],\n    '0516': ['CS', '1', 'ReformattingOperationInitialViewDirection'],\n    '0520': ['CS', '1-n', 'ThreeDRenderingType'],\n    '0600': ['SQ', '1', 'SortingOperationsSequence'],\n    '0602': ['CS', '1', 'SortByCategory'],\n    '0604': ['CS', '1', 'SortingDirection'],\n    '0700': ['CS', '2', 'DisplaySetPatientOrientation'],\n    '0702': ['CS', '1', 'VOIType'],\n    '0704': ['CS', '1', 'PseudoColorType'],\n    '0705': ['SQ', '1', 'PseudoColorPaletteInstanceReferenceSequence'],\n    '0706': ['CS', '1', 'ShowGrayscaleInverted'],\n    '0710': ['CS', '1', 'ShowImageTrueSizeFlag'],\n    '0712': ['CS', '1', 'ShowGraphicAnnotationFlag'],\n    '0714': ['CS', '1', 'ShowPatientDemographicsFlag'],\n    '0716': ['CS', '1', 'ShowAcquisitionTechniquesFlag'],\n    '0717': ['CS', '1', 'DisplaySetHorizontalJustification'],\n    '0718': ['CS', '1', 'DisplaySetVerticalJustification']\n  },\n  '0074': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0120': ['FD', '1', 'ContinuationStartMeterset'],\n    '0121': ['FD', '1', 'ContinuationEndMeterset'],\n    '1000': ['CS', '1', 'ProcedureStepState'],\n    '1002': ['SQ', '1', 'ProcedureStepProgressInformationSequence'],\n    '1004': ['DS', '1', 'ProcedureStepProgress'],\n    '1006': ['ST', '1', 'ProcedureStepProgressDescription'],\n    '1007': ['SQ', '1', 'ProcedureStepProgressParametersSequence'],\n    '1008': ['SQ', '1', 'ProcedureStepCommunicationsURISequence'],\n    '100A': ['UR', '1', 'ContactURI'],\n    '100C': ['LO', '1', 'ContactDisplayName'],\n    '100E': ['SQ', '1', 'ProcedureStepDiscontinuationReasonCodeSequence'],\n    '1020': ['SQ', '1', 'BeamTaskSequence'],\n    '1022': ['CS', '1', 'BeamTaskType'],\n    '1024': ['IS', '1', 'BeamOrderIndexTrial'],\n    '1025': ['CS', '1', 'AutosequenceFlag'],\n    '1026': ['FD', '1', 'TableTopVerticalAdjustedPosition'],\n    '1027': ['FD', '1', 'TableTopLongitudinalAdjustedPosition'],\n    '1028': ['FD', '1', 'TableTopLateralAdjustedPosition'],\n    '102A': ['FD', '1', 'PatientSupportAdjustedAngle'],\n    '102B': ['FD', '1', 'TableTopEccentricAdjustedAngle'],\n    '102C': ['FD', '1', 'TableTopPitchAdjustedAngle'],\n    '102D': ['FD', '1', 'TableTopRollAdjustedAngle'],\n    '1030': ['SQ', '1', 'DeliveryVerificationImageSequence'],\n    '1032': ['CS', '1', 'VerificationImageTiming'],\n    '1034': ['CS', '1', 'DoubleExposureFlag'],\n    '1036': ['CS', '1', 'DoubleExposureOrdering'],\n    '1038': ['DS', '1', 'DoubleExposureMetersetTrial'],\n    '103A': ['DS', '4', 'DoubleExposureFieldDeltaTrial'],\n    '1040': ['SQ', '1', 'RelatedReferenceRTImageSequence'],\n    '1042': ['SQ', '1', 'GeneralMachineVerificationSequence'],\n    '1044': ['SQ', '1', 'ConventionalMachineVerificationSequence'],\n    '1046': ['SQ', '1', 'IonMachineVerificationSequence'],\n    '1048': ['SQ', '1', 'FailedAttributesSequence'],\n    '104A': ['SQ', '1', 'OverriddenAttributesSequence'],\n    '104C': ['SQ', '1', 'ConventionalControlPointVerificationSequence'],\n    '104E': ['SQ', '1', 'IonControlPointVerificationSequence'],\n    '1050': ['SQ', '1', 'AttributeOccurrenceSequence'],\n    '1052': ['AT', '1', 'AttributeOccurrencePointer'],\n    '1054': ['UL', '1', 'AttributeItemSelector'],\n    '1056': ['LO', '1', 'AttributeOccurrencePrivateCreator'],\n    '1057': ['IS', '1-n', 'SelectorSequencePointerItems'],\n    '1200': ['CS', '1', 'ScheduledProcedureStepPriority'],\n    '1202': ['LO', '1', 'WorklistLabel'],\n    '1204': ['LO', '1', 'ProcedureStepLabel'],\n    '1210': ['SQ', '1', 'ScheduledProcessingParametersSequence'],\n    '1212': ['SQ', '1', 'PerformedProcessingParametersSequence'],\n    '1216': ['SQ', '1', 'UnifiedProcedureStepPerformedProcedureSequence'],\n    '1220': ['SQ', '1', 'RelatedProcedureStepSequence'],\n    '1222': ['LO', '1', 'ProcedureStepRelationshipType'],\n    '1224': ['SQ', '1', 'ReplacedProcedureStepSequence'],\n    '1230': ['LO', '1', 'DeletionLock'],\n    '1234': ['AE', '1', 'ReceivingAE'],\n    '1236': ['AE', '1', 'RequestingAE'],\n    '1238': ['LT', '1', 'ReasonForCancellation'],\n    '1242': ['CS', '1', 'SCPStatus'],\n    '1244': ['CS', '1', 'SubscriptionListStatus'],\n    '1246': ['CS', '1', 'UnifiedProcedureStepListStatus'],\n    '1324': ['UL', '1', 'BeamOrderIndex'],\n    '1338': ['FD', '1', 'DoubleExposureMeterset'],\n    '133A': ['FD', '4', 'DoubleExposureFieldDelta'],\n    '1401': ['SQ', '1', 'BrachyTaskSequence'],\n    '1402': ['DS', '1', 'ContinuationStartTotalReferenceAirKerma'],\n    '1403': ['DS', '1', 'ContinuationEndTotalReferenceAirKerma'],\n    '1404': ['IS', '1', 'ContinuationPulseNumber'],\n    '1405': ['SQ', '1', 'ChannelDeliveryOrderSequence'],\n    '1406': ['IS', '1', 'ReferencedChannelNumber'],\n    '1407': ['DS', '1', 'StartCumulativeTimeWeight'],\n    '1408': ['DS', '1', 'EndCumulativeTimeWeight'],\n    '1409': ['SQ', '1', 'OmittedChannelSequence'],\n    '140A': ['CS', '1', 'ReasonForChannelOmission'],\n    '140B': ['LO', '1', 'ReasonForChannelOmissionDescription'],\n    '140C': ['IS', '1', 'ChannelDeliveryOrderIndex'],\n    '140D': ['SQ', '1', 'ChannelDeliveryContinuationSequence'],\n    '140E': ['SQ', '1', 'OmittedApplicationSetupSequence']\n  },\n  '0076': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['LO', '1', 'ImplantAssemblyTemplateName'],\n    '0003': ['LO', '1', 'ImplantAssemblyTemplateIssuer'],\n    '0006': ['LO', '1', 'ImplantAssemblyTemplateVersion'],\n    '0008': ['SQ', '1', 'ReplacedImplantAssemblyTemplateSequence'],\n    '000A': ['CS', '1', 'ImplantAssemblyTemplateType'],\n    '000C': ['SQ', '1', 'OriginalImplantAssemblyTemplateSequence'],\n    '000E': ['SQ', '1', 'DerivationImplantAssemblyTemplateSequence'],\n    '0010': ['SQ', '1', 'ImplantAssemblyTemplateTargetAnatomySequence'],\n    '0020': ['SQ', '1', 'ProcedureTypeCodeSequence'],\n    '0030': ['LO', '1', 'SurgicalTechnique'],\n    '0032': ['SQ', '1', 'ComponentTypesSequence'],\n    '0034': ['SQ', '1', 'ComponentTypeCodeSequence'],\n    '0036': ['CS', '1', 'ExclusiveComponentType'],\n    '0038': ['CS', '1', 'MandatoryComponentType'],\n    '0040': ['SQ', '1', 'ComponentSequence'],\n    '0055': ['US', '1', 'ComponentID'],\n    '0060': ['SQ', '1', 'ComponentAssemblySequence'],\n    '0070': ['US', '1', 'Component1ReferencedID'],\n    '0080': ['US', '1', 'Component1ReferencedMatingFeatureSetID'],\n    '0090': ['US', '1', 'Component1ReferencedMatingFeatureID'],\n    '00A0': ['US', '1', 'Component2ReferencedID'],\n    '00B0': ['US', '1', 'Component2ReferencedMatingFeatureSetID'],\n    '00C0': ['US', '1', 'Component2ReferencedMatingFeatureID']\n  },\n  '0078': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['LO', '1', 'ImplantTemplateGroupName'],\n    '0010': ['ST', '1', 'ImplantTemplateGroupDescription'],\n    '0020': ['LO', '1', 'ImplantTemplateGroupIssuer'],\n    '0024': ['LO', '1', 'ImplantTemplateGroupVersion'],\n    '0026': ['SQ', '1', 'ReplacedImplantTemplateGroupSequence'],\n    '0028': ['SQ', '1', 'ImplantTemplateGroupTargetAnatomySequence'],\n    '002A': ['SQ', '1', 'ImplantTemplateGroupMembersSequence'],\n    '002E': ['US', '1', 'ImplantTemplateGroupMemberID'],\n    '0050': ['FD', '3', 'ThreeDImplantTemplateGroupMemberMatchingPoint'],\n    '0060': ['FD', '9', 'ThreeDImplantTemplateGroupMemberMatchingAxes'],\n    '0070': ['SQ', '1', 'ImplantTemplateGroupMemberMatching2DCoordinatesSequence'],\n    '0090': ['FD', '2', 'TwoDImplantTemplateGroupMemberMatchingPoint'],\n    '00A0': ['FD', '4', 'TwoDImplantTemplateGroupMemberMatchingAxes'],\n    '00B0': ['SQ', '1', 'ImplantTemplateGroupVariationDimensionSequence'],\n    '00B2': ['LO', '1', 'ImplantTemplateGroupVariationDimensionName'],\n    '00B4': ['SQ', '1', 'ImplantTemplateGroupVariationDimensionRankSequence'],\n    '00B6': ['US', '1', 'ReferencedImplantTemplateGroupMemberID'],\n    '00B8': ['US', '1', 'ImplantTemplateGroupVariationDimensionRank']\n  },\n  '0080': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['SQ', '1', 'SurfaceScanAcquisitionTypeCodeSequence'],\n    '0002': ['SQ', '1', 'SurfaceScanModeCodeSequence'],\n    '0003': ['SQ', '1', 'RegistrationMethodCodeSequence'],\n    '0004': ['FD', '1', 'ShotDurationTime'],\n    '0005': ['FD', '1', 'ShotOffsetTime'],\n    '0006': ['US', '1-n', 'SurfacePointPresentationValueData'],\n    '0007': ['US', '3-3n', 'SurfacePointColorCIELabValueData'],\n    '0008': ['SQ', '1', 'UVMappingSequence'],\n    '0009': ['SH', '1', 'TextureLabel'],\n    '0010': ['OF', '1', 'UValueData'],\n    '0011': ['OF', '1', 'VValueData'],\n    '0012': ['SQ', '1', 'ReferencedTextureSequence'],\n    '0013': ['SQ', '1', 'ReferencedSurfaceDataSequence']\n  },\n  '0082': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'AssessmentSummary'],\n    '0003': ['UT', '1', 'AssessmentSummaryDescription'],\n    '0004': ['SQ', '1', 'AssessedSOPInstanceSequence'],\n    '0005': ['SQ', '1', 'ReferencedComparisonSOPInstanceSequence'],\n    '0006': ['UL', '1', 'NumberOfAssessmentObservations'],\n    '0007': ['SQ', '1', 'AssessmentObservationsSequence'],\n    '0008': ['CS', '1', 'ObservationSignificance'],\n    '000A': ['UT', '1', 'ObservationDescription'],\n    '000C': ['SQ', '1', 'StructuredConstraintObservationSequence'],\n    '0010': ['SQ', '1', 'AssessedAttributeValueSequence'],\n    '0016': ['LO', '1', 'AssessmentSetID'],\n    '0017': ['SQ', '1', 'AssessmentRequesterSequence'],\n    '0018': ['LO', '1', 'SelectorAttributeName'],\n    '0019': ['LO', '1', 'SelectorAttributeKeyword'],\n    '0021': ['SQ', '1', 'AssessmentTypeCodeSequence'],\n    '0022': ['SQ', '1', 'ObservationBasisCodeSequence'],\n    '0023': ['LO', '1', 'AssessmentLabel'],\n    '0032': ['CS', '1', 'ConstraintType'],\n    '0033': ['UT', '1', 'SpecificationSelectionGuidance'],\n    '0034': ['SQ', '1', 'ConstraintValueSequence'],\n    '0035': ['SQ', '1', 'RecommendedDefaultValueSequence'],\n    '0036': ['CS', '1', 'ConstraintViolationSignificance'],\n    '0037': ['UT', '1', 'ConstraintViolationCondition'],\n    '0038': ['CS', '1', 'ModifiableConstraintFlag']\n  },\n  '0088': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0130': ['SH', '1', 'StorageMediaFileSetID'],\n    '0140': ['UI', '1', 'StorageMediaFileSetUID'],\n    '0200': ['SQ', '1', 'IconImageSequence'],\n    '0904': ['LO', '1', 'TopicTitle'],\n    '0906': ['ST', '1', 'TopicSubject'],\n    '0910': ['LO', '1', 'TopicAuthor'],\n    '0912': ['LO', '1-32', 'TopicKeywords']\n  },\n  '0100': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0410': ['CS', '1', 'SOPInstanceStatus'],\n    '0420': ['DT', '1', 'SOPAuthorizationDateTime'],\n    '0424': ['LT', '1', 'SOPAuthorizationComment'],\n    '0426': ['LO', '1', 'AuthorizationEquipmentCertificationNumber']\n  },\n  '0400': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0005': ['US', '1', 'MACIDNumber'],\n    '0010': ['UI', '1', 'MACCalculationTransferSyntaxUID'],\n    '0015': ['CS', '1', 'MACAlgorithm'],\n    '0020': ['AT', '1-n', 'DataElementsSigned'],\n    '0100': ['UI', '1', 'DigitalSignatureUID'],\n    '0105': ['DT', '1', 'DigitalSignatureDateTime'],\n    '0110': ['CS', '1', 'CertificateType'],\n    '0115': ['OB', '1', 'CertificateOfSigner'],\n    '0120': ['OB', '1', 'Signature'],\n    '0305': ['CS', '1', 'CertifiedTimestampType'],\n    '0310': ['OB', '1', 'CertifiedTimestamp'],\n    '0315': ['FL', '1', ''],\n    '0401': ['SQ', '1', 'DigitalSignaturePurposeCodeSequence'],\n    '0402': ['SQ', '1', 'ReferencedDigitalSignatureSequence'],\n    '0403': ['SQ', '1', 'ReferencedSOPInstanceMACSequence'],\n    '0404': ['OB', '1', 'MAC'],\n    '0500': ['SQ', '1', 'EncryptedAttributesSequence'],\n    '0510': ['UI', '1', 'EncryptedContentTransferSyntaxUID'],\n    '0520': ['OB', '1', 'EncryptedContent'],\n    '0550': ['SQ', '1', 'ModifiedAttributesSequence'],\n    '0551': ['SQ', '1', 'NonconformingModifiedAttributesSequence'],\n    '0552': ['OB', '1', 'NonconformingDataElementValue'],\n    '0561': ['SQ', '1', 'OriginalAttributesSequence'],\n    '0562': ['DT', '1', 'AttributeModificationDateTime'],\n    '0563': ['LO', '1', 'ModifyingSystem'],\n    '0564': ['LO', '1', 'SourceOfPreviousValues'],\n    '0565': ['CS', '1', 'ReasonForTheAttributeModification'],\n    '0600': ['CS', '1', 'InstanceOriginStatus']\n  },\n  '1000': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['US', '3', 'EscapeTriplet'],\n    '0011': ['US', '3', 'RunLengthTriplet'],\n    '0012': ['US', '1', 'HuffmanTableSize'],\n    '0013': ['US', '3', 'HuffmanTableTriplet'],\n    '0014': ['US', '1', 'ShiftTableSize'],\n    '0015': ['US', '3', 'ShiftTableTriplet']\n  },\n  '1010': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0004': ['US', '1-n', 'ZonalMap']\n  },\n  '2000': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['IS', '1', 'NumberOfCopies'],\n    '001E': ['SQ', '1', 'PrinterConfigurationSequence'],\n    '0020': ['CS', '1', 'PrintPriority'],\n    '0030': ['CS', '1', 'MediumType'],\n    '0040': ['CS', '1', 'FilmDestination'],\n    '0050': ['LO', '1', 'FilmSessionLabel'],\n    '0060': ['IS', '1', 'MemoryAllocation'],\n    '0061': ['IS', '1', 'MaximumMemoryAllocation'],\n    '0062': ['CS', '1', 'ColorImagePrintingFlag'],\n    '0063': ['CS', '1', 'CollationFlag'],\n    '0065': ['CS', '1', 'AnnotationFlag'],\n    '0067': ['CS', '1', 'ImageOverlayFlag'],\n    '0069': ['CS', '1', 'PresentationLUTFlag'],\n    '006A': ['CS', '1', 'ImageBoxPresentationLUTFlag'],\n    '00A0': ['US', '1', 'MemoryBitDepth'],\n    '00A1': ['US', '1', 'PrintingBitDepth'],\n    '00A2': ['SQ', '1', 'MediaInstalledSequence'],\n    '00A4': ['SQ', '1', 'OtherMediaAvailableSequence'],\n    '00A8': ['SQ', '1', 'SupportedImageDisplayFormatsSequence'],\n    '0500': ['SQ', '1', 'ReferencedFilmBoxSequence'],\n    '0510': ['SQ', '1', 'ReferencedStoredPrintSequence']\n  },\n  '2010': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['ST', '1', 'ImageDisplayFormat'],\n    '0030': ['CS', '1', 'AnnotationDisplayFormatID'],\n    '0040': ['CS', '1', 'FilmOrientation'],\n    '0050': ['CS', '1', 'FilmSizeID'],\n    '0052': ['CS', '1', 'PrinterResolutionID'],\n    '0054': ['CS', '1', 'DefaultPrinterResolutionID'],\n    '0060': ['CS', '1', 'MagnificationType'],\n    '0080': ['CS', '1', 'SmoothingType'],\n    '00A6': ['CS', '1', 'DefaultMagnificationType'],\n    '00A7': ['CS', '1-n', 'OtherMagnificationTypesAvailable'],\n    '00A8': ['CS', '1', 'DefaultSmoothingType'],\n    '00A9': ['CS', '1-n', 'OtherSmoothingTypesAvailable'],\n    '0100': ['CS', '1', 'BorderDensity'],\n    '0110': ['CS', '1', 'EmptyImageDensity'],\n    '0120': ['US', '1', 'MinDensity'],\n    '0130': ['US', '1', 'MaxDensity'],\n    '0140': ['CS', '1', 'Trim'],\n    '0150': ['ST', '1', 'ConfigurationInformation'],\n    '0152': ['LT', '1', 'ConfigurationInformationDescription'],\n    '0154': ['IS', '1', 'MaximumCollatedFilms'],\n    '015E': ['US', '1', 'Illumination'],\n    '0160': ['US', '1', 'ReflectedAmbientLight'],\n    '0376': ['DS', '2', 'PrinterPixelSpacing'],\n    '0500': ['SQ', '1', 'ReferencedFilmSessionSequence'],\n    '0510': ['SQ', '1', 'ReferencedImageBoxSequence'],\n    '0520': ['SQ', '1', 'ReferencedBasicAnnotationBoxSequence']\n  },\n  '2020': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['US', '1', 'ImageBoxPosition'],\n    '0020': ['CS', '1', 'Polarity'],\n    '0030': ['DS', '1', 'RequestedImageSize'],\n    '0040': ['CS', '1', 'RequestedDecimateCropBehavior'],\n    '0050': ['CS', '1', 'RequestedResolutionID'],\n    '00A0': ['CS', '1', 'RequestedImageSizeFlag'],\n    '00A2': ['CS', '1', 'DecimateCropResult'],\n    '0110': ['SQ', '1', 'BasicGrayscaleImageSequence'],\n    '0111': ['SQ', '1', 'BasicColorImageSequence'],\n    '0130': ['SQ', '1', 'ReferencedImageOverlayBoxSequence'],\n    '0140': ['SQ', '1', 'ReferencedVOILUTBoxSequence']\n  },\n  '2030': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['US', '1', 'AnnotationPosition'],\n    '0020': ['LO', '1', 'TextString']\n  },\n  '2040': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['SQ', '1', 'ReferencedOverlayPlaneSequence'],\n    '0011': ['US', '1-99', 'ReferencedOverlayPlaneGroups'],\n    '0020': ['SQ', '1', 'OverlayPixelDataSequence'],\n    '0060': ['CS', '1', 'OverlayMagnificationType'],\n    '0070': ['CS', '1', 'OverlaySmoothingType'],\n    '0072': ['CS', '1', 'OverlayOrImageMagnification'],\n    '0074': ['US', '1', 'MagnifyToNumberOfColumns'],\n    '0080': ['CS', '1', 'OverlayForegroundDensity'],\n    '0082': ['CS', '1', 'OverlayBackgroundDensity'],\n    '0090': ['CS', '1', 'OverlayMode'],\n    '0100': ['CS', '1', 'ThresholdDensity'],\n    '0500': ['SQ', '1', 'ReferencedImageBoxSequenceRetired']\n  },\n  '2050': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['SQ', '1', 'PresentationLUTSequence'],\n    '0020': ['CS', '1', 'PresentationLUTShape'],\n    '0500': ['SQ', '1', 'ReferencedPresentationLUTSequence']\n  },\n  '2100': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['SH', '1', 'PrintJobID'],\n    '0020': ['CS', '1', 'ExecutionStatus'],\n    '0030': ['CS', '1', 'ExecutionStatusInfo'],\n    '0040': ['DA', '1', 'CreationDate'],\n    '0050': ['TM', '1', 'CreationTime'],\n    '0070': ['AE', '1', 'Originator'],\n    '0140': ['AE', '1', 'DestinationAE'],\n    '0160': ['SH', '1', 'OwnerID'],\n    '0170': ['IS', '1', 'NumberOfFilms'],\n    '0500': ['SQ', '1', 'ReferencedPrintJobSequencePullStoredPrint']\n  },\n  '2110': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['CS', '1', 'PrinterStatus'],\n    '0020': ['CS', '1', 'PrinterStatusInfo'],\n    '0030': ['LO', '1', 'PrinterName'],\n    '0099': ['SH', '1', 'PrintQueueID']\n  },\n  '2120': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['CS', '1', 'QueueStatus'],\n    '0050': ['SQ', '1', 'PrintJobDescriptionSequence'],\n    '0070': ['SQ', '1', 'ReferencedPrintJobSequence']\n  },\n  '2130': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['SQ', '1', 'PrintManagementCapabilitiesSequence'],\n    '0015': ['SQ', '1', 'PrinterCharacteristicsSequence'],\n    '0030': ['SQ', '1', 'FilmBoxContentSequence'],\n    '0040': ['SQ', '1', 'ImageBoxContentSequence'],\n    '0050': ['SQ', '1', 'AnnotationContentSequence'],\n    '0060': ['SQ', '1', 'ImageOverlayBoxContentSequence'],\n    '0080': ['SQ', '1', 'PresentationLUTContentSequence'],\n    '00A0': ['SQ', '1', 'ProposedStudySequence'],\n    '00C0': ['SQ', '1', 'OriginalImageSequence']\n  },\n  '2200': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'LabelUsingInformationExtractedFromInstances'],\n    '0002': ['UT', '1', 'LabelText'],\n    '0003': ['CS', '1', 'LabelStyleSelection'],\n    '0004': ['LT', '1', 'MediaDisposition'],\n    '0005': ['LT', '1', 'BarcodeValue'],\n    '0006': ['CS', '1', 'BarcodeSymbology'],\n    '0007': ['CS', '1', 'AllowMediaSplitting'],\n    '0008': ['CS', '1', 'IncludeNonDICOMObjects'],\n    '0009': ['CS', '1', 'IncludeDisplayApplication'],\n    '000A': ['CS', '1', 'PreserveCompositeInstancesAfterMediaCreation'],\n    '000B': ['US', '1', 'TotalNumberOfPiecesOfMediaCreated'],\n    '000C': ['LO', '1', 'RequestedMediaApplicationProfile'],\n    '000D': ['SQ', '1', 'ReferencedStorageMediaSequence'],\n    '000E': ['AT', '1-n', 'FailureAttributes'],\n    '000F': ['CS', '1', 'AllowLossyCompression'],\n    '0020': ['CS', '1', 'RequestPriority']\n  },\n  '3002': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SH', '1', 'RTImageLabel'],\n    '0003': ['LO', '1', 'RTImageName'],\n    '0004': ['ST', '1', 'RTImageDescription'],\n    '000A': ['CS', '1', 'ReportedValuesOrigin'],\n    '000C': ['CS', '1', 'RTImagePlane'],\n    '000D': ['DS', '3', 'XRayImageReceptorTranslation'],\n    '000E': ['DS', '1', 'XRayImageReceptorAngle'],\n    '0010': ['DS', '6', 'RTImageOrientation'],\n    '0011': ['DS', '2', 'ImagePlanePixelSpacing'],\n    '0012': ['DS', '2', 'RTImagePosition'],\n    '0020': ['SH', '1', 'RadiationMachineName'],\n    '0022': ['DS', '1', 'RadiationMachineSAD'],\n    '0024': ['DS', '1', 'RadiationMachineSSD'],\n    '0026': ['DS', '1', 'RTImageSID'],\n    '0028': ['DS', '1', 'SourceToReferenceObjectDistance'],\n    '0029': ['IS', '1', 'FractionNumber'],\n    '0030': ['SQ', '1', 'ExposureSequence'],\n    '0032': ['DS', '1', 'MetersetExposure'],\n    '0034': ['DS', '4', 'DiaphragmPosition'],\n    '0040': ['SQ', '1', 'FluenceMapSequence'],\n    '0041': ['CS', '1', 'FluenceDataSource'],\n    '0042': ['DS', '1', 'FluenceDataScale'],\n    '0050': ['SQ', '1', 'PrimaryFluenceModeSequence'],\n    '0051': ['CS', '1', 'FluenceMode'],\n    '0052': ['SH', '1', 'FluenceModeID']\n  },\n  '3004': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'DVHType'],\n    '0002': ['CS', '1', 'DoseUnits'],\n    '0004': ['CS', '1', 'DoseType'],\n    '0005': ['CS', '1', 'SpatialTransformOfDose'],\n    '0006': ['LO', '1', 'DoseComment'],\n    '0008': ['DS', '3', 'NormalizationPoint'],\n    '000A': ['CS', '1', 'DoseSummationType'],\n    '000C': ['DS', '2-n', 'GridFrameOffsetVector'],\n    '000E': ['DS', '1', 'DoseGridScaling'],\n    '0010': ['SQ', '1', 'RTDoseROISequence'],\n    '0012': ['DS', '1', 'DoseValue'],\n    '0014': ['CS', '1-3', 'TissueHeterogeneityCorrection'],\n    '0040': ['DS', '3', 'DVHNormalizationPoint'],\n    '0042': ['DS', '1', 'DVHNormalizationDoseValue'],\n    '0050': ['SQ', '1', 'DVHSequence'],\n    '0052': ['DS', '1', 'DVHDoseScaling'],\n    '0054': ['CS', '1', 'DVHVolumeUnits'],\n    '0056': ['IS', '1', 'DVHNumberOfBins'],\n    '0058': ['DS', '2-2n', 'DVHData'],\n    '0060': ['SQ', '1', 'DVHReferencedROISequence'],\n    '0062': ['CS', '1', 'DVHROIContributionType'],\n    '0070': ['DS', '1', 'DVHMinimumDose'],\n    '0072': ['DS', '1', 'DVHMaximumDose'],\n    '0074': ['DS', '1', 'DVHMeanDose']\n  },\n  '3006': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SH', '1', 'StructureSetLabel'],\n    '0004': ['LO', '1', 'StructureSetName'],\n    '0006': ['ST', '1', 'StructureSetDescription'],\n    '0008': ['DA', '1', 'StructureSetDate'],\n    '0009': ['TM', '1', 'StructureSetTime'],\n    '0010': ['SQ', '1', 'ReferencedFrameOfReferenceSequence'],\n    '0012': ['SQ', '1', 'RTReferencedStudySequence'],\n    '0014': ['SQ', '1', 'RTReferencedSeriesSequence'],\n    '0016': ['SQ', '1', 'ContourImageSequence'],\n    '0018': ['SQ', '1', 'PredecessorStructureSetSequence'],\n    '0020': ['SQ', '1', 'StructureSetROISequence'],\n    '0022': ['IS', '1', 'ROINumber'],\n    '0024': ['UI', '1', 'ReferencedFrameOfReferenceUID'],\n    '0026': ['LO', '1', 'ROIName'],\n    '0028': ['ST', '1', 'ROIDescription'],\n    '002A': ['IS', '3', 'ROIDisplayColor'],\n    '002C': ['DS', '1', 'ROIVolume'],\n    '0030': ['SQ', '1', 'RTRelatedROISequence'],\n    '0033': ['CS', '1', 'RTROIRelationship'],\n    '0036': ['CS', '1', 'ROIGenerationAlgorithm'],\n    '0037': ['SQ', '1', 'ROIDerivationAlgorithmIdentificationSequence'],\n    '0038': ['LO', '1', 'ROIGenerationDescription'],\n    '0039': ['SQ', '1', 'ROIContourSequence'],\n    '0040': ['SQ', '1', 'ContourSequence'],\n    '0042': ['CS', '1', 'ContourGeometricType'],\n    '0044': ['DS', '1', 'ContourSlabThickness'],\n    '0045': ['DS', '3', 'ContourOffsetVector'],\n    '0046': ['IS', '1', 'NumberOfContourPoints'],\n    '0048': ['IS', '1', 'ContourNumber'],\n    '0049': ['IS', '1-n', 'AttachedContours'],\n    '004A': ['SQ', '1', 'SourcePixelPlanesCharacteristicsSequence'],\n    '0050': ['DS', '3-3n', 'ContourData'],\n    '0080': ['SQ', '1', 'RTROIObservationsSequence'],\n    '0082': ['IS', '1', 'ObservationNumber'],\n    '0084': ['IS', '1', 'ReferencedROINumber'],\n    '0085': ['SH', '1', 'ROIObservationLabel'],\n    '0086': ['SQ', '1', 'RTROIIdentificationCodeSequence'],\n    '0088': ['ST', '1', 'ROIObservationDescription'],\n    '00A0': ['SQ', '1', 'RelatedRTROIObservationsSequence'],\n    '00A4': ['CS', '1', 'RTROIInterpretedType'],\n    '00A6': ['PN', '1', 'ROIInterpreter'],\n    '00B0': ['SQ', '1', 'ROIPhysicalPropertiesSequence'],\n    '00B2': ['CS', '1', 'ROIPhysicalProperty'],\n    '00B4': ['DS', '1', 'ROIPhysicalPropertyValue'],\n    '00B6': ['SQ', '1', 'ROIElementalCompositionSequence'],\n    '00B7': ['US', '1', 'ROIElementalCompositionAtomicNumber'],\n    '00B8': ['FL', '1', 'ROIElementalCompositionAtomicMassFraction'],\n    '00B9': ['SQ', '1', 'AdditionalRTROIIdentificationCodeSequence'],\n    '00C0': ['SQ', '1', 'FrameOfReferenceRelationshipSequence'],\n    '00C2': ['UI', '1', 'RelatedFrameOfReferenceUID'],\n    '00C4': ['CS', '1', 'FrameOfReferenceTransformationType'],\n    '00C6': ['DS', '16', 'FrameOfReferenceTransformationMatrix'],\n    '00C8': ['LO', '1', 'FrameOfReferenceTransformationComment'],\n    '00C9': ['SQ', '1', 'PatientLocationCoordinatesSequence'],\n    '00CA': ['SQ', '1', 'PatientLocationCoordinatesCodeSequence'],\n    '00CB': ['SQ', '1', 'PatientSupportPositionSequence']\n  },\n  '3008': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['SQ', '1', 'MeasuredDoseReferenceSequence'],\n    '0012': ['ST', '1', 'MeasuredDoseDescription'],\n    '0014': ['CS', '1', 'MeasuredDoseType'],\n    '0016': ['DS', '1', 'MeasuredDoseValue'],\n    '0020': ['SQ', '1', 'TreatmentSessionBeamSequence'],\n    '0021': ['SQ', '1', 'TreatmentSessionIonBeamSequence'],\n    '0022': ['IS', '1', 'CurrentFractionNumber'],\n    '0024': ['DA', '1', 'TreatmentControlPointDate'],\n    '0025': ['TM', '1', 'TreatmentControlPointTime'],\n    '002A': ['CS', '1', 'TreatmentTerminationStatus'],\n    '002B': ['SH', '1', 'TreatmentTerminationCode'],\n    '002C': ['CS', '1', 'TreatmentVerificationStatus'],\n    '0030': ['SQ', '1', 'ReferencedTreatmentRecordSequence'],\n    '0032': ['DS', '1', 'SpecifiedPrimaryMeterset'],\n    '0033': ['DS', '1', 'SpecifiedSecondaryMeterset'],\n    '0036': ['DS', '1', 'DeliveredPrimaryMeterset'],\n    '0037': ['DS', '1', 'DeliveredSecondaryMeterset'],\n    '003A': ['DS', '1', 'SpecifiedTreatmentTime'],\n    '003B': ['DS', '1', 'DeliveredTreatmentTime'],\n    '0040': ['SQ', '1', 'ControlPointDeliverySequence'],\n    '0041': ['SQ', '1', 'IonControlPointDeliverySequence'],\n    '0042': ['DS', '1', 'SpecifiedMeterset'],\n    '0044': ['DS', '1', 'DeliveredMeterset'],\n    '0045': ['FL', '1', 'MetersetRateSet'],\n    '0046': ['FL', '1', 'MetersetRateDelivered'],\n    '0047': ['FL', '1-n', 'ScanSpotMetersetsDelivered'],\n    '0048': ['DS', '1', 'DoseRateDelivered'],\n    '0050': ['SQ', '1', 'TreatmentSummaryCalculatedDoseReferenceSequence'],\n    '0052': ['DS', '1', 'CumulativeDoseToDoseReference'],\n    '0054': ['DA', '1', 'FirstTreatmentDate'],\n    '0056': ['DA', '1', 'MostRecentTreatmentDate'],\n    '005A': ['IS', '1', 'NumberOfFractionsDelivered'],\n    '0060': ['SQ', '1', 'OverrideSequence'],\n    '0061': ['AT', '1', 'ParameterSequencePointer'],\n    '0062': ['AT', '1', 'OverrideParameterPointer'],\n    '0063': ['IS', '1', 'ParameterItemIndex'],\n    '0064': ['IS', '1', 'MeasuredDoseReferenceNumber'],\n    '0065': ['AT', '1', 'ParameterPointer'],\n    '0066': ['ST', '1', 'OverrideReason'],\n    '0067': ['US', '1', 'ParameterValueNumber'],\n    '0068': ['SQ', '1', 'CorrectedParameterSequence'],\n    '006A': ['FL', '1', 'CorrectionValue'],\n    '0070': ['SQ', '1', 'CalculatedDoseReferenceSequence'],\n    '0072': ['IS', '1', 'CalculatedDoseReferenceNumber'],\n    '0074': ['ST', '1', 'CalculatedDoseReferenceDescription'],\n    '0076': ['DS', '1', 'CalculatedDoseReferenceDoseValue'],\n    '0078': ['DS', '1', 'StartMeterset'],\n    '007A': ['DS', '1', 'EndMeterset'],\n    '0080': ['SQ', '1', 'ReferencedMeasuredDoseReferenceSequence'],\n    '0082': ['IS', '1', 'ReferencedMeasuredDoseReferenceNumber'],\n    '0090': ['SQ', '1', 'ReferencedCalculatedDoseReferenceSequence'],\n    '0092': ['IS', '1', 'ReferencedCalculatedDoseReferenceNumber'],\n    '00A0': ['SQ', '1', 'BeamLimitingDeviceLeafPairsSequence'],\n    '00B0': ['SQ', '1', 'RecordedWedgeSequence'],\n    '00C0': ['SQ', '1', 'RecordedCompensatorSequence'],\n    '00D0': ['SQ', '1', 'RecordedBlockSequence'],\n    '00D1': ['SQ', '1', 'RecordedBlockSlabSequence'],\n    '00E0': ['SQ', '1', 'TreatmentSummaryMeasuredDoseReferenceSequence'],\n    '00F0': ['SQ', '1', 'RecordedSnoutSequence'],\n    '00F2': ['SQ', '1', 'RecordedRangeShifterSequence'],\n    '00F4': ['SQ', '1', 'RecordedLateralSpreadingDeviceSequence'],\n    '00F6': ['SQ', '1', 'RecordedRangeModulatorSequence'],\n    '0100': ['SQ', '1', 'RecordedSourceSequence'],\n    '0105': ['LO', '1', 'SourceSerialNumber'],\n    '0110': ['SQ', '1', 'TreatmentSessionApplicationSetupSequence'],\n    '0116': ['CS', '1', 'ApplicationSetupCheck'],\n    '0120': ['SQ', '1', 'RecordedBrachyAccessoryDeviceSequence'],\n    '0122': ['IS', '1', 'ReferencedBrachyAccessoryDeviceNumber'],\n    '0130': ['SQ', '1', 'RecordedChannelSequence'],\n    '0132': ['DS', '1', 'SpecifiedChannelTotalTime'],\n    '0134': ['DS', '1', 'DeliveredChannelTotalTime'],\n    '0136': ['IS', '1', 'SpecifiedNumberOfPulses'],\n    '0138': ['IS', '1', 'DeliveredNumberOfPulses'],\n    '013A': ['DS', '1', 'SpecifiedPulseRepetitionInterval'],\n    '013C': ['DS', '1', 'DeliveredPulseRepetitionInterval'],\n    '0140': ['SQ', '1', 'RecordedSourceApplicatorSequence'],\n    '0142': ['IS', '1', 'ReferencedSourceApplicatorNumber'],\n    '0150': ['SQ', '1', 'RecordedChannelShieldSequence'],\n    '0152': ['IS', '1', 'ReferencedChannelShieldNumber'],\n    '0160': ['SQ', '1', 'BrachyControlPointDeliveredSequence'],\n    '0162': ['DA', '1', 'SafePositionExitDate'],\n    '0164': ['TM', '1', 'SafePositionExitTime'],\n    '0166': ['DA', '1', 'SafePositionReturnDate'],\n    '0168': ['TM', '1', 'SafePositionReturnTime'],\n    '0171': ['SQ', '1', 'PulseSpecificBrachyControlPointDeliveredSequence'],\n    '0172': ['US', '1', 'PulseNumber'],\n    '0173': ['SQ', '1', 'BrachyPulseControlPointDeliveredSequence'],\n    '0200': ['CS', '1', 'CurrentTreatmentStatus'],\n    '0202': ['ST', '1', 'TreatmentStatusComment'],\n    '0220': ['SQ', '1', 'FractionGroupSummarySequence'],\n    '0223': ['IS', '1', 'ReferencedFractionNumber'],\n    '0224': ['CS', '1', 'FractionGroupType'],\n    '0230': ['CS', '1', 'BeamStopperPosition'],\n    '0240': ['SQ', '1', 'FractionStatusSummarySequence'],\n    '0250': ['DA', '1', 'TreatmentDate'],\n    '0251': ['TM', '1', 'TreatmentTime']\n  },\n  '300A': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SH', '1', 'RTPlanLabel'],\n    '0003': ['LO', '1', 'RTPlanName'],\n    '0004': ['ST', '1', 'RTPlanDescription'],\n    '0006': ['DA', '1', 'RTPlanDate'],\n    '0007': ['TM', '1', 'RTPlanTime'],\n    '0009': ['LO', '1-n', 'TreatmentProtocols'],\n    '000A': ['CS', '1', 'PlanIntent'],\n    '000B': ['LO', '1-n', 'TreatmentSites'],\n    '000C': ['CS', '1', 'RTPlanGeometry'],\n    '000E': ['ST', '1', 'PrescriptionDescription'],\n    '0010': ['SQ', '1', 'DoseReferenceSequence'],\n    '0012': ['IS', '1', 'DoseReferenceNumber'],\n    '0013': ['UI', '1', 'DoseReferenceUID'],\n    '0014': ['CS', '1', 'DoseReferenceStructureType'],\n    '0015': ['CS', '1', 'NominalBeamEnergyUnit'],\n    '0016': ['LO', '1', 'DoseReferenceDescription'],\n    '0018': ['DS', '3', 'DoseReferencePointCoordinates'],\n    '001A': ['DS', '1', 'NominalPriorDose'],\n    '0020': ['CS', '1', 'DoseReferenceType'],\n    '0021': ['DS', '1', 'ConstraintWeight'],\n    '0022': ['DS', '1', 'DeliveryWarningDose'],\n    '0023': ['DS', '1', 'DeliveryMaximumDose'],\n    '0025': ['DS', '1', 'TargetMinimumDose'],\n    '0026': ['DS', '1', 'TargetPrescriptionDose'],\n    '0027': ['DS', '1', 'TargetMaximumDose'],\n    '0028': ['DS', '1', 'TargetUnderdoseVolumeFraction'],\n    '002A': ['DS', '1', 'OrganAtRiskFullVolumeDose'],\n    '002B': ['DS', '1', 'OrganAtRiskLimitDose'],\n    '002C': ['DS', '1', 'OrganAtRiskMaximumDose'],\n    '002D': ['DS', '1', 'OrganAtRiskOverdoseVolumeFraction'],\n    '0040': ['SQ', '1', 'ToleranceTableSequence'],\n    '0042': ['IS', '1', 'ToleranceTableNumber'],\n    '0043': ['SH', '1', 'ToleranceTableLabel'],\n    '0044': ['DS', '1', 'GantryAngleTolerance'],\n    '0046': ['DS', '1', 'BeamLimitingDeviceAngleTolerance'],\n    '0048': ['SQ', '1', 'BeamLimitingDeviceToleranceSequence'],\n    '004A': ['DS', '1', 'BeamLimitingDevicePositionTolerance'],\n    '004B': ['FL', '1', 'SnoutPositionTolerance'],\n    '004C': ['DS', '1', 'PatientSupportAngleTolerance'],\n    '004E': ['DS', '1', 'TableTopEccentricAngleTolerance'],\n    '004F': ['FL', '1', 'TableTopPitchAngleTolerance'],\n    '0050': ['FL', '1', 'TableTopRollAngleTolerance'],\n    '0051': ['DS', '1', 'TableTopVerticalPositionTolerance'],\n    '0052': ['DS', '1', 'TableTopLongitudinalPositionTolerance'],\n    '0053': ['DS', '1', 'TableTopLateralPositionTolerance'],\n    '0055': ['CS', '1', 'RTPlanRelationship'],\n    '0070': ['SQ', '1', 'FractionGroupSequence'],\n    '0071': ['IS', '1', 'FractionGroupNumber'],\n    '0072': ['LO', '1', 'FractionGroupDescription'],\n    '0078': ['IS', '1', 'NumberOfFractionsPlanned'],\n    '0079': ['IS', '1', 'NumberOfFractionPatternDigitsPerDay'],\n    '007A': ['IS', '1', 'RepeatFractionCycleLength'],\n    '007B': ['LT', '1', 'FractionPattern'],\n    '0080': ['IS', '1', 'NumberOfBeams'],\n    '0082': ['DS', '3', 'BeamDoseSpecificationPoint'],\n    '0083': ['UI', '1', 'ReferencedDoseReferenceUID'],\n    '0084': ['DS', '1', 'BeamDose'],\n    '0086': ['DS', '1', 'BeamMeterset'],\n    '0088': ['FL', '1', 'BeamDosePointDepth'],\n    '0089': ['FL', '1', 'BeamDosePointEquivalentDepth'],\n    '008A': ['FL', '1', 'BeamDosePointSSD'],\n    '008B': ['CS', '1', 'BeamDoseMeaning'],\n    '008C': ['SQ', '1', 'BeamDoseVerificationControlPointSequence'],\n    '008D': ['FL', '1', 'AverageBeamDosePointDepth'],\n    '008E': ['FL', '1', 'AverageBeamDosePointEquivalentDepth'],\n    '008F': ['FL', '1', 'AverageBeamDosePointSSD'],\n    '0090': ['CS', '1', 'BeamDoseType'],\n    '0091': ['DS', '1', 'AlternateBeamDose'],\n    '0092': ['CS', '1', 'AlternateBeamDoseType'],\n    '0093': ['CS', '1', 'DepthValueAveragingFlag'],\n    '0094': ['DS', '1', 'BeamDosePointSourceToExternalContourDistance'],\n    '00A0': ['IS', '1', 'NumberOfBrachyApplicationSetups'],\n    '00A2': ['DS', '3', 'BrachyApplicationSetupDoseSpecificationPoint'],\n    '00A4': ['DS', '1', 'BrachyApplicationSetupDose'],\n    '00B0': ['SQ', '1', 'BeamSequence'],\n    '00B2': ['SH', '1', 'TreatmentMachineName'],\n    '00B3': ['CS', '1', 'PrimaryDosimeterUnit'],\n    '00B4': ['DS', '1', 'SourceAxisDistance'],\n    '00B6': ['SQ', '1', 'BeamLimitingDeviceSequence'],\n    '00B8': ['CS', '1', 'RTBeamLimitingDeviceType'],\n    '00BA': ['DS', '1', 'SourceToBeamLimitingDeviceDistance'],\n    '00BB': ['FL', '1', 'IsocenterToBeamLimitingDeviceDistance'],\n    '00BC': ['IS', '1', 'NumberOfLeafJawPairs'],\n    '00BE': ['DS', '3-n', 'LeafPositionBoundaries'],\n    '00C0': ['IS', '1', 'BeamNumber'],\n    '00C2': ['LO', '1', 'BeamName'],\n    '00C3': ['ST', '1', 'BeamDescription'],\n    '00C4': ['CS', '1', 'BeamType'],\n    '00C5': ['FD', '1', 'BeamDeliveryDurationLimit'],\n    '00C6': ['CS', '1', 'RadiationType'],\n    '00C7': ['CS', '1', 'HighDoseTechniqueType'],\n    '00C8': ['IS', '1', 'ReferenceImageNumber'],\n    '00CA': ['SQ', '1', 'PlannedVerificationImageSequence'],\n    '00CC': ['LO', '1-n', 'ImagingDeviceSpecificAcquisitionParameters'],\n    '00CE': ['CS', '1', 'TreatmentDeliveryType'],\n    '00D0': ['IS', '1', 'NumberOfWedges'],\n    '00D1': ['SQ', '1', 'WedgeSequence'],\n    '00D2': ['IS', '1', 'WedgeNumber'],\n    '00D3': ['CS', '1', 'WedgeType'],\n    '00D4': ['SH', '1', 'WedgeID'],\n    '00D5': ['IS', '1', 'WedgeAngle'],\n    '00D6': ['DS', '1', 'WedgeFactor'],\n    '00D7': ['FL', '1', 'TotalWedgeTrayWaterEquivalentThickness'],\n    '00D8': ['DS', '1', 'WedgeOrientation'],\n    '00D9': ['FL', '1', 'IsocenterToWedgeTrayDistance'],\n    '00DA': ['DS', '1', 'SourceToWedgeTrayDistance'],\n    '00DB': ['FL', '1', 'WedgeThinEdgePosition'],\n    '00DC': ['SH', '1', 'BolusID'],\n    '00DD': ['ST', '1', 'BolusDescription'],\n    '00DE': ['DS', '1', 'EffectiveWedgeAngle'],\n    '00E0': ['IS', '1', 'NumberOfCompensators'],\n    '00E1': ['SH', '1', 'MaterialID'],\n    '00E2': ['DS', '1', 'TotalCompensatorTrayFactor'],\n    '00E3': ['SQ', '1', 'CompensatorSequence'],\n    '00E4': ['IS', '1', 'CompensatorNumber'],\n    '00E5': ['SH', '1', 'CompensatorID'],\n    '00E6': ['DS', '1', 'SourceToCompensatorTrayDistance'],\n    '00E7': ['IS', '1', 'CompensatorRows'],\n    '00E8': ['IS', '1', 'CompensatorColumns'],\n    '00E9': ['DS', '2', 'CompensatorPixelSpacing'],\n    '00EA': ['DS', '2', 'CompensatorPosition'],\n    '00EB': ['DS', '1-n', 'CompensatorTransmissionData'],\n    '00EC': ['DS', '1-n', 'CompensatorThicknessData'],\n    '00ED': ['IS', '1', 'NumberOfBoli'],\n    '00EE': ['CS', '1', 'CompensatorType'],\n    '00EF': ['SH', '1', 'CompensatorTrayID'],\n    '00F0': ['IS', '1', 'NumberOfBlocks'],\n    '00F2': ['DS', '1', 'TotalBlockTrayFactor'],\n    '00F3': ['FL', '1', 'TotalBlockTrayWaterEquivalentThickness'],\n    '00F4': ['SQ', '1', 'BlockSequence'],\n    '00F5': ['SH', '1', 'BlockTrayID'],\n    '00F6': ['DS', '1', 'SourceToBlockTrayDistance'],\n    '00F7': ['FL', '1', 'IsocenterToBlockTrayDistance'],\n    '00F8': ['CS', '1', 'BlockType'],\n    '00F9': ['LO', '1', 'AccessoryCode'],\n    '00FA': ['CS', '1', 'BlockDivergence'],\n    '00FB': ['CS', '1', 'BlockMountingPosition'],\n    '00FC': ['IS', '1', 'BlockNumber'],\n    '00FE': ['LO', '1', 'BlockName'],\n    '0100': ['DS', '1', 'BlockThickness'],\n    '0102': ['DS', '1', 'BlockTransmission'],\n    '0104': ['IS', '1', 'BlockNumberOfPoints'],\n    '0106': ['DS', '2-2n', 'BlockData'],\n    '0107': ['SQ', '1', 'ApplicatorSequence'],\n    '0108': ['SH', '1', 'ApplicatorID'],\n    '0109': ['CS', '1', 'ApplicatorType'],\n    '010A': ['LO', '1', 'ApplicatorDescription'],\n    '010C': ['DS', '1', 'CumulativeDoseReferenceCoefficient'],\n    '010E': ['DS', '1', 'FinalCumulativeMetersetWeight'],\n    '0110': ['IS', '1', 'NumberOfControlPoints'],\n    '0111': ['SQ', '1', 'ControlPointSequence'],\n    '0112': ['IS', '1', 'ControlPointIndex'],\n    '0114': ['DS', '1', 'NominalBeamEnergy'],\n    '0115': ['DS', '1', 'DoseRateSet'],\n    '0116': ['SQ', '1', 'WedgePositionSequence'],\n    '0118': ['CS', '1', 'WedgePosition'],\n    '011A': ['SQ', '1', 'BeamLimitingDevicePositionSequence'],\n    '011C': ['DS', '2-2n', 'LeafJawPositions'],\n    '011E': ['DS', '1', 'GantryAngle'],\n    '011F': ['CS', '1', 'GantryRotationDirection'],\n    '0120': ['DS', '1', 'BeamLimitingDeviceAngle'],\n    '0121': ['CS', '1', 'BeamLimitingDeviceRotationDirection'],\n    '0122': ['DS', '1', 'PatientSupportAngle'],\n    '0123': ['CS', '1', 'PatientSupportRotationDirection'],\n    '0124': ['DS', '1', 'TableTopEccentricAxisDistance'],\n    '0125': ['DS', '1', 'TableTopEccentricAngle'],\n    '0126': ['CS', '1', 'TableTopEccentricRotationDirection'],\n    '0128': ['DS', '1', 'TableTopVerticalPosition'],\n    '0129': ['DS', '1', 'TableTopLongitudinalPosition'],\n    '012A': ['DS', '1', 'TableTopLateralPosition'],\n    '012C': ['DS', '3', 'IsocenterPosition'],\n    '012E': ['DS', '3', 'SurfaceEntryPoint'],\n    '0130': ['DS', '1', 'SourceToSurfaceDistance'],\n    '0131': ['FL', '1', 'AverageBeamDosePointSourceToExternalContourDistance'],\n    '0132': ['FL', '1', 'SourceToExternalContourDistance'],\n    '0133': ['FL', '3', 'ExternalContourEntryPoint'],\n    '0134': ['DS', '1', 'CumulativeMetersetWeight'],\n    '0140': ['FL', '1', 'TableTopPitchAngle'],\n    '0142': ['CS', '1', 'TableTopPitchRotationDirection'],\n    '0144': ['FL', '1', 'TableTopRollAngle'],\n    '0146': ['CS', '1', 'TableTopRollRotationDirection'],\n    '0148': ['FL', '1', 'HeadFixationAngle'],\n    '014A': ['FL', '1', 'GantryPitchAngle'],\n    '014C': ['CS', '1', 'GantryPitchRotationDirection'],\n    '014E': ['FL', '1', 'GantryPitchAngleTolerance'],\n    '0150': ['CS', '1', 'FixationEye'],\n    '0151': ['DS', '1', 'ChairHeadFramePosition'],\n    '0152': ['DS', '1', 'HeadFixationAngleTolerance'],\n    '0153': ['DS', '1', 'ChairHeadFramePositionTolerance'],\n    '0154': ['DS', '1', 'FixationLightAzimuthalAngleTolerance'],\n    '0155': ['DS', '1', 'FixationLightPolarAngleTolerance'],\n    '0180': ['SQ', '1', 'PatientSetupSequence'],\n    '0182': ['IS', '1', 'PatientSetupNumber'],\n    '0183': ['LO', '1', 'PatientSetupLabel'],\n    '0184': ['LO', '1', 'PatientAdditionalPosition'],\n    '0190': ['SQ', '1', 'FixationDeviceSequence'],\n    '0192': ['CS', '1', 'FixationDeviceType'],\n    '0194': ['SH', '1', 'FixationDeviceLabel'],\n    '0196': ['ST', '1', 'FixationDeviceDescription'],\n    '0198': ['SH', '1', 'FixationDevicePosition'],\n    '0199': ['FL', '1', 'FixationDevicePitchAngle'],\n    '019A': ['FL', '1', 'FixationDeviceRollAngle'],\n    '01A0': ['SQ', '1', 'ShieldingDeviceSequence'],\n    '01A2': ['CS', '1', 'ShieldingDeviceType'],\n    '01A4': ['SH', '1', 'ShieldingDeviceLabel'],\n    '01A6': ['ST', '1', 'ShieldingDeviceDescription'],\n    '01A8': ['SH', '1', 'ShieldingDevicePosition'],\n    '01B0': ['CS', '1', 'SetupTechnique'],\n    '01B2': ['ST', '1', 'SetupTechniqueDescription'],\n    '01B4': ['SQ', '1', 'SetupDeviceSequence'],\n    '01B6': ['CS', '1', 'SetupDeviceType'],\n    '01B8': ['SH', '1', 'SetupDeviceLabel'],\n    '01BA': ['ST', '1', 'SetupDeviceDescription'],\n    '01BC': ['DS', '1', 'SetupDeviceParameter'],\n    '01D0': ['ST', '1', 'SetupReferenceDescription'],\n    '01D2': ['DS', '1', 'TableTopVerticalSetupDisplacement'],\n    '01D4': ['DS', '1', 'TableTopLongitudinalSetupDisplacement'],\n    '01D6': ['DS', '1', 'TableTopLateralSetupDisplacement'],\n    '0200': ['CS', '1', 'BrachyTreatmentTechnique'],\n    '0202': ['CS', '1', 'BrachyTreatmentType'],\n    '0206': ['SQ', '1', 'TreatmentMachineSequence'],\n    '0210': ['SQ', '1', 'SourceSequence'],\n    '0212': ['IS', '1', 'SourceNumber'],\n    '0214': ['CS', '1', 'SourceType'],\n    '0216': ['LO', '1', 'SourceManufacturer'],\n    '0218': ['DS', '1', 'ActiveSourceDiameter'],\n    '021A': ['DS', '1', 'ActiveSourceLength'],\n    '021B': ['SH', '1', 'SourceModelID'],\n    '021C': ['LO', '1', 'SourceDescription'],\n    '0222': ['DS', '1', 'SourceEncapsulationNominalThickness'],\n    '0224': ['DS', '1', 'SourceEncapsulationNominalTransmission'],\n    '0226': ['LO', '1', 'SourceIsotopeName'],\n    '0228': ['DS', '1', 'SourceIsotopeHalfLife'],\n    '0229': ['CS', '1', 'SourceStrengthUnits'],\n    '022A': ['DS', '1', 'ReferenceAirKermaRate'],\n    '022B': ['DS', '1', 'SourceStrength'],\n    '022C': ['DA', '1', 'SourceStrengthReferenceDate'],\n    '022E': ['TM', '1', 'SourceStrengthReferenceTime'],\n    '0230': ['SQ', '1', 'ApplicationSetupSequence'],\n    '0232': ['CS', '1', 'ApplicationSetupType'],\n    '0234': ['IS', '1', 'ApplicationSetupNumber'],\n    '0236': ['LO', '1', 'ApplicationSetupName'],\n    '0238': ['LO', '1', 'ApplicationSetupManufacturer'],\n    '0240': ['IS', '1', 'TemplateNumber'],\n    '0242': ['SH', '1', 'TemplateType'],\n    '0244': ['LO', '1', 'TemplateName'],\n    '0250': ['DS', '1', 'TotalReferenceAirKerma'],\n    '0260': ['SQ', '1', 'BrachyAccessoryDeviceSequence'],\n    '0262': ['IS', '1', 'BrachyAccessoryDeviceNumber'],\n    '0263': ['SH', '1', 'BrachyAccessoryDeviceID'],\n    '0264': ['CS', '1', 'BrachyAccessoryDeviceType'],\n    '0266': ['LO', '1', 'BrachyAccessoryDeviceName'],\n    '026A': ['DS', '1', 'BrachyAccessoryDeviceNominalThickness'],\n    '026C': ['DS', '1', 'BrachyAccessoryDeviceNominalTransmission'],\n    '0271': ['DS', '1', 'ChannelEffectiveLength'],\n    '0272': ['DS', '1', 'ChannelInnerLength'],\n    '0273': ['SH', '1', 'AfterloaderChannelID'],\n    '0274': ['DS', '1', 'SourceApplicatorTipLength'],\n    '0280': ['SQ', '1', 'ChannelSequence'],\n    '0282': ['IS', '1', 'ChannelNumber'],\n    '0284': ['DS', '1', 'ChannelLength'],\n    '0286': ['DS', '1', 'ChannelTotalTime'],\n    '0288': ['CS', '1', 'SourceMovementType'],\n    '028A': ['IS', '1', 'NumberOfPulses'],\n    '028C': ['DS', '1', 'PulseRepetitionInterval'],\n    '0290': ['IS', '1', 'SourceApplicatorNumber'],\n    '0291': ['SH', '1', 'SourceApplicatorID'],\n    '0292': ['CS', '1', 'SourceApplicatorType'],\n    '0294': ['LO', '1', 'SourceApplicatorName'],\n    '0296': ['DS', '1', 'SourceApplicatorLength'],\n    '0298': ['LO', '1', 'SourceApplicatorManufacturer'],\n    '029C': ['DS', '1', 'SourceApplicatorWallNominalThickness'],\n    '029E': ['DS', '1', 'SourceApplicatorWallNominalTransmission'],\n    '02A0': ['DS', '1', 'SourceApplicatorStepSize'],\n    '02A1': ['IS', '1', 'ApplicatorShapeReferencedROINumber'],\n    '02A2': ['IS', '1', 'TransferTubeNumber'],\n    '02A4': ['DS', '1', 'TransferTubeLength'],\n    '02B0': ['SQ', '1', 'ChannelShieldSequence'],\n    '02B2': ['IS', '1', 'ChannelShieldNumber'],\n    '02B3': ['SH', '1', 'ChannelShieldID'],\n    '02B4': ['LO', '1', 'ChannelShieldName'],\n    '02B8': ['DS', '1', 'ChannelShieldNominalThickness'],\n    '02BA': ['DS', '1', 'ChannelShieldNominalTransmission'],\n    '02C8': ['DS', '1', 'FinalCumulativeTimeWeight'],\n    '02D0': ['SQ', '1', 'BrachyControlPointSequence'],\n    '02D2': ['DS', '1', 'ControlPointRelativePosition'],\n    '02D4': ['DS', '3', 'ControlPoint3DPosition'],\n    '02D6': ['DS', '1', 'CumulativeTimeWeight'],\n    '02E0': ['CS', '1', 'CompensatorDivergence'],\n    '02E1': ['CS', '1', 'CompensatorMountingPosition'],\n    '02E2': ['DS', '1-n', 'SourceToCompensatorDistance'],\n    '02E3': ['FL', '1', 'TotalCompensatorTrayWaterEquivalentThickness'],\n    '02E4': ['FL', '1', 'IsocenterToCompensatorTrayDistance'],\n    '02E5': ['FL', '1', 'CompensatorColumnOffset'],\n    '02E6': ['FL', '1-n', 'IsocenterToCompensatorDistances'],\n    '02E7': ['FL', '1', 'CompensatorRelativeStoppingPowerRatio'],\n    '02E8': ['FL', '1', 'CompensatorMillingToolDiameter'],\n    '02EA': ['SQ', '1', 'IonRangeCompensatorSequence'],\n    '02EB': ['LT', '1', 'CompensatorDescription'],\n    '0302': ['IS', '1', 'RadiationMassNumber'],\n    '0304': ['IS', '1', 'RadiationAtomicNumber'],\n    '0306': ['SS', '1', 'RadiationChargeState'],\n    '0308': ['CS', '1', 'ScanMode'],\n    '0309': ['CS', '1', 'ModulatedScanModeType'],\n    '030A': ['FL', '2', 'VirtualSourceAxisDistances'],\n    '030C': ['SQ', '1', 'SnoutSequence'],\n    '030D': ['FL', '1', 'SnoutPosition'],\n    '030F': ['SH', '1', 'SnoutID'],\n    '0312': ['IS', '1', 'NumberOfRangeShifters'],\n    '0314': ['SQ', '1', 'RangeShifterSequence'],\n    '0316': ['IS', '1', 'RangeShifterNumber'],\n    '0318': ['SH', '1', 'RangeShifterID'],\n    '0320': ['CS', '1', 'RangeShifterType'],\n    '0322': ['LO', '1', 'RangeShifterDescription'],\n    '0330': ['IS', '1', 'NumberOfLateralSpreadingDevices'],\n    '0332': ['SQ', '1', 'LateralSpreadingDeviceSequence'],\n    '0334': ['IS', '1', 'LateralSpreadingDeviceNumber'],\n    '0336': ['SH', '1', 'LateralSpreadingDeviceID'],\n    '0338': ['CS', '1', 'LateralSpreadingDeviceType'],\n    '033A': ['LO', '1', 'LateralSpreadingDeviceDescription'],\n    '033C': ['FL', '1', 'LateralSpreadingDeviceWaterEquivalentThickness'],\n    '0340': ['IS', '1', 'NumberOfRangeModulators'],\n    '0342': ['SQ', '1', 'RangeModulatorSequence'],\n    '0344': ['IS', '1', 'RangeModulatorNumber'],\n    '0346': ['SH', '1', 'RangeModulatorID'],\n    '0348': ['CS', '1', 'RangeModulatorType'],\n    '034A': ['LO', '1', 'RangeModulatorDescription'],\n    '034C': ['SH', '1', 'BeamCurrentModulationID'],\n    '0350': ['CS', '1', 'PatientSupportType'],\n    '0352': ['SH', '1', 'PatientSupportID'],\n    '0354': ['LO', '1', 'PatientSupportAccessoryCode'],\n    '0355': ['LO', '1', 'TrayAccessoryCode'],\n    '0356': ['FL', '1', 'FixationLightAzimuthalAngle'],\n    '0358': ['FL', '1', 'FixationLightPolarAngle'],\n    '035A': ['FL', '1', 'MetersetRate'],\n    '0360': ['SQ', '1', 'RangeShifterSettingsSequence'],\n    '0362': ['LO', '1', 'RangeShifterSetting'],\n    '0364': ['FL', '1', 'IsocenterToRangeShifterDistance'],\n    '0366': ['FL', '1', 'RangeShifterWaterEquivalentThickness'],\n    '0370': ['SQ', '1', 'LateralSpreadingDeviceSettingsSequence'],\n    '0372': ['LO', '1', 'LateralSpreadingDeviceSetting'],\n    '0374': ['FL', '1', 'IsocenterToLateralSpreadingDeviceDistance'],\n    '0380': ['SQ', '1', 'RangeModulatorSettingsSequence'],\n    '0382': ['FL', '1', 'RangeModulatorGatingStartValue'],\n    '0384': ['FL', '1', 'RangeModulatorGatingStopValue'],\n    '0386': ['FL', '1', 'RangeModulatorGatingStartWaterEquivalentThickness'],\n    '0388': ['FL', '1', 'RangeModulatorGatingStopWaterEquivalentThickness'],\n    '038A': ['FL', '1', 'IsocenterToRangeModulatorDistance'],\n    '038F': ['FL', '1-n', 'ScanSpotTimeOffset'],\n    '0390': ['SH', '1', 'ScanSpotTuneID'],\n    '0391': ['IS', '1-n', 'ScanSpotPrescribedIndices'],\n    '0392': ['IS', '1', 'NumberOfScanSpotPositions'],\n    '0393': ['CS', '1', 'ScanSpotReordered'],\n    '0394': ['FL', '1-n', 'ScanSpotPositionMap'],\n    '0395': ['CS', '1', 'ScanSpotReorderingAllowed'],\n    '0396': ['FL', '1-n', 'ScanSpotMetersetWeights'],\n    '0398': ['FL', '2', 'ScanningSpotSize'],\n    '0399': ['FL', '2-2n', 'ScanSpotSizesDelivered'],\n    '039A': ['IS', '1', 'NumberOfPaintings'],\n    '03A0': ['SQ', '1', 'IonToleranceTableSequence'],\n    '03A2': ['SQ', '1', 'IonBeamSequence'],\n    '03A4': ['SQ', '1', 'IonBeamLimitingDeviceSequence'],\n    '03A6': ['SQ', '1', 'IonBlockSequence'],\n    '03A8': ['SQ', '1', 'IonControlPointSequence'],\n    '03AA': ['SQ', '1', 'IonWedgeSequence'],\n    '03AC': ['SQ', '1', 'IonWedgePositionSequence'],\n    '0401': ['SQ', '1', 'ReferencedSetupImageSequence'],\n    '0402': ['ST', '1', 'SetupImageComment'],\n    '0410': ['SQ', '1', 'MotionSynchronizationSequence'],\n    '0412': ['FL', '3', 'ControlPointOrientation'],\n    '0420': ['SQ', '1', 'GeneralAccessorySequence'],\n    '0421': ['SH', '1', 'GeneralAccessoryID'],\n    '0422': ['ST', '1', 'GeneralAccessoryDescription'],\n    '0423': ['CS', '1', 'GeneralAccessoryType'],\n    '0424': ['IS', '1', 'GeneralAccessoryNumber'],\n    '0425': ['FL', '1', 'SourceToGeneralAccessoryDistance'],\n    '0426': ['DS', '1', 'IsocenterToGeneralAccessoryDistance'],\n    '0431': ['SQ', '1', 'ApplicatorGeometrySequence'],\n    '0432': ['CS', '1', 'ApplicatorApertureShape'],\n    '0433': ['FL', '1', 'ApplicatorOpening'],\n    '0434': ['FL', '1', 'ApplicatorOpeningX'],\n    '0435': ['FL', '1', 'ApplicatorOpeningY'],\n    '0436': ['FL', '1', 'SourceToApplicatorMountingPositionDistance'],\n    '0440': ['IS', '1', 'NumberOfBlockSlabItems'],\n    '0441': ['SQ', '1', 'BlockSlabSequence'],\n    '0442': ['DS', '1', 'BlockSlabThickness'],\n    '0443': ['US', '1', 'BlockSlabNumber'],\n    '0450': ['SQ', '1', 'DeviceMotionControlSequence'],\n    '0451': ['CS', '1', 'DeviceMotionExecutionMode'],\n    '0452': ['CS', '1', 'DeviceMotionObservationMode'],\n    '0453': ['SQ', '1', 'DeviceMotionParameterCodeSequence'],\n    '0501': ['FL', '1', 'DistalDepthFraction'],\n    '0502': ['FL', '1', 'DistalDepth'],\n    '0503': ['FL', '2', 'NominalRangeModulationFractions'],\n    '0504': ['FL', '2', 'NominalRangeModulatedRegionDepths'],\n    '0505': ['SQ', '1', 'DepthDoseParametersSequence'],\n    '0506': ['SQ', '1', 'DeliveredDepthDoseParametersSequence'],\n    '0507': ['FL', '1', 'DeliveredDistalDepthFraction'],\n    '0508': ['FL', '1', 'DeliveredDistalDepth'],\n    '0509': ['FL', '2', 'DeliveredNominalRangeModulationFractions'],\n    '0510': ['FL', '2', 'DeliveredNominalRangeModulatedRegionDepths'],\n    '0511': ['CS', '1', 'DeliveredReferenceDoseDefinition'],\n    '0512': ['CS', '1', 'ReferenceDoseDefinition'],\n    '0600': ['US', '1', 'RTControlPointIndex'],\n    '0601': ['US', '1', 'RadiationGenerationModeIndex'],\n    '0602': ['US', '1', 'ReferencedDefinedDeviceIndex'],\n    '0603': ['US', '1', 'RadiationDoseIdentificationIndex'],\n    '0604': ['US', '1', 'NumberOfRTControlPoints'],\n    '0605': ['US', '1', 'ReferencedRadiationGenerationModeIndex'],\n    '0606': ['US', '1', 'TreatmentPositionIndex'],\n    '0607': ['US', '1', 'ReferencedDeviceIndex'],\n    '0608': ['LO', '1', 'TreatmentPositionGroupLabel'],\n    '0609': ['UI', '1', 'TreatmentPositionGroupUID'],\n    '060A': ['SQ', '1', 'TreatmentPositionGroupSequence'],\n    '060B': ['US', '1', 'ReferencedTreatmentPositionIndex'],\n    '060C': ['US', '1', 'ReferencedRadiationDoseIdentificationIndex'],\n    '060D': ['FD', '1', 'RTAccessoryHolderWaterEquivalentThickness'],\n    '060E': ['US', '1', 'ReferencedRTAccessoryHolderDeviceIndex'],\n    '060F': ['CS', '1', 'RTAccessoryHolderSlotExistenceFlag'],\n    '0610': ['SQ', '1', 'RTAccessoryHolderSlotSequence'],\n    '0611': ['LO', '1', 'RTAccessoryHolderSlotID'],\n    '0612': ['FD', '1', 'RTAccessoryHolderSlotDistance'],\n    '0613': ['FD', '1', 'RTAccessorySlotDistance'],\n    '0614': ['SQ', '1', 'RTAccessoryHolderDefinitionSequence'],\n    '0615': ['LO', '1', 'RTAccessoryDeviceSlotID'],\n    '0616': ['SQ', '1', 'RTRadiationSequence'],\n    '0617': ['SQ', '1', 'RadiationDoseSequence'],\n    '0618': ['SQ', '1', 'RadiationDoseIdentificationSequence'],\n    '0619': ['LO', '1', 'RadiationDoseIdentificationLabel'],\n    '061A': ['CS', '1', 'ReferenceDoseType'],\n    '061B': ['CS', '1', 'PrimaryDoseValueIndicator'],\n    '061C': ['SQ', '1', 'DoseValuesSequence'],\n    '061D': ['CS', '1-n', 'DoseValuePurpose'],\n    '061E': ['FD', '3', 'ReferenceDosePointCoordinates'],\n    '061F': ['SQ', '1', 'RadiationDoseValuesParametersSequence'],\n    '0620': ['SQ', '1', 'MetersetToDoseMappingSequence'],\n    '0621': ['SQ', '1', 'ExpectedInVivoMeasurementValuesSequence'],\n    '0622': ['US', '1', 'ExpectedInVivoMeasurementValueIndex'],\n    '0623': ['LO', '1', 'RadiationDoseInVivoMeasurementLabel'],\n    '0624': ['FD', '2', 'RadiationDoseCentralAxisDisplacement'],\n    '0625': ['FD', '1', 'RadiationDoseValue'],\n    '0626': ['FD', '1', 'RadiationDoseSourceToSkinDistance'],\n    '0627': ['FD', '3', 'RadiationDoseMeasurementPointCoordinates'],\n    '0628': ['FD', '1', 'RadiationDoseSourceToExternalContourDistance'],\n    '0629': ['SQ', '1', 'RTToleranceSetSequence'],\n    '062A': ['LO', '1', 'RTToleranceSetLabel'],\n    '062B': ['SQ', '1', 'AttributeToleranceValuesSequence'],\n    '062C': ['FD', '1', 'ToleranceValue'],\n    '062D': ['SQ', '1', 'PatientSupportPositionToleranceSequence'],\n    '062E': ['FD', '1', 'TreatmentTimeLimit'],\n    '062F': ['SQ', '1', 'CArmPhotonElectronControlPointSequence'],\n    '0630': ['SQ', '1', 'ReferencedRTRadiationSequence'],\n    '0631': ['SQ', '1', 'ReferencedRTInstanceSequence'],\n    '0632': ['SQ', '1', 'ReferencedRTPatientSetupSequence'],\n    '0634': ['FD', '1', 'SourceToPatientSurfaceDistance'],\n    '0635': ['SQ', '1', 'TreatmentMachineSpecialModeCodeSequence'],\n    '0636': ['US', '1', 'IntendedNumberOfFractions'],\n    '0637': ['CS', '1', 'RTRadiationSetIntent'],\n    '0638': ['CS', '1', 'RTRadiationPhysicalAndGeometricContentDetailFlag'],\n    '0639': ['CS', '1', 'RTRecordFlag'],\n    '063A': ['SQ', '1', 'TreatmentDeviceIdentificationSequence'],\n    '063B': ['SQ', '1', 'ReferencedRTPhysicianIntentSequence'],\n    '063C': ['FD', '1', 'CumulativeMeterset'],\n    '063D': ['FD', '1', 'DeliveryRate'],\n    '063E': ['SQ', '1', 'DeliveryRateUnitSequence'],\n    '063F': ['SQ', '1', 'TreatmentPositionSequence'],\n    '0640': ['FD', '1', 'RadiationSourceAxisDistance'],\n    '0641': ['US', '1', 'NumberOfRTBeamLimitingDevices'],\n    '0642': ['FD', '1', 'RTBeamLimitingDeviceProximalDistance'],\n    '0643': ['FD', '1', 'RTBeamLimitingDeviceDistalDistance'],\n    '0644': ['SQ', '1', 'ParallelRTBeamDelimiterDeviceOrientationLabelCodeSequence'],\n    '0645': ['FD', '1', 'BeamModifierOrientationAngle'],\n    '0646': ['SQ', '1', 'FixedRTBeamDelimiterDeviceSequence'],\n    '0647': ['SQ', '1', 'ParallelRTBeamDelimiterDeviceSequence'],\n    '0648': ['US', '1', 'NumberOfParallelRTBeamDelimiters'],\n    '0649': ['FD', '2-n', 'ParallelRTBeamDelimiterBoundaries'],\n    '064A': ['FD', '2-n', 'ParallelRTBeamDelimiterPositions'],\n    '064B': ['FD', '2', 'RTBeamLimitingDeviceOffset'],\n    '064C': ['SQ', '1', 'RTBeamDelimiterGeometrySequence'],\n    '064D': ['SQ', '1', 'RTBeamLimitingDeviceDefinitionSequence'],\n    '064E': ['CS', '1', 'ParallelRTBeamDelimiterOpeningMode'],\n    '064F': ['CS', '1-n', 'ParallelRTBeamDelimiterLeafMountingSide'],\n    '0650': ['UI', '1', 'PatientSetupUID'],\n    '0651': ['SQ', '1', 'WedgeDefinitionSequence'],\n    '0652': ['FD', '1', 'RadiationBeamWedgeAngle'],\n    '0653': ['FD', '1', 'RadiationBeamWedgeThinEdgeDistance'],\n    '0654': ['FD', '1', 'RadiationBeamEffectiveWedgeAngle'],\n    '0655': ['US', '1', 'NumberOfWedgePositions'],\n    '0656': ['SQ', '1', 'RTBeamLimitingDeviceOpeningSequence'],\n    '0657': ['US', '1', 'NumberOfRTBeamLimitingDeviceOpenings'],\n    '0658': ['SQ', '1', 'RadiationDosimeterUnitSequence'],\n    '0659': ['SQ', '1', 'RTDeviceDistanceReferenceLocationCodeSequence'],\n    '065A': ['SQ', '1', 'RadiationDeviceConfigurationAndCommissioningKeySequence'],\n    '065B': ['SQ', '1', 'PatientSupportPositionParameterSequence'],\n    '065C': ['CS', '1', 'PatientSupportPositionSpecificationMethod'],\n    '065D': ['SQ', '1', 'PatientSupportPositionDeviceParameterSequence'],\n    '065E': ['US', '1', 'DeviceOrderIndex'],\n    '065F': ['US', '1', 'PatientSupportPositionParameterOrderIndex'],\n    '0660': ['SQ', '1', 'PatientSupportPositionDeviceToleranceSequence'],\n    '0661': ['US', '1', 'PatientSupportPositionToleranceOrderIndex'],\n    '0662': ['SQ', '1', 'CompensatorDefinitionSequence'],\n    '0663': ['CS', '1', 'CompensatorMapOrientation'],\n    '0664': ['OF', '1', 'CompensatorProximalThicknessMap'],\n    '0665': ['OF', '1', 'CompensatorDistalThicknessMap'],\n    '0666': ['FD', '1', 'CompensatorBasePlaneOffset'],\n    '0667': ['SQ', '1', 'CompensatorShapeFabricationCodeSequence'],\n    '0668': ['SQ', '1', 'CompensatorShapeSequence'],\n    '0669': ['FD', '1', 'RadiationBeamCompensatorMillingToolDiameter'],\n    '066A': ['SQ', '1', 'BlockDefinitionSequence'],\n    '066B': ['OF', '1', 'BlockEdgeData'],\n    '066C': ['CS', '1', 'BlockOrientation'],\n    '066D': ['FD', '1', 'RadiationBeamBlockThickness'],\n    '066E': ['FD', '1', 'RadiationBeamBlockSlabThickness'],\n    '066F': ['SQ', '1', 'BlockEdgeDataSequence'],\n    '0670': ['US', '1', 'NumberOfRTAccessoryHolders'],\n    '0671': ['SQ', '1', 'GeneralAccessoryDefinitionSequence'],\n    '0672': ['US', '1', 'NumberOfGeneralAccessories'],\n    '0673': ['SQ', '1', 'BolusDefinitionSequence'],\n    '0674': ['US', '1', 'NumberOfBoluses'],\n    '0675': ['UI', '1', 'EquipmentFrameOfReferenceUID'],\n    '0676': ['ST', '1', 'EquipmentFrameOfReferenceDescription'],\n    '0677': ['SQ', '1', 'EquipmentReferencePointCoordinatesSequence'],\n    '0678': ['SQ', '1', 'EquipmentReferencePointCodeSequence'],\n    '0679': ['FD', '1', 'RTBeamLimitingDeviceAngle'],\n    '067A': ['FD', '1', 'SourceRollAngle'],\n    '067B': ['SQ', '1', 'RadiationGenerationModeSequence'],\n    '067C': ['SH', '1', 'RadiationGenerationModeLabel'],\n    '067D': ['ST', '1', 'RadiationGenerationModeDescription'],\n    '067E': ['SQ', '1', 'RadiationGenerationModeMachineCodeSequence'],\n    '067F': ['SQ', '1', 'RadiationTypeCodeSequence'],\n    '0680': ['DS', '1', 'NominalEnergy'],\n    '0681': ['DS', '1', 'MinimumNominalEnergy'],\n    '0682': ['DS', '1', 'MaximumNominalEnergy'],\n    '0683': ['SQ', '1', 'RadiationFluenceModifierCodeSequence'],\n    '0684': ['SQ', '1', 'EnergyUnitCodeSequence'],\n    '0685': ['US', '1', 'NumberOfRadiationGenerationModes'],\n    '0686': ['SQ', '1', 'PatientSupportDevicesSequence'],\n    '0687': ['US', '1', 'NumberOfPatientSupportDevices'],\n    '0688': ['FD', '1', 'RTBeamModifierDefinitionDistance'],\n    '0689': ['SQ', '1', 'BeamAreaLimitSequence'],\n    '068A': ['SQ', '1', 'ReferencedRTPrescriptionSequence'],\n    '0700': ['UI', '1', 'TreatmentSessionUID'],\n    '0701': ['CS', '1', 'RTRadiationUsage'],\n    '0702': ['SQ', '1', 'ReferencedRTRadiationSetSequence'],\n    '0703': ['SQ', '1', 'ReferencedRTRadiationRecordSequence'],\n    '0704': ['US', '1', 'RTRadiationSetDeliveryNumber'],\n    '0705': ['US', '1', 'ClinicalFractionNumber'],\n    '0706': ['CS', '1', 'RTTreatmentFractionCompletionStatus'],\n    '0707': ['CS', '1', 'RTRadiationSetUsage'],\n    '0708': ['CS', '1', 'TreatmentDeliveryContinuationFlag'],\n    '0709': ['CS', '1', 'TreatmentRecordContentOrigin'],\n    '0714': ['CS', '1', 'RTTreatmentTerminationStatus'],\n    '0715': ['SQ', '1', 'RTTreatmentTerminationReasonCodeSequence'],\n    '0716': ['SQ', '1', 'MachineSpecificTreatmentTerminationCodeSequence'],\n    '0722': ['SQ', '1', 'RTRadiationSalvageRecordControlPointSequence'],\n    '0723': ['CS', '1', 'StartingMetersetValueKnownFlag'],\n    '0730': ['ST', '1', 'TreatmentTerminationDescription'],\n    '0731': ['SQ', '1', 'TreatmentToleranceViolationSequence'],\n    '0732': ['CS', '1', 'TreatmentToleranceViolationCategory'],\n    '0733': ['SQ', '1', 'TreatmentToleranceViolationAttributeSequence'],\n    '0734': ['ST', '1', 'TreatmentToleranceViolationDescription'],\n    '0735': ['ST', '1', 'TreatmentToleranceViolationIdentification'],\n    '0736': ['DT', '1', 'TreatmentToleranceViolationDateTime'],\n    '073A': ['DT', '1', 'RecordedRTControlPointDateTime'],\n    '073B': ['US', '1', 'ReferencedRadiationRTControlPointIndex'],\n    '073E': ['SQ', '1', 'AlternateValueSequence'],\n    '073F': ['SQ', '1', 'ConfirmationSequence'],\n    '0740': ['SQ', '1', 'InterlockSequence'],\n    '0741': ['DT', '1', 'InterlockDateTime'],\n    '0742': ['ST', '1', 'InterlockDescription'],\n    '0743': ['SQ', '1', 'InterlockOriginatingDeviceSequence'],\n    '0744': ['SQ', '1', 'InterlockCodeSequence'],\n    '0745': ['SQ', '1', 'InterlockResolutionCodeSequence'],\n    '0746': ['SQ', '1', 'InterlockResolutionUserSequence'],\n    '0760': ['DT', '1', 'OverrideDateTime'],\n    '0761': ['SQ', '1', 'TreatmentToleranceViolationTypeCodeSequence'],\n    '0762': ['SQ', '1', 'TreatmentToleranceViolationCauseCodeSequence'],\n    '0772': ['SQ', '1', 'MeasuredMetersetToDoseMappingSequence'],\n    '0773': ['US', '1', 'ReferencedExpectedInVivoMeasurementValueIndex'],\n    '0774': ['SQ', '1', 'DoseMeasurementDeviceCodeSequence'],\n    '0780': ['SQ', '1', 'AdditionalParameterRecordingInstanceSequence'],\n    '0782': ['US', '1', ''],\n    '0783': ['ST', '1', 'InterlockOriginDescription'],\n    '0784': ['SQ', '1', 'RTPatientPositionScopeSequence'],\n    '0785': ['UI', '1', 'ReferencedTreatmentPositionGroupUID'],\n    '0786': ['US', '1', 'RadiationOrderIndex'],\n    '0787': ['SQ', '1', 'OmittedRadiationSequence'],\n    '0788': ['SQ', '1', 'ReasonForOmissionCodeSequence'],\n    '0789': ['SQ', '1', 'RTDeliveryStartPatientPositionSequence'],\n    '078A': ['SQ', '1', 'RTTreatmentPreparationPatientPositionSequence'],\n    '078B': ['SQ', '1', 'ReferencedRTTreatmentPreparationSequence'],\n    '078C': ['SQ', '1', 'ReferencedPatientSetupPhotoSequence'],\n    '078D': ['SQ', '1', 'PatientTreatmentPreparationMethodCodeSequence'],\n    '078E': ['LT', '1', 'PatientTreatmentPreparationProcedureParameterDescription'],\n    '078F': ['SQ', '1', 'PatientTreatmentPreparationDeviceSequence'],\n    '0790': ['SQ', '1', 'PatientTreatmentPreparationProcedureSequence'],\n    '0791': ['SQ', '1', 'PatientTreatmentPreparationProcedureCodeSequence'],\n    '0792': ['LT', '1', 'PatientTreatmentPreparationMethodDescription'],\n    '0793': ['SQ', '1', 'PatientTreatmentPreparationProcedureParameterSequence'],\n    '0794': ['LT', '1', 'PatientSetupPhotoDescription'],\n    '0795': ['US', '1', 'PatientTreatmentPreparationProcedureIndex'],\n    '0796': ['US', '1', 'ReferencedPatientSetupProcedureIndex'],\n    '0797': ['SQ', '1', 'RTRadiationTaskSequence'],\n    '0798': ['SQ', '1', 'RTPatientPositionDisplacementSequence'],\n    '0799': ['SQ', '1', 'RTPatientPositionSequence'],\n    '079A': ['LO', '1', 'DisplacementReferenceLabel'],\n    '079B': ['FD', '16', 'DisplacementMatrix'],\n    '079C': ['SQ', '1', 'PatientSupportDisplacementSequence'],\n    '079D': ['SQ', '1', 'DisplacementReferenceLocationCodeSequence'],\n    '079E': ['CS', '1', 'RTRadiationSetDeliveryUsage']\n  },\n  '300C': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SQ', '1', 'ReferencedRTPlanSequence'],\n    '0004': ['SQ', '1', 'ReferencedBeamSequence'],\n    '0006': ['IS', '1', 'ReferencedBeamNumber'],\n    '0007': ['IS', '1', 'ReferencedReferenceImageNumber'],\n    '0008': ['DS', '1', 'StartCumulativeMetersetWeight'],\n    '0009': ['DS', '1', 'EndCumulativeMetersetWeight'],\n    '000A': ['SQ', '1', 'ReferencedBrachyApplicationSetupSequence'],\n    '000C': ['IS', '1', 'ReferencedBrachyApplicationSetupNumber'],\n    '000E': ['IS', '1', 'ReferencedSourceNumber'],\n    '0020': ['SQ', '1', 'ReferencedFractionGroupSequence'],\n    '0022': ['IS', '1', 'ReferencedFractionGroupNumber'],\n    '0040': ['SQ', '1', 'ReferencedVerificationImageSequence'],\n    '0042': ['SQ', '1', 'ReferencedReferenceImageSequence'],\n    '0050': ['SQ', '1', 'ReferencedDoseReferenceSequence'],\n    '0051': ['IS', '1', 'ReferencedDoseReferenceNumber'],\n    '0055': ['SQ', '1', 'BrachyReferencedDoseReferenceSequence'],\n    '0060': ['SQ', '1', 'ReferencedStructureSetSequence'],\n    '006A': ['IS', '1', 'ReferencedPatientSetupNumber'],\n    '0080': ['SQ', '1', 'ReferencedDoseSequence'],\n    '00A0': ['IS', '1', 'ReferencedToleranceTableNumber'],\n    '00B0': ['SQ', '1', 'ReferencedBolusSequence'],\n    '00C0': ['IS', '1', 'ReferencedWedgeNumber'],\n    '00D0': ['IS', '1', 'ReferencedCompensatorNumber'],\n    '00E0': ['IS', '1', 'ReferencedBlockNumber'],\n    '00F0': ['IS', '1', 'ReferencedControlPointIndex'],\n    '00F2': ['SQ', '1', 'ReferencedControlPointSequence'],\n    '00F4': ['IS', '1', 'ReferencedStartControlPointIndex'],\n    '00F6': ['IS', '1', 'ReferencedStopControlPointIndex'],\n    '0100': ['IS', '1', 'ReferencedRangeShifterNumber'],\n    '0102': ['IS', '1', 'ReferencedLateralSpreadingDeviceNumber'],\n    '0104': ['IS', '1', 'ReferencedRangeModulatorNumber'],\n    '0111': ['SQ', '1', 'OmittedBeamTaskSequence'],\n    '0112': ['CS', '1', 'ReasonForOmission'],\n    '0113': ['LO', '1', 'ReasonForOmissionDescription'],\n    '0114': ['SQ', '1', 'PrescriptionOverviewSequence'],\n    '0115': ['FL', '1', 'TotalPrescriptionDose'],\n    '0116': ['SQ', '1', 'PlanOverviewSequence'],\n    '0117': ['US', '1', 'PlanOverviewIndex'],\n    '0118': ['US', '1', 'ReferencedPlanOverviewIndex'],\n    '0119': ['US', '1', 'NumberOfFractionsIncluded'],\n    '0120': ['SQ', '1', 'DoseCalibrationConditionsSequence'],\n    '0121': ['FD', '1', 'AbsorbedDoseToMetersetRatio'],\n    '0122': ['FD', '2', 'DelineatedRadiationFieldSize'],\n    '0123': ['CS', '1', 'DoseCalibrationConditionsVerifiedFlag'],\n    '0124': ['FD', '1', 'CalibrationReferencePointDepth'],\n    '0125': ['SQ', '1', 'GatingBeamHoldTransitionSequence'],\n    '0126': ['CS', '1', 'BeamHoldTransition'],\n    '0127': ['DT', '1', 'BeamHoldTransitionDateTime'],\n    '0128': ['SQ', '1', 'BeamHoldOriginatingDeviceSequence']\n  },\n  '300E': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['CS', '1', 'ApprovalStatus'],\n    '0004': ['DA', '1', 'ReviewDate'],\n    '0005': ['TM', '1', 'ReviewTime'],\n    '0008': ['PN', '1', 'ReviewerName']\n  },\n  '3010': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['SQ', '1', 'RadiobiologicalDoseEffectSequence'],\n    '0002': ['CS', '1', 'RadiobiologicalDoseEffectFlag'],\n    '0003': ['SQ', '1', 'EffectiveDoseCalculationMethodCategoryCodeSequence'],\n    '0004': ['SQ', '1', 'EffectiveDoseCalculationMethodCodeSequence'],\n    '0005': ['LO', '1', 'EffectiveDoseCalculationMethodDescription'],\n    '0006': ['UI', '1', 'ConceptualVolumeUID'],\n    '0007': ['SQ', '1', 'OriginatingSOPInstanceReferenceSequence'],\n    '0008': ['SQ', '1', 'ConceptualVolumeConstituentSequence'],\n    '0009': ['SQ', '1', 'EquivalentConceptualVolumeInstanceReferenceSequence'],\n    '000A': ['SQ', '1', 'EquivalentConceptualVolumesSequence'],\n    '000B': ['UI', '1', 'ReferencedConceptualVolumeUID'],\n    '000C': ['UT', '1', 'ConceptualVolumeCombinationExpression'],\n    '000D': ['US', '1', 'ConceptualVolumeConstituentIndex'],\n    '000E': ['CS', '1', 'ConceptualVolumeCombinationFlag'],\n    '000F': ['ST', '1', 'ConceptualVolumeCombinationDescription'],\n    '0010': ['CS', '1', 'ConceptualVolumeSegmentationDefinedFlag'],\n    '0011': ['SQ', '1', 'ConceptualVolumeSegmentationReferenceSequence'],\n    '0012': ['SQ', '1', 'ConceptualVolumeConstituentSegmentationReferenceSequence'],\n    '0013': ['UI', '1', 'ConstituentConceptualVolumeUID'],\n    '0014': ['SQ', '1', 'DerivationConceptualVolumeSequence'],\n    '0015': ['UI', '1', 'SourceConceptualVolumeUID'],\n    '0016': ['SQ', '1', 'ConceptualVolumeDerivationAlgorithmSequence'],\n    '0017': ['ST', '1', 'ConceptualVolumeDescription'],\n    '0018': ['SQ', '1', 'SourceConceptualVolumeSequence'],\n    '0019': ['SQ', '1', 'AuthorIdentificationSequence'],\n    '001A': ['LO', '1', 'ManufacturerModelVersion'],\n    '001B': ['UC', '1', 'DeviceAlternateIdentifier'],\n    '001C': ['CS', '1', 'DeviceAlternateIdentifierType'],\n    '001D': ['LT', '1', 'DeviceAlternateIdentifierFormat'],\n    '001E': ['LO', '1', 'SegmentationCreationTemplateLabel'],\n    '001F': ['UI', '1', 'SegmentationTemplateUID'],\n    '0020': ['US', '1', 'ReferencedSegmentReferenceIndex'],\n    '0021': ['SQ', '1', 'SegmentReferenceSequence'],\n    '0022': ['US', '1', 'SegmentReferenceIndex'],\n    '0023': ['SQ', '1', 'DirectSegmentReferenceSequence'],\n    '0024': ['SQ', '1', 'CombinationSegmentReferenceSequence'],\n    '0025': ['SQ', '1', 'ConceptualVolumeSequence'],\n    '0026': ['SQ', '1', 'SegmentedRTAccessoryDeviceSequence'],\n    '0027': ['SQ', '1', 'SegmentCharacteristicsSequence'],\n    '0028': ['SQ', '1', 'RelatedSegmentCharacteristicsSequence'],\n    '0029': ['US', '1', 'SegmentCharacteristicsPrecedence'],\n    '002A': ['SQ', '1', 'RTSegmentAnnotationSequence'],\n    '002B': ['SQ', '1', 'SegmentAnnotationCategoryCodeSequence'],\n    '002C': ['SQ', '1', 'SegmentAnnotationTypeCodeSequence'],\n    '002D': ['LO', '1', 'DeviceLabel'],\n    '002E': ['SQ', '1', 'DeviceTypeCodeSequence'],\n    '002F': ['SQ', '1', 'SegmentAnnotationTypeModifierCodeSequence'],\n    '0030': ['SQ', '1', 'PatientEquipmentRelationshipCodeSequence'],\n    '0031': ['UI', '1', 'ReferencedFiducialsUID'],\n    '0032': ['SQ', '1', 'PatientTreatmentOrientationSequence'],\n    '0033': ['SH', '1', 'UserContentLabel'],\n    '0034': ['LO', '1', 'UserContentLongLabel'],\n    '0035': ['SH', '1', 'EntityLabel'],\n    '0036': ['LO', '1', 'EntityName'],\n    '0037': ['ST', '1', 'EntityDescription'],\n    '0038': ['LO', '1', 'EntityLongLabel'],\n    '0039': ['US', '1', 'DeviceIndex'],\n    '003A': ['US', '1', 'RTTreatmentPhaseIndex'],\n    '003B': ['UI', '1', 'RTTreatmentPhaseUID'],\n    '003C': ['US', '1', 'RTPrescriptionIndex'],\n    '003D': ['US', '1', 'RTSegmentAnnotationIndex'],\n    '003E': ['US', '1', 'BasisRTTreatmentPhaseIndex'],\n    '003F': ['US', '1', 'RelatedRTTreatmentPhaseIndex'],\n    '0040': ['US', '1', 'ReferencedRTTreatmentPhaseIndex'],\n    '0041': ['US', '1', 'ReferencedRTPrescriptionIndex'],\n    '0042': ['US', '1', 'ReferencedParentRTPrescriptionIndex'],\n    '0043': ['ST', '1', 'ManufacturerDeviceIdentifier'],\n    '0044': ['SQ', '1', 'InstanceLevelReferencedPerformedProcedureStepSequence'],\n    '0045': ['CS', '1', 'RTTreatmentPhaseIntentPresenceFlag'],\n    '0046': ['CS', '1', 'RadiotherapyTreatmentType'],\n    '0047': ['CS', '1-n', 'TeletherapyRadiationType'],\n    '0048': ['CS', '1-n', 'BrachytherapySourceType'],\n    '0049': ['SQ', '1', 'ReferencedRTTreatmentPhaseSequence'],\n    '004A': ['SQ', '1', 'ReferencedDirectSegmentInstanceSequence'],\n    '004B': ['SQ', '1', 'IntendedRTTreatmentPhaseSequence'],\n    '004C': ['DA', '1', 'IntendedPhaseStartDate'],\n    '004D': ['DA', '1', 'IntendedPhaseEndDate'],\n    '004E': ['SQ', '1', 'RTTreatmentPhaseIntervalSequence'],\n    '004F': ['CS', '1', 'TemporalRelationshipIntervalAnchor'],\n    '0050': ['FD', '1', 'MinimumNumberOfIntervalDays'],\n    '0051': ['FD', '1', 'MaximumNumberOfIntervalDays'],\n    '0052': ['UI', '1-n', 'PertinentSOPClassesInStudy'],\n    '0053': ['UI', '1-n', 'PertinentSOPClassesInSeries'],\n    '0054': ['LO', '1', 'RTPrescriptionLabel'],\n    '0055': ['SQ', '1', 'RTPhysicianIntentPredecessorSequence'],\n    '0056': ['LO', '1', 'RTTreatmentApproachLabel'],\n    '0057': ['SQ', '1', 'RTPhysicianIntentSequence'],\n    '0058': ['US', '1', 'RTPhysicianIntentIndex'],\n    '0059': ['CS', '1', 'RTTreatmentIntentType'],\n    '005A': ['UT', '1', 'RTPhysicianIntentNarrative'],\n    '005B': ['SQ', '1', 'RTProtocolCodeSequence'],\n    '005C': ['ST', '1', 'ReasonForSuperseding'],\n    '005D': ['SQ', '1', 'RTDiagnosisCodeSequence'],\n    '005E': ['US', '1', 'ReferencedRTPhysicianIntentIndex'],\n    '005F': ['SQ', '1', 'RTPhysicianIntentInputInstanceSequence'],\n    '0060': ['SQ', '1', 'RTAnatomicPrescriptionSequence'],\n    '0061': ['UT', '1', 'PriorTreatmentDoseDescription'],\n    '0062': ['SQ', '1', 'PriorTreatmentReferenceSequence'],\n    '0063': ['CS', '1', 'DosimetricObjectiveEvaluationScope'],\n    '0064': ['SQ', '1', 'TherapeuticRoleCategoryCodeSequence'],\n    '0065': ['SQ', '1', 'TherapeuticRoleTypeCodeSequence'],\n    '0066': ['US', '1', 'ConceptualVolumeOptimizationPrecedence'],\n    '0067': ['SQ', '1', 'ConceptualVolumeCategoryCodeSequence'],\n    '0068': ['CS', '1', 'ConceptualVolumeBlockingConstraint'],\n    '0069': ['SQ', '1', 'ConceptualVolumeTypeCodeSequence'],\n    '006A': ['SQ', '1', 'ConceptualVolumeTypeModifierCodeSequence'],\n    '006B': ['SQ', '1', 'RTPrescriptionSequence'],\n    '006C': ['SQ', '1', 'DosimetricObjectiveSequence'],\n    '006D': ['SQ', '1', 'DosimetricObjectiveTypeCodeSequence'],\n    '006E': ['UI', '1', 'DosimetricObjectiveUID'],\n    '006F': ['UI', '1', 'ReferencedDosimetricObjectiveUID'],\n    '0070': ['SQ', '1', 'DosimetricObjectiveParameterSequence'],\n    '0071': ['SQ', '1', 'ReferencedDosimetricObjectivesSequence'],\n    '0073': ['CS', '1', 'AbsoluteDosimetricObjectiveFlag'],\n    '0074': ['FD', '1', 'DosimetricObjectiveWeight'],\n    '0075': ['CS', '1', 'DosimetricObjectivePurpose'],\n    '0076': ['SQ', '1', 'PlanningInputInformationSequence'],\n    '0077': ['LO', '1', 'TreatmentSite'],\n    '0078': ['SQ', '1', 'TreatmentSiteCodeSequence'],\n    '0079': ['SQ', '1', 'FractionPatternSequence'],\n    '007A': ['UT', '1', 'TreatmentTechniqueNotes'],\n    '007B': ['UT', '1', 'PrescriptionNotes'],\n    '007C': ['IS', '1', 'NumberOfIntervalFractions'],\n    '007D': ['US', '1', 'NumberOfFractions'],\n    '007E': ['US', '1', 'IntendedDeliveryDuration'],\n    '007F': ['UT', '1', 'FractionationNotes'],\n    '0080': ['SQ', '1', 'RTTreatmentTechniqueCodeSequence'],\n    '0081': ['SQ', '1', 'PrescriptionNotesSequence'],\n    '0082': ['SQ', '1', 'FractionBasedRelationshipSequence'],\n    '0083': ['CS', '1', 'FractionBasedRelationshipIntervalAnchor'],\n    '0084': ['FD', '1', 'MinimumHoursBetweenFractions'],\n    '0085': ['TM', '1-n', 'IntendedFractionStartTime'],\n    '0086': ['LT', '1', 'IntendedStartDayOfWeek'],\n    '0087': ['SQ', '1', 'WeekdayFractionPatternSequence'],\n    '0088': ['SQ', '1', 'DeliveryTimeStructureCodeSequence'],\n    '0089': ['SQ', '1', 'TreatmentSiteModifierCodeSequence'],\n    '0090': ['CS', '1', 'RoboticBaseLocationIndicator'],\n    '0091': ['SQ', '1', 'RoboticPathNodeSetCodeSequence'],\n    '0092': ['UL', '1', 'RoboticNodeIdentifier'],\n    '0093': ['FD', '3', 'RTTreatmentSourceCoordinates'],\n    '0094': ['FD', '1', 'RadiationSourceCoordinateSystemYawAngle'],\n    '0095': ['FD', '1', 'RadiationSourceCoordinateSystemRollAngle'],\n    '0096': ['FD', '1', 'RadiationSourceCoordinateSystemPitchAngle'],\n    '0097': ['SQ', '1', 'RoboticPathControlPointSequence'],\n    '0098': ['SQ', '1', 'TomotherapeuticControlPointSequence'],\n    '0099': ['FD', '1-n', 'TomotherapeuticLeafOpenDurations'],\n    '009A': ['FD', '1-n', 'TomotherapeuticLeafInitialClosedDurations']\n  },\n  '4000': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['LT', '1', 'Arbitrary'],\n    '4000': ['LT', '1', 'TextComments']\n  },\n  '4008': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0040': ['SH', '1', 'ResultsID'],\n    '0042': ['LO', '1', 'ResultsIDIssuer'],\n    '0050': ['SQ', '1', 'ReferencedInterpretationSequence'],\n    '00FF': ['CS', '1', 'ReportProductionStatusTrial'],\n    '0100': ['DA', '1', 'InterpretationRecordedDate'],\n    '0101': ['TM', '1', 'InterpretationRecordedTime'],\n    '0102': ['PN', '1', 'InterpretationRecorder'],\n    '0103': ['LO', '1', 'ReferenceToRecordedSound'],\n    '0108': ['DA', '1', 'InterpretationTranscriptionDate'],\n    '0109': ['TM', '1', 'InterpretationTranscriptionTime'],\n    '010A': ['PN', '1', 'InterpretationTranscriber'],\n    '010B': ['ST', '1', 'InterpretationText'],\n    '010C': ['PN', '1', 'InterpretationAuthor'],\n    '0111': ['SQ', '1', 'InterpretationApproverSequence'],\n    '0112': ['DA', '1', 'InterpretationApprovalDate'],\n    '0113': ['TM', '1', 'InterpretationApprovalTime'],\n    '0114': ['PN', '1', 'PhysicianApprovingInterpretation'],\n    '0115': ['LT', '1', 'InterpretationDiagnosisDescription'],\n    '0117': ['SQ', '1', 'InterpretationDiagnosisCodeSequence'],\n    '0118': ['SQ', '1', 'ResultsDistributionListSequence'],\n    '0119': ['PN', '1', 'DistributionName'],\n    '011A': ['LO', '1', 'DistributionAddress'],\n    '0200': ['SH', '1', 'InterpretationID'],\n    '0202': ['LO', '1', 'InterpretationIDIssuer'],\n    '0210': ['CS', '1', 'InterpretationTypeID'],\n    '0212': ['CS', '1', 'InterpretationStatusID'],\n    '0300': ['ST', '1', 'Impressions'],\n    '4000': ['ST', '1', 'ResultsComments']\n  },\n  '4010': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'LowEnergyDetectors'],\n    '0002': ['CS', '1', 'HighEnergyDetectors'],\n    '0004': ['SQ', '1', 'DetectorGeometrySequence'],\n    '1001': ['SQ', '1', 'ThreatROIVoxelSequence'],\n    '1004': ['FL', '3', 'ThreatROIBase'],\n    '1005': ['FL', '3', 'ThreatROIExtents'],\n    '1006': ['OB', '1', 'ThreatROIBitmap'],\n    '1007': ['SH', '1', 'RouteSegmentID'],\n    '1008': ['CS', '1', 'GantryType'],\n    '1009': ['CS', '1', 'OOIOwnerType'],\n    '100A': ['SQ', '1', 'RouteSegmentSequence'],\n    '1010': ['US', '1', 'PotentialThreatObjectID'],\n    '1011': ['SQ', '1', 'ThreatSequence'],\n    '1012': ['CS', '1', 'ThreatCategory'],\n    '1013': ['LT', '1', 'ThreatCategoryDescription'],\n    '1014': ['CS', '1', 'ATDAbilityAssessment'],\n    '1015': ['CS', '1', 'ATDAssessmentFlag'],\n    '1016': ['FL', '1', 'ATDAssessmentProbability'],\n    '1017': ['FL', '1', 'Mass'],\n    '1018': ['FL', '1', 'Density'],\n    '1019': ['FL', '1', 'ZEffective'],\n    '101A': ['SH', '1', 'BoardingPassID'],\n    '101B': ['FL', '3', 'CenterOfMass'],\n    '101C': ['FL', '3', 'CenterOfPTO'],\n    '101D': ['FL', '6-n', 'BoundingPolygon'],\n    '101E': ['SH', '1', 'RouteSegmentStartLocationID'],\n    '101F': ['SH', '1', 'RouteSegmentEndLocationID'],\n    '1020': ['CS', '1', 'RouteSegmentLocationIDType'],\n    '1021': ['CS', '1-n', 'AbortReason'],\n    '1023': ['FL', '1', 'VolumeOfPTO'],\n    '1024': ['CS', '1', 'AbortFlag'],\n    '1025': ['DT', '1', 'RouteSegmentStartTime'],\n    '1026': ['DT', '1', 'RouteSegmentEndTime'],\n    '1027': ['CS', '1', 'TDRType'],\n    '1028': ['CS', '1', 'InternationalRouteSegment'],\n    '1029': ['LO', '1-n', 'ThreatDetectionAlgorithmAndVersion'],\n    '102A': ['SH', '1', 'AssignedLocation'],\n    '102B': ['DT', '1', 'AlarmDecisionTime'],\n    '1031': ['CS', '1', 'AlarmDecision'],\n    '1033': ['US', '1', 'NumberOfTotalObjects'],\n    '1034': ['US', '1', 'NumberOfAlarmObjects'],\n    '1037': ['SQ', '1', 'PTORepresentationSequence'],\n    '1038': ['SQ', '1', 'ATDAssessmentSequence'],\n    '1039': ['CS', '1', 'TIPType'],\n    '103A': ['CS', '1', 'DICOSVersion'],\n    '1041': ['DT', '1', 'OOIOwnerCreationTime'],\n    '1042': ['CS', '1', 'OOIType'],\n    '1043': ['FL', '3', 'OOISize'],\n    '1044': ['CS', '1', 'AcquisitionStatus'],\n    '1045': ['SQ', '1', 'BasisMaterialsCodeSequence'],\n    '1046': ['CS', '1', 'PhantomType'],\n    '1047': ['SQ', '1', 'OOIOwnerSequence'],\n    '1048': ['CS', '1', 'ScanType'],\n    '1051': ['LO', '1', 'ItineraryID'],\n    '1052': ['SH', '1', 'ItineraryIDType'],\n    '1053': ['LO', '1', 'ItineraryIDAssigningAuthority'],\n    '1054': ['SH', '1', 'RouteID'],\n    '1055': ['SH', '1', 'RouteIDAssigningAuthority'],\n    '1056': ['CS', '1', 'InboundArrivalType'],\n    '1058': ['SH', '1', 'CarrierID'],\n    '1059': ['CS', '1', 'CarrierIDAssigningAuthority'],\n    '1060': ['FL', '3', 'SourceOrientation'],\n    '1061': ['FL', '3', 'SourcePosition'],\n    '1062': ['FL', '1', 'BeltHeight'],\n    '1064': ['SQ', '1', 'AlgorithmRoutingCodeSequence'],\n    '1067': ['CS', '1', 'TransportClassification'],\n    '1068': ['LT', '1', 'OOITypeDescriptor'],\n    '1069': ['FL', '1', 'TotalProcessingTime'],\n    '106C': ['OB', '1', 'DetectorCalibrationData'],\n    '106D': ['CS', '1', 'AdditionalScreeningPerformed'],\n    '106E': ['CS', '1', 'AdditionalInspectionSelectionCriteria'],\n    '106F': ['SQ', '1', 'AdditionalInspectionMethodSequence'],\n    '1070': ['CS', '1', 'AITDeviceType'],\n    '1071': ['SQ', '1', 'QRMeasurementsSequence'],\n    '1072': ['SQ', '1', 'TargetMaterialSequence'],\n    '1073': ['FD', '1', 'SNRThreshold'],\n    '1075': ['DS', '1', 'ImageScaleRepresentation'],\n    '1076': ['SQ', '1', 'ReferencedPTOSequence'],\n    '1077': ['SQ', '1', 'ReferencedTDRInstanceSequence'],\n    '1078': ['ST', '1', 'PTOLocationDescription'],\n    '1079': ['SQ', '1', 'AnomalyLocatorIndicatorSequence'],\n    '107A': ['FL', '3', 'AnomalyLocatorIndicator'],\n    '107B': ['SQ', '1', 'PTORegionSequence'],\n    '107C': ['CS', '1', 'InspectionSelectionCriteria'],\n    '107D': ['SQ', '1', 'SecondaryInspectionMethodSequence'],\n    '107E': ['DS', '6', 'PRCSToRCSOrientation']\n  },\n  '4FFE': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['SQ', '1', 'MACParametersSequence']\n  },\n  '5000': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0005': ['US', '1', 'CurveDimensions'],\n    '0010': ['US', '1', 'NumberOfPoints'],\n    '0020': ['CS', '1', 'TypeOfData'],\n    '0022': ['LO', '1', 'CurveDescription'],\n    '0030': ['SH', '1-n', 'AxisUnits'],\n    '0040': ['SH', '1-n', 'AxisLabels'],\n    '0103': ['US', '1', 'DataValueRepresentation'],\n    '0104': ['US', '1-n', 'MinimumCoordinateValue'],\n    '0105': ['US', '1-n', 'MaximumCoordinateValue'],\n    '0106': ['SH', '1-n', 'CurveRange'],\n    '0110': ['US', '1-n', 'CurveDataDescriptor'],\n    '0112': ['US', '1-n', 'CoordinateStartValue'],\n    '0114': ['US', '1-n', 'CoordinateStepValue'],\n    '1001': ['CS', '1', 'CurveActivationLayer'],\n    '2000': ['US', '1', 'AudioType'],\n    '2002': ['US', '1', 'AudioSampleFormat'],\n    '2004': ['US', '1', 'NumberOfChannels'],\n    '2006': ['UL', '1', 'NumberOfSamples'],\n    '2008': ['UL', '1', 'SampleRate'],\n    '200A': ['UL', '1', 'TotalTime'],\n    '200C': ['ox', '1', 'AudioSampleData'],\n    '200E': ['LT', '1', 'AudioComments'],\n    '2500': ['LO', '1', 'CurveLabel'],\n    '2600': ['SQ', '1', 'CurveReferencedOverlaySequence'],\n    '2610': ['US', '1', 'CurveReferencedOverlayGroup'],\n    '3000': ['ox', '1', 'CurveData']\n  },\n  '5200': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '9229': ['SQ', '1', 'SharedFunctionalGroupsSequence'],\n    '9230': ['SQ', '1', 'PerFrameFunctionalGroupsSequence']\n  },\n  '5400': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0100': ['SQ', '1', 'WaveformSequence'],\n    '0110': ['ox', '1', 'ChannelMinimumValue'],\n    '0112': ['ox', '1', 'ChannelMaximumValue'],\n    '1004': ['US', '1', 'WaveformBitsAllocated'],\n    '1006': ['CS', '1', 'WaveformSampleInterpretation'],\n    '100A': ['ox', '1', 'WaveformPaddingValue'],\n    '1010': ['ox', '1', 'WaveformData']\n  },\n  '5600': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['OF', '1', 'FirstOrderPhaseCorrectionAngle'],\n    '0020': ['OF', '1', 'SpectroscopyData']\n  },\n  '6000': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['US', '1', 'OverlayRows'],\n    '0011': ['US', '1', 'OverlayColumns'],\n    '0012': ['US', '1', 'OverlayPlanes'],\n    '0015': ['IS', '1', 'NumberOfFramesInOverlay'],\n    '0022': ['LO', '1', 'OverlayDescription'],\n    '0040': ['CS', '1', 'OverlayType'],\n    '0045': ['LO', '1', 'OverlaySubtype'],\n    '0050': ['SS', '2', 'OverlayOrigin'],\n    '0051': ['US', '1', 'ImageFrameOrigin'],\n    '0052': ['US', '1', 'OverlayPlaneOrigin'],\n    '0060': ['CS', '1', 'OverlayCompressionCode'],\n    '0061': ['SH', '1', 'OverlayCompressionOriginator'],\n    '0062': ['SH', '1', 'OverlayCompressionLabel'],\n    '0063': ['CS', '1', 'OverlayCompressionDescription'],\n    '0066': ['AT', '1-n', 'OverlayCompressionStepPointers'],\n    '0068': ['US', '1', 'OverlayRepeatInterval'],\n    '0069': ['US', '1', 'OverlayBitsGrouped'],\n    '0100': ['US', '1', 'OverlayBitsAllocated'],\n    '0102': ['US', '1', 'OverlayBitPosition'],\n    '0110': ['CS', '1', 'OverlayFormat'],\n    '0200': ['US', '1', 'OverlayLocation'],\n    '0800': ['CS', '1-n', 'OverlayCodeLabel'],\n    '0802': ['US', '1', 'OverlayNumberOfTables'],\n    '0803': ['AT', '1-n', 'OverlayCodeTableLocation'],\n    '0804': ['US', '1', 'OverlayBitsForCodeWord'],\n    '1001': ['CS', '1', 'OverlayActivationLayer'],\n    '1100': ['US', '1', 'OverlayDescriptorGray'],\n    '1101': ['US', '1', 'OverlayDescriptorRed'],\n    '1102': ['US', '1', 'OverlayDescriptorGreen'],\n    '1103': ['US', '1', 'OverlayDescriptorBlue'],\n    '1200': ['US', '1-n', 'OverlaysGray'],\n    '1201': ['US', '1-n', 'OverlaysRed'],\n    '1202': ['US', '1-n', 'OverlaysGreen'],\n    '1203': ['US', '1-n', 'OverlaysBlue'],\n    '1301': ['IS', '1', 'ROIArea'],\n    '1302': ['DS', '1', 'ROIMean'],\n    '1303': ['DS', '1', 'ROIStandardDeviation'],\n    '1500': ['LO', '1', 'OverlayLabel'],\n    '3000': ['ox', '1', 'OverlayData'],\n    '4000': ['LT', '1', 'OverlayComments']\n  },\n  '7F00': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['ox', '1', 'VariablePixelData'],\n    '0011': ['US', '1', 'VariableNextDataGroup'],\n    '0020': ['OW', '1', 'VariableCoefficientsSDVN'],\n    '0030': ['OW', '1', 'VariableCoefficientsSDHN'],\n    '0040': ['OW', '1', 'VariableCoefficientsSDDN']\n  },\n  '7FE0': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['OV', '1', 'ExtendedOffsetTable'],\n    '0002': ['OV', '1', 'ExtendedOffsetTableLengths'],\n    '0008': ['OF', '1', 'FloatPixelData'],\n    '0009': ['OD', '1', 'DoubleFloatPixelData'],\n    '0010': ['ox', '1', 'PixelData'],\n    '0020': ['OW', '1', 'CoefficientsSDVN'],\n    '0030': ['OW', '1', 'CoefficientsSDHN'],\n    '0040': ['OW', '1', 'CoefficientsSDDN']\n  },\n  'FFFA': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    'FFFA': ['SQ', '1', 'DigitalSignaturesSequence']\n  },\n  'FFFC': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    'FFFC': ['OB', '1', 'DataSetTrailingPadding']\n  },\n  'FFFE': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    'E000': ['NONE', '1', 'Item'],\n    'E00D': ['NONE', '1', 'ItemDelimitationItem'],\n    'E0DD': ['NONE', '1', 'SequenceDelimitationItem']\n  }\n}; // Dictionary\n\n/**\n * Add tags to the dictionary.\n *\n * @param {string} group The group key.\n * @param {Object<string, string[]>} tags The tags to add as an\n *   object indexed by element key with values as:\n *   [VR, multiplicity, TagName] (all strings).\n */\nexport function addTagsToDictionary(group, tags) {\n  // TODO: add checks!\n  dictionary[group] = tags;\n}\n\n/**\n * Tag groups: key to name pairs.\n * Copied from gdcm-2.6.1\\Source\\DataDictionary\\GroupName.dic\n * -> removed duplicates (commented).\n *\n * @type {Object<string, string>}\n */\nexport const tagGroups = {\n  '0000': 'Command',\n  '0002': 'Meta Element',\n  '0004': 'File Set',\n  //'0004': 'Directory',\n  '0008': 'Identifying',\n  '0009': 'SPI Identifying',\n  '0010': 'Patient',\n  '0012': 'Clinical Trial',\n  '0018': 'Acquisition',\n  '0019': 'SPI Acquisition',\n  '0020': 'Image',\n  '0021': 'SPI Image',\n  '0022': 'Ophtalmology',\n  '0028': 'Image Presentation',\n  '0032': 'Study',\n  '0038': 'Visit',\n  '003A': 'Waveform',\n  '0040': 'Procedure',\n  //'0040': ''Modality Worklist',\n  '0042': 'Encapsulated Document',\n  '0050': 'Device Informations',\n  //'0050': 'XRay Angio Device',\n  '0054': 'Nuclear Medicine',\n  '0060': 'Histogram',\n  '0070': 'Presentation State',\n  '0072': 'Hanging Protocol',\n  '0088': 'Storage',\n  //'0088': 'Medicine',\n  '0100': 'Authorization',\n  '0400': 'Digital Signature',\n  '1000': 'Code Table',\n  '1010': 'Zonal Map',\n  '2000': 'Film Session',\n  '2010': 'Film Box',\n  '2020': 'Image Box',\n  '2030': 'Annotation',\n  '2040': 'Overlay Box',\n  '2050': 'Presentation LUT',\n  '2100': 'Print Job',\n  '2110': 'Printer',\n  '2120': 'Queue',\n  '2130': 'Print Content',\n  '2200': 'Media Creation',\n  '3002': 'RT Image',\n  '3004': 'RT Dose',\n  '3006': 'RT StructureSet',\n  '3008': 'RT Treatment',\n  '300A': 'RT Plan',\n  '300C': 'RT Relationship',\n  '300E': 'RT Approval',\n  '4000': 'Text',\n  '4008': 'Results',\n  '4FFE': 'MAC Parameters',\n  '5000': 'Curve',\n  '5002': 'Curve',\n  '5004': 'Curve',\n  '5006': 'Curve',\n  '5008': 'Curve',\n  '500A': 'Curve',\n  '500C': 'Curve',\n  '500E': 'Curve',\n  '5400': 'Waveform Data',\n  '6000': 'Overlays',\n  '6002': 'Overlays',\n  '6004': 'Overlays',\n  '6008': 'Overlays',\n  '600A': 'Overlays',\n  '600C': 'Overlays',\n  '600E': 'Overlays',\n  'FFFC': 'Generic',\n  '7FE0': 'Pixel Data',\n  'FFFF': 'Unknown'\n};\n\n/**\n * List of Value Representation (VR) with 32bit Value Length (VL).\n *\n * Added locally used 'ox'.\n * See {@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/chapter_7.html#table_7.1-1}.\n *\n * @type {Object<string, boolean>}\n */\nconst vr32bitVL = {\n  OB: true,\n  OD: true,\n  OF: true,\n  OL: true,\n  OV: true,\n  OW: true,\n  SQ: true,\n  SV: true,\n  UC: true,\n  UN: true,\n  UR: true,\n  UT: true,\n  UV: true,\n  ox: true\n};\n\n/**\n * Does the input Value Representation (VR) have a 32bit Value Length (VL).\n *\n * @param {string} vr The data Value Representation (VR).\n * @returns {boolean} True if this VR has a 32-bit VL.\n */\nexport function is32bitVLVR(vr) {\n  return typeof vr32bitVL[vr] !== 'undefined';\n}\n\n/**\n * List of string VR with extended or replaced default character repertoire defined in\n *   Specific Character Set (0008,0005).\n *\n * See {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/chapter_6.html#sect_6.1.2.2}.\n *\n * @type {Object<string, boolean>}\n */\nconst vrCharSetString = {\n  SH: true,\n  LO: true,\n  UC: true,\n  ST: true,\n  LT: true,\n  UT: true,\n  PN: true\n};\n\n/**\n * Does the input Value Representation (VR) have an special character repertoire.\n *\n * @param {string} vr The data VR.\n * @returns {boolean} True if this VR has a special char set.\n */\nexport function isCharSetStringVR(vr) {\n  return typeof vrCharSetString[vr] !== 'undefined';\n}\n\n/**\n * VR equivalent javascript types.\n *\n * See {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_6.2.html#table_6.2-1}.\n *\n * @type {Object<string, string>}\n */\nexport const vrTypes = {\n  AE: 'string',\n  AS: 'string',\n  AT: undefined,\n  CS: 'string',\n  DA: 'string',\n  DS: 'string',\n  DT: 'string',\n  FL: 'Float32',\n  FD: 'Float64',\n  IS: 'string',\n  LO: 'string',\n  LT: 'string',\n  OB: 'Uint8',\n  OD: 'Uint64',\n  OF: 'Uint32',\n  OL: 'Uint32',\n  OV: 'Uint64',\n  OW: 'Uint16',\n  PN: 'string',\n  SH: 'string',\n  SL: 'Int32',\n  SQ: undefined,\n  SS: 'Int16',\n  ST: 'string',\n  SV: 'Int64',\n  TM: 'string',\n  UC: 'string',\n  UI: 'string',\n  UL: 'Uint32',\n  UN: 'Uint8',\n  UR: 'string',\n  US: 'Uint16',\n  UT: 'string',\n  UV: 'Uint64'\n};\n\n/**\n * Transfer syntaxes.\n *\n * See {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part06/chapter_A.html#table_A-1}.\n *\n * @type {Object<string, string>}\n */\nexport const transferSyntaxes = {\n  '1.2.840.10008.1.2': 'Implicit VR Little Endian',\n  '1.2.840.10008.1.2.1': 'Explicit VR Little Endian',\n  '1.2.840.10008.1.2.1.98': 'Encapsulated Uncompressed Explicit VR Little Endian',\n  '1.2.840.10008.1.2.1.99': 'Deflated Explicit VR Little Endian',\n  '1.2.840.10008.1.2.2': 'Explicit VR Big Endian (Retired)',\n  '1.2.840.10008.1.2.4.50': 'JPEG Baseline (Process 1)',\n  '1.2.840.10008.1.2.4.51': 'JPEG Extended (Process 2 & 4)',\n  '1.2.840.10008.1.2.4.52': 'JPEG Extended (Process 3 & 5) (Retired)',\n  '1.2.840.10008.1.2.4.53': 'JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) (Retired)',\n  '1.2.840.10008.1.2.4.54': 'JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9) (Retired)',\n  '1.2.840.10008.1.2.4.55': 'JPEG Full Progression, Non-Hierarchical (Process 10 & 12) (Retired)',\n  '1.2.840.10008.1.2.4.56': 'JPEG Full Progression, Non-Hierarchical (Process 11 & 13) (Retired)',\n  '1.2.840.10008.1.2.4.57': 'JPEG Lossless, Non-Hierarchical (Process 14)',\n  '1.2.840.10008.1.2.4.58': 'JPEG Lossless, Non-Hierarchical (Process 15) (Retired)',\n  '1.2.840.10008.1.2.4.59': 'JPEG Extended, Hierarchical (Process 16 & 18) (Retired)',\n  '1.2.840.10008.1.2.4.60': 'JPEG Extended, Hierarchical (Process 17 & 19) (Retired)',\n  '1.2.840.10008.1.2.4.61': 'JPEG Spectral Selection, Hierarchical (Process 20 & 22) (Retired)',\n  '1.2.840.10008.1.2.4.62': 'JPEG Spectral Selection, Hierarchical (Process 21 & 23) (Retired)',\n  '1.2.840.10008.1.2.4.63': 'JPEG Full Progression, Hierarchical (Process 24 & 26) (Retired)',\n  '1.2.840.10008.1.2.4.64': 'JPEG Full Progression, Hierarchical (Process 25 & 27) (Retired)',\n  '1.2.840.10008.1.2.4.65': 'JPEG Lossless, Hierarchical (Process 28) (Retired)',\n  '1.2.840.10008.1.2.4.66': 'JPEG Lossless, Hierarchical (Process 29) (Retired)',\n  '1.2.840.10008.1.2.4.70': 'JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1])',\n  '1.2.840.10008.1.2.4.80': 'JPEG-LS Lossless Image Compression',\n  '1.2.840.10008.1.2.4.81': 'JPEG-LS Lossy (Near-Lossless) Image Compression',\n  '1.2.840.10008.1.2.4.90': 'JPEG 2000 Image Compression (Lossless Only)',\n  '1.2.840.10008.1.2.4.91': 'JPEG 2000 Image Compression',\n  '1.2.840.10008.1.2.4.92': 'JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)',\n  '1.2.840.10008.1.2.4.93': 'JPEG 2000 Part 2 Multi-component Image Compression',\n  '1.2.840.10008.1.2.4.94': 'JPIP Referenced',\n  '1.2.840.10008.1.2.4.95': 'JPIP Referenced Deflate',\n  '1.2.840.10008.1.2.4.100': 'MPEG2 Main Profile / Main Level',\n  '1.2.840.10008.1.2.4.101': 'MPEG2 Main Profile / High Level',\n  '1.2.840.10008.1.2.4.102': 'MPEG-4 AVC/H.264 High Profile / Level 4.1',\n  '1.2.840.10008.1.2.4.103': 'MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1',\n  '1.2.840.10008.1.2.4.104': 'MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video',\n  '1.2.840.10008.1.2.4.105': 'MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video',\n  '1.2.840.10008.1.2.4.106': 'MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2',\n  '1.2.840.10008.1.2.4.107': 'HEVC/H.265 Main Profile / Level 5.1',\n  '1.2.840.10008.1.2.4.108': 'HEVC/H.265 Main 10 Profile / Level 5.1',\n  '1.2.840.10008.1.2.5': 'RLE Lossless',\n  '1.2.840.10008.1.2.6.1': 'RFC 2557 MIME encapsulation (Retired)',\n  '1.2.840.10008.1.2.6.2': 'XML Encoding (Retired)',\n  '1.2.840.10008.1.2.7.1': 'SMPTE ST 2110-20 Uncompressed Progressive Active Video',\n  '1.2.840.10008.1.2.7.2': 'SMPTE ST 2110-20 Uncompressed Interlaced Active Video',\n  '1.2.840.10008.1.2.7.3': 'SMPTE ST 2110-30 PCM Digital Audio',\n  '1.2.840.10008.1.20': 'Papyrus 3 Implicit VR Little Endian (Retired)'\n};\n\n/**\n * Transfer syntaxes indexed by keyword.\n *\n * @type {Object<string, string>}\n */\nexport const transferSyntaxKeywords = {\n  ImplicitVRLittleEndian: '1.2.840.10008.1.2',\n  ExplicitVRLittleEndian: '1.2.840.10008.1.2.1',\n  EncapsulatedUncompressedExplicitVRLittleEndian: '1.2.840.10008.1.2.1.98',\n  DeflatedExplicitVRLittleEndian: '1.2.840.10008.1.2.1.99',\n  ExplicitVRBigEndian: '1.2.840.10008.1.2.2',\n  JPEGBaseline8Bit: '1.2.840.10008.1.2.4.50',\n  JPEGExtended12Bit: '1.2.840.10008.1.2.4.51',\n  JPEGExtended35: '1.2.840.10008.1.2.4.52',\n  JPEGSpectralSelectionNonHierarchical68: '1.2.840.10008.1.2.4.53',\n  JPEGSpectralSelectionNonHierarchical79: '1.2.840.10008.1.2.4.54',\n  JPEGFullProgressionNonHierarchical1012: '1.2.840.10008.1.2.4.55',\n  JPEGFullProgressionNonHierarchical1113: '1.2.840.10008.1.2.4.56',\n  JPEGLossless: '1.2.840.10008.1.2.4.57',\n  JPEGLosslessNonHierarchical15: '1.2.840.10008.1.2.4.58',\n  JPEGExtendedHierarchical1618: '1.2.840.10008.1.2.4.59',\n  JPEGExtendedHierarchical1719: '1.2.840.10008.1.2.4.60',\n  JPEGSpectralSelectionHierarchical2022: '1.2.840.10008.1.2.4.61',\n  JPEGSpectralSelectionHierarchical2123: '1.2.840.10008.1.2.4.62',\n  JPEGFullProgressionHierarchical2426: '1.2.840.10008.1.2.4.63',\n  JPEGFullProgressionHierarchical2527: '1.2.840.10008.1.2.4.64',\n  JPEGLosslessHierarchical28: '1.2.840.10008.1.2.4.65',\n  JPEGLosslessHierarchical29: '1.2.840.10008.1.2.4.66',\n  JPEGLosslessSV1: '1.2.840.10008.1.2.4.70',\n  JPEGLSLossless: '1.2.840.10008.1.2.4.80',\n  JPEGLSNearLossless: '1.2.840.10008.1.2.4.81',\n  JPEG2000Lossless: '1.2.840.10008.1.2.4.90',\n  JPEG2000: '1.2.840.10008.1.2.4.91',\n  JPEG2000MCLossless: '1.2.840.10008.1.2.4.92',\n  JPEG2000MC: '1.2.840.10008.1.2.4.93',\n  JPIPReferenced: '1.2.840.10008.1.2.4.94',\n  JPIPReferencedDeflate: '1.2.840.10008.1.2.4.95',\n  MPEG2MPML: '1.2.840.10008.1.2.4.100',\n  MPEG2MPHL: '1.2.840.10008.1.2.4.101',\n  MPEG4HP41: '1.2.840.10008.1.2.4.102',\n  MPEG4HP41BD: '1.2.840.10008.1.2.4.103',\n  MPEG4HP422D: '1.2.840.10008.1.2.4.104',\n  MPEG4HP423D: '1.2.840.10008.1.2.4.105',\n  MPEG4HP42STEREO: '1.2.840.10008.1.2.4.106',\n  HEVCMP51: '1.2.840.10008.1.2.4.107',\n  HEVCM10P51: '1.2.840.10008.1.2.4.108',\n  RLELossless: '1.2.840.10008.1.2.5',\n  RFC2557MIMEEncapsulation: '1.2.840.10008.1.2.6.1',\n  XMLEncoding: '1.2.840.10008.1.2.6.2',\n  SMPTEST211020UncompressedProgressiveActiveVideo: '1.2.840.10008.1.2.7.1',\n  SMPTEST211020UncompressedInterlacedActiveVideo: '1.2.840.10008.1.2.7.2',\n  SMPTEST211030PCMDigitalAudio: '1.2.840.10008.1.2.7.3',\n  Papyrus3ImplicitVRLittleEndian: '1.2.840.10008.1.20'\n};\n","import {\n  dictionary,\n  tagGroups\n} from './dictionary';\n\n/**\n * Immutable tag.\n */\nexport class Tag {\n\n  /**\n   * The tag group.\n   *\n   * @type {string}\n   */\n  #group;\n\n  /**\n   * The tag element.\n   *\n   * @type {string}\n   */\n  #element;\n\n  /**\n   * @param {string} group The tag group as '####'.\n   * @param {string} element The tag element as '####'.\n   */\n  constructor(group, element) {\n    if (!group || typeof group === 'undefined') {\n      throw new Error('Cannot create tag with no group.');\n    }\n    if (group.length !== 4) {\n      throw new Error('Cannot create tag with badly sized group: ' + group);\n    }\n    if (!element || typeof element === 'undefined') {\n      throw new Error('Cannot create tag with no element.');\n    }\n    if (element.length !== 4) {\n      throw new Error('Cannot create tag with badly sized element: ' + element);\n    }\n    this.#group = group;\n    this.#element = element;\n  }\n\n  /**\n   * Get the tag group.\n   *\n   * @returns {string} The tag group.\n   */\n  getGroup() {\n    return this.#group;\n  }\n\n  /**\n   * Get the tag element.\n   *\n   * @returns {string} The tag element.\n   */\n  getElement() {\n    return this.#element;\n  }\n\n  /**\n   * Get as string representation of the tag: 'key: name'.\n   *\n   * @returns {string} A string representing the tag.\n   */\n  toString() {\n    return this.getKey() + ': ' + this.getNameFromDictionary();\n  }\n\n  /**\n   * Check for Tag equality.\n   *\n   * @param {Tag} rhs The other tag to compare to.\n   * @returns {boolean} True if both tags are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      typeof rhs !== 'undefined' &&\n      this.#group === rhs.getGroup() &&\n      this.#element === rhs.getElement();\n  }\n\n  /**\n   * Get the group-element key used to store DICOM elements.\n   *\n   * @returns {string} The key as '########'.\n   */\n  getKey() {\n    return this.#group + this.#element;\n  }\n\n  /**\n   * Get the group name as defined in TagGroups.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return tagGroups[this.#group];\n  }\n\n  /**\n   * Does this tag have a VR.\n   * Basically not the Item, ItemDelimitationItem nor\n   *  SequenceDelimitationItem tags.\n   *\n   * @returns {boolean} True if this tag has a VR.\n   */\n  isWithVR() {\n    return !(this.#group === 'FFFE' &&\n      (this.#element === 'E000' ||\n      this.#element === 'E00D' ||\n      this.#element === 'E0DD')\n    );\n  }\n\n  /**\n   * Is the tag group a private tag group ?\n   *\n   * See: {@link http://dicom.nema.org/medical/dicom/2022a/output/html/part05.html#sect_7.8}.\n   *\n   * @returns {boolean} True if the tag group is private,\n   *   ie if its group is an odd number.\n   */\n  isPrivate() {\n    return parseInt(this.#group, 16) % 2 === 1;\n  }\n\n  /**\n   * Get the tag info from the dicom dictionary.\n   *\n   * @returns {string[]|undefined} The info as [vr, multiplicity, name].\n   */\n  #getInfoFromDictionary() {\n    let info;\n    if (typeof dictionary[this.#group] !== 'undefined' &&\n      typeof dictionary[this.#group][this.#element] !==\n        'undefined') {\n      info = dictionary[this.#group][this.#element];\n    }\n    return info;\n  }\n\n  /**\n   * Get the tag Value Representation (VR) from the dicom dictionary.\n   *\n   * @returns {string|undefined} The VR.\n   */\n  getVrFromDictionary() {\n    let vr;\n    const info = this.#getInfoFromDictionary();\n    if (typeof info !== 'undefined') {\n      vr = info[0];\n    }\n    return vr;\n  }\n\n  /**\n   * Get the tag name from the dicom dictionary.\n   *\n   * @returns {string|undefined} The VR.\n   */\n  getNameFromDictionary() {\n    let name;\n    const info = this.#getInfoFromDictionary();\n    if (typeof info !== 'undefined') {\n      name = info[2];\n    }\n    return name;\n  }\n\n} // Tag class\n\n/**\n * Tag compare function.\n *\n * @param {Tag} a The first tag.\n * @param {Tag} b The second tag.\n * @returns {number} The result of the tag comparison,\n *   positive for b before a, negative for a before b and\n *   zero to keep same order.\n */\nexport function tagCompareFunction(a, b) {\n  // first by group\n  let res = parseInt(a.getGroup(), 16) - parseInt(b.getGroup(), 16);\n  if (res === 0) {\n    // by element if same group\n    res = parseInt(a.getElement(), 16) - parseInt(b.getElement(), 16);\n  }\n  return res;\n}\n\n/**\n * Split a group-element key used to store DICOM elements.\n *\n * @param {string} key The key in form \"00280102\" as generated by tag::getKey.\n * @returns {Tag} The DICOM tag.\n */\nexport function getTagFromKey(key) {\n  if (!key || typeof key === 'undefined') {\n    throw new Error('Cannot create tag with no key.');\n  }\n  if (key.length !== 8) {\n    throw new Error('Cannot create tag with badly sized key: ' + key);\n  }\n  return new Tag(key.substring(0, 4), key.substring(4, 8));\n}\n\n/**\n * Get the TransferSyntaxUID Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getTransferSyntaxUIDTag() {\n  return new Tag('0002', '0010');\n}\n\n/**\n * Get the FileMetaInformationGroupLength Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getFileMetaInformationGroupLengthTag() {\n  return new Tag('0002', '0000');\n}\n\n/**\n * Is the input tag the FileMetaInformationGroupLength Tag.\n *\n * @param {Tag} tag The tag to test.\n * @returns {boolean} True if the asked tag.\n */\nexport function isFileMetaInformationGroupLengthTag(tag) {\n  return tag.equals(getFileMetaInformationGroupLengthTag());\n}\n\n/**\n * Get the Item Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getItemTag() {\n  return new Tag('FFFE', 'E000');\n}\n\n/**\n * Is the input tag the Item Tag.\n *\n * @param {Tag} tag The tag to test.\n * @returns {boolean} True if the asked tag.\n */\nexport function isItemTag(tag) {\n  // faster than tag.equals(getItemTag());\n  return tag.getKey() === 'FFFEE000';\n}\n\n/**\n * Get the ItemDelimitationItem Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getItemDelimitationItemTag() {\n  return new Tag('FFFE', 'E00D');\n}\n\n/**\n * Is the input tag the ItemDelimitationItem Tag.\n *\n * @param {Tag} tag The tag to test.\n * @returns {boolean} True if the asked tag.\n */\nexport function isItemDelimitationItemTag(tag) {\n  // faster than tag.equals(getItemDelimitationItemTag());\n  return tag.getKey() === 'FFFEE00D';\n}\n\n/**\n * Get the SequenceDelimitationItem Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getSequenceDelimitationItemTag() {\n  return new Tag('FFFE', 'E0DD');\n}\n\n/**\n * Is the input tag the SequenceDelimitationItem Tag.\n *\n * @param {Tag} tag The tag to test.\n * @returns {boolean} True if the asked tag.\n */\nexport function isSequenceDelimitationItemTag(tag) {\n  // faster than tag.equals(getSequenceDelimitationItemTag());\n  return tag.getKey() === 'FFFEE0DD';\n}\n\n/**\n * Get the PixelData Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getPixelDataTag() {\n  return new Tag('7FE0', '0010');\n}\n\n/**\n * Is the input tag the PixelData Tag.\n *\n * @param {Tag} tag The tag to test.\n * @returns {boolean} True if the asked tag.\n */\nexport function isPixelDataTag(tag) {\n  // faster than tag.equals(getPixelDataTag());\n  return tag.getKey() === '7FE00010';\n}\n\n/**\n * Get a tag from the dictionary using a tag string name.\n *\n * @param {string} tagName The tag string name.\n * @returns {Tag|undefined} The tag object or null if not found.\n */\nexport function getTagFromDictionary(tagName) {\n  if (typeof tagName === 'undefined' || tagName === null) {\n    return null;\n  }\n  let group = null;\n  let element = null;\n  const dict = dictionary;\n  const keys0 = Object.keys(dict);\n  let keys1 = null;\n  let foundTag = false;\n  // search through dictionary\n  for (let k0 = 0, lenK0 = keys0.length; k0 < lenK0; ++k0) {\n    group = keys0[k0];\n    keys1 = Object.keys(dict[group]);\n    for (let k1 = 0, lenK1 = keys1.length; k1 < lenK1; ++k1) {\n      element = keys1[k1];\n      if (dict[group][element][2] === tagName) {\n        foundTag = true;\n        break;\n      }\n    }\n    if (foundTag) {\n      break;\n    }\n  }\n  let tag;\n  if (foundTag) {\n    tag = new Tag(group, element);\n  }\n  return tag;\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {Tag} from './dicomTag';\n/* eslint-enable no-unused-vars */\n\n/**\n * DICOM data element.\n */\nexport class DataElement {\n  /**\n   * The element Value Representation.\n   *\n   * @type {string}\n   */\n  vr;\n  /**\n   * The element value.\n   *\n   * @type {Array}\n   */\n  value;\n\n  // [start] internal values\n  // only present during parsing or writing otherwise not set\n\n  /**\n   * The element dicom tag.\n   *\n   * @type {Tag}\n   */\n  tag;\n\n  /**\n   * The element Value Length.\n   *\n   * @type {number}\n   */\n  vl;\n\n  /**\n   * Flag to know if defined or undefined sequence length.\n   *\n   * @type {boolean}\n   */\n  undefinedLength;\n\n  /**\n   * The element start offset.\n   *\n   * @type {number}\n   */\n  startOffset;\n\n  /**\n   * The element end offset.\n   *\n   * @type {number}\n   */\n  endOffset;\n\n  /**\n   * The sequence items.\n   *\n   * @type {Array}\n   */\n  items;\n\n  // [end] internal values\n\n  /**\n   * @param {string} vr The element VR (Value Representation).\n   */\n  constructor(vr) {\n    this.vr = vr;\n  }\n}\n\n/**\n * Safely get an elements' first value from a list of elements.\n *\n * @param {Object<string, DataElement>} tags The list of tags.\n * @param {string} key The tag key as for example '00100020'.\n * @returns {any|undefined} The elements' value or undefined.\n */\nexport function safeGet(tags, key) {\n  let res;\n  if (typeof tags[key] !== 'undefined') {\n    res = tags[key].value[0];\n  }\n  return res;\n};\n","/**\n * Is the Native endianness Little Endian.\n *\n * @returns {boolean} True if little endian.\n */\nexport function isNativeLittleEndian() {\n  return new Int8Array(new Int16Array([1]).buffer)[0] > 0;\n}\n\n/**\n * Flip an array's endianness.\n * Inspired from [DataStream.js]{@link https://github.com/kig/DataStream.js}.\n *\n * @param {object} array The array to flip (modified).\n */\nfunction flipArrayEndianness(array) {\n  const blen = array.byteLength;\n  const u8 = new Uint8Array(array.buffer, array.byteOffset, blen);\n  const bpe = array.BYTES_PER_ELEMENT;\n  let tmp;\n  for (let i = 0; i < blen; i += bpe) {\n    for (let j = i + bpe - 1, k = i; j > k; j--, k++) {\n      tmp = u8[k];\n      u8[k] = u8[j];\n      u8[j] = tmp;\n    }\n  }\n}\n\n/**\n * Data reader.\n */\nexport class DataReader {\n\n  /**\n   * The input buffer.\n   *\n   * @type {ArrayBuffer}\n   */\n  #buffer;\n\n  /**\n   * Is the endianness Little Endian.\n   *\n   * @type {boolean}\n   */\n  #isLittleEndian = true;\n\n  /**\n   * Is the Native endianness Little Endian.\n   *\n   * @type {boolean}\n   */\n  #isNativeLittleEndian = isNativeLittleEndian();\n\n  /**\n   * Flag to know if the TypedArray data needs flipping.\n   *\n   * @type {boolean}\n   */\n  #needFlip;\n\n  /**\n   * The main data view.\n   *\n   * @type {DataView}\n   */\n  #view;\n\n  /**\n   * @param {ArrayBuffer} buffer The input array buffer.\n   * @param {boolean} [isLittleEndian] Flag to tell if the data is little\n   *   or big endian (default: true).\n   */\n  constructor(buffer, isLittleEndian) {\n    this.#buffer = buffer;\n    // Set endian flag if not defined.\n    if (typeof isLittleEndian !== 'undefined') {\n      this.#isLittleEndian = isLittleEndian;\n    }\n    this.#needFlip = (this.#isLittleEndian !== this.#isNativeLittleEndian);\n    this.#view = new DataView(buffer);\n  }\n\n  /**\n   * Read Uint16 (2 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readUint16(byteOffset) {\n    return this.#view.getUint16(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read Int16 (2 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readInt16(byteOffset) {\n    return this.#view.getInt16(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read Uint32 (4 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readUint32(byteOffset) {\n    return this.#view.getUint32(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read BigUint64 (8 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {bigint} The read data.\n   */\n  readBigUint64(byteOffset) {\n    return this.#view.getBigUint64(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read Int32 (4 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readInt32(byteOffset) {\n    return this.#view.getInt32(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read BigInt64 (8 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {bigint} The read data.\n   */\n  readBigInt64(byteOffset) {\n    return this.#view.getBigInt64(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read Float32 (4 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readFloat32(byteOffset) {\n    return this.#view.getFloat32(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read Float64 (8 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readFloat64(byteOffset) {\n    return this.#view.getFloat64(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read binary (0/1) array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Uint8Array} The read data.\n   */\n  readBinaryArray(byteOffset, size) {\n    // input\n    const bitArray = new Uint8Array(this.#buffer, byteOffset, size);\n    // result\n    const byteArrayLength = 8 * bitArray.length;\n    const data = new Uint8Array(byteArrayLength);\n    let bitNumber = 0;\n    let bitIndex = 0;\n    for (let i = 0; i < byteArrayLength; ++i) {\n      bitNumber = i % 8;\n      bitIndex = Math.floor(i / 8);\n      // see https://stackoverflow.com/questions/4854207/get-a-specific-bit-from-byte/4854257\n      // @ts-ignore\n      data[i] = 255 * ((bitArray[bitIndex] & (1 << bitNumber)) !== 0);\n    }\n    return data;\n  }\n\n  /**\n   * Read Uint8 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Uint8Array} The read data.\n   */\n  readUint8Array(byteOffset, size) {\n    return new Uint8Array(this.#buffer, byteOffset, size);\n  }\n\n  /**\n   * Read Int8 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Int8Array} The read data.\n   */\n  readInt8Array(byteOffset, size) {\n    return new Int8Array(this.#buffer, byteOffset, size);\n  }\n\n  /**\n   * Read Uint16 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Uint16Array} The read data.\n   */\n  readUint16Array(byteOffset, size) {\n    const bpe = Uint16Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Uint16Array.BYTES_PER_ELEMENT (=2)\n    if (byteOffset % bpe === 0) {\n      data = new Uint16Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Uint16Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readUint16(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Int16 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Int16Array} The read data.\n   */\n  readInt16Array(byteOffset, size) {\n    const bpe = Int16Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Int16Array.BYTES_PER_ELEMENT (=2)\n    if (byteOffset % bpe === 0) {\n      data = new Int16Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Int16Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readInt16(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Uint32 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Uint32Array} The read data.\n   */\n  readUint32Array(byteOffset, size) {\n    const bpe = Uint32Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Uint32Array.BYTES_PER_ELEMENT (=4)\n    if (byteOffset % bpe === 0) {\n      data = new Uint32Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Uint32Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readUint32(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Uint64 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {BigUint64Array} The read data.\n   */\n  readUint64Array(byteOffset, size) {\n    const bpe = BigUint64Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of BigUint64Array.BYTES_PER_ELEMENT (=8)\n    if (byteOffset % bpe === 0) {\n      data = new BigUint64Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new BigUint64Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readBigUint64(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Int32 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Int32Array} The read data.\n   */\n  readInt32Array(byteOffset, size) {\n    const bpe = Int32Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Int32Array.BYTES_PER_ELEMENT (=4)\n    if (byteOffset % bpe === 0) {\n      data = new Int32Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Int32Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readInt32(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Int64 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {BigInt64Array} The read data.\n   */\n  readInt64Array(byteOffset, size) {\n    const bpe = BigInt64Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of BigInt64Array.BYTES_PER_ELEMENT (=8)\n    if (byteOffset % bpe === 0) {\n      data = new BigInt64Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new BigInt64Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readBigInt64(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Float32 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Float32Array} The read data.\n   */\n  readFloat32Array(byteOffset, size) {\n    const bpe = Float32Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Float32Array.BYTES_PER_ELEMENT (=4)\n    if (byteOffset % bpe === 0) {\n      data = new Float32Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Float32Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readFloat32(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Float64 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Float64Array} The read data.\n   */\n  readFloat64Array(byteOffset, size) {\n    const bpe = Float64Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Float64Array.BYTES_PER_ELEMENT (=8)\n    if (byteOffset % bpe === 0) {\n      data = new Float64Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Float64Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readFloat64(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read data as an hexadecimal string of length 4 (no '0x' prefix).\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {string} The read data ('####').\n   */\n  readHex(byteOffset) {\n    // read and convert to hex string\n    const str = this.readUint16(byteOffset).toString(16);\n    // return padded\n    return '0000'.substring(0, 4 - str.length) + str.toUpperCase();\n  }\n\n} // class DataReader\n","import {\n  Tag,\n  getTransferSyntaxUIDTag,\n  isSequenceDelimitationItemTag,\n  isItemDelimitationItemTag,\n  isPixelDataTag\n} from './dicomTag';\nimport {\n  is32bitVLVR,\n  isCharSetStringVR,\n  transferSyntaxes,\n  transferSyntaxKeywords,\n  vrTypes,\n} from './dictionary';\nimport {\n  safeGet,\n  DataElement\n} from './dataElement';\nimport {DataReader} from './dataReader';\nimport {logger} from '../utils/logger';\n\n/**\n * List of DICOM data elements indexed via a 8 character string formed from\n * the group and element numbers.\n *\n * @typedef {Object<string, DataElement>} DataElements\n */\n\n/**\n * Get the version of the library.\n *\n * @returns {string} The version of the library.\n */\nexport function getDwvVersion() {\n  return '0.35.0-beta.11';\n}\n\n/**\n * Check that an input buffer includes the DICOM prefix 'DICM'\n *   after the 128 bytes preamble.\n *\n * Ref: [DICOM File Meta]{@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part10/chapter_7.html#sect_7.1}.\n *\n * @param {ArrayBuffer} buffer The buffer to check.\n * @returns {boolean} True if the buffer includes the prefix.\n */\nexport function hasDicomPrefix(buffer) {\n  // check size: typed array constructor will throw RangeError if\n  // byteOffset + length * TypedArray.BYTES_PER_ELEMENT > buffer.byteLength\n  if (buffer.byteLength < 132) {\n    return false;\n  }\n  const prefixArray = new Uint8Array(buffer, 128, 4);\n  const stringReducer = function (previous, current) {\n    return previous += String.fromCharCode(current);\n  };\n  return prefixArray.reduce(stringReducer, '') === 'DICM';\n}\n\n// Zero-width space (u200B)\n// @ts-ignore\nconst ZWS = String.fromCharCode('u200B');\n\n/**\n * Clean string: remove zero-width space ending and trim.\n * Warning: no tests are done on the input, will fail if\n *   null or undefined or not string.\n * Exported for tests only.\n *\n * @param {string} inputStr The string to clean.\n * @returns {string} The cleaned string.\n */\nexport function cleanString(inputStr) {\n  let res = inputStr;\n  // get rid of ending zero-width space\n  const lastIndex = inputStr.length - 1;\n  if (inputStr[lastIndex] === ZWS) {\n    res = inputStr.substring(0, lastIndex);\n  }\n  // trim spaces\n  res = res.trim();\n  // return\n  return res;\n}\n\n/**\n * Get the utfLabel (used by the TextDecoder) from a character set term.\n *\n * References:\n * - DICOM [Value Encoding]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/chapter_6.html},\n * - DICOM [Specific Character Set]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.12.html#sect_C.12.1.1.2},\n * - [TextDecoder#Parameters]{@link https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/TextDecoder#Parameters}.\n *\n * @param {string} charSetTerm The DICOM character set.\n * @returns {string} The corresponding UTF label.\n */\nfunction getUtfLabel(charSetTerm) {\n  let label = 'utf-8';\n  if (charSetTerm === 'ISO_IR 100') {\n    label = 'iso-8859-1';\n  } else if (charSetTerm === 'ISO_IR 101') {\n    label = 'iso-8859-2';\n  } else if (charSetTerm === 'ISO_IR 109') {\n    label = 'iso-8859-3';\n  } else if (charSetTerm === 'ISO_IR 110') {\n    label = 'iso-8859-4';\n  } else if (charSetTerm === 'ISO_IR 144') {\n    label = 'iso-8859-5';\n  } else if (charSetTerm === 'ISO_IR 127') {\n    label = 'iso-8859-6';\n  } else if (charSetTerm === 'ISO_IR 126') {\n    label = 'iso-8859-7';\n  } else if (charSetTerm === 'ISO_IR 138') {\n    label = 'iso-8859-8';\n  } else if (charSetTerm === 'ISO_IR 148') {\n    label = 'iso-8859-9';\n  } else if (charSetTerm === 'ISO_IR 13') {\n    label = 'shift-jis';\n  } else if (charSetTerm === 'ISO_IR 166') {\n    label = 'iso-8859-11';\n  } else if (charSetTerm === 'ISO 2022 IR 87') {\n    label = 'iso-2022-jp';\n  } else if (charSetTerm === 'ISO 2022 IR 149') {\n    // not supported by TextDecoder when it says it should...\n    //label = \"iso-2022-kr\";\n  } else if (charSetTerm === 'ISO 2022 IR 58') {\n    // not supported by TextDecoder...\n    //label = \"iso-2022-cn\";\n  } else if (charSetTerm === 'ISO_IR 192') {\n    label = 'utf-8';\n  } else if (charSetTerm === 'GB18030') {\n    label = 'gb18030';\n  } else if (charSetTerm === 'GB2312') {\n    label = 'gb2312';\n  } else if (charSetTerm === 'GBK') {\n    label = 'chinese';\n  }\n  return label;\n}\n\n/**\n * Default text decoder.\n */\nclass DefaultTextDecoder {\n  /**\n   * Decode an input string buffer.\n   *\n   * @param {Uint8Array} buffer The buffer to decode.\n   * @returns {string} The decoded string.\n   */\n  decode(buffer) {\n    let result = '';\n    for (let i = 0, leni = buffer.length; i < leni; ++i) {\n      result += String.fromCharCode(buffer[i]);\n    }\n    return result;\n  }\n}\n\n/**\n * Get patient orientation label in the reverse direction.\n *\n * @param {string} ori Patient Orientation value.\n * @returns {string} Reverse Orientation Label.\n */\nexport function getReverseOrientation(ori) {\n  if (!ori) {\n    return null;\n  }\n  // reverse labels\n  const rlabels = {\n    L: 'R',\n    R: 'L',\n    A: 'P',\n    P: 'A',\n    H: 'F',\n    F: 'H'\n  };\n\n  let rori = '';\n  for (let n = 0; n < ori.length; n++) {\n    const o = ori.substring(n, n + 1);\n    const r = rlabels[o];\n    if (r) {\n      rori += r;\n    }\n  }\n  // return\n  return rori;\n}\n\n/**\n * Tell if a given syntax is an implicit one (element with no VR).\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if an implicit syntax.\n */\nexport function isImplicitTransferSyntax(syntax) {\n  return syntax === transferSyntaxKeywords.ImplicitVRLittleEndian;\n}\n\n/**\n * Tell if a given syntax is a big endian syntax.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a big endian syntax.\n */\nexport function isBigEndianTransferSyntax(syntax) {\n  return syntax === transferSyntaxKeywords.ExplicitVRBigEndian;\n}\n\n/**\n * Tell if a given syntax is a JPEG baseline one.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a jpeg baseline syntax.\n */\nexport function isJpegBaselineTransferSyntax(syntax) {\n  return syntax === transferSyntaxKeywords.JPEGBaseline8Bit ||\n    syntax === transferSyntaxKeywords.JPEGExtended12Bit;\n}\n\n/**\n * Tell if a given syntax is a JPEG Lossless one.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a jpeg lossless syntax.\n */\nexport function isJpegLosslessTransferSyntax(syntax) {\n  return syntax === transferSyntaxKeywords.JPEGLossless ||\n    syntax === transferSyntaxKeywords.JPEGLosslessSV1;\n}\n\n/**\n * Tell if a given syntax is a JPEG 2000 one.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a jpeg 2000 syntax.\n */\nexport function isJpeg2000TransferSyntax(syntax) {\n  return syntax.match(/1.2.840.10008.1.2.4.9/) !== null;\n}\n\n/**\n * Tell if a given syntax is a RLE (Run-length encoding) one.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a RLE syntax.\n */\nfunction isRleTransferSyntax(syntax) {\n  return syntax === transferSyntaxKeywords.RLELossless;\n}\n\n/**\n * Tell if a given syntax needs decompression.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {string|undefined} The name of the decompression algorithm.\n */\nexport function getSyntaxDecompressionName(syntax) {\n  let algo;\n  if (isJpeg2000TransferSyntax(syntax)) {\n    algo = 'jpeg2000';\n  } else if (isJpegBaselineTransferSyntax(syntax)) {\n    algo = 'jpeg-baseline';\n  } else if (isJpegLosslessTransferSyntax(syntax)) {\n    algo = 'jpeg-lossless';\n  } else if (isRleTransferSyntax(syntax)) {\n    algo = 'rle';\n  }\n  return algo;\n}\n\n/**\n * Tell if a given syntax is supported for reading.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a supported syntax.\n */\nfunction isReadSupportedTransferSyntax(syntax) {\n  return (syntax === transferSyntaxKeywords.ImplicitVRLittleEndian ||\n    syntax === transferSyntaxKeywords.ExplicitVRLittleEndian ||\n    syntax === transferSyntaxKeywords.ExplicitVRBigEndian ||\n    isJpegBaselineTransferSyntax(syntax) ||\n    isJpegLosslessTransferSyntax(syntax) ||\n    isJpeg2000TransferSyntax(syntax) ||\n    isRleTransferSyntax(syntax));\n}\n\n/**\n * Get a transfer syntax name from its UID.\n *\n * @param {string} syntax The transfer syntax UID value.\n * @returns {string} The transfer syntax name.\n */\nexport function getTransferSyntaxName(syntax) {\n  let name = 'Unknown';\n  if (typeof transferSyntaxes[syntax] !== 'undefined') {\n    name = transferSyntaxes[syntax];\n  }\n  return name;\n}\n\n/**\n * Guess the transfer syntax from the first data element.\n *\n * See {@link https://github.com/ivmartel/dwv/issues/188}\n *   (Allow to load DICOM with no DICM preamble) for more details.\n *\n * @param {DataElement} firstDataElement The first data element\n *   of the DICOM header.\n * @returns {DataElement} The transfer syntax data element.\n */\nfunction guessTransferSyntax(firstDataElement) {\n  const oEightGroupBigEndian = '0800';\n  const oEightGroupLittleEndian = '0008';\n  // check that group is 0008\n  const group = firstDataElement.tag.getGroup();\n  if (group !== oEightGroupBigEndian &&\n    group !== oEightGroupLittleEndian) {\n    throw new Error(\n      'Not a valid DICOM file (no magic DICM word found' +\n        ' and first element not in 0008 group)'\n    );\n  }\n  // reasonable assumption: 2 uppercase characters => explicit vr\n  const vr = firstDataElement.vr;\n  const vr0 = vr.charCodeAt(0);\n  const vr1 = vr.charCodeAt(1);\n  const implicit = (vr0 >= 65 && vr0 <= 90 && vr1 >= 65 && vr1 <= 90)\n    ? false : true;\n  // guess transfer syntax\n  let syntax = null;\n  if (group === oEightGroupLittleEndian) {\n    if (implicit) {\n      syntax = transferSyntaxKeywords.ImplicitVRLittleEndian;\n    } else {\n      syntax = transferSyntaxKeywords.ExplicitVRLittleEndian;\n    }\n  } else {\n    if (implicit) {\n      // ImplicitVRBigEndian: impossible\n      throw new Error(\n        'Not a valid DICOM file (no magic DICM word found' +\n        'and implicit VR big endian detected)'\n      );\n    } else {\n      syntax = transferSyntaxKeywords.ExplicitVRBigEndian;\n    }\n  }\n  // set transfer syntax data element\n  const dataElement = new DataElement('UI');\n  dataElement.tag = getTransferSyntaxUIDTag();\n  dataElement.value = [syntax];\n  dataElement.vl = dataElement.value[0].length;\n  dataElement.startOffset = firstDataElement.startOffset;\n  dataElement.endOffset = dataElement.startOffset + dataElement.vl;\n\n  return dataElement;\n}\n\n/**\n * Get the appropriate TypedArray in function of arguments.\n *\n * @param {number} bitsAllocated The number of bites used to store\n *   the data: [8, 16, 32].\n * @param {number} pixelRepresentation The pixel representation,\n *   0:unsigned;1:signed.\n * @param {number} size The size of the new array.\n * @returns {Uint8Array|Int8Array|Uint16Array|Int16Array|Uint32Array|Int32Array}\n *   The good typed array.\n */\nexport function getTypedArray(bitsAllocated, pixelRepresentation, size) {\n  let res = null;\n  try {\n    if (bitsAllocated === 1 || bitsAllocated === 8) {\n      if (pixelRepresentation === 0) {\n        res = new Uint8Array(size);\n      } else {\n        res = new Int8Array(size);\n      }\n    } else if (bitsAllocated === 16) {\n      if (pixelRepresentation === 0) {\n        res = new Uint16Array(size);\n      } else {\n        res = new Int16Array(size);\n      }\n    } else if (bitsAllocated === 32) {\n      if (pixelRepresentation === 0) {\n        res = new Uint32Array(size);\n      } else {\n        res = new Int32Array(size);\n      }\n    }\n  } catch (error) {\n    if (error instanceof RangeError) {\n      const powerOf2 = Math.floor(Math.log(size) / Math.log(2));\n      logger.error('Cannot allocate array of size: ' +\n        size + ' (>2^' + powerOf2 + ').');\n    }\n  }\n  return res;\n}\n\n/**\n * Get the number of bytes occupied by a data element prefix,\n *   (without its value).\n *\n * WARNING: this is valid for tags with a VR, if not sure use\n *   the 'isTagWithVR' function first.\n *\n * Reference:\n * - [Data Element explicit]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/chapter_7.html#table_7.1-1},\n * - [Data Element implicit]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_7.5.2.html#table_7.5-1}.\n *\n * ```\n * | Tag | VR  | VL | Value |\n * | 4   | 2   | 2  | X     | -> regular explicit: 8 + X\n * | 4   | 2+2 | 4  | X     | -> 32bit VL: 12 + X\n *\n * | Tag | VL | Value |\n * | 4   | 4  | X     | -> implicit (32bit VL): 8 + X\n *\n * | Tag | Len | Value |\n * | 4   | 4   | X     | -> item: 8 + X\n * ```\n *\n * @param {string} vr The Value Representation of the element.\n * @param {boolean} isImplicit Does the data use implicit VR?\n * @returns {number} The size of the element prefix.\n */\nexport function getDataElementPrefixByteSize(vr, isImplicit) {\n  return isImplicit ? 8 : is32bitVLVR(vr) ? 12 : 8;\n}\n\n/**\n * Is the input VR a known VR.\n *\n * @param {string} vr The vr to test.\n * @returns {boolean} True if known.\n */\nfunction isKnownVR(vr) {\n  const extraVrTypes = ['NONE', 'ox', 'xx', 'xs'];\n  const knownTypes = Object.keys(vrTypes).concat(extraVrTypes);\n  return knownTypes.includes(vr);\n}\n\n/**\n * Small list of used tag keys.\n */\nconst TagKeys = {\n  TransferSyntax: '00020010',\n  SpecificCharacterSet: '00080005',\n  NumberOfFrames: '00280008',\n  BitsAllocated: '00280100',\n  PixelRepresentation: '00280103',\n  PixelData: '7FE00010'\n};\n\n/**\n * DicomParser class.\n *\n * @example\n * // XMLHttpRequest onload callback\n * const onload = function (event) {\n *   // setup the dicom parser\n *   const dicomParser = new dwv.DicomParser();\n *   // parse the buffer\n *   dicomParser.parse(event.target.response);\n *   // get the dicom tags\n *   const tags = dicomParser.getDicomElements();\n *   // display the modality\n *   const div = document.getElementById('dwv');\n *   div.appendChild(document.createTextNode(\n *     'Modality: ' + tags['00080060'].value[0]\n *   ));\n * };\n * // DICOM file request\n * const request = new XMLHttpRequest();\n * const url = 'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm';\n * request.open('GET', url);\n * request.responseType = 'arraybuffer';\n * request.onload = onload;\n * request.send();\n */\nexport class DicomParser {\n\n  /**\n   * The list of DICOM elements.\n   *\n   * @type {DataElements}\n   */\n  #dataElements = {};\n\n  /**\n   * Default character set (optional).\n   *\n   * @type {string}\n   */\n  #defaultCharacterSet;\n\n  /**\n   * Default text decoder.\n   *\n   * @type {DefaultTextDecoder}\n   */\n  #defaultTextDecoder = new DefaultTextDecoder();\n\n  /**\n   * Special text decoder.\n   *\n   * @type {DefaultTextDecoder|TextDecoder}\n   */\n  #textDecoder = this.#defaultTextDecoder;\n\n  /**\n   * Decode an input string buffer using the default text decoder.\n   *\n   * @param {Uint8Array} buffer The buffer to decode.\n   * @returns {string} The decoded string.\n   */\n  #decodeString(buffer) {\n    return this.#defaultTextDecoder.decode(buffer);\n  }\n\n  /**\n   * Decode an input string buffer using the 'special' text decoder.\n   *\n   * @param {Uint8Array} buffer The buffer to decode.\n   * @returns {string} The decoded string.\n   */\n  #decodeSpecialString(buffer) {\n    return this.#textDecoder.decode(buffer);\n  }\n\n  /**\n   * Get the default character set.\n   *\n   * @returns {string} The default character set.\n   */\n  getDefaultCharacterSet() {\n    return this.#defaultCharacterSet;\n  }\n\n  /**\n   * Set the default character set.\n   *\n   * @param {string} characterSet The input character set.\n   */\n  setDefaultCharacterSet(characterSet) {\n    this.#defaultCharacterSet = characterSet;\n  }\n\n  /**\n   * Set the text decoder character set.\n   *\n   * @param {string} characterSet The input character set.\n   */\n  setDecoderCharacterSet(characterSet) {\n    /**\n     * The text decoder.\n     *\n     * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder}.\n     *\n     * @external TextDecoder\n     */\n    this.#textDecoder = new TextDecoder(characterSet);\n  }\n\n  // not using type DataElements since the typedef is not exported with the API\n\n  /**\n   * Get the DICOM data elements.\n   *\n   * @returns {Object<string, DataElement>} The data elements.\n   */\n  getDicomElements() {\n    return this.#dataElements;\n  }\n\n  /**\n   * Safely get an elements' first value from the parsed elements.\n   *\n   * @param {string} key The tag key as for example '00100020'.\n   * @returns {any|undefined} The elements' value or undefined.\n   */\n  safeGet(key) {\n    return safeGet(this.#dataElements, key);\n  }\n\n  /**\n   * Read a DICOM tag.\n   *\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} offset The offset where to start to read.\n   * @returns {object} An object containing the tag and the end offset.\n   */\n  #readTag(reader, offset) {\n    // group\n    const group = reader.readHex(offset);\n    offset += Uint16Array.BYTES_PER_ELEMENT;\n    // element\n    const element = reader.readHex(offset);\n    offset += Uint16Array.BYTES_PER_ELEMENT;\n    // return\n    return {\n      tag: new Tag(group, element),\n      endOffset: offset\n    };\n  }\n\n  /**\n   * Read an item data element.\n   *\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} offset The offset where to start to read.\n   * @param {boolean} implicit Is the DICOM VR implicit?\n   * @returns {object} The item data as a list of data elements.\n   */\n  #readItemDataElement(reader, offset, implicit) {\n    const itemData = {};\n\n    // read the first item\n    let item = this.#readDataElement(reader, offset, implicit);\n    offset = item.endOffset;\n\n    // exit if it is a sequence delimitation item\n    if (isSequenceDelimitationItemTag(item.tag)) {\n      return {\n        data: itemData,\n        endOffset: item.endOffset,\n        isSeqDelim: true\n      };\n    }\n\n    // store item (mainly to keep vl)\n    itemData[item.tag.getKey()] = {\n      tag: item.tag,\n      vr: 'NONE',\n      vl: item.vl,\n      undefinedLength: item.undefinedLength\n    };\n\n    if (!item.undefinedLength) {\n      // explicit VR item: read until the end offset\n      const endOffset = offset;\n      offset -= item.vl;\n      while (offset < endOffset) {\n        item = this.#readDataElement(reader, offset, implicit);\n        offset = item.endOffset;\n        itemData[item.tag.getKey()] = item;\n      }\n    } else {\n      // implicit VR item: read until the item delimitation item\n      let isItemDelim = false;\n      while (!isItemDelim) {\n        item = this.#readDataElement(reader, offset, implicit);\n        offset = item.endOffset;\n        isItemDelim = isItemDelimitationItemTag(item.tag);\n        if (!isItemDelim) {\n          itemData[item.tag.getKey()] = item;\n        }\n      }\n    }\n\n    return {\n      data: itemData,\n      endOffset: offset,\n      isSeqDelim: false\n    };\n  }\n\n  /**\n   * Read the pixel item data element.\n   * Ref: [Single frame fragments]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_A.4.html#table_A.4-1}.\n   *\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} offset The offset where to start to read.\n   * @param {boolean} implicit Is the DICOM VR implicit?\n   * @returns {object} The item data as an array of data elements.\n   */\n  #readPixelItemDataElement(\n    reader, offset, implicit) {\n    const itemData = [];\n\n    // first item: basic offset table\n    let item = this.#readDataElement(reader, offset, implicit);\n    const offsetTableVl = item.vl;\n    offset = item.endOffset;\n\n    // read until the sequence delimitation item\n    let isSeqDelim = false;\n    while (!isSeqDelim) {\n      item = this.#readDataElement(reader, offset, implicit);\n      offset = item.endOffset;\n      isSeqDelim = isSequenceDelimitationItemTag(item.tag);\n      if (!isSeqDelim) {\n        // force pixel item vr to OB\n        item.vr = 'OB';\n        itemData.push(item);\n      }\n    }\n\n    return {\n      data: itemData,\n      endOffset: offset,\n      offsetTableVl: offsetTableVl\n    };\n  }\n\n  /**\n   * Read a DICOM data element.\n   *\n   * Reference: [DICOM VRs]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_6.2.html#table_6.2-1}.\n   *\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} offset The offset where to start to read.\n   * @param {boolean} implicit Is the DICOM VR implicit?\n   * @param {Tag} [untilTag] Optional tag to stop the reading once reached,\n   *   the returned element will only contain the tag.\n   * @returns {DataElement} The data element.\n   */\n  #readDataElement(reader, offset, implicit, untilTag) {\n    // Tag: group, element\n    const readTagRes = this.#readTag(reader, offset);\n    const tag = readTagRes.tag;\n\n    if (typeof untilTag !== 'undefined' &&\n      tag.equals(untilTag)) {\n      const element = new DataElement('');\n      element.tag = tag;\n      return element;\n    }\n\n    offset = readTagRes.endOffset;\n\n    // Value Representation (VR)\n    let vr = null;\n    let is32bitVL = false;\n    if (tag.isWithVR()) {\n      // implicit VR\n      if (implicit) {\n        vr = tag.getVrFromDictionary();\n        if (typeof vr === 'undefined') {\n          vr = 'UN';\n        }\n        is32bitVL = true;\n      } else {\n        vr = this.#decodeString(reader.readUint8Array(offset, 2));\n        offset += 2 * Uint8Array.BYTES_PER_ELEMENT;\n        is32bitVL = is32bitVLVR(vr);\n        // reserved 2 bytes\n        if (is32bitVL) {\n          offset += 2 * Uint8Array.BYTES_PER_ELEMENT;\n        }\n      }\n    } else {\n      vr = 'NONE';\n      is32bitVL = true;\n    }\n\n    // check vr\n    if (!isKnownVR(vr)) {\n      logger.warn('Unknown VR: ' + vr +\n        ' (for tag ' + tag.getKey() + '), treating as \\'UN\\'');\n      vr = 'UN';\n    }\n\n    // Value Length (VL)\n    let vl = 0;\n    if (is32bitVL) {\n      vl = reader.readUint32(offset);\n      offset += Uint32Array.BYTES_PER_ELEMENT;\n    } else {\n      vl = reader.readUint16(offset);\n      offset += Uint16Array.BYTES_PER_ELEMENT;\n    }\n\n    // check the value of VL\n    let undefinedLength = false;\n    if (vl === 0xffffffff) {\n      undefinedLength = true;\n      vl = 0;\n    }\n\n    // treat private tag with unknown VR and zero VL as a sequence (see #799)\n    if (tag.isPrivate() && vr === 'UN' && vl === 0) {\n      vr = 'SQ';\n    }\n\n    let startOffset = offset;\n    let endOffset = startOffset + vl;\n\n    // read sequence elements\n    let data;\n    if (isPixelDataTag(tag) && undefinedLength) {\n      // pixel data sequence (implicit)\n      const pixItemData =\n        this.#readPixelItemDataElement(reader, offset, implicit);\n      offset = pixItemData.endOffset;\n      startOffset += pixItemData.offsetTableVl;\n      data = pixItemData.data;\n      endOffset = offset;\n      vl = offset - startOffset;\n    } else if (vr === 'SQ') {\n      // sequence\n      data = [];\n      let itemData;\n      if (!undefinedLength) {\n        if (vl !== 0) {\n          // explicit VR sequence: read until the end offset\n          const sqEndOffset = offset + vl;\n          while (offset < sqEndOffset) {\n            itemData = this.#readItemDataElement(reader, offset, implicit);\n            data.push(itemData.data);\n            offset = itemData.endOffset;\n          }\n          endOffset = offset;\n          vl = offset - startOffset;\n        }\n      } else {\n        // implicit VR sequence: read until the sequence delimitation item\n        let isSeqDelim = false;\n        while (!isSeqDelim) {\n          itemData = this.#readItemDataElement(reader, offset, implicit);\n          isSeqDelim = itemData.isSeqDelim;\n          offset = itemData.endOffset;\n          // do not store the delimitation item\n          if (!isSeqDelim) {\n            data.push(itemData.data);\n          }\n        }\n        endOffset = offset;\n        vl = offset - startOffset;\n      }\n    }\n\n    // return\n    const element = new DataElement(vr);\n    element.tag = tag;\n    element.vl = vl;\n    element.startOffset = startOffset;\n    element.endOffset = endOffset;\n    // only set if true (only for sequences and items)\n    if (undefinedLength) {\n      element.undefinedLength = undefinedLength;\n    }\n    if (data) {\n      element.items = data;\n    }\n    return element;\n  }\n\n  /**\n   * Interpret the data of an element.\n   *\n   * @param {DataElement} element The data element.\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} [pixelRepresentation] PixelRepresentation 0->unsigned,\n   *   1->signed (needed for pixel data or VR=xs).\n   * @param {number} [bitsAllocated] Bits allocated (needed for pixel data).\n   * @returns {object} The interpreted data.\n   */\n  #interpretElement(\n    element, reader, pixelRepresentation, bitsAllocated) {\n\n    const tag = element.tag;\n    const vl = element.vl;\n    const vr = element.vr;\n    const offset = element.startOffset;\n\n    // data\n    let data = null;\n    const vrType = vrTypes[vr];\n    if (isPixelDataTag(tag)) {\n      if (element.undefinedLength) {\n        // implicit pixel data sequence\n        data = [];\n        for (let j = 0; j < element.items.length; ++j) {\n          data.push(this.#interpretElement(\n            element.items[j], reader,\n            pixelRepresentation, bitsAllocated));\n        }\n        // remove non parsed items\n        delete element.items;\n      } else {\n        // check bits allocated and VR\n        // https://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_A.2.html\n        if (bitsAllocated > 8 && vr === 'OB') {\n          logger.warn(\n            'Reading DICOM pixel data with bitsAllocated>8 and OB VR' +\n            ', treating as OW'\n          );\n          element.vr = 'OW';\n        }\n        // read\n        data = [];\n        if (bitsAllocated === 1) {\n          data.push(reader.readBinaryArray(offset, vl));\n        } else if (bitsAllocated === 8) {\n          if (pixelRepresentation === 0) {\n            data.push(reader.readUint8Array(offset, vl));\n          } else {\n            data.push(reader.readInt8Array(offset, vl));\n          }\n        } else if (bitsAllocated === 16) {\n          if (pixelRepresentation === 0) {\n            data.push(reader.readUint16Array(offset, vl));\n          } else {\n            data.push(reader.readInt16Array(offset, vl));\n          }\n        } else {\n          throw new Error('Unsupported bits allocated: ' + bitsAllocated);\n        }\n      }\n    } else if (typeof vrType !== 'undefined') {\n      if (vrType === 'Uint8') {\n        data = reader.readUint8Array(offset, vl);\n      } else if (vrType === 'Uint16') {\n        data = reader.readUint16Array(offset, vl);\n        // keep as binary for 'O*' VR\n        if (vr[0] !== 'O') {\n          data = Array.from(data);\n        }\n      } else if (vrType === 'Uint32') {\n        data = reader.readUint32Array(offset, vl);\n        // keep as binary for 'O*' VR\n        if (vr[0] !== 'O') {\n          data = Array.from(data);\n        }\n      } else if (vrType === 'Uint64') {\n        data = reader.readUint64Array(offset, vl);\n      } else if (vrType === 'Int16') {\n        data = Array.from(reader.readInt16Array(offset, vl));\n      } else if (vrType === 'Int32') {\n        data = Array.from(reader.readInt32Array(offset, vl));\n      } else if (vrType === 'Int64') {\n        data = reader.readInt64Array(offset, vl);\n      } else if (vrType === 'Float32') {\n        data = Array.from(reader.readFloat32Array(offset, vl));\n      } else if (vrType === 'Float64') {\n        data = Array.from(reader.readFloat64Array(offset, vl));\n      } else if (vrType === 'string') {\n        const stream = reader.readUint8Array(offset, vl);\n        if (isCharSetStringVR(vr)) {\n          data = this.#decodeSpecialString(stream);\n        } else {\n          data = this.#decodeString(stream);\n        }\n        data = cleanString(data).split('\\\\');\n      } else {\n        throw new Error('Unknown VR type: ' + vrType);\n      }\n    } else if (vr === 'xx') {\n      // US or OW\n      data = Array.from(reader.readUint16Array(offset, vl));\n    } else if (vr === 'ox') {\n      // OB or OW\n      if (bitsAllocated === 8) {\n        if (pixelRepresentation === 0) {\n          data = Array.from(reader.readUint8Array(offset, vl));\n        } else {\n          data = Array.from(reader.readInt8Array(offset, vl));\n        }\n      } else {\n        if (pixelRepresentation === 0) {\n          data = Array.from(reader.readUint16Array(offset, vl));\n        } else {\n          data = Array.from(reader.readInt16Array(offset, vl));\n        }\n      }\n    } else if (vr === 'xs') {\n      // (US or SS) or (US or SS or OW)\n      if (pixelRepresentation === 0) {\n        data = Array.from(reader.readUint16Array(offset, vl));\n      } else {\n        data = Array.from(reader.readInt16Array(offset, vl));\n      }\n    } else if (vr === 'AT') {\n      // attribute\n      const raw = reader.readUint16Array(offset, vl);\n      data = [];\n      for (let i = 0, leni = raw.length; i < leni; i += 2) {\n        const stri = raw[i].toString(16);\n        const stri1 = raw[i + 1].toString(16);\n        let str = '(';\n        str += '0000'.substring(0, 4 - stri.length) + stri.toUpperCase();\n        str += ',';\n        str += '0000'.substring(0, 4 - stri1.length) + stri1.toUpperCase();\n        str += ')';\n        data.push(str);\n      }\n    } else if (vr === 'SQ') {\n      // sequence\n      data = [];\n      for (let k = 0; k < element.items.length; ++k) {\n        const item = element.items[k];\n        const itemData = {};\n        const keys = Object.keys(item);\n        let sqBitsAllocated = bitsAllocated;\n        let sqPixelRepresentation = pixelRepresentation;\n        for (let l = 0; l < keys.length; ++l) {\n          // check if local bitsAllocated\n          // (inside item loop to get interpreted value)\n          let dataElement = item[TagKeys.BitsAllocated];\n          if (typeof dataElement !== 'undefined' &&\n            typeof dataElement.value !== 'undefined') {\n            sqBitsAllocated = dataElement.value[0];\n          }\n          // check if local pixelRepresentation\n          // (inside item loop to get interpreted value)\n          dataElement = item[TagKeys.PixelRepresentation];\n          if (typeof dataElement !== 'undefined' &&\n            typeof dataElement.value !== 'undefined') {\n            sqPixelRepresentation = dataElement.value[0];\n          }\n          const subElement = item[keys[l]];\n          subElement.value = this.#interpretElement(\n            subElement, reader,\n            sqPixelRepresentation, sqBitsAllocated);\n          delete subElement.tag;\n          delete subElement.vl;\n          delete subElement.startOffset;\n          delete subElement.endOffset;\n          itemData[keys[l]] = subElement;\n        }\n        data.push(itemData);\n      }\n      // remove non parsed elements\n      delete element.items;\n    } else if (vr === 'NONE') {\n      // no VR -> no data\n      data = [];\n    } else {\n      logger.warn('Unknown VR: ' + vr +\n        ' (for tag ' + element.tag.getKey() + ')');\n      // empty data...\n      data = [];\n    }\n\n    return data;\n  }\n\n  /**\n   * Interpret the data of a list of elements.\n   *\n   * @param {DataElements} elements A list of data elements.\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} pixelRepresentation PixelRepresentation 0->unsigned,\n   *   1->signed.\n   * @param {number} bitsAllocated Bits allocated.\n   */\n  #interpret(\n    elements, reader,\n    pixelRepresentation, bitsAllocated) {\n\n    const keys = Object.keys(elements);\n    for (let i = 0; i < keys.length; ++i) {\n      const element = elements[keys[i]];\n      if (typeof element.value === 'undefined') {\n        element.value = this.#interpretElement(\n          element, reader, pixelRepresentation, bitsAllocated);\n      }\n      // delete interpretation specific properties\n      delete element.tag;\n      delete element.vl;\n      delete element.startOffset;\n      delete element.endOffset;\n    }\n  }\n\n  /**\n   * Parse a DICOM buffer.\n   * Fills in the member object 'dataElements'.\n   *\n   * @param {ArrayBuffer} buffer The input array buffer.\n   * @param {Tag} [untilTag] Optional tag to stop the parsing once reached.\n   */\n  parse(buffer, untilTag) {\n    let offset = 0;\n    let syntax = '';\n    let dataElement = null;\n    // default readers\n    const metaReader = new DataReader(buffer);\n    let dataReader = new DataReader(buffer);\n\n    // 128 -> 132: magic word\n    offset = 128;\n    const magicword = this.#decodeString(metaReader.readUint8Array(offset, 4));\n    offset += 4 * Uint8Array.BYTES_PER_ELEMENT;\n    if (magicword === 'DICM') {\n      // 0002, 0000: FileMetaInformationGroupLength (vr='UL')\n      dataElement = this.#readDataElement(metaReader, offset, false);\n      dataElement.value = this.#interpretElement(dataElement, metaReader);\n      // increment offset\n      offset = dataElement.endOffset;\n      // store the data element\n      this.#dataElements[dataElement.tag.getKey()] = dataElement;\n      // get meta length\n      const metaLength = dataElement.value[0];\n\n      // meta elements\n      const metaEnd = offset + metaLength;\n      while (offset < metaEnd) {\n        // get the data element\n        dataElement = this.#readDataElement(metaReader, offset, false);\n        offset = dataElement.endOffset;\n        // store the data element\n        this.#dataElements[dataElement.tag.getKey()] = dataElement;\n      }\n\n      // check the TransferSyntaxUID (has to be there!)\n      dataElement = this.#dataElements[TagKeys.TransferSyntax];\n      if (typeof dataElement === 'undefined') {\n        throw new Error('Not a valid DICOM file (no TransferSyntaxUID found)');\n      }\n      dataElement.value = this.#interpretElement(dataElement, metaReader);\n      syntax = dataElement.value[0];\n\n    } else {\n      logger.warn('No DICM prefix, trying to guess tansfer syntax.');\n      // read first element\n      dataElement = this.#readDataElement(dataReader, 0, false);\n      // guess transfer syntax\n      const tsElement = guessTransferSyntax(dataElement);\n      // store\n      this.#dataElements[tsElement.tag.getKey()] = tsElement;\n      syntax = tsElement.value[0];\n      // reset offset\n      offset = 0;\n    }\n\n    // check transfer syntax support\n    if (!isReadSupportedTransferSyntax(syntax)) {\n      throw new Error('Unsupported DICOM transfer syntax: \\'' + syntax +\n        '\\' (' + getTransferSyntaxName(syntax) + ')');\n    }\n\n    // set implicit flag\n    let implicit = false;\n    if (isImplicitTransferSyntax(syntax)) {\n      implicit = true;\n    }\n\n    // Big Endian\n    if (isBigEndianTransferSyntax(syntax)) {\n      dataReader = new DataReader(buffer, false);\n    }\n\n    let reachedUntilTag = false;\n\n    // DICOM data elements\n    while (offset < buffer.byteLength) {\n      // get the data element\n      dataElement = this.#readDataElement(\n        dataReader, offset, implicit, untilTag);\n      // until tag\n      if (typeof untilTag !== 'undefined' &&\n        dataElement.tag.equals(untilTag)) {\n        reachedUntilTag = true;\n        break;\n      }\n      // increment offset\n      offset = dataElement.endOffset;\n      // store the data element\n      const key = dataElement.tag.getKey();\n      if (typeof this.#dataElements[key] === 'undefined') {\n        this.#dataElements[key] = dataElement;\n      } else {\n        logger.warn('Not saving duplicate tag: ' + key);\n      }\n    }\n\n    // safety checks...\n    if (isNaN(offset)) {\n      throw new Error('Problem while parsing, bad offset');\n    }\n    if (!reachedUntilTag && buffer.byteLength !== offset) {\n      logger.warn('Did not reach the end of the buffer: ' +\n        offset + ' != ' + buffer.byteLength);\n    }\n\n    //-------------------------------------------------\n    // values needed for data interpretation\n\n    // pixel specific\n    let pixelRepresentation = 0;\n    let bitsAllocated = 16;\n    if (typeof this.#dataElements[TagKeys.PixelData] !== 'undefined') {\n      // PixelRepresentation 0->unsigned, 1->signed\n      dataElement = this.#dataElements[TagKeys.PixelRepresentation];\n      if (typeof dataElement !== 'undefined') {\n        dataElement.value = this.#interpretElement(dataElement, dataReader);\n        pixelRepresentation = dataElement.value[0];\n      } else {\n        logger.warn(\n          'Reading DICOM pixel data with default pixelRepresentation.');\n      }\n\n      // BitsAllocated\n      dataElement = this.#dataElements[TagKeys.BitsAllocated];\n      if (typeof dataElement !== 'undefined') {\n        dataElement.value = this.#interpretElement(dataElement, dataReader);\n        bitsAllocated = dataElement.value[0];\n      } else {\n        logger.warn('Reading DICOM pixel data with default bitsAllocated.');\n      }\n    }\n\n    // default character set\n    if (typeof this.#defaultCharacterSet !== 'undefined') {\n      this.setDecoderCharacterSet(this.#defaultCharacterSet);\n    }\n\n    // SpecificCharacterSet\n    dataElement = this.#dataElements[TagKeys.SpecificCharacterSet];\n    if (typeof dataElement !== 'undefined') {\n      dataElement.value = this.#interpretElement(dataElement, dataReader);\n      let charSetTerm;\n      if (dataElement.value.length === 1) {\n        charSetTerm = dataElement.value[0];\n      } else {\n        charSetTerm = dataElement.value[1];\n        logger.warn('Unsupported character set with code extensions: \\'' +\n          charSetTerm + '\\'.');\n      }\n      this.setDecoderCharacterSet(getUtfLabel(charSetTerm));\n    }\n\n    // interpret the dicom elements\n    this.#interpret(\n      this.#dataElements, dataReader,\n      pixelRepresentation, bitsAllocated\n    );\n\n    // handle fragmented pixel buffer\n    // Reference: http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_8.2.html\n    // (third note, \"Depending on the transfer syntax...\")\n    dataElement = this.#dataElements[TagKeys.PixelData];\n    if (typeof dataElement !== 'undefined') {\n      if (dataElement.undefinedLength) {\n        let numberOfFrames = 1;\n        if (typeof this.#dataElements[TagKeys.NumberOfFrames] !== 'undefined') {\n          numberOfFrames = Number(\n            this.#dataElements[TagKeys.NumberOfFrames].value[0]\n          );\n        }\n        const pixItems = dataElement.value;\n        if (pixItems.length > 1 && pixItems.length > numberOfFrames) {\n          // concatenate pixel data items\n          // concat does not work on typed arrays\n          //this.pixelBuffer = this.pixelBuffer.concat( dataElement.data );\n          // manual concat...\n          const nItemPerFrame = pixItems.length / numberOfFrames;\n          const newPixItems = [];\n          let index = 0;\n          for (let f = 0; f < numberOfFrames; ++f) {\n            index = f * nItemPerFrame;\n            // calculate the size of a frame\n            let size = 0;\n            for (let i = 0; i < nItemPerFrame; ++i) {\n              size += pixItems[index + i].length;\n            }\n            // create new buffer\n            const newBuffer = new pixItems[0].constructor(size);\n            // fill new buffer\n            let fragOffset = 0;\n            for (let j = 0; j < nItemPerFrame; ++j) {\n              newBuffer.set(pixItems[index + j], fragOffset);\n              fragOffset += pixItems[index + j].length;\n            }\n            newPixItems[f] = newBuffer;\n          }\n          // store as pixel data\n          dataElement.value = newPixItems;\n        }\n      }\n    }\n  }\n\n} // class DicomParser\n","import {logger} from './logger';\n\n/**\n * ListenerHandler class: handles add/removing and firing listeners.\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget#example}.\n */\nexport class ListenerHandler {\n  /**\n   * Listeners.\n   *\n   * @type {object}\n   */\n  #listeners = {};\n\n  /**\n   * Add an event listener.\n   *\n   * @param {string} type The event type.\n   * @param {object} callback The method associated with the provided\n   *    event type, will be called with the fired event.\n   */\n  add(type, callback) {\n    // create array if not present\n    if (typeof this.#listeners[type] === 'undefined') {\n      this.#listeners[type] = [];\n    }\n    // add callback to listeners array\n    this.#listeners[type].push(callback);\n  }\n\n  /**\n   * Remove an event listener.\n   *\n   * @param {string} type The event type.\n   * @param {object} callback The method associated with the provided\n   *   event type.\n   */\n  remove(type, callback) {\n    // check if the type is present\n    if (typeof this.#listeners[type] === 'undefined') {\n      return;\n    }\n    // remove from listeners array\n    let nFound = 0;\n    for (let i = 0; i < this.#listeners[type].length; ++i) {\n      if (this.#listeners[type][i] === callback) {\n        ++nFound;\n        this.#listeners[type].splice(i, 1);\n      }\n    }\n    if (nFound === 0) {\n      logger.debug('No callback found on remove listener for type ' + type);\n    }\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  fireEvent = (event) => {\n    // check if they are listeners for the event type\n    if (typeof this.#listeners[event.type] === 'undefined') {\n      return;\n    }\n    // fire events from a copy of the listeners array\n    // to avoid interference from possible add/remove\n    const stack = this.#listeners[event.type].slice();\n    for (let i = 0; i < stack.length; ++i) {\n      stack[i](event);\n    }\n  };\n}\n","import {Index} from '../math/index';\nimport {Point2D} from '../math/point';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {Matrix33} from '../math/matrix';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get an simple iterator for a given range for a one component data.\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols}.\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start The start of the range (included).\n * @param {number} end The end of the range (excluded).\n * @param {number} [increment] The increment between indicies (default=1).\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function simpleRange(dataAccessor, start, end, increment) {\n  if (typeof increment === 'undefined') {\n    increment = 1;\n  }\n  let nextIndex = start;\n  // result\n  return {\n    next: function () {\n      if (nextIndex < end) {\n        const result = {\n          value: dataAccessor(nextIndex),\n          done: false,\n          index: nextIndex\n        };\n        nextIndex += increment;\n        return result;\n      }\n      return {\n        done: true,\n        index: end\n      };\n    }\n  };\n}\n\n/**\n * Get an iterator for a given range for a one component data.\n *\n * Using 'maxIter' and not an 'end' index since it fails in some edge cases\n * (for ex coronal2, ie zxy).\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start Zero-based index at which to start the iteration.\n * @param {number} maxIter The maximum number of iterations.\n * @param {number} increment Increment between indicies.\n * @param {number} blockMaxIter Number of applied increment after which\n *   blockIncrement is applied.\n * @param {number} blockIncrement Increment after blockMaxIter is reached,\n *   the value is from block start to the next block start.\n * @param {boolean} reverse1 If true, loop from end to start.\n *   WARN: don't forget to set the value of start as the last index!\n * @param {boolean} reverse2 If true, loop from block end to block start.\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function range(dataAccessor, start, maxIter, increment,\n  blockMaxIter, blockIncrement, reverse1, reverse2) {\n  if (typeof reverse1 === 'undefined') {\n    reverse1 = false;\n  }\n  if (typeof reverse2 === 'undefined') {\n    reverse2 = false;\n  }\n\n  // first index of the iteration\n  let nextIndex = start;\n  // adapt first index and increments to reverse values\n  if (reverse1) {\n    blockIncrement *= -1;\n    if (reverse2) {\n      // start at end of line\n      nextIndex -= (blockMaxIter - 1) * increment;\n    } else {\n      increment *= -1;\n    }\n  } else {\n    if (reverse2) {\n      // start at end of line\n      nextIndex += (blockMaxIter - 1) * increment;\n      increment *= -1;\n    }\n  }\n  const finalBlockIncrement = blockIncrement - blockMaxIter * increment;\n\n  // counters\n  let mainCount = 0;\n  let blockCount = 0;\n  // result\n  return {\n    next: function () {\n      if (mainCount < maxIter) {\n        const result = {\n          value: dataAccessor(nextIndex),\n          done: false,\n          index: nextIndex\n        };\n        nextIndex += increment;\n        ++mainCount;\n        ++blockCount;\n        if (blockCount === blockMaxIter) {\n          blockCount = 0;\n          nextIndex += finalBlockIncrement;\n        }\n        return result;\n      }\n      return {\n        done: true,\n        index: nextIndex\n      };\n    }\n  };\n}\n\n/**\n * Get an iterator for a given range with bounds (for a one component data).\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols}.\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start The start of the range (included).\n * @param {number} end The end of the range (excluded).\n * @param {number} increment The increment between indicies.\n * @param {number} regionSize The size of the region to iterate through.\n * @param {number} regionOffset The offset between regions.\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function rangeRegion(\n  dataAccessor, start, end, increment, regionSize, regionOffset) {\n  let nextIndex = start;\n  let regionElementCount = 0;\n  // result\n  return {\n    next: function () {\n      if (nextIndex < end) {\n        const result = {\n          value: dataAccessor(nextIndex),\n          done: false,\n          index: nextIndex\n        };\n        regionElementCount += 1;\n        nextIndex += increment;\n        if (regionElementCount === regionSize) {\n          regionElementCount = 0;\n          nextIndex += regionOffset;\n        }\n        return result;\n      }\n      return {\n        done: true,\n        index: end\n      };\n    }\n  };\n}\n\n/**\n * Get an iterator for a given range with bounds (for a one component data).\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols}.\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start The start of the range (included).\n * @param {number} end The end of the range (excluded).\n * @param {number} increment The increment between indicies.\n * @param {number[][]} regions An array of regions: [off0, size, off1].\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function rangeRegions(\n  dataAccessor, start, end, increment, regions) {\n  let nextIndex = start;\n  let regionCount = 0;\n  let regionElementCount = 0;\n  // result\n  return {\n    next: function () {\n      if (nextIndex < end) {\n        const result = {\n          value: dataAccessor(nextIndex),\n          done: false,\n          index: nextIndex\n        };\n        regionElementCount += 1;\n        nextIndex += increment;\n        if (regionElementCount === regions[regionCount][1]) {\n          regionElementCount = 0;\n          // off1 of current group\n          nextIndex += regions[regionCount][2];\n          regionCount += 1;\n          // off0 of next group\n          if (regionCount < regions.length) {\n            nextIndex += regions[regionCount][0];\n          }\n        }\n        return result;\n      }\n      return {\n        done: true,\n        index: end\n      };\n    }\n  };\n}\n\n/**\n * Get an iterator for a given range for a 3 components data.\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols}.\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start The start of the range (included).\n * @param {number} end The end of the range (excluded).\n *   (end - start) needs to be a multiple of 3...\n * @param {number} increment The increment between indicies (default=1).\n * @param {boolean} isPlanar A flag to know if the data is planar\n *   (RRRR...GGGG...BBBB...) or not (RGBRGBRGBRGB...), defaults to false.\n * @returns {object} A 3 components iterator folowing the iterator and iterable\n *   protocol, the value is an array of size 3 with each component.\n */\nexport function simpleRange3d(\n  dataAccessor, start, end, increment, isPlanar) {\n  if (typeof increment === 'undefined') {\n    increment = 1;\n  }\n  if (typeof isPlanar === 'undefined') {\n    isPlanar = false;\n  }\n  let nextIndex = start;\n  let componentIncrement = 1;\n  if (isPlanar) {\n    componentIncrement = (end - start) / 3;\n  } else {\n    increment *= 3;\n  }\n  let nextIndex1 = nextIndex + componentIncrement;\n  let nextIndex2 = nextIndex + 2 * componentIncrement;\n\n  // result\n  return {\n    next: function () {\n      if (nextIndex < end) {\n        const result = {\n          value: [\n            dataAccessor(nextIndex),\n            dataAccessor(nextIndex1),\n            dataAccessor(nextIndex2)\n          ],\n          done: false,\n          index: [nextIndex, nextIndex1, nextIndex2]\n        };\n        nextIndex += increment;\n        nextIndex1 += increment;\n        nextIndex2 += increment;\n        return result;\n      }\n      return {\n        done: true,\n        index: [end]\n      };\n    }\n  };\n}\n\n/**\n * Get an iterator for a given range for a 3 components data.\n *\n * Using 'maxIter' and not an 'end' index since it fails in some edge cases\n * (for ex coronal2, ie zxy).\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start Zero-based index at which to start the iteration.\n * @param {number} maxIter The maximum number of iterations.\n * @param {number} increment Increment between indicies.\n * @param {number} blockMaxIter Number of applied increment after which\n *   blockIncrement is applied.\n * @param {number} blockIncrement Increment after blockMaxIter is reached,\n *   the value is from block start to the next block start.\n * @param {boolean} reverse1 If true, loop from end to start.\n *   WARN: don't forget to set the value of start as the last index!\n * @param {boolean} reverse2 If true, loop from block end to block start.\n * @param {boolean} isPlanar A flag to know if the data is planar\n *   (RRRR...GGGG...BBBB...) or not (RGBRGBRGBRGB...), defaults to false.\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function range3d(dataAccessor, start, maxIter, increment,\n  blockMaxIter, blockIncrement, reverse1, reverse2, isPlanar) {\n  const iters = [];\n  if (isPlanar) {\n    iters.push(range(\n      dataAccessor, start, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n    iters.push(range(\n      dataAccessor, start + maxIter * increment, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n    iters.push(range(\n      dataAccessor, start + 2 * maxIter * increment, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n  } else {\n    increment *= 3;\n    blockIncrement *= 3;\n    iters.push(range(\n      dataAccessor, start, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n    iters.push(range(\n      dataAccessor, start + 1, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n    iters.push(range(\n      dataAccessor, start + 2, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n  }\n\n  // result\n  return {\n    next: function () {\n      const r0 = iters[0].next();\n      const r1 = iters[1].next();\n      const r2 = iters[2].next();\n      if (!r0.done) {\n        return {\n          value: [\n            r0.value,\n            r1.value,\n            r2.value\n          ],\n          done: false,\n          index: [\n            r0.index,\n            r1.index,\n            r2.index\n          ]\n        };\n      }\n      return {\n        done: true,\n        index: r2.index\n      };\n    }\n  };\n}\n\n/**\n * Get a list of values for a given iterator.\n *\n * @param {object} iterator The iterator to use to loop through data.\n * @returns {Array} The list of values.\n */\nexport function getIteratorValues(iterator) {\n  const values = [];\n  let ival = iterator.next();\n  while (!ival.done) {\n    values.push(ival.value);\n    ival = iterator.next();\n  }\n  return values;\n}\n\n/**\n * Get a slice index iterator.\n *\n * @param {Image} image The image to parse.\n * @param {Index} index The current index.\n * @param {boolean} isRescaled Flag for rescaled values (default false).\n * @param {Matrix33} viewOrientation The view orientation.\n * @returns {object} The slice iterator.\n */\nexport function getSliceIterator(\n  image, index, isRescaled, viewOrientation) {\n  const size = image.getGeometry().getSize();\n  // zero-ify non direction index\n  let dirMax2Index = 2;\n  if (viewOrientation && typeof viewOrientation !== 'undefined') {\n    dirMax2Index = viewOrientation.getColAbsMax(2).index;\n  }\n  const posValues = index.getValues();\n  // keep the main direction and any other than 3D\n  const indexFilter = function (element, i) {\n    return (i === dirMax2Index || i > 2) ? element : 0;\n  };\n  const posStart = new Index(posValues.map(indexFilter));\n  let start = size.indexToOffset(posStart);\n\n  // default to non rescaled data\n  if (typeof isRescaled === 'undefined') {\n    isRescaled = false;\n  }\n  let dataAccessor = null;\n  if (isRescaled) {\n    dataAccessor = function (offset) {\n      return image.getRescaledValueAtOffset(offset);\n    };\n  } else {\n    dataAccessor = function (offset) {\n      return image.getValueAtOffset(offset);\n    };\n  }\n\n  const ncols = size.get(0);\n  const nrows = size.get(1);\n  const nslices = size.get(2);\n  let sliceSize = size.getDimSize(2);\n\n  const ncomp = image.getNumberOfComponents();\n  const isPlanar = image.getPlanarConfiguration() === 1;\n  const getRange = function (\n    dataAccessor, start, maxIter, increment,\n    blockMaxIter, blockIncrement, reverse1, reverse2) {\n    if (ncomp === 1) {\n      return range(dataAccessor, start, maxIter, increment,\n        blockMaxIter, blockIncrement, reverse1, reverse2);\n    } else if (ncomp === 3) {\n      return range3d(dataAccessor, 3 * start, maxIter, increment,\n        blockMaxIter, blockIncrement, reverse1, reverse2, isPlanar);\n    }\n  };\n\n  let rangeObj = null;\n  if (viewOrientation && typeof viewOrientation !== 'undefined') {\n    const dirMax0 = viewOrientation.getColAbsMax(0);\n    const dirMax2 = viewOrientation.getColAbsMax(2);\n\n    // default reverse\n    const reverse1 = false;\n    const reverse2 = false;\n\n    let maxIter = null;\n    if (dirMax2.index === 2) {\n      // axial\n      maxIter = ncols * nrows;\n      if (dirMax0.index === 0) {\n        // xyz\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, 1, ncols, ncols, reverse1, reverse2);\n      } else {\n        // yxz\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, ncols, nrows, 1, reverse1, reverse2);\n      }\n    } else if (dirMax2.index === 0) {\n      // sagittal\n      maxIter = nslices * nrows;\n      if (dirMax0.index === 1) {\n        // yzx\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, ncols, nrows, sliceSize, reverse1, reverse2);\n      } else {\n        // zyx\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, sliceSize, nslices, ncols, reverse1, reverse2);\n      }\n    } else if (dirMax2.index === 1) {\n      // coronal\n      maxIter = nslices * ncols;\n      if (dirMax0.index === 0) {\n        // xzy\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, 1, ncols, sliceSize, reverse1, reverse2);\n      } else {\n        // zxy\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, sliceSize, nslices, 1, reverse1, reverse2);\n      }\n    } else {\n      throw new Error('Unknown direction: ' + dirMax2.index);\n    }\n  } else {\n    if (image.getNumberOfComponents() === 1) {\n      rangeObj = simpleRange(dataAccessor, start, start + sliceSize);\n    } else if (image.getNumberOfComponents() === 3) {\n      // 3 times bigger...\n      start *= 3;\n      sliceSize *= 3;\n      rangeObj = simpleRange3d(\n        dataAccessor, start, start + sliceSize, 1, isPlanar);\n    } else {\n      throw new Error('Unsupported number of components: ' +\n        image.getNumberOfComponents());\n    }\n  }\n\n  return rangeObj;\n}\n\n/**\n * Get a slice index iterator for a rectangular region.\n *\n * @param {Image} image The image to parse.\n * @param {Index} index The current index.\n * @param {boolean} isRescaled Flag for rescaled values (default false).\n * @param {Point2D} min The minimum position (optional).\n * @param {Point2D} max The maximum position (optional).\n * @returns {object} The slice iterator.\n */\nexport function getRegionSliceIterator(\n  image, index, isRescaled, min, max) {\n  if (image.getNumberOfComponents() !== 1) {\n    throw new Error('Unsupported number of components for region iterator: ' +\n      image.getNumberOfComponents());\n  }\n\n  // default to non rescaled data\n  if (typeof isRescaled === 'undefined') {\n    isRescaled = false;\n  }\n  let dataAccessor = null;\n  if (isRescaled) {\n    dataAccessor = function (offset) {\n      return image.getRescaledValueAtOffset(offset);\n    };\n  } else {\n    dataAccessor = function (offset) {\n      return image.getValueAtOffset(offset);\n    };\n  }\n\n  const size = image.getGeometry().getSize();\n  if (typeof min === 'undefined') {\n    min = new Point2D(0, 0);\n  }\n  if (typeof max === 'undefined') {\n    max = new Point2D(\n      size.get(0) - 1,\n      size.get(1)\n    );\n  }\n  // position to pixel for max: extra X is ok, remove extra Y\n  const startOffset = size.indexToOffset(index.getWithNew2D(\n    min.getX(), min.getY()\n  ));\n  const endOffset = size.indexToOffset(index.getWithNew2D(\n    max.getX(), max.getY() - 1\n  ));\n\n  // minimum 1 column\n  const rangeNumberOfColumns = Math.max(1, max.getX() - min.getX());\n  const rowIncrement = size.get(0) - rangeNumberOfColumns;\n\n  return rangeRegion(\n    dataAccessor, startOffset, endOffset + 1,\n    1, rangeNumberOfColumns, rowIncrement);\n}\n\n/**\n * Get a slice index iterator for a rectangular region.\n *\n * @param {Image} image The image to parse.\n * @param {Index} index The current index.\n * @param {boolean} isRescaled Flag for rescaled values (default false).\n * @param {number[][][]} regions An array of [x, y] pairs (min, max).\n * @returns {object|undefined} The slice iterator.\n */\nexport function getVariableRegionSliceIterator(\n  image, index, isRescaled, regions) {\n  if (image.getNumberOfComponents() !== 1) {\n    throw new Error('Unsupported number of components for region iterator: ' +\n      image.getNumberOfComponents());\n  }\n\n  // default to non rescaled data\n  if (typeof isRescaled === 'undefined') {\n    isRescaled = false;\n  }\n  let dataAccessor = null;\n  if (isRescaled) {\n    dataAccessor = function (offset) {\n      return image.getRescaledValueAtOffset(offset);\n    };\n  } else {\n    dataAccessor = function (offset) {\n      return image.getValueAtOffset(offset);\n    };\n  }\n\n  const size = image.getGeometry().getSize();\n\n  const offsetRegions = [];\n  let region;\n  let min = null;\n  let max = null;\n  let regionIndex = null;\n  for (let i = 0; i < regions.length; ++i) {\n    region = regions[i];\n    const width = region[1][0] - region[0][0];\n    if (width !== 0) {\n      regionIndex = i;\n      if (!min) {\n        min = region[0];\n      }\n      offsetRegions.push([\n        region[0][0],\n        width,\n        size.get(0) - region[1][0]\n      ]);\n    }\n  }\n  if (regionIndex !== null) {\n    max = regions[regionIndex][1];\n  }\n\n  // exit if no offsets\n  if (offsetRegions.length === 0) {\n    return undefined;\n  }\n\n  const startOffset = size.indexToOffset(index.getWithNew2D(\n    min[0], min[1]\n  ));\n  const endOffset = size.indexToOffset(index.getWithNew2D(\n    max[0], max[1]\n  ));\n\n  return rangeRegions(\n    dataAccessor, startOffset, endOffset + 1,\n    1, offsetRegions);\n}\n\n/**\n * Get a multiple value iterator. The input array defines the values and\n * their start index.\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols}.\n *\n * @param {Array} values An array of {index, value} pairs.\n * @param {number} end The end of the range (excluded).\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function valueRange(values, end) {\n  let nextIndex = 0;\n  let nextValueIndex = 0;\n  // result\n  return {\n    next: function () {\n      if (nextIndex < end) {\n        if (nextValueIndex + 1 < values.length &&\n          nextIndex >= values[nextValueIndex + 1].index) {\n          ++nextValueIndex;\n        }\n        const result = {\n          value: values[nextValueIndex].value,\n          done: false,\n          index: nextIndex\n        };\n        ++nextIndex;\n        return result;\n      }\n      return {\n        done: true,\n        index: end\n      };\n    }\n  };\n}\n","/**\n * Rescale Slope and Intercept.\n */\nexport class RescaleSlopeAndIntercept {\n\n  /**\n   * The slope.\n   *\n   * @type {number}\n   */\n  #slope;\n\n  /**\n   * The intercept.\n   *\n   * @type {number}\n   */\n  #intercept;\n\n  /**\n   * @param {number} slope The slope of the RSI.\n   * @param {number} intercept The intercept of the RSI.\n   */\n  constructor(slope, intercept) {\n    /*// Check the rescale slope.\n      if(typeof(slope) === 'undefined') {\n          slope = 1;\n      }\n      // Check the rescale intercept.\n      if(typeof(intercept) === 'undefined') {\n          intercept = 0;\n      }*/\n    this.#slope = slope;\n    this.#intercept = intercept;\n  }\n\n  /**\n   * Get the slope of the RSI.\n   *\n   * @returns {number} The slope of the RSI.\n   */\n  getSlope() {\n    return this.#slope;\n  }\n\n  /**\n   * Get the intercept of the RSI.\n   *\n   * @returns {number} The intercept of the RSI.\n   */\n  getIntercept() {\n    return this.#intercept;\n  }\n\n  /**\n   * Apply the RSI on an input value.\n   *\n   * @param {number} value The input value.\n   * @returns {number} The value to rescale.\n   */\n  apply(value) {\n    return value * this.#slope + this.#intercept;\n  }\n\n  /**\n   * Check for RSI equality.\n   *\n   * @param {RescaleSlopeAndIntercept} rhs The other RSI to compare to.\n   * @returns {boolean} True if both RSI are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      typeof rhs !== 'undefined' &&\n      this.getSlope() === rhs.getSlope() &&\n      this.getIntercept() === rhs.getIntercept();\n  }\n\n  /**\n   * Is this RSI an ID RSI.\n   *\n   * @returns {boolean} True if the RSI has a slope of 1 and no intercept.\n   */\n  isID() {\n    return (this.getSlope() === 1 && this.getIntercept() === 0);\n  }\n\n} // class RescaleSlopeAndIntercept\n","import {Index} from '../math/index';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Matrix33} from '../math/matrix';\nimport {Scalar2D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Immutable Size class.\n * Warning: the input array is NOT cloned, modifying it will\n *  modify the index values.\n */\nexport class Size {\n\n  /**\n   * The size values.\n   *\n   * @type {number[]}\n   */\n  #values;\n\n  /**\n   * @param {number[]} values The size values.\n   */\n  constructor(values) {\n    if (!values || typeof values === 'undefined') {\n      throw new Error('Cannot create size with no values.');\n    }\n    if (values.length === 0) {\n      throw new Error('Cannot create size with empty values.');\n    }\n    const valueCheck = function (val) {\n      return !isNaN(val) && val !== 0;\n    };\n    if (!values.every(valueCheck)) {\n      throw new Error('Cannot create size with non number or zero values.');\n    }\n    this.#values = values;\n  }\n\n  /**\n   * Get the size value at the given array index.\n   *\n   * @param {number} i The index to get.\n   * @returns {number} The value.\n   */\n  get(i) {\n    return this.#values[i];\n  }\n\n  /**\n   * Get the length of the index.\n   *\n   * @returns {number} The length.\n   */\n  length() {\n    return this.#values.length;\n  }\n\n  /**\n   * Get a string representation of the size.\n   *\n   * @returns {string} The Size as a string.\n   */\n  toString() {\n    return '(' + this.#values.toString() + ')';\n  }\n\n  /**\n   * Get the values of this index.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return this.#values.slice();\n  }\n\n  /**\n   * Check if a dimension exists and has more than one element.\n   *\n   * @param {number} dimension The dimension to check.\n   * @returns {boolean} True if the size is more than one.\n   */\n  moreThanOne(dimension) {\n    return this.length() >= dimension + 1 && this.get(dimension) !== 1;\n  }\n\n  /**\n   * Check if the associated data is scrollable in 3D.\n   *\n   * @param {Matrix33} [viewOrientation] The orientation matrix.\n   * @returns {boolean} True if scrollable.\n   */\n  canScroll3D(viewOrientation) {\n    let dimension = 2;\n    if (typeof viewOrientation !== 'undefined') {\n      dimension = viewOrientation.getThirdColMajorDirection();\n    }\n    return this.moreThanOne(dimension);\n  }\n\n  /**\n   * Check if the associated data is scrollable: either in 3D or\n   * in other directions.\n   *\n   * @param {Matrix33} viewOrientation The orientation matrix.\n   * @returns {boolean} True if scrollable.\n   */\n  canScroll(viewOrientation) {\n    let canScroll = this.canScroll3D(viewOrientation);\n    // check possible other dimensions\n    for (let i = 3; i < this.length(); ++i) {\n      canScroll = canScroll || this.moreThanOne(i);\n    }\n    return canScroll;\n  }\n\n  /**\n   * Get the size of a given dimension.\n   *\n   * @param {number} dimension The dimension.\n   * @param {number} [start] Optional start dimension to start counting from.\n   * @returns {number} The size.\n   */\n  getDimSize(dimension, start) {\n    if (dimension > this.length()) {\n      return null;\n    }\n    if (typeof start === 'undefined') {\n      start = 0;\n    } else {\n      if (start < 0 || start > dimension) {\n        throw new Error('Invalid start value for getDimSize');\n      }\n    }\n    let size = 1;\n    for (let i = start; i < dimension; ++i) {\n      size *= this.get(i);\n    }\n    return size;\n  }\n\n  /**\n   * Get the total size.\n   *\n   * @param {number} [start] Optional start dimension to base the offset on.\n   * @returns {number} The total size.\n   */\n  getTotalSize(start) {\n    return this.getDimSize(this.length(), start);\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Size} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    // check input\n    if (!rhs) {\n      return false;\n    }\n    // check length\n    const length = this.length();\n    if (length !== rhs.length()) {\n      return false;\n    }\n    // check values\n    for (let i = 0; i < length; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        return false;\n      }\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Check that an index is within bounds.\n   *\n   * @param {Index} index The index to check.\n   * @param {number[]} dirs Optional list of directions to check.\n   * @returns {boolean} True if the given coordinates are within bounds.\n   */\n  isInBounds(index, dirs) {\n    // check input\n    if (!index) {\n      return false;\n    }\n    // check length\n    const length = this.length();\n    if (length !== index.length()) {\n      return false;\n    }\n    // create dirs if not there\n    if (typeof dirs === 'undefined') {\n      dirs = [];\n      for (let j = 0; j < length; ++j) {\n        dirs.push(j);\n      }\n    } else {\n      for (let k = 0; k < length; ++k) {\n        if (dirs[k] > length - 1) {\n          throw new Error('Wrong input dir value: ' + dirs[k]);\n        }\n      }\n    }\n    // check values is 0 <= v < size\n    const inBound = function (value, size) {\n      return value >= 0 && value < size;\n    };\n    // check\n    for (let i = 0; i < dirs.length; ++i) {\n      if (!inBound(index.get(dirs[i]), this.get(dirs[i]))) {\n        return false;\n      }\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Convert an index to an offset in memory.\n   *\n   * @param {Index} index The index to convert.\n   * @param {number} [start] Optional start dimension to base the offset on.\n   * @returns {number} The offset.\n   */\n  indexToOffset(index, start) {\n    // TODO check for equality\n    if (index.length() < this.length()) {\n      throw new Error('Incompatible index and size length');\n    }\n    if (typeof start === 'undefined') {\n      start = 0;\n    } else {\n      if (start < 0 || start > this.length() - 1) {\n        throw new Error('Invalid start value for indexToOffset');\n      }\n    }\n    let offset = 0;\n    for (let i = start; i < this.length(); ++i) {\n      offset += index.get(i) * this.getDimSize(i, start);\n    }\n    return offset;\n  }\n\n  /**\n   * Convert an offset in memory to an index.\n   *\n   * @param {number} offset The offset to convert.\n   * @returns {Index} The index.\n   */\n  offsetToIndex(offset) {\n    const values = new Array(this.length());\n    let off = offset;\n    let dimSize = 0;\n    for (let i = this.length() - 1; i > 0; --i) {\n      dimSize = this.getDimSize(i);\n      values[i] = Math.floor(off / dimSize);\n      off = off - values[i] * dimSize;\n    }\n    values[0] = off;\n    return new Index(values);\n  }\n\n  /**\n   * Get the 2D base of this size.\n   *\n   * @returns {Scalar2D} The 2D base [0,1] as {x,y}.\n   */\n  get2D() {\n    return {\n      x: this.get(0),\n      y: this.get(1)\n    };\n  }\n\n} // Size class\n","/**\n * Statistics storage class.\n * 'simple' statistics do not include median, p25 nor p75.\n */\nexport class Statistics {\n  /**\n   * Minimum.\n   *\n   * @type {number}\n   */\n  min;\n  /**\n   * Maximum.\n   *\n   * @type {number}\n   */\n  max;\n  /**\n   * Mean.\n   *\n   * @type {number}\n   */\n  mean;\n  /**\n   * Standard deviation.\n   *\n   * @type {number}\n   */\n  stdDev;\n  /**\n   * Median.\n   *\n   * @type {number|undefined}\n   */\n  median;\n  /**\n   * 25th percentile.\n   *\n   * @type {number|undefined}\n   */\n  p25;\n  /**\n   * 75th percentile.\n   *\n   * @type {number|undefined}\n   */\n  p75;\n\n  /**\n   * @param {number} min The minimum.\n   * @param {number} max The maxnimum.\n   * @param {number} mean The mean.\n   * @param {number} stdDev The standard deviation.\n   */\n  constructor(min, max, mean, stdDev) {\n    this.min = min;\n    this.max = max;\n    this.mean = mean;\n    this.stdDev = stdDev;\n  }\n}\n\n/**\n * Get statistics on an input array of number.\n * Note: could use {@link https://github.com/tmcw/simple-statistics}.\n *\n * @param {number[]} values The array of values to extract stats from.\n * @param {string[]} flags A list of stat value names to calculate.\n * @returns {Statistics} A statistics object.\n */\nexport function getStats(values, flags) {\n  if (includesFullStatsFlags(flags)) {\n    return getFullStats(values);\n  } else {\n    return getBasicStats(values);\n  }\n}\n\n/**\n * Does the input flag list contain a full stat element?\n *\n * @param {string[]} flags A list of stat values to calculate.\n * @returns {boolean} True if one of the flags is a full stat flag.\n */\nfunction includesFullStatsFlags(flags) {\n  return typeof flags !== 'undefined' &&\n    flags !== null &&\n    (flags.includes('median') ||\n    flags.includes('p25') ||\n    flags.includes('p75'));\n}\n\n/**\n * Get simple stats: minimum, maximum, mean and standard deviation\n * of an array of values.\n *\n * @param {number[]} values The array of values to extract stats from.\n * @returns {Statistics} Simple statistics (no median, p25 nor p75).\n */\nexport function getBasicStats(values) {\n  let min = values[0];\n  let max = min;\n  let sum = 0;\n  let sumSqr = 0;\n  let val = 0;\n  const length = values.length;\n  for (let i = 0; i < length; ++i) {\n    val = values[i];\n    if (val < min) {\n      min = val;\n    } else if (val > max) {\n      max = val;\n    }\n    sum += val;\n    sumSqr += val * val;\n  }\n\n  const mean = sum / length;\n  // see http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance\n  let variance = sumSqr / length - mean * mean;\n  if (variance < 0) {\n    variance = 0;\n  }\n  const stdDev = Math.sqrt(variance);\n\n  return new Statistics(min, max, mean, stdDev);\n}\n\n/**\n * Get full stats: minimum, maximum, mean, standard deviation, median, 25%\n * and 75% percentile of an array of values.\n *\n * @param {number[]} values The array of values to extract stats from.\n * @returns {Statistics} Complete statistics (includes median, p25 and p75).\n */\nfunction getFullStats(values) {\n  // get basic stats\n  const stats = getBasicStats(values);\n\n  // sort array... can get slow...\n  values.sort(function (a, b) {\n    return a - b;\n  });\n\n  stats.median = getPercentile(values, 0.5);\n  stats.p25 = getPercentile(values, 0.25);\n  stats.p75 = getPercentile(values, 0.75);\n\n  return stats;\n}\n\n/**\n * Get an arrays' percentile. Uses linear interpolation for percentiles\n *   that lie between data points.\n * See: {@link https://en.wikipedia.org/wiki/Percentile} (second variant interpolation).\n *\n * @param {number[]} values The sorted array of values.\n * @param {number} ratio The percentile ratio [0-1].\n * @returns {number} The percentile.\n */\nfunction getPercentile(values, ratio) {\n  // check input\n  if (values.length === 0) {\n    throw new Error('Empty array provided for percentile calculation.');\n  }\n  if (ratio < 0 || ratio > 1) {\n    throw new Error(\n      'Invalid ratio provided for percentile calculation: ' + ratio);\n  }\n  // return min for ratio=0 amd max for ratio=1\n  if (ratio === 0) {\n    return values[0];\n  } else if (ratio === 1) {\n    return values[values.length - 1];\n  }\n  // general case: interpolate between indices if needed\n  const i = (values.length - 1) * ratio;\n  const i0 = Math.floor(i);\n  const v0 = values[i0];\n  const v1 = values[i0 + 1];\n  return v0 + (v1 - v0) * (i - i0);\n}\n\n/**\n * Unique ID generator.\n *\n * See {@link http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript}\n *   and this {@link http://stackoverflow.com/a/13403498 answer}.\n *\n * @returns {string} A unique ID.\n */\nexport function guid() {\n  return Math.random().toString(36).substring(2, 15);\n}\n\n/**\n * Number range.\n */\nexport class NumberRange {\n  /**\n   * @type {number}\n   */\n  min;\n  /**\n   * @type {number}\n   */\n  max;\n  /**\n   * @param {number} min The minimum.\n   * @param {number} max The maximum.\n   */\n  constructor(min, max) {\n    this.min = min;\n    this.max = max;\n  }\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {Scalar2D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Immutable Spacing class.\n * Warning: the input array is NOT cloned, modifying it will\n *  modify the index values.\n */\nexport class Spacing {\n\n  /**\n   * The spacing values.\n   *\n   * @type {number[]}\n   */\n  #values;\n\n  /**\n   * @param {number[]} values The spacing values.\n   */\n  constructor(values) {\n    if (!values || typeof values === 'undefined') {\n      throw new Error('Cannot create spacing with no values.');\n    }\n    if (values.length === 0) {\n      throw new Error('Cannot create spacing with empty values.');\n    }\n    const valueCheck = function (val) {\n      return !isNaN(val) && val !== 0;\n    };\n    if (!values.every(valueCheck)) {\n      throw new Error('Cannot create spacing with non number or zero values.');\n    }\n    this.#values = values;\n  }\n\n  /**\n   * Get the spacing value at the given array index.\n   *\n   * @param {number} i The index to get.\n   * @returns {number} The value.\n   */\n  get(i) {\n    return this.#values[i];\n  }\n\n  /**\n   * Get the length of the spacing.\n   *\n   * @returns {number} The length.\n   */\n  length() {\n    return this.#values.length;\n  }\n\n  /**\n   * Get a string representation of the spacing.\n   *\n   * @returns {string} The spacing as a string.\n   */\n  toString() {\n    return '(' + this.#values.toString() + ')';\n  }\n\n  /**\n   * Get the values of this spacing.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return this.#values.slice();\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Spacing} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    // check input\n    if (!rhs) {\n      return false;\n    }\n    // check length\n    const length = this.length();\n    if (length !== rhs.length()) {\n      return false;\n    }\n    // check values\n    for (let i = 0; i < length; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        return false;\n      }\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Get the 2D base of this size.\n   *\n   * @returns {Scalar2D} The 2D base [col,row] as {x,y}.\n   */\n  get2D() {\n    return {\n      x: this.get(0),\n      y: this.get(1)\n    };\n  }\n\n} // Spacing class\n","import {\n  getIdentityMat33,\n  REAL_WORLD_EPSILON\n} from '../math/matrix';\nimport {Point3D, Point} from '../math/point';\nimport {Vector3D} from '../math/vector';\nimport {Index} from '../math/index';\nimport {getBasicStats} from '../math/stats';\nimport {precisionRound} from '../utils/string';\nimport {logger} from '../utils/logger';\nimport {Size} from './size';\nimport {Spacing} from './spacing';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Matrix33} from '../math/matrix';\n/* eslint-enable no-unused-vars */\n\n/**\n * 2D/3D Geometry class.\n */\nexport class Geometry {\n\n  /**\n   * Array of origins.\n   *\n   * @type {Point3D[]}\n   */\n  #origins;\n\n  /**\n   * Data size.\n   *\n   * @type {Size}\n   */\n  #size;\n\n  /**\n   * Data spacing.\n   *\n   * @type {Spacing}\n   */\n  #spacing;\n\n  /**\n   * Local helper object for time points.\n   *\n   * @type {Object<string, Point3D[]>}\n   */\n  #timeOrigins = {};\n\n  /**\n   * Initial time index.\n   *\n   * @type {number}\n   */\n  #initialTime;\n\n  /**\n   * Data orientation.\n   *\n   * @type {Matrix33}\n   */\n  #orientation = getIdentityMat33();\n\n  /**\n   * Flag to know if new origins were added.\n   *\n   * @type {boolean}\n   */\n  #newOrigins = false;\n\n  /**\n   * @param {Point3D[]} origins The object origins.\n   * @param {Size} size The object size.\n   * @param {Spacing} spacing The object spacing.\n   * @param {Matrix33} [orientation] The object orientation (3*3 matrix,\n   *   default to 3*3 identity).\n   * @param {number} [time] Optional time index.\n   */\n  constructor(origins, size, spacing, orientation, time) {\n    this.#origins = origins;\n    this.#size = size;\n    this.#spacing = spacing;\n    if (typeof time !== 'undefined') {\n      this.#initialTime = time;\n      this.#timeOrigins[time] = origins;\n    }\n    // check input orientation\n    if (typeof orientation !== 'undefined') {\n      this.#orientation = orientation;\n    }\n  }\n\n  /**\n   * Get the time value that was passed at construction.\n   *\n   * @returns {number} The time value.\n   */\n  getInitialTime() {\n    return this.#initialTime;\n  }\n\n  /**\n   * Get the total number of slices.\n   * Can be different from what is stored in the size object\n   *  during a volume with time points creation process.\n   *\n   * @returns {number} The total count.\n   */\n  getCurrentTotalNumberOfSlices() {\n    const keys = Object.keys(this.#timeOrigins);\n    if (keys.length === 0) {\n      return this.#origins.length;\n    }\n    let count = 0;\n    for (let i = 0; i < keys.length; ++i) {\n      count += this.#timeOrigins[keys[i]].length;\n    }\n    return count;\n  }\n\n  /**\n   * Check if a time point has associated slices.\n   *\n   * @param {number} time The time point to check.\n   * @returns {boolean} True if slices are present.\n   */\n  hasSlicesAtTime(time) {\n    return typeof this.#timeOrigins[time] !== 'undefined';\n  }\n\n  /**\n   * Get the number of slices stored for time points preceding\n   * the input one.\n   *\n   * @param {number} time The time point to check.\n   * @returns {number|undefined} The count.\n   */\n  getCurrentNumberOfSlicesBeforeTime(time) {\n    const keys = Object.keys(this.#timeOrigins);\n    if (keys.length === 0) {\n      return undefined;\n    }\n    let count = 0;\n    for (let i = 0; i < keys.length; ++i) {\n      const key = keys[i];\n      if (parseInt(key, 10) === time) {\n        break;\n      }\n      count += this.#timeOrigins[key].length;\n    }\n    return count;\n  }\n\n  /**\n   * Get the object origin.\n   * This should be the lowest origin to ease calculations (?).\n   *\n   * @returns {Point3D} The object origin.\n   */\n  getOrigin() {\n    return this.#origins[0];\n  }\n\n  /**\n   * Get the object origins.\n   *\n   * @returns {Point3D[]} The object origins.\n   */\n  getOrigins() {\n    return this.#origins;\n  }\n\n  /**\n   * Check if a point is in the origin list.\n   *\n   * @param {Point3D} point3D The point to check.\n   * @param {number} tol The comparison tolerance\n   *   default to Number.EPSILON.\n   * @returns {boolean} True if in list.\n   */\n  includesOrigin(point3D, tol) {\n    for (let i = 0; i < this.#origins.length; ++i) {\n      if (this.#origins[i].isSimilar(point3D, tol)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Get the object size.\n   * Warning: the size comes as stored in DICOM, meaning that it could\n   * be oriented.\n   *\n   * @param {Matrix33} [viewOrientation] The view orientation (optional).\n   * @returns {Size} The object size.\n   */\n  getSize(viewOrientation) {\n    let res = this.#size;\n    if (viewOrientation && typeof viewOrientation !== 'undefined') {\n      let values = getOrientedArray3D(\n        [\n          this.#size.get(0),\n          this.#size.get(1),\n          this.#size.get(2)\n        ],\n        viewOrientation);\n      values = values.map(Math.abs);\n      res = new Size(values.concat(this.#size.getValues().slice(3)));\n    }\n    return res;\n  }\n\n  /**\n   * Calculate slice spacing from origins and replace current\n   *   if needed.\n   */\n  #updateSliceSpacing() {\n    const geoSliceSpacing = getSliceGeometrySpacing(this.#origins);\n    // update local if needed\n    if (typeof geoSliceSpacing !== 'undefined' &&\n      this.#spacing.get(2) !== geoSliceSpacing) {\n      logger.trace('Using geometric spacing ' + geoSliceSpacing +\n        ' instead of tag spacing ' + this.#spacing.get(2));\n      const values = this.#spacing.getValues();\n      values[2] = geoSliceSpacing;\n      this.#spacing = new Spacing(values);\n    }\n  }\n\n  /**\n   * Get the object spacing.\n   * Warning: the spacing comes as stored in DICOM, meaning that it could\n   * be oriented.\n   *\n   * @param {Matrix33} [viewOrientation] The view orientation (optional).\n   * @returns {Spacing} The object spacing.\n   */\n  getSpacing(viewOrientation) {\n    // update slice spacing after appendSlice\n    if (this.#newOrigins) {\n      this.#updateSliceSpacing();\n      this.#newOrigins = false;\n    }\n    let res = this.#spacing;\n    if (viewOrientation && typeof viewOrientation !== 'undefined') {\n      let orientedValues = getOrientedArray3D(\n        [\n          this.#spacing.get(0),\n          this.#spacing.get(1),\n          this.#spacing.get(2)\n        ],\n        viewOrientation);\n      orientedValues = orientedValues.map(Math.abs);\n      res = new Spacing(orientedValues);\n    }\n    return res;\n  }\n\n  /**\n   * Get the image spacing in real world.\n   *\n   * @returns {Spacing} The object spacing.\n   */\n  getRealSpacing() {\n    // asOneAndZeros to not change spacing values...\n    return this.getSpacing(\n      this.#orientation.getInverse().asOneAndZeros()\n    );\n  }\n\n  /**\n   * Get the object orientation.\n   *\n   * @returns {Matrix33} The object orientation.\n   */\n  getOrientation() {\n    return this.#orientation;\n  }\n\n  /**\n   * Get the slice position of a point in the current slice layout.\n   * Slice indices increase with decreasing origins (high index -> low origin),\n   * this simplified the handling of reconstruction since it means\n   * the displayed data is in the same 'direction' as the extracted data.\n   * As seen in the getOrigin method, the main origin is the lowest one.\n   * This implies that the index to world and reverse method do some flipping\n   * magic...\n   *\n   * @param {Point3D} point The point to evaluate.\n   * @param {number} time Optional time index.\n   * @returns {number} The slice index.\n   */\n  getSliceIndex(point, time) {\n    // cannot use this.worldToIndex(point).getK() since\n    // we cannot guaranty consecutive slices...\n\n    let localOrigins = this.#origins;\n    if (typeof time !== 'undefined') {\n      localOrigins = this.#timeOrigins[time];\n    }\n\n    // find the closest origin\n    const closestOriginIndex = point.getClosest(localOrigins);\n    const closestOrigin = localOrigins[closestOriginIndex];\n\n    // direction between the input point and the closest origin\n    const pointDir = point.minus(closestOrigin);\n\n    // use third orientation matrix column as plane normal vector\n    const normal = new Vector3D(\n      this.#orientation.get(0, 2),\n      this.#orientation.get(1, 2),\n      this.#orientation.get(2, 2)\n    );\n\n    // codirectional vectors: above slice index\n    // oposite vectors: below slice index\n    const isCodirectional = normal.isCodirectional(pointDir);\n    const sliceIndex = isCodirectional\n      ? closestOriginIndex + 1 : closestOriginIndex;\n\n    return sliceIndex;\n  }\n\n  /**\n   * Append an origin to the geometry.\n   *\n   * @param {Point3D} origin The origin to append.\n   * @param {number} index The index at which to append.\n   * @param {number} [time] Optional time index.\n   */\n  appendOrigin(origin, index, time) {\n    // equal callback\n    const equalToOrigin = function (element) {\n      return element.equals(origin);\n    };\n    if (typeof time !== 'undefined') {\n      // check if not already in list\n      const found = this.#timeOrigins[time].find(equalToOrigin);\n      if (typeof found !== 'undefined') {\n        throw new Error('Cannot append same time origin twice');\n      }\n      // add in origin array\n      this.#timeOrigins[time].splice(index, 0, origin);\n    }\n    if (typeof time === 'undefined' || time === this.#initialTime) {\n      // check if not already in list\n      const found = this.#origins.find(equalToOrigin);\n      if (typeof found !== 'undefined') {\n        throw new Error('Cannot append same origin twice');\n      }\n      // update flag\n      this.#newOrigins = true;\n      // add in origin array\n      this.#origins.splice(index, 0, origin);\n      // increment second dimension\n      const values = this.#size.getValues();\n      values[2] += 1;\n      this.#size = new Size(values);\n    }\n  }\n\n  /**\n   * Append a frame to the geometry.\n   *\n   * @param {Point3D} origin The origin to append.\n   * @param {number} time Optional time index.\n   */\n  appendFrame(origin, time) {\n    // add origin to list\n    this.#timeOrigins[time] = [origin];\n    // increment third dimension\n    const sizeValues = this.#size.getValues();\n    const spacingValues = this.#spacing.getValues();\n    if (sizeValues.length === 4) {\n      sizeValues[3] += 1;\n    } else {\n      sizeValues.push(2);\n      spacingValues.push(1);\n    }\n    this.#size = new Size(sizeValues);\n    this.#spacing = new Spacing(spacingValues);\n  }\n\n  /**\n   * Get a string representation of the geometry.\n   *\n   * @returns {string} The geometry as a string.\n   */\n  toString() {\n    return 'Origin: ' + this.getOrigin() +\n      ', Size: ' + this.getSize() +\n      ', Spacing: ' + this.getSpacing() +\n      ', Orientation: ' + this.getOrientation();\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Geometry} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.getOrigin().equals(rhs.getOrigin()) &&\n      this.getSize().equals(rhs.getSize()) &&\n      this.getSpacing().equals(rhs.getSpacing());\n  }\n\n  /**\n   * Check that a point is within bounds.\n   *\n   * @param {Point} point The point to check.\n   * @returns {boolean} True if the given coordinates are within bounds.\n   */\n  isInBounds(point) {\n    return this.isIndexInBounds(this.worldToIndex(point));\n  }\n\n  /**\n   * Check that a index is within bounds.\n   *\n   * @param {Index} index The index to check.\n   * @param {number[]} [dirs] Optional list of directions to check.\n   * @returns {boolean} True if the given coordinates are within bounds.\n   */\n  isIndexInBounds(index, dirs) {\n    return this.getSize().isInBounds(index, dirs);\n  }\n\n  /**\n   * Get the geometrical range, ie the minimum and maximum\n   *   positions.\n   *\n   * @returns {Point[]} The min and max positions.\n   */\n  getRange() {\n    const nDims = this.getSize().length();\n    const minValues = new Array(nDims);\n    minValues.fill(0);\n    const minIndex = new Index(minValues);\n    const maxIndex = new Index(this.getSize().getValues());\n    return [\n      this.indexToWorld(minIndex),\n      this.indexToWorld(maxIndex)\n    ];\n  }\n\n  /**\n   * Convert an index into world coordinates.\n   *\n   * @param {Index} index The index to convert.\n   * @returns {Point} The corresponding point.\n   */\n  indexToWorld(index) {\n    // apply spacing\n    // (spacing is oriented, apply before orientation)\n    const spacing = this.getSpacing();\n    const orientedPoint3D = new Point3D(\n      index.get(0) * spacing.get(0),\n      index.get(1) * spacing.get(1),\n      index.get(2) * spacing.get(2)\n    );\n    // de-orient\n    const point3D = this.getOrientation().multiplyPoint3D(orientedPoint3D);\n    // keep >3d values\n    const values = index.getValues();\n    const origin = this.getOrigin();\n    values[0] = origin.getX() + point3D.getX();\n    values[1] = origin.getY() + point3D.getY();\n    values[2] = origin.getZ() + point3D.getZ();\n    // return point\n    return new Point(values);\n  }\n\n  /**\n   * Convert a 3D point into world coordinates.\n   *\n   * @param {Point3D} point The 3D point to convert.\n   * @returns {Point3D} The corresponding world 3D point.\n   */\n  pointToWorld(point) {\n    // apply spacing\n    // (spacing is oriented, apply before orientation)\n    const spacing = this.getSpacing();\n    const orientedPoint3D = new Point3D(\n      point.getX() * spacing.get(0),\n      point.getY() * spacing.get(1),\n      point.getZ() * spacing.get(2)\n    );\n    // de-orient\n    const point3D = this.getOrientation().multiplyPoint3D(orientedPoint3D);\n    // return point3D\n    const origin = this.getOrigin();\n    return new Point3D(\n      origin.getX() + point3D.getX(),\n      origin.getY() + point3D.getY(),\n      origin.getZ() + point3D.getZ()\n    );\n  }\n\n  /**\n   * Convert world coordinates into an index.\n   *\n   * @param {Point} point The point to convert.\n   * @returns {Index} The corresponding index.\n   */\n  worldToIndex(point) {\n    // compensate for origin\n    // (origin is not oriented, compensate before orientation)\n    // TODO: use slice origin...\n    const origin = this.getOrigin();\n    const point3D = new Point3D(\n      point.get(0) - origin.getX(),\n      point.get(1) - origin.getY(),\n      point.get(2) - origin.getZ()\n    );\n    // orient\n    const orientedPoint3D =\n      this.getOrientation().getInverse().multiplyPoint3D(point3D);\n    // keep >3d values\n    const values = point.getValues();\n    // apply spacing and round\n    const spacing = this.getSpacing();\n    values[0] = Math.round(orientedPoint3D.getX() / spacing.get(0));\n    values[1] = Math.round(orientedPoint3D.getY() / spacing.get(1));\n    values[2] = Math.round(orientedPoint3D.getZ() / spacing.get(2));\n\n    // return index\n    return new Index(values);\n  }\n\n  /**\n   * Convert world coordinates into an point.\n   *\n   * @param {Point} point The world point to convert.\n   * @returns {Point3D} The corresponding point.\n   */\n  worldToPoint(point) {\n    // compensate for origin\n    // (origin is not oriented, compensate before orientation)\n    const origin = this.getOrigin();\n    const point3D = new Point3D(\n      point.get(0) - origin.getX(),\n      point.get(1) - origin.getY(),\n      point.get(2) - origin.getZ()\n    );\n    // orient\n    const orientedPoint3D =\n      this.getOrientation().getInverse().multiplyPoint3D(point3D);\n    // keep >3d values\n    const values = point.getValues();\n    // apply spacing and round\n    const spacing = this.getSpacing();\n    values[0] = orientedPoint3D.getX() / spacing.get(0);\n    values[1] = orientedPoint3D.getY() / spacing.get(1);\n    values[2] = orientedPoint3D.getZ() / spacing.get(2);\n\n    // return index\n    return new Point3D(values[0], values[1], values[2]);\n  }\n\n} // class Geometry\n\n/**\n * Get the oriented values of an input 3D array.\n *\n * @param {number[]} array3D The 3D array.\n * @param {Matrix33} orientation The orientation 3D matrix.\n * @returns {number[]} The values reordered according to the orientation.\n */\nexport function getOrientedArray3D(array3D, orientation) {\n  // values = orientation * orientedValues\n  // -> inv(orientation) * values = orientedValues\n  return orientation.getInverse().multiplyArray3D(array3D);\n}\n\n/**\n * Get the raw values of an oriented input 3D array.\n *\n * @param {number[]} array3D The 3D array.\n * @param {Matrix33} orientation The orientation 3D matrix.\n * @returns {number[]} The values reordered to compensate the orientation.\n */\nexport function getDeOrientedArray3D(array3D, orientation) {\n  // values = orientation * orientedValues\n  return orientation.multiplyArray3D(array3D);\n}\n\n/**\n * Get the slice spacing from the difference in the Z directions\n * of input origins.\n *\n * @param {Point3D[]} origins An array of Point3D.\n * @returns {number|undefined} The spacing.\n */\nexport function getSliceGeometrySpacing(origins) {\n  // check origins\n  if (origins.length <= 1) {\n    return;\n  }\n\n  const spacings = [];\n  for (let i = 0; i < origins.length - 1; ++i) {\n    const origin1 = origins[i];\n    const origin2 = origins[i + 1];\n    const sliceSpacing = origin1.getDistance(origin2);\n    if (sliceSpacing === 0) {\n      throw new Error('Zero slice spacing ' +\n        origin1.toString() + ' ' + origin2.toString());\n    }\n    spacings.push(sliceSpacing);\n  }\n\n  // use rounded mean value as spacing\n  const stats = getBasicStats(spacings);\n  const spacing = precisionRound(stats.mean, 4);\n\n  // warn if non constant\n  if (stats.stdDev > REAL_WORLD_EPSILON) {\n    logger.warn('Varying slice spacing, value: ' + spacing +\n      ' (mean: ' + stats.mean +\n      ', min: ' + stats.min +\n      ', max: ' + stats.max +\n      ', stdDev: ' + stats.stdDev + ')');\n  }\n\n  return spacing;\n}\n\n/**\n * Merge two geometries into one using the largest size and\n *   smallest resolution.\n *\n * @param {Geometry} geometry1 The first geometry.\n * @param {Geometry} geometry2 The second geometry.\n * @returns {Geometry} The merged geometry.\n */\nexport function mergeGeometries(geometry1, geometry2) {\n  const minByIndex = function (array1, array2) {\n    return array1.map((v, i) => Math.min(v, array2[i]));\n  };\n  const maxByIndex = function (array1, array2) {\n    return array1.map((v, i) => Math.max(v, array2[i]));\n  };\n\n  const newSize = new Size(maxByIndex(\n    geometry1.getSize().getValues(),\n    geometry2.getSize().getValues()\n  ));\n  const newSpacing = new Spacing(minByIndex(\n    geometry1.getSpacing().getValues(),\n    geometry2.getSpacing().getValues()\n  ));\n\n  const range1 = geometry1.getRange();\n  const range2 = geometry2.getRange();\n  const minValues = minByIndex(\n    range1[0].getValues(),\n    range2[0].getValues()\n  );\n  const newOrigins = [];\n  for (let i = 0; i < newSize.get(2); ++i) {\n    const values = minValues.slice();\n    values[2] = minValues[2] + i * newSpacing.get(2);\n    newOrigins.push(new Point3D(\n      values[0], values[1], values[2]\n    ));\n  }\n\n  return new Geometry(\n    newOrigins,\n    newSize,\n    newSpacing,\n    geometry1.getOrientation()\n  );\n}\n","import {DataElement} from './dataElement';\n\n/**\n * Pad an input string with a '0' to form a 2 digit one.\n *\n * @param {string} str The string to pad.\n * @returns {string} The padded string.\n */\nfunction padZeroTwoDigit(str) {\n  return ('0' + str).slice(-2);\n}\n\n/**\n * Get a 'date' object with {year, monthIndex, day} ready for the\n *   Date constructor from a DICOM element with vr=DA.\n *\n * @param {DataElement} element The DICOM element with date information.\n * @returns {{year, monthIndex, day}|undefined} The 'date' object.\n */\nexport function getDate(element) {\n  if (typeof element === 'undefined') {\n    return undefined;\n  }\n  if (element.value.length !== 1) {\n    return undefined;\n  }\n  const daValue = element.value[0];\n  // Two possible formats:\n  // - standard 'YYYYMMDD'\n  // - non-standard 'YYYY.MM.DD' (previous ACR-NEMA)\n  let monthBeginIndex = 4;\n  let dayBeginIndex = 6;\n  if (daValue.length === 10) {\n    monthBeginIndex = 5;\n    dayBeginIndex = 8;\n  }\n  const daYears = parseInt(daValue.substring(0, 4), 10);\n  // 0-11 range\n  const daMonthIndex = daValue.length >= monthBeginIndex + 2\n    ? parseInt(daValue.substring(\n      monthBeginIndex, monthBeginIndex + 2), 10) - 1 : 0;\n  const daDay = daValue.length === dayBeginIndex + 2\n    ? parseInt(daValue.substring(\n      dayBeginIndex, dayBeginIndex + 2), 10) : 0;\n  return {\n    year: daYears,\n    monthIndex: daMonthIndex,\n    day: daDay\n  };\n}\n\n/**\n * Get a time object with {hours, minutes, seconds} ready for the\n *   Date constructor from a DICOM element with vr=TM.\n *\n * @param {DataElement} element The DICOM element with date information.\n * @returns {{hours, minutes, seconds, milliseconds}|undefined} The time object.\n */\nexport function getTime(element) {\n  if (typeof element === 'undefined') {\n    return undefined;\n  }\n  if (element.value.length !== 1) {\n    return undefined;\n  }\n  // format: HH[MMSS.FFFFFF]\n  const tmValue = element.value[0];\n  const tmHours = parseInt(tmValue.substring(0, 2), 10);\n  const tmMinutes = tmValue.length >= 4\n    ? parseInt(tmValue.substring(2, 4), 10) : 0;\n  const tmSeconds = tmValue.length >= 6\n    ? parseInt(tmValue.substring(4, 6), 10) : 0;\n  const tmFracSecondsStr = tmValue.length >= 8\n    ? tmValue.substring(7, 10) : 0;\n  const tmMilliSeconds = tmFracSecondsStr === 0 ? 0\n    : parseInt(tmFracSecondsStr, 10) *\n      Math.pow(10, 3 - tmFracSecondsStr.length);\n  return {\n    hours: tmHours,\n    minutes: tmMinutes,\n    seconds: tmSeconds,\n    milliseconds: tmMilliSeconds\n  };\n}\n\n/**\n * Get a 'dateTime' object with {date, time} ready for the\n *   Date constructor from a DICOM element with vr=DT.\n *\n * @param {DataElement} element The DICOM element with date-time information.\n * @returns {{date, time}|undefined} The time object.\n */\nexport function getDateTime(element) {\n  if (typeof element === 'undefined') {\n    return undefined;\n  }\n  if (element.value.length !== 1) {\n    return undefined;\n  }\n  // format: YYYYMMDDHHMMSS.FFFFFF&ZZXX\n  const dtFullValue = element.value[0];\n  // remove offset (&ZZXX)\n  const dtValue = dtFullValue.split('&')[0];\n  const dateDataElement = new DataElement('DA');\n  dateDataElement.value = [dtValue.substring(0, 8)];\n  const dtDate = getDate(dateDataElement);\n  const timeDataElement = new DataElement('TM');\n  timeDataElement.value = [dtValue.substring(8)];\n  const dtTime = dtValue.length >= 9\n    ? getTime(timeDataElement) : undefined;\n  return {\n    date: dtDate,\n    time: dtTime\n  };\n}\n\n/**\n * Extract date values from a Date object.\n *\n * @param {Date} date The input date.\n * @returns {{year, monthIndex, day}} A 'date' object.\n */\nexport function dateToDateObj(date) {\n  return {\n    year: date.getFullYear().toString(),\n    monthIndex: padZeroTwoDigit((date.getMonth() + 1).toString()),\n    day: padZeroTwoDigit(date.getDate().toString())\n  };\n}\n\n/**\n * Extract time values from a Date object.\n *\n * @param {Date} date The input date.\n * @returns {{hours, minutes, seconds}} A 'time' object.\n */\nexport function dateToTimeObj(date) {\n  return {\n    hours: padZeroTwoDigit(date.getHours().toString()),\n    minutes: padZeroTwoDigit(date.getMinutes().toString()),\n    seconds: padZeroTwoDigit(date.getSeconds().toString())\n  };\n}\n\n/**\n * Get a DICOM formated date string.\n *\n * @param {{year, monthIndex, day}} dateObj The date to format.\n * @returns {string} The formated date.\n */\nexport function getDicomDate(dateObj) {\n  // YYYYMMDD\n  return (\n    dateObj.year +\n    dateObj.monthIndex +\n    dateObj.day\n  );\n}\n\n/**\n * Get a DICOM formated time string.\n *\n * @param {{hours, minutes, seconds}} dateObj The date to format.\n * @returns {string} The formated time.\n */\nexport function getDicomTime(dateObj) {\n  // HHMMSS\n  return (\n    dateObj.hours +\n    dateObj.minutes +\n    dateObj.seconds\n  );\n}\n\n/**\n * Get a DICOM formated datetime string.\n *\n * @param {{date, time}} datetime The datetime to format.\n * @returns {string} The formated datetime.\n */\nexport function getDicomDateTime(datetime) {\n  // HHMMSS\n  let res = getDicomDate(datetime.date);\n  if (typeof datetime.time !== 'undefined') {\n    res += getDicomTime(datetime.time);\n  }\n  return res;\n}\n","import {Vector3D} from './vector';\nimport {\n  Matrix33,\n  getIdentityMat33\n} from './matrix';\n\n/**\n * Create a 3x3 coronal (xzy) matrix.\n *\n * @returns {Matrix33} The coronal matrix.\n */\nexport function getCoronalMat33() {\n  /* eslint-disable @stylistic/js/array-element-newline */\n  return new Matrix33([\n    1, 0, 0,\n    0, 0, 1,\n    0, -1, 0\n  ]);\n  /* eslint-enable @stylistic/js/array-element-newline */\n}\n\n/**\n * Create a 3x3 sagittal (yzx) matrix.\n *\n * @returns {Matrix33} The sagittal matrix.\n */\nexport function getSagittalMat33() {\n  /* eslint-disable @stylistic/js/array-element-newline */\n  return new Matrix33([\n    0, 0, -1,\n    1, 0, 0,\n    0, -1, 0\n  ]);\n  /* eslint-enable @stylistic/js/array-element-newline */\n}\n\n/**\n * Default anatomical plane orientations.\n */\nexport const Orientation = {\n  /**\n   * Axial, also known as transverse.\n   */\n  Axial: 'axial',\n  /**\n   * Coronal, also known as frontal.\n   */\n  Coronal: 'coronal',\n  /**\n   * Sagittal, also known as anteroposterior.\n   */\n  Sagittal: 'sagittal'\n};\n\n/**\n * Get an orientation matrix from a name.\n *\n * @param {string} name The orientation name.\n * @returns {Matrix33|undefined} The orientation matrix.\n */\nexport function getMatrixFromName(name) {\n  let matrix;\n  if (name === Orientation.Axial) {\n    matrix = getIdentityMat33();\n  } else if (name === Orientation.Coronal) {\n    matrix = getCoronalMat33();\n  } else if (name === Orientation.Sagittal) {\n    matrix = getSagittalMat33();\n  }\n  return matrix;\n}\n\n/**\n * Get the orientation code of an orientation matrix. Each letter defines\n * the towards direction. Letters are: R (right), L (left),\n * A (anterior), P (posterior), I (inferior) and S (superior).\n *\n * @param {Matrix33} matrix The orientation matrix.\n * @returns {string} The orientation code.\n */\nexport function getOrientationStringLPS(matrix) {\n  const v0 = new Vector3D(\n    matrix.get(0, 0),\n    matrix.get(1, 0),\n    matrix.get(2, 0)\n  );\n  const v1 = new Vector3D(\n    matrix.get(0, 1),\n    matrix.get(1, 1),\n    matrix.get(2, 1)\n  );\n  const v2 = new Vector3D(\n    matrix.get(0, 2),\n    matrix.get(1, 2),\n    matrix.get(2, 2)\n  );\n  return getVectorStringLPS(v0) +\n    getVectorStringLPS(v1) +\n    getVectorStringLPS(v2);\n}\n\n/**\n * Get the orientation code of an orientation vector.\n * Credits: David Clunie, {@link https://www.dclunie.com/medical-image-faq/html/part2.html}.\n *\n * @param {Vector3D} vector The orientation vector.\n * @returns {string} The orientation code.\n */\nfunction getVectorStringLPS(vector) {\n  let abs = new Vector3D(\n    Math.abs(vector.getX()),\n    Math.abs(vector.getY()),\n    Math.abs(vector.getZ())\n  );\n\n  let orientation = '';\n  const orientationX = vector.getX() < 0 ? 'R' : 'L';\n  const orientationY = vector.getY() < 0 ? 'A' : 'P';\n  // as defined in DICOM\n  //const orientationZ = vector.getZ() < 0 ? 'F' : 'H';\n  const orientationZ = vector.getZ() < 0 ? 'I' : 'S';\n\n  const threshold = 0.0001;\n\n  for (let i = 0; i < 3; i++) {\n    if (abs.getX() > threshold &&\n      abs.getX() > abs.getY() &&\n      abs.getX() > abs.getZ()) {\n      orientation += orientationX;\n      abs = new Vector3D(0, abs.getY(), abs.getZ());\n    } else if (abs.getY() > threshold &&\n      abs.getY() > abs.getX() &&\n      abs.getY() > abs.getZ()) {\n      orientation += orientationY;\n      abs = new Vector3D(abs.getX(), 0, abs.getZ());\n    } else if (abs.getZ() > threshold &&\n      abs.getZ() > abs.getX() &&\n      abs.getZ() > abs.getY()) {\n      orientation += orientationZ;\n      abs = new Vector3D(abs.getX(), abs.getY(), 0);\n    } else {\n      break;\n    }\n  }\n\n  return orientation;\n}\n\n/**\n * Get the LPS 'group' (axial, coronal or sagittal) from a LPS code.\n *\n * @param {string} code The LPS code string.\n * @returns {string|undefined} The group.\n */\nfunction getLPSGroup(code) {\n  let orientStr;\n  const axialCodes =\n    ['LPS', 'LAI', 'RPI', 'RAS', 'ALS', 'ARI', 'PLI', 'PRS'];\n  const coronalCodes =\n    ['LSA', 'LIP', 'RSP', 'RIA', 'ILA', 'IRP', 'SLP', 'SRA'];\n  const sagittalCodes =\n    ['PSL', 'PIR', 'ASR', 'AIL', 'IAR', 'IPL', 'SAL', 'SPR'];\n  if (axialCodes.includes(code)) {\n    orientStr = Orientation.Axial;\n  } else if (coronalCodes.includes(code)) {\n    orientStr = Orientation.Coronal;\n  } else if (sagittalCodes.includes(code)) {\n    orientStr = Orientation.Sagittal;\n  }\n  return orientStr;\n}\n\n/**\n * Get the name of an image orientation patient.\n *\n * @param {number[]} cosines The image orientation\n *   patient cosines (6 values).\n * @returns {string|undefined} The orientation\n *   name: axial, coronal or sagittal.\n */\nexport function getOrientationName(cosines) {\n  let name;\n  const orientMatrix = getOrientationFromCosines(cosines);\n  if (typeof orientMatrix !== 'undefined') {\n    const lpsStr = getOrientationStringLPS(orientMatrix.asOneAndZeros());\n    name = getLPSGroup(lpsStr);\n  }\n  return name;\n}\n\n/**\n * Get the orientation matrix associated to the direction cosines.\n *\n * @param {number[]} cosines The image orientation\n *   patient cosines (6 values).\n * @returns {Matrix33|undefined} The orientation matrix.\n */\nexport function getOrientationFromCosines(cosines) {\n  let orientationMatrix;\n  if (typeof cosines !== 'undefined' && cosines.length === 6) {\n    const rowCosines = new Vector3D(cosines[0], cosines[1], cosines[2]);\n    const colCosines = new Vector3D(cosines[3], cosines[4], cosines[5]);\n    const normal = rowCosines.crossProduct(colCosines);\n    /* eslint-disable @stylistic/js/array-element-newline */\n    orientationMatrix = new Matrix33([\n      rowCosines.getX(), colCosines.getX(), normal.getX(),\n      rowCosines.getY(), colCosines.getY(), normal.getY(),\n      rowCosines.getZ(), colCosines.getZ(), normal.getZ()\n    ]);\n    /* eslint-enable @stylistic/js/array-element-newline */\n  }\n  return orientationMatrix;\n}\n\n/**\n * Get the direction cosines from an orientation matrix.\n *\n * @param {Matrix33} matrix The input matrix.\n * @returns {number[]} The image orientation\n *   patient cosines (6 values).\n */\nexport function getCosinesFromOrientation(matrix) {\n  return [\n    matrix.get(0, 0),\n    matrix.get(1, 0),\n    matrix.get(2, 0),\n    matrix.get(0, 1),\n    matrix.get(1, 1),\n    matrix.get(2, 1)\n  ];\n}\n\n/**\n * Get the view orientation according to an image and target orientation.\n * The view orientation is used to go from target to image space.\n *\n * @param {Matrix33} imageOrientation The image geometry.\n * @param {Matrix33} targetOrientation The target orientation.\n * @returns {Matrix33} The view orientation.\n */\nexport function getViewOrientation(imageOrientation, targetOrientation) {\n  let viewOrientation = getIdentityMat33();\n  if (typeof targetOrientation !== 'undefined') {\n    // i: image, v: view, t: target, O: orientation, P: point\n    // [Img] -- Oi --> [Real] <-- Ot -- [Target]\n    // Pi = (Oi)-1 * Ot * Pt = Ov * Pt\n    // -> Ov = (Oi)-1 * Ot\n    // TODO: asOneAndZeros simplifies but not nice...\n    viewOrientation =\n      imageOrientation.asOneAndZeros().getInverse().multiply(targetOrientation);\n  }\n  // TODO: why abs???\n  return viewOrientation.getAbs();\n}\n\n/**\n * Get the target orientation according to an image and view orientation.\n * The target orientation is used to go from target to real space.\n *\n * @param {Matrix33} imageOrientation The image geometry.\n * @param {Matrix33} viewOrientation The view orientation.\n * @returns {Matrix33} The target orientation.\n */\nexport function getTargetOrientation(imageOrientation, viewOrientation) {\n  // i: image, v: view, t: target, O: orientation, P: point\n  // [Img] -- Oi --> [Real] <-- Ot -- [Target]\n  // Pi = (Oi)-1 * Ot * Pt = Ov * Pt\n  // -> Ot = Oi * Ov\n  // note: asOneAndZeros as in getViewOrientation...\n  let targetOrientation =\n    imageOrientation.asOneAndZeros().multiply(viewOrientation);\n\n  // TODO: why abs???\n  const simpleImageOrientation = imageOrientation.asOneAndZeros().getAbs();\n  if (simpleImageOrientation.equals(getCoronalMat33().getAbs())) {\n    targetOrientation = targetOrientation.getAbs();\n  }\n\n  return targetOrientation;\n}\n","import {custom} from '../app/custom';\nimport {\n  DicomParser,\n  getTransferSyntaxName,\n  isJpeg2000TransferSyntax,\n  isJpegBaselineTransferSyntax,\n  isJpegLosslessTransferSyntax\n} from './dicomParser';\nimport {\n  getDate,\n  getTime,\n  getDateTime\n} from './dicomDate';\nimport {\n  isPixelDataTag,\n  isItemDelimitationItemTag,\n  isSequenceDelimitationItemTag,\n  getItemTag,\n  getItemDelimitationItemTag,\n  getSequenceDelimitationItemTag,\n  getPixelDataTag,\n  getTagFromKey\n} from './dicomTag';\nimport {isNativeLittleEndian} from './dataReader';\nimport {getOrientationFromCosines} from '../math/orientation';\nimport {Spacing} from '../image/spacing';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Tag} from './dicomTag';\nimport {DataElement} from './dataElement';\nimport {Matrix33} from '../math/matrix';\n/* eslint-enable no-unused-vars */\n\n/**\n * @typedef {Object<string, DataElement>} DataElements\n */\n\n/**\n * Dump the DICOM tags to a string in the same way as the\n * DCMTK `dcmdump` command (https://support.dcmtk.org/docs-dcmrt/dcmdump.html).\n *\n * @param {Object<string, DataElement>} dicomElements The dicom elements.\n * @returns {string} The dumped file.\n */\nexport function dcmdump(dicomElements) {\n  const keys = Object.keys(dicomElements);\n  let result = '\\n';\n  result += '# Dicom-File-Format\\n';\n  result += '\\n';\n  result += '# Dicom-Meta-Information-Header\\n';\n  result += '# Used TransferSyntax: ';\n  if (isNativeLittleEndian()) {\n    result += 'Little Endian Explicit\\n';\n  } else {\n    result += 'NOT Little Endian Explicit\\n';\n  }\n  let dicomElement = null;\n  let tag = null;\n  let checkHeader = true;\n  for (let i = 0, leni = keys.length; i < leni; ++i) {\n    dicomElement = dicomElements[keys[i]];\n    tag = getTagFromKey(keys[i]);\n    if (checkHeader && tag.getGroup() !== '0002') {\n      result += '\\n';\n      result += '# Dicom-Data-Set\\n';\n      result += '# Used TransferSyntax: ';\n      const syntax = dicomElements['00020010'].value[0];\n      result += getTransferSyntaxName(syntax);\n      result += '\\n';\n      checkHeader = false;\n    }\n    result += getElementAsString(tag, dicomElement) + '\\n';\n  }\n  return result;\n}\n\n/**\n * Get a data element value as a string.\n *\n * @param {Tag} tag The DICOM tag.\n * @param {object} dicomElement The DICOM element.\n * @param {boolean} [pretty] When set to true, returns a 'pretified' content.\n * @returns {string} A string representation of the DICOM element.\n */\nfunction getElementValueAsString(tag, dicomElement, pretty) {\n  let str = '';\n  const strLenLimit = 65;\n\n  // dafault to pretty output\n  if (typeof pretty === 'undefined') {\n    pretty = true;\n  }\n  // check dicom element input\n  if (typeof dicomElement === 'undefined' || dicomElement === null) {\n    return str;\n  }\n\n  // Polyfill for Number.isInteger.\n  const isInteger = Number.isInteger || function (value) {\n    return typeof value === 'number' &&\n      isFinite(value) &&\n      Math.floor(value) === value;\n  };\n\n  // TODO Support sequences.\n\n  if (dicomElement.vr !== 'SQ' &&\n    dicomElement.value.length === 1 && dicomElement.value[0] === '') {\n    str += '(no value available)';\n  } else if (isPixelDataTag(tag) &&\n    dicomElement.undefinedLength) {\n    str = '(PixelSequence)';\n  } else if (dicomElement.vr === 'DA' && pretty) {\n    const daObj = getDate(dicomElement);\n    const da = new Date(daObj.year, daObj.monthIndex, daObj.day);\n    str = da.toLocaleDateString();\n  } else if (dicomElement.vr === 'TM' && pretty) {\n    const tmObj = getTime(dicomElement);\n    str = tmObj.hours + ':' + tmObj.minutes + ':' + tmObj.seconds;\n  } else {\n    let isOtherVR = false;\n    if (dicomElement.vr.length !== 0) {\n      isOtherVR = (dicomElement.vr[0].toUpperCase() === 'O');\n    }\n    const isFloatNumberVR = (dicomElement.vr === 'FL' ||\n      dicomElement.vr === 'FD' ||\n      dicomElement.vr === 'DS');\n    let valueStr = '';\n    for (let k = 0, lenk = dicomElement.value.length; k < lenk; ++k) {\n      valueStr = '';\n      if (k !== 0) {\n        valueStr += '\\\\';\n      }\n      if (isFloatNumberVR) {\n        const num = Number(dicomElement.value[k]);\n        if (!isInteger(num) && pretty) {\n          valueStr += num.toPrecision(4);\n        } else {\n          valueStr += num.toString();\n        }\n      } else if (isOtherVR) {\n        let tmp = dicomElement.value[k].toString(16);\n        if (dicomElement.vr === 'OB') {\n          tmp = '00'.substring(0, 2 - tmp.length) + tmp;\n        } else {\n          tmp = '0000'.substring(0, 4 - tmp.length) + tmp;\n        }\n        valueStr += tmp;\n      } else {\n        valueStr += dicomElement.value[k];\n      }\n      // check length\n      if (str.length + valueStr.length <= strLenLimit) {\n        str += valueStr;\n      } else {\n        str += '...';\n        break;\n      }\n    }\n  }\n  return str;\n}\n\n/**\n * Get a data element as a string.\n *\n * @param {Tag} tag The DICOM tag.\n * @param {object} dicomElement The DICOM element.\n * @param {string} [prefix] A string to prepend this one.\n * @returns {string} The element as a string.\n */\nfunction getElementAsString(tag, dicomElement, prefix) {\n  // default prefix\n  prefix = prefix || '';\n\n  // get tag anme from dictionary\n  const tagName = tag.getNameFromDictionary();\n\n  let deSize = dicomElement.value.length;\n  let isOtherVR = false;\n  if (dicomElement.vr.length !== 0) {\n    isOtherVR = (dicomElement.vr[0].toUpperCase() === 'O');\n  }\n\n  // no size for delimitations\n  if (isItemDelimitationItemTag(tag) ||\n    isSequenceDelimitationItemTag(tag)) {\n    deSize = 0;\n  } else if (isOtherVR) {\n    deSize = 1;\n  }\n\n  const isPixSequence = (isPixelDataTag(tag) &&\n    dicomElement.undefinedLength);\n\n  let line = null;\n\n  // (group,element)\n  line = '(';\n  line += tag.getGroup().toLowerCase();\n  line += ',';\n  line += tag.getElement().toLowerCase();\n  line += ') ';\n  // value representation\n  line += dicomElement.vr;\n  // value\n  if (dicomElement.vr !== 'SQ' &&\n    dicomElement.value.length === 1 &&\n    dicomElement.value[0] === '') {\n    line += ' (no value available)';\n    deSize = 0;\n  } else {\n    // simple number display\n    if (dicomElement.vr === 'na') {\n      line += ' ';\n      line += dicomElement.value[0];\n    } else if (isPixSequence) {\n      // pixel sequence\n      line += ' (PixelSequence #=' + deSize + ')';\n    } else if (dicomElement.vr === 'SQ') {\n      line += ' (Sequence with';\n      if (dicomElement.undefinedLength) {\n        line += ' undefined';\n      } else {\n        line += ' explicit';\n      }\n      line += ' length #=';\n      line += dicomElement.value.length;\n      line += ')';\n    } else if (isOtherVR ||\n        dicomElement.vr === 'pi' ||\n        dicomElement.vr === 'UL' ||\n        dicomElement.vr === 'US' ||\n        dicomElement.vr === 'SL' ||\n        dicomElement.vr === 'SS' ||\n        dicomElement.vr === 'FL' ||\n        dicomElement.vr === 'FD' ||\n        dicomElement.vr === 'AT') {\n      // 'O'ther array, limited display length\n      line += ' ';\n      line += getElementValueAsString(tag, dicomElement, false);\n    } else {\n      // default\n      line += ' [';\n      line += getElementValueAsString(tag, dicomElement, false);\n      line += ']';\n    }\n  }\n\n  // align #\n  const nSpaces = 55 - line.length;\n  if (nSpaces > 0) {\n    for (let s = 0; s < nSpaces; ++s) {\n      line += ' ';\n    }\n  }\n  line += ' # ';\n  if (dicomElement.vl < 100) {\n    line += ' ';\n  }\n  if (dicomElement.vl < 10) {\n    line += ' ';\n  }\n  line += dicomElement.vl;\n  line += ', ';\n  line += deSize; //dictElement[1];\n  line += ' ';\n  if (tagName !== null) {\n    line += tagName;\n  } else {\n    line += 'Unknown Tag & Data';\n  }\n\n  let message = null;\n\n  // continue for sequence\n  if (dicomElement.vr === 'SQ') {\n    let item = null;\n    for (let l = 0, lenl = dicomElement.value.length; l < lenl; ++l) {\n      item = dicomElement.value[l];\n      const itemKeys = Object.keys(item);\n      if (itemKeys.length === 0) {\n        continue;\n      }\n\n      // get the item element\n      const itemTag = getItemTag();\n      const itemElement = item['FFFEE000'];\n      message = '(Item with';\n      if (itemElement.undefinedLength) {\n        message += ' undefined';\n      } else {\n        message += ' explicit';\n      }\n      message += ' length #=' + (itemKeys.length - 1) + ')';\n      itemElement.value = [message];\n      itemElement.vr = 'na';\n\n      line += '\\n';\n      line += getElementAsString(itemTag, itemElement, prefix + '  ');\n\n      for (let m = 0, lenm = itemKeys.length; m < lenm; ++m) {\n        const itemTag = getTagFromKey(itemKeys[m]);\n        if (itemKeys[m] !== 'xFFFEE000') {\n          line += '\\n';\n          line += getElementAsString(itemTag, item[itemKeys[m]],\n            prefix + '    ');\n        }\n      }\n\n      message = '(ItemDelimitationItem';\n      if (!itemElement.undefinedLength) {\n        message += ' for re-encoding';\n      }\n      message += ')';\n      const itemDelimTag = getItemDelimitationItemTag();\n      const itemDelimElement = {\n        vr: 'na',\n        vl: '0',\n        value: [message]\n      };\n      line += '\\n';\n      line += getElementAsString(\n        itemDelimTag, itemDelimElement, prefix + '  ');\n\n    }\n\n    message = '(SequenceDelimitationItem';\n    if (!dicomElement.undefinedLength) {\n      message += ' for re-encod.';\n    }\n    message += ')';\n    const sqDelimTag = getSequenceDelimitationItemTag();\n    const sqDelimElement = {\n      vr: 'na',\n      vl: '0',\n      value: [message]\n    };\n    line += '\\n';\n    line += getElementAsString(sqDelimTag, sqDelimElement, prefix);\n  } else if (isPixSequence) {\n    // pixel sequence\n    let pixItem = null;\n    for (let n = 0, lenn = dicomElement.value.length; n < lenn; ++n) {\n      pixItem = dicomElement.value[n];\n      line += '\\n';\n      pixItem.vr = 'pi';\n      line += getElementAsString(\n        getPixelDataTag(), pixItem, prefix + '  ');\n    }\n\n    const pixDelimTag = getSequenceDelimitationItemTag();\n    const pixDelimElement = {\n      vr: 'na',\n      vl: '0',\n      value: ['(SequenceDelimitationItem)']\n    };\n    line += '\\n';\n    line += getElementAsString(pixDelimTag, pixDelimElement, prefix);\n  }\n\n  return prefix + line;\n}\n\n/**\n * Extract the 2D size from dicom elements.\n *\n * @param {DataElements} elements The DICOM elements.\n * @returns {number[]} The size.\n */\nexport function getImage2DSize(elements) {\n  // rows\n  const rows = elements['00280010'];\n  if (typeof rows === 'undefined') {\n    throw new Error('Missing DICOM image number of rows');\n  }\n  if (rows.value.length === 0) {\n    throw new Error('Empty DICOM image number of rows');\n  }\n  // columns\n  const columns = elements['00280011'];\n  if (typeof columns === 'undefined') {\n    throw new Error('Missing DICOM image number of columns');\n  }\n  if (columns.value.length === 0) {\n    throw new Error('Empty DICOM image number of columns');\n  }\n  return [columns.value[0], rows.value[0]];\n}\n\n/**\n * Get the pixel spacing from the different spacing tags.\n *\n * @param {DataElements} elements The DICOM elements.\n * @returns {Spacing} The read spacing or the default [1,1].\n */\nexport function getPixelSpacing(elements) {\n  // default\n  let rowSpacing = 1;\n  let columnSpacing = 1;\n\n  // 1. PixelSpacing\n  // 2. ImagerPixelSpacing\n  // 3. NominalScannedPixelSpacing\n  // 4. PixelAspectRatio\n  const keys = ['00280030', '00181164', '00182010', '00280034'];\n  for (let k = 0; k < keys.length; ++k) {\n    const spacing = elements[keys[k]];\n    if (spacing && spacing.value.length === 2) {\n      // spacing order: [row, column]\n      rowSpacing = parseFloat(spacing.value[0]);\n      columnSpacing = parseFloat(spacing.value[1]);\n      break;\n    }\n  }\n\n  // check\n  if (columnSpacing === 0) {\n    logger.warn('Zero column spacing.');\n    columnSpacing = 1;\n  }\n  if (rowSpacing === 0) {\n    logger.warn('Zero row spacing.');\n    rowSpacing = 1;\n  }\n\n  // return\n  // (slice spacing will be calculated using the image position patient)\n  return new Spacing([columnSpacing, rowSpacing, 1]);\n}\n\n/**\n * Get the time from a list of tags. Defaults\n *   does nohting.\n *\n * @param {DataElements} elements The DICOM elements.\n * @returns {number|undefined} The time value if available.\n */\nexport function getTagTime(elements) {\n  if (typeof custom.getTagTime !== 'undefined') {\n    return custom.getTagTime(elements);\n  } else {\n    return;\n  }\n}\n\n/**\n * Get pixel data unit from a list of tags.\n *\n * @param {DataElements} elements The DICOM elements.\n * @returns {string|undefined} The unit value if available.\n */\nexport function getTagPixelUnit(elements) {\n  if (typeof custom.getTagPixelUnit !== 'undefined') {\n    return custom.getTagPixelUnit(elements);\n  } else {\n    return defaultGetTagPixelUnit(elements);\n  }\n}\n\n/**\n * Default get pixel data unit.\n *\n * @param {DataElements} elements The DICOM elements.\n * @returns {string|undefined} The unit value if available.\n */\nfunction defaultGetTagPixelUnit(elements) {\n  let unit;\n  // 1. RescaleType\n  // 2. Units (for PET)\n  const keys = ['00281054', '00541001'];\n  for (let i = 0; i < keys.length; ++i) {\n    const element = elements[keys[i]];\n    if (typeof element !== 'undefined') {\n      unit = element.value[0];\n      break;\n    }\n  }\n  // default rescale type for CT\n  if (typeof unit === 'undefined') {\n    const element = elements['00080060'];\n    if (typeof element !== 'undefined') {\n      const modality = element.value[0];\n      if (modality === 'CT') {\n        unit = 'HU';\n      }\n    }\n  }\n  return unit;\n}\n\n/**\n * Check the dimension organization from a dicom element.\n *\n * @param {DataElements} dataElements The root dicom element.\n * @returns {object} The dimension organizations and indices.\n */\nexport function getDimensionOrganization(dataElements) {\n  // Dimension Organization Sequence (required)\n  const orgSq = dataElements['00209221'];\n  if (typeof orgSq === 'undefined' || orgSq.value.length !== 1) {\n    throw new Error('Unsupported dimension organization sequence length');\n  }\n  // Dimension Organization UID\n  const orgUID = orgSq.value[0]['00209164'].value[0];\n\n  // Dimension Index Sequence (conditionally required)\n  const indices = [];\n  const indexSqElem = dataElements['00209222'];\n  if (typeof indexSqElem !== 'undefined') {\n    const indexSq = indexSqElem.value;\n    // expecting 2D index\n    if (indexSq.length !== 2) {\n      throw new Error('Unsupported dimension index sequence length');\n    }\n    let indexPointer;\n    for (let i = 0; i < indexSq.length; ++i) {\n      // Dimension Organization UID (required)\n      const indexOrg = indexSq[i]['00209164'].value[0];\n      if (indexOrg !== orgUID) {\n        throw new Error(\n          'Dimension Index Sequence contains a unknown Dimension Organization');\n      }\n      // Dimension Index Pointer (required)\n      indexPointer = indexSq[i]['00209165'].value[0];\n\n      const index = {\n        DimensionOrganizationUID: indexOrg,\n        DimensionIndexPointer: indexPointer\n      };\n      // Dimension Description Label (optional)\n      if (typeof indexSq[i]['00209421'] !== 'undefined') {\n        index.DimensionDescriptionLabel = indexSq[i]['00209421'].value[0];\n      }\n      // store\n      indices.push(index);\n    }\n    // expecting Image Position at last position\n    if (indexPointer !== '(0020,0032)') {\n      throw new Error('Unsupported non image position as last index');\n    }\n  }\n\n  return {\n    organizations: {\n      value: [\n        {\n          DimensionOrganizationUID: orgUID\n        }\n      ]\n    },\n    indices: {\n      value: indices\n    }\n  };\n}\n\n/**\n * Get a spacing object from a dicom measure element.\n *\n * @param {DataElements} dataElements The dicom element.\n * @returns {Spacing} A spacing object.\n */\nexport function getSpacingFromMeasure(dataElements) {\n  // Pixel Spacing\n  if (typeof dataElements['00280030'] === 'undefined') {\n    return null;\n  }\n  const pixelSpacing = dataElements['00280030'];\n  // spacing order: [row, column]\n  const spacingValues = [\n    parseFloat(pixelSpacing.value[1]),\n    parseFloat(pixelSpacing.value[0]),\n  ];\n  // Spacing Between Slices\n  if (typeof dataElements['00180088'] !== 'undefined') {\n    spacingValues.push(parseFloat(dataElements['00180088'].value[0]));\n  }\n  return new Spacing(spacingValues);\n}\n\n/**\n * Get an orientation matrix from a dicom orientation element.\n *\n * @param {DataElements} dataElements The dicom element.\n * @returns {Matrix33|undefined} The orientation matrix.\n */\nexport function getOrientationMatrix(dataElements) {\n  const imageOrientationPatient = dataElements['00200037'];\n  let orientationMatrix;\n  // slice orientation (cosines are matrices' columns)\n  // http://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.7.6.2.html#sect_C.7.6.2.1.1\n  if (typeof imageOrientationPatient !== 'undefined') {\n    orientationMatrix =\n      getOrientationFromCosines(\n        imageOrientationPatient.value.map((item) => parseFloat(item))\n      );\n  }\n  return orientationMatrix;\n}\n\n/**\n * Get a dicom item from a measure sequence.\n *\n * @param {Spacing} spacing The spacing object.\n * @returns {object} The dicom item.\n */\nexport function getDicomMeasureItem(spacing) {\n  return {\n    SpacingBetweenSlices: spacing.get(2),\n    PixelSpacing: [spacing.get(1), spacing.get(0)]\n  };\n}\n\n/**\n * Get a dicom element from a plane orientation sequence.\n *\n * @param {Matrix33} orientation The image orientation.\n * @returns {object} The dicom element.\n */\nexport function getDicomPlaneOrientationItem(orientation) {\n  return {\n    ImageOrientationPatient: [\n      orientation.get(0, 0),\n      orientation.get(1, 0),\n      orientation.get(2, 0),\n      orientation.get(0, 1),\n      orientation.get(1, 1),\n      orientation.get(2, 1)\n    ]\n  };\n}\n\n/**\n * Gets the sop class uid from the data elements.\n *\n * @param {object} dataElements The data elements. *.\n * @returns {string | undefined} The sop class uid value.\n */\nexport function getSopClassUid(dataElements) {\n  const SOPClassUID = dataElements['00080016'];\n  if (typeof SOPClassUID !== 'undefined') {\n    return SOPClassUID.value[0];\n  }\n  return;\n}\n\n/**\n * Check if the received string represents a secondary capture.\n *\n * @param {string} SOPClassUID The sop class uid.\n * @returns {boolean} True if it is secondary capture.\n */\nexport function isSecondatyCapture(SOPClassUID) {\n  const pattern = /^1\\.2\\.840\\.10008\\.5\\.1\\.4\\.1\\.1\\.7/;\n  return !SOPClassUID && pattern.test(SOPClassUID);\n}\n\n/**\n * Gets the photometric interpretation from the data elements.\n *\n * @param {object} dataElements The data elements.\n * @returns {string | undefined} The photometric interpretation value.\n */\nexport function getPhotometricInterpretation(dataElements) {\n  const photometricInterpretation = dataElements['00280004'];\n  const syntaxElement = dataElements['00020010'];\n  const spp = dataElements['00280002'];\n  // samplesPerPixel\n  let samplesPerPixel = 1;\n  if (typeof spp !== 'undefined') {\n    samplesPerPixel = spp.value[0];\n  }\n\n  if (typeof photometricInterpretation !== 'undefined' &&\n  typeof syntaxElement !== 'undefined') {\n    let photo = photometricInterpretation.value[0].toUpperCase();\n    // TransferSyntaxUID\n    const syntax = syntaxElement.value[0];\n    const jpeg2000 = isJpeg2000TransferSyntax(syntax);\n    const jpegBase = isJpegBaselineTransferSyntax(syntax);\n    const jpegLoss = isJpegLosslessTransferSyntax(syntax);\n    // jpeg decoders output RGB data\n    if ((jpeg2000 || jpegBase || jpegLoss) &&\n      (photo !== 'MONOCHROME1' && photo !== 'MONOCHROME2')) {\n      photo = 'RGB';\n    }\n    // check samples per pixels\n    if (photo === 'RGB' && samplesPerPixel === 1) {\n      photo = 'PALETTE COLOR';\n    }\n    return photo;\n  }\n}\n\n/**\n * Check if an input photometricInterpretation is monochrome.\n *\n * @param {string} photometricInterpretation The photometric interpretation.\n * @returns {boolean} True if the input string starts with 'MONOCHROME'.\n */\nexport function isMonochrome(photometricInterpretation) {\n  return typeof photometricInterpretation !== 'undefined' &&\n    photometricInterpretation.match(/MONOCHROME/) !== null;\n}\n\n/**\n * Check an input tag.\n *\n * @param {object} element The element to check.\n * @param {string} name The element name.\n * @param {Array} [values] The expected values.\n * @returns {string} A warning if the element is not as expected.\n */\nfunction checkTag(element, name, values) {\n  let warning = '';\n  if (typeof element === 'undefined') {\n    warning += ' ' + name + ' is undefined,';\n  } else if (element.value.length === 0) {\n    warning += ' ' + name + ' is empty,';\n  } else {\n    if (typeof values !== 'undefined') {\n      for (let i = 0; i < values.length; ++i) {\n\n        if (!element.value.includes(values[i])) {\n          warning += ' ' + name + ' does not contain ' + values[i] +\n            ' (value: ' + element.value + '),';\n        }\n      }\n    }\n  }\n  return warning;\n}\n\n/**\n * Get the decayed dose (Bq).\n *\n * @param {object} elements The DICOM elements to check.\n * @returns {object} The value and a warning if\n *   the elements are not as expected.\n */\nfunction getDecayedDose(elements) {\n  let warning = '';\n  let warn;\n\n  // SeriesDate (type1)\n  const seriesDateEl = elements['00080021'];\n  const seriesDateObj = getDate(seriesDateEl);\n\n  let totalDose;\n  let halfLife;\n  let radioStart;\n\n  const radioInfoSqStr = 'RadiopharmaceuticalInformationSequence (00540016)';\n  const radioInfoSq = elements['00540016'];\n  warning += checkTag(radioInfoSq, radioInfoSqStr);\n  if (typeof radioInfoSq !== 'undefined') {\n    if (radioInfoSq.value.length !== 1) {\n      logger.warn(\n        'Found more than 1 istopes in RadiopharmaceuticalInformation Sequence.'\n      );\n    }\n\n    // RadionuclideTotalDose (type3, Bq)\n    const totalDoseStr = 'RadionuclideTotalDose (00181074)';\n    const totalDoseEl = radioInfoSq.value[0]['00181074'];\n    warn = checkTag(totalDoseEl, totalDoseStr);\n    if (warn.length === 0) {\n      const dose = parseFloat(totalDoseEl.value[0]);\n      if (!isNaN(dose)) {\n        totalDose = dose;\n      } else {\n        warning += ' TotalDose is not a number';\n      }\n    } else {\n      warning += warn;\n    }\n\n    // RadionuclideHalfLife (type3, seconds)\n    const halfLifeStr = 'RadionuclideHalfLife (00181075)';\n    const halfLifeEl = radioInfoSq.value[0]['00181075'];\n    warn = checkTag(halfLifeEl, halfLifeStr);\n    if (warn.length === 0) {\n      const hl = parseFloat(halfLifeEl.value[0]);\n      if (!isNaN(hl)) {\n        halfLife = hl;\n      } else {\n        warning += ' HalfLife is not a number';\n      }\n    } else {\n      warning += warn;\n    }\n\n    // RadiopharmaceuticalStartDateTime (type3)\n    const radioStartDateTimeEl = radioInfoSq.value[0]['00181078'];\n    let radioStartDateObj;\n    let radioStartTimeObj;\n    if (typeof radioStartDateTimeEl === 'undefined') {\n      // use seriesDate as radioStartDate\n      radioStartDateObj = seriesDateObj;\n      // try RadiopharmaceuticalStartTime (type3)\n      const radioStartTimeEl = radioInfoSq.value[0]['00181072'];\n      radioStartTimeObj = getTime(radioStartTimeEl);\n    } else {\n      const radioStartDateTime = getDateTime(radioStartDateTimeEl);\n      radioStartDateObj = radioStartDateTime.date;\n      radioStartTimeObj = radioStartDateTime.time;\n    }\n    if (typeof radioStartTimeObj === 'undefined') {\n      radioStartTimeObj = {\n        hours: 0, minutes: 0, seconds: 0, milliseconds: 0\n      };\n    }\n    radioStart = new Date(\n      radioStartDateObj.year,\n      radioStartDateObj.monthIndex,\n      radioStartDateObj.day,\n      radioStartTimeObj.hours,\n      radioStartTimeObj.minutes,\n      radioStartTimeObj.seconds,\n      radioStartTimeObj.milliseconds\n    );\n  }\n\n  // SeriesTime (type1)\n  const seriesTimeEl = elements['00080031'];\n  const seriesTimeObj = getTime(seriesTimeEl);\n  // Series date/time\n  let scanStart = new Date(\n    seriesDateObj.year,\n    seriesDateObj.monthIndex,\n    seriesDateObj.day,\n    seriesTimeObj.hours,\n    seriesTimeObj.minutes,\n    seriesTimeObj.seconds,\n    seriesTimeObj.milliseconds\n  );\n\n  // scanStart Date check\n  // AcquisitionDate (type3)\n  const acqDateEl = elements['00080022'];\n  // AcquisitionTime (type3)\n  const acqTimeEl = elements['00080032'];\n  if (typeof acqDateEl !== 'undefined' &&\n    typeof acqTimeEl !== 'undefined') {\n    const acqDateObj = getDate(acqDateEl);\n    const acqTimeObj = getTime(acqTimeEl);\n    const acqDate = new Date(\n      acqDateObj.year,\n      acqDateObj.monthIndex,\n      acqDateObj.day,\n      acqTimeObj.hours,\n      acqTimeObj.minutes,\n      acqTimeObj.seconds,\n      acqTimeObj.milliseconds\n    );\n\n    if (scanStart > acqDate) {\n      const diff = scanStart.getTime() - acqDate.getTime();\n      const warn = 'Series date/time is after Aquisition date/time (diff=' +\n        diff.toString() + 'ms) ';\n      logger.debug(warn);\n\n      // back compute from center (average count rate) of time window\n      // for bed position (frame) in series (reliable in all cases)\n\n      let frameRefTime = 0;\n      const frameRefTimeElStr = 'FrameReferenceTime (00541300)';\n      const frameRefTimeEl = elements['00541300'];\n      warning += checkTag(frameRefTimeEl, frameRefTimeElStr);\n      if (typeof frameRefTimeEl !== 'undefined') {\n        frameRefTime = frameRefTimeEl.value[0];\n      }\n      let actualFrameDuration = 0;\n      const actualFrameDurationElStr = 'ActualFrameDuration (0018,1242)';\n      const actualFrameDurationEl = elements['00181242'];\n      warning += checkTag(actualFrameDurationEl, actualFrameDurationElStr);\n      if (typeof actualFrameDurationEl !== 'undefined') {\n        actualFrameDuration = actualFrameDurationEl.value[0];\n      }\n      if (frameRefTime > 0 && actualFrameDuration > 0) {\n        // convert to seconds\n        actualFrameDuration = actualFrameDuration / 1000;\n        frameRefTime = frameRefTime / 1000;\n        const decayConstant = Math.log(2) / halfLife;\n        const decayDuringFrame = decayConstant * actualFrameDuration;\n        const averageCountRateTimeWithinFrame =\n          1 /\n          decayConstant *\n          Math.log(decayDuringFrame / (1 - Math.exp(-decayDuringFrame)));\n        const offsetSeconds = averageCountRateTimeWithinFrame - frameRefTime;\n        scanStart = new Date(\n          acqDateObj.year,\n          acqDateObj.monthIndex,\n          acqDateObj.day,\n          acqTimeObj.hours,\n          acqTimeObj.minutes,\n          acqTimeObj.seconds + offsetSeconds,\n          acqTimeObj.milliseconds\n        );\n      }\n    }\n  }\n\n  // decayed dose (Bq)\n  let decayedDose;\n  if (typeof scanStart !== 'undefined' &&\n    typeof radioStart !== 'undefined' &&\n    typeof totalDose !== 'undefined' &&\n    typeof halfLife !== 'undefined') {\n    // decay time (s) (Date diff is in milliseconds)\n    const decayTime = (scanStart.getTime() - radioStart.getTime()) / 1000;\n    const decay = Math.pow(2, (-decayTime / halfLife));\n    decayedDose = totalDose * decay;\n  }\n\n  return {\n    value: decayedDose,\n    warning: warning\n  };\n}\n\n/**\n * Get the PET SUV factor.\n *\n * Ref:\n * - {@link https://qibawiki.rsna.org/index.php/Standardized_Uptake_Value_(SUV)#SUV_Calculation},\n * - {@link https://qibawiki.rsna.org/images/6/62/SUV_vendorneutral_pseudocode_happypathonly_20180626_DAC.pdf},\n * - {@link https://qibawiki.rsna.org/images/8/86/SUV_vendorneutral_pseudocode_20180626_DAC.pdf}.\n *\n * @param {object} elements The DICOM elements.\n * @returns {object} The value and a warning if\n *   the elements are not as expected.\n */\nexport function getSuvFactor(elements) {\n  let warning = '';\n  const result = {};\n\n\n  // CorrectedImage (type2): must contain ATTN and DECY\n  const corrImageTagStr = 'Corrected Image (00280051)';\n  const corrImageEl = elements['00280051'];\n  warning += checkTag(corrImageEl, corrImageTagStr, ['ATTN', 'DECY']);\n  // DecayCorrection (type1): must be START\n  const decayCorrTagStr = 'Decay Correction (00541102)';\n  const decayCorrEl = elements['00541102'];\n  warning += checkTag(decayCorrEl, decayCorrTagStr, ['START']);\n  // Units (type1): must be BQML\n  const unitTagStr = 'Units (00541001)';\n  const unitEl = elements['00541001'];\n  warning += checkTag(unitEl, unitTagStr, ['BQML']);\n\n  // PatientWeight (type3, kg)\n  let patWeight;\n  const patientWeightStr = ' PatientWeight (00101030)';\n  const patWeightEl = elements['00101030'];\n  const warn = checkTag(patWeightEl, patientWeightStr);\n  if (warn.length === 0) {\n    const weight = parseFloat(patWeightEl.value[0]);\n    if (!isNaN(weight)) {\n      patWeight = weight;\n    } else {\n      warning += ' PatientWeight is not a number';\n    }\n  } else {\n    warning += warn;\n  }\n\n  // Decayed dose (Bq)\n  const decayedDose = getDecayedDose(elements);\n  warning += decayedDose.warning;\n\n\n  if (warning.length !== 0) {\n    result.warning = 'Cannot calculate PET SUV:' + warning;\n  } else {\n    // SUV factor (grams/Bq)\n    result.value = (patWeight * 1000) / decayedDose.value;\n  }\n\n  return result;\n}\n\n\n/**\n * Get the file list from a DICOMDIR.\n *\n * @param {object} data The buffer data of the DICOMDIR.\n * @returns {Array|undefined} The file list as an array ordered by\n *   STUDY > SERIES > IMAGES.\n */\nexport function getFileListFromDicomDir(data) {\n  // parse file\n  const parser = new DicomParser();\n  parser.parse(data);\n  const elements = parser.getDicomElements();\n\n  // Directory Record Sequence\n  if (typeof elements['00041220'] === 'undefined' ||\n    typeof elements['00041220'].value === 'undefined') {\n    logger.warn('No Directory Record Sequence found in DICOMDIR.');\n    return undefined;\n  }\n  const dirSeq = elements['00041220'].value;\n\n  if (dirSeq.length === 0) {\n    logger.warn('The Directory Record Sequence of the DICOMDIR is empty.');\n    return undefined;\n  }\n\n  const records = [];\n  let series = null;\n  let study = null;\n  for (let i = 0; i < dirSeq.length; ++i) {\n    // Directory Record Type\n    if (typeof dirSeq[i]['00041430'] === 'undefined' ||\n      typeof dirSeq[i]['00041430'].value === 'undefined') {\n      continue;\n    }\n    const recType = dirSeq[i]['00041430'].value[0];\n\n    // supposed to come in order...\n    if (recType === 'STUDY') {\n      study = [];\n      records.push(study);\n    } else if (recType === 'SERIES') {\n      series = [];\n      study.push(series);\n    } else if (recType === 'IMAGE') {\n      // Referenced File ID\n      if (typeof dirSeq[i]['00041500'] === 'undefined' ||\n        typeof dirSeq[i]['00041500'].value === 'undefined') {\n        continue;\n      }\n      const refFileIds = dirSeq[i]['00041500'].value;\n      // join ids\n      series.push(refFileIds.join('/'));\n    }\n  }\n  return records;\n}\n","import {Size} from './size';\nimport {Geometry} from './geometry';\nimport {RescaleSlopeAndIntercept} from './rsi';\nimport {WindowLevel} from './windowLevel';\nimport {Image} from './image';\nimport {ColourMap} from './luts';\nimport {safeGet} from '../dicom/dataElement';\nimport {\n  isJpeg2000TransferSyntax,\n  isJpegBaselineTransferSyntax,\n  isJpegLosslessTransferSyntax\n} from '../dicom/dicomParser';\nimport {\n  getImage2DSize,\n  getPixelSpacing,\n  getTagPixelUnit,\n  getTagTime,\n  getSuvFactor,\n  getOrientationMatrix,\n  isSecondatyCapture,\n  getPhotometricInterpretation,\n  getSopClassUid,\n  isMonochrome\n} from '../dicom/dicomElementsWrapper';\nimport {Point3D} from '../math/point';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from '../dicom/dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * @typedef {Object<string, DataElement>} DataElements\n */\n\n/**\n * {@link Image} factory.\n */\nexport class ImageFactory {\n\n  /**\n   * Possible warning created by checkElements.\n   *\n   * @type {string|undefined}\n   */\n  #warning;\n\n  /**\n   * The PET SUV factor.\n   *\n   * @type {number|undefined}\n   */\n  #suvFactor;\n\n  /**\n   * Get a warning string if elements are not as expected.\n   * Created by checkElements.\n   *\n   * @returns {string|undefined} The warning.\n   */\n  getWarning() {\n    return this.#warning;\n  }\n\n  /**\n   * Check dicom elements.\n   *\n   * @param {DataElements} dataElements The DICOM data elements.\n   * @returns {string|undefined} A possible warning.\n   * @throws Error for missing or wrong data.\n   */\n  checkElements(dataElements) {\n    // reset\n    this.#warning = undefined;\n    // will throw if columns or rows is not defined\n    getImage2DSize(dataElements);\n    // check PET SUV\n    let modality;\n    const element = dataElements['00080060'];\n    if (typeof element !== 'undefined') {\n      modality = element.value[0];\n\n      if (modality === 'PT') {\n        const photometricInterpretation =\n        getPhotometricInterpretation(dataElements);\n        const SOPClassUID = getSopClassUid(dataElements);\n        if (isSecondatyCapture(SOPClassUID) ||\n                !isMonochrome(photometricInterpretation)) {\n          return this.#warning;\n        }\n        const suvFactor = getSuvFactor(dataElements);\n        this.#suvFactor = suvFactor.value;\n        this.#warning = suvFactor.warning;\n      }\n    }\n\n    return this.#warning;\n  }\n\n  /**\n   * Get an {@link Image} object from the read DICOM file.\n   *\n   * @param {DataElements} dataElements The DICOM tags.\n   * @param {Uint8Array | Int8Array |\n   *   Uint16Array | Int16Array |\n   *   Uint32Array | Int32Array} pixelBuffer The pixel buffer.\n   * @param {number} numberOfFiles The input number of files.\n   * @returns {Image} A new Image.\n   * @throws Error for missing or wrong data.\n   */\n  create(dataElements, pixelBuffer, numberOfFiles) {\n    const size2D = getImage2DSize(dataElements);\n    const sizeValues = [size2D[0], size2D[1], 1];\n\n    // NumberOfFrames\n    const numberOfFramesEl = dataElements['00280008'];\n    if (typeof numberOfFramesEl !== 'undefined') {\n      const number = parseInt(numberOfFramesEl.value[0], 10);\n      if (number > 1) {\n        sizeValues.push(number);\n      }\n    }\n\n    // image size\n    const size = new Size(sizeValues);\n\n    // image spacing\n    const spacing = getPixelSpacing(dataElements);\n\n    // TransferSyntaxUID\n    const syntax = dataElements['00020010'].value[0];\n    const jpeg2000 = isJpeg2000TransferSyntax(syntax);\n    const jpegBase = isJpegBaselineTransferSyntax(syntax);\n    const jpegLoss = isJpegLosslessTransferSyntax(syntax);\n\n    // ImagePositionPatient\n    const imagePositionPatient = dataElements['00200032'];\n    // slice position\n    let slicePosition = new Array(0, 0, 0);\n    if (typeof imagePositionPatient !== 'undefined') {\n      slicePosition = [\n        parseFloat(imagePositionPatient.value[0]),\n        parseFloat(imagePositionPatient.value[1]),\n        parseFloat(imagePositionPatient.value[2])\n      ];\n    }\n\n    // Image orientation patient\n    const orientationMatrix = getOrientationMatrix(dataElements);\n\n    // geometry\n    const origin = new Point3D(\n      slicePosition[0], slicePosition[1], slicePosition[2]);\n    const time = getTagTime(dataElements);\n    const geometry = new Geometry(\n      [origin], size, spacing, orientationMatrix, time);\n\n    // SOP Instance UID\n    let sopInstanceUid;\n    const siu = dataElements['00080018'];\n    if (typeof siu !== 'undefined') {\n      sopInstanceUid = siu.value[0];\n    }\n\n    // Sample per pixels\n    let samplesPerPixel = 1;\n    const spp = dataElements['00280002'];\n    if (typeof spp !== 'undefined') {\n      samplesPerPixel = spp.value[0];\n    }\n\n    // check buffer size\n    const bufferSize = size.getTotalSize() * samplesPerPixel;\n    if (bufferSize !== pixelBuffer.length) {\n      logger.warn('Badly sized pixel buffer: ' +\n        pixelBuffer.length + ' != ' + bufferSize);\n      if (bufferSize < pixelBuffer.length) {\n        pixelBuffer = pixelBuffer.slice(0, size.getTotalSize());\n      } else {\n        throw new Error('Underestimated buffer size, can\\'t fix it...');\n      }\n    }\n\n    // image\n    const image = new Image(geometry, pixelBuffer, [sopInstanceUid]);\n    // PhotometricInterpretation\n    const photometricInterpretation = dataElements['00280004'];\n    if (typeof photometricInterpretation !== 'undefined') {\n      let photo = photometricInterpretation.value[0].toUpperCase();\n      // jpeg decoders output RGB data\n      if ((jpeg2000 || jpegBase || jpegLoss) &&\n        (photo !== 'MONOCHROME1' && photo !== 'MONOCHROME2')) {\n        photo = 'RGB';\n      }\n      // check samples per pixels\n      if (photo === 'RGB' && samplesPerPixel === 1) {\n        photo = 'PALETTE COLOR';\n      }\n      image.setPhotometricInterpretation(photo);\n    }\n    // PlanarConfiguration\n    const planarConfiguration = dataElements['00280006'];\n    if (typeof planarConfiguration !== 'undefined') {\n      image.setPlanarConfiguration(planarConfiguration.value[0]);\n    }\n\n    // rescale slope and intercept\n    let slope = 1;\n    // RescaleSlope\n    const rescaleSlope = dataElements['00281053'];\n    if (typeof rescaleSlope !== 'undefined') {\n      const value = parseFloat(rescaleSlope.value[0]);\n      if (!isNaN(value)) {\n        slope = value;\n      }\n    }\n    let intercept = 0;\n    // RescaleIntercept\n    const rescaleIntercept = dataElements['00281052'];\n    if (typeof rescaleIntercept !== 'undefined') {\n      const value = parseFloat(rescaleIntercept.value[0]);\n      if (!isNaN(value)) {\n        intercept = value;\n      }\n    }\n\n    // meta information\n    const meta = {\n      numberOfFiles: numberOfFiles\n    };\n\n    // Modality\n    const modality = dataElements['00080060'];\n    if (typeof modality !== 'undefined') {\n      meta.Modality = modality.value[0];\n    }\n\n    // PET SUV\n    let isPetWithSuv = false;\n    let intensityFactor = 1;\n    if (typeof this.#suvFactor !== 'undefined') {\n      isPetWithSuv = true;\n      intensityFactor = this.#suvFactor;\n      logger.info('Applying PET SUV calibration: ' + intensityFactor);\n      slope *= intensityFactor;\n      intercept *= intensityFactor;\n    }\n    const rsi = new RescaleSlopeAndIntercept(slope, intercept);\n    image.setRescaleSlopeAndIntercept(rsi);\n\n    const safeGetLocal = function (key) {\n      return safeGet(dataElements, key);\n    };\n\n    // defaults\n    meta.TransferSyntaxUID = safeGetLocal('00020010');\n    meta.MediaStorageSOPClassUID = safeGetLocal('00020002');\n    meta.SOPClassUID = safeGetLocal('00080016');\n    meta.Modality = safeGetLocal('00080060');\n    meta.ImageType = safeGetLocal('00080008');\n    meta.SamplesPerPixel = safeGetLocal('00280002');\n    meta.PhotometricInterpretation = safeGetLocal('00280004');\n    meta.PixelRepresentation = safeGetLocal('00280103');\n    meta.BitsAllocated = safeGetLocal('00280100');\n    meta.BitsStored = safeGetLocal('00280101');\n    meta.HighBit = safeGetLocal('00280102');\n\n    // Study\n    meta.StudyDate = safeGetLocal('00080020');\n    meta.StudyTime = safeGetLocal('00080030');\n    meta.StudyInstanceUID = safeGetLocal('0020000D');\n    meta.StudyID = safeGetLocal('00200010');\n    // Series\n    meta.SeriesInstanceUID = safeGetLocal('0020000E');\n    meta.SeriesNumber = safeGetLocal('00200011');\n    // ReferringPhysicianName\n    meta.ReferringPhysicianName = safeGetLocal('00080090');\n    // patient info\n    meta.PatientName = safeGetLocal('00100010');\n    meta.PatientID = safeGetLocal('00100020');\n    meta.PatientBirthDate = safeGetLocal('00100030');\n    meta.PatientSex = safeGetLocal('00100040');\n    // General Equipment Module\n    meta.Manufacturer = safeGetLocal('00080070');\n    meta.ManufacturerModelName = safeGetLocal('00081090');\n    meta.DeviceSerialNumber = safeGetLocal('00181000');\n    meta.SoftwareVersions = safeGetLocal('00181020');\n\n    meta.ImageOrientationPatient = safeGetLocal('00200037');\n    meta.FrameOfReferenceUID = safeGetLocal('00200052');\n\n    // PixelRepresentation -> is signed\n    meta.IsSigned = meta.PixelRepresentation === 1;\n    // local pixel unit\n    if (isPetWithSuv) {\n      meta.pixelUnit = 'SUV';\n    } else {\n      const pixelUnit = getTagPixelUnit(dataElements);\n      if (typeof pixelUnit !== 'undefined') {\n        meta.pixelUnit = pixelUnit;\n      }\n    }\n    // window level presets\n    const windowPresets = {};\n    const windowCenter = dataElements['00281050'];\n    const windowWidth = dataElements['00281051'];\n    const windowCWExplanation = dataElements['00281055'];\n    if (typeof windowCenter !== 'undefined' &&\n      typeof windowWidth !== 'undefined') {\n      let name;\n      for (let j = 0; j < windowCenter.value.length; ++j) {\n        const center = parseFloat(windowCenter.value[j]);\n        let width = parseFloat(windowWidth.value[j]);\n        if (center && width && width !== 0) {\n          name = '';\n          if (typeof windowCWExplanation !== 'undefined') {\n            name = windowCWExplanation.value[j];\n          }\n          if (name === '') {\n            name = 'Default' + j;\n          }\n          width *= intensityFactor;\n          if (width < 1) {\n            width = 1;\n          }\n          windowPresets[name] = {\n            wl: [new WindowLevel(\n              center * intensityFactor,\n              width\n            )],\n            name: name\n          };\n        }\n        if (width === 0) {\n          logger.warn('Zero window width found in DICOM.');\n        }\n      }\n    }\n    meta.windowPresets = windowPresets;\n\n    // PALETTE COLOR luts\n    if (image.getPhotometricInterpretation() === 'PALETTE COLOR') {\n      // Red Palette Color Lookup Table Data\n      const redLutElement = dataElements['00281201'];\n      // Green Palette Color Lookup Table Data\n      const greenLutElement = dataElements['00281202'];\n      // Blue Palette Color Lookup Table Data\n      const blueLutElement = dataElements['00281203'];\n      let redLut;\n      let greenLut;\n      let blueLut;\n      // check red palette descriptor (should all be equal)\n      // Red Palette Color Lookup Table Descriptor\n      // 0: number of entries in the lookup table\n      // 1: first input value mapped\n      // 2: number of bits for each entry in the Lookup Table Data (8 or 16)\n      const descriptor = dataElements['00281101'];\n      if (typeof descriptor !== 'undefined' &&\n        descriptor.value.length === 3) {\n        if (descriptor.value[2] === 16) {\n          let doScale = false;\n          // (C.7.6.3.1.5 Palette Color Lookup Table Descriptor)\n          // Some implementations have encoded 8 bit entries with 16 bits\n          // allocated, padding the high bits;\n          let descSize = descriptor.value[0];\n          // (C.7.6.3.1.5 Palette Color Lookup Table Descriptor)\n          // The first Palette Color Lookup Table Descriptor value is the\n          // number of entries in the lookup table. When the number of table\n          // entries is equal to 216 then this value shall be 0.\n          if (descSize === 0) {\n            descSize = 65536;\n          }\n          // red palette VL\n          // TODO vl is undefined, find info elsewhere...\n          const vlSize = redLutElement.vl;\n          // check double size\n          if (vlSize !== 2 * descSize) {\n            doScale = true;\n            logger.info('16bits lut but size is not double. desc: ' +\n              descSize + ' vl: ' + vlSize);\n          }\n          // (C.7.6.3.1.6 Palette Color Lookup Table Data)\n          // Palette color values must always be scaled across the full\n          // range of available intensities\n          const bitsAllocated = parseInt(\n            dataElements['00280100'].value[0], 10);\n          if (bitsAllocated === 8) {\n            doScale = true;\n            logger.info(\n              'Scaling 16bits color lut since bits allocated is 8.');\n          }\n\n          if (doScale) {\n            const scaleTo8 = function (value) {\n              return value >> 8;\n            };\n\n            redLut = redLutElement.value.map(scaleTo8);\n            greenLut = greenLutElement.value.map(scaleTo8);\n            blueLut = blueLutElement.value.map(scaleTo8);\n          }\n        } else if (descriptor.value[2] === 8) {\n          // lut with vr=OW was read as Uint16, convert it to Uint8\n          logger.info(\n            'Scaling 16bits color lut since the lut descriptor is 8.');\n          let clone = redLutElement.value.slice(0);\n          // @ts-expect-error\n          redLut = Array.from(new Uint8Array(clone.buffer));\n          clone = greenLutElement.value.slice(0);\n          // @ts-expect-error\n          greenLut = Array.from(new Uint8Array(clone.buffer));\n          clone = blueLutElement.value.slice(0);\n          // @ts-expect-error\n          blueLut = Array.from(new Uint8Array(clone.buffer));\n        }\n      }\n      // set the palette\n      image.setPaletteColourMap(new ColourMap(redLut, greenLut, blueLut));\n    }\n\n    // RecommendedDisplayFrameRate\n    const recommendedDisplayFrameRate = dataElements['00082144'];\n    if (typeof recommendedDisplayFrameRate !== 'undefined') {\n      meta.RecommendedDisplayFrameRate = parseInt(\n        recommendedDisplayFrameRate.value[0], 10);\n    }\n\n    // store the meta data\n    image.setMeta(meta);\n\n    return image;\n  }\n\n}","/**\n * Data writer.\n */\nexport class DataWriter {\n\n  /**\n   * Is the endianness Little Endian.\n   *\n   * @type {boolean}\n   */\n  #isLittleEndian = true;\n\n  /**\n   * The main data view.\n   *\n   * @type {DataView}\n   */\n  #view;\n\n  /**\n   * @param {ArrayBuffer} buffer The input array buffer.\n   * @param {boolean} [isLittleEndian] Flag to tell if the data is\n   *   little or big endian.\n   */\n  constructor(buffer, isLittleEndian) {\n    // Set endian flag if not defined.\n    if (typeof isLittleEndian !== 'undefined') {\n      this.#isLittleEndian = isLittleEndian;\n    }\n    this.#view = new DataView(buffer);\n  }\n\n  /**\n   * Write Uint8 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint8(byteOffset, value) {\n    this.#view.setUint8(byteOffset, value);\n    return byteOffset + Uint8Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Int8 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt8(byteOffset, value) {\n    this.#view.setInt8(byteOffset, value);\n    return byteOffset + Int8Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Uint16 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint16(byteOffset, value) {\n    this.#view.setUint16(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Uint16Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Int16 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt16(byteOffset, value) {\n    this.#view.setInt16(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Int16Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Uint32 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint32(byteOffset, value) {\n    this.#view.setUint32(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Uint32Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Uint64 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {bigint} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint64(byteOffset, value) {\n    this.#view.setBigUint64(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + BigUint64Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Int32 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt32(byteOffset, value) {\n    this.#view.setInt32(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Int32Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Int64 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {bigint} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt64(byteOffset, value) {\n    this.#view.setBigInt64(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + BigInt64Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Float32 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeFloat32(byteOffset, value) {\n    this.#view.setFloat32(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Float32Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Float64 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeFloat64(byteOffset, value) {\n    this.#view.setFloat64(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Float64Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write string data of length 4 as hexadecimal (no '0x' prefix).\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {string} str The hexadecimal string to write ('####').\n   * @returns {number} The new offset position.\n   */\n  writeHex(byteOffset, str) {\n    // remove first two chars and parse\n    const value = parseInt(str, 16);\n    this.#view.setUint16(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Uint16Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write a boolean array as binary.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeBinaryArray(byteOffset, array) {\n    if (array.length % 8 !== 0) {\n      throw new Error('Cannot write boolean array as binary.');\n    }\n    let byte = null;\n    let val = null;\n    for (let i = 0, len = array.length; i < len; i += 8) {\n      byte = 0;\n      for (let j = 0; j < 8; ++j) {\n        val = array[i + j] === 0 ? 0 : 1;\n        byte += val << j;\n      }\n      byteOffset = this.writeUint8(byteOffset, byte);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Uint8 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array|Uint8Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint8Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeUint8(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Int8 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt8Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeInt8(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Uint16 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint16Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeUint16(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Int16 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt16Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeInt16(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Uint32 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint32Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeUint32(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Uint64 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint64Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeUint64(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Int32 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt32Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeInt32(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Int64 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt64Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeInt64(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Float32 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeFloat32Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeFloat32(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Float64 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeFloat64Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeFloat64(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n} // class DataWriter\n","import {\n  is32bitVLVR,\n  isCharSetStringVR,\n  vrTypes\n} from './dictionary';\nimport {\n  Tag,\n  getTagFromDictionary,\n  getTagFromKey,\n  getItemTag,\n  getItemDelimitationItemTag,\n  getSequenceDelimitationItemTag,\n  getFileMetaInformationGroupLengthTag,\n  isPixelDataTag,\n  isItemTag,\n  isItemDelimitationItemTag,\n  tagCompareFunction\n} from './dicomTag';\nimport {\n  getDwvVersion,\n  isImplicitTransferSyntax,\n  isBigEndianTransferSyntax,\n  getDataElementPrefixByteSize\n} from './dicomParser';\nimport {DataElement} from './dataElement';\nimport {DataWriter} from './dataWriter';\nimport {DataReader} from './dataReader';\nimport {logger} from '../utils/logger';\n\n/**\n * Get the dwv UID prefix.\n * Issued by Medical Connections Ltd (www.medicalconnections.co.uk)\n *   on 25/10/2017.\n *\n * @returns {string} The dwv UID prefix.\n */\nfunction getDwvUIDPrefix() {\n  return '1.2.826.0.1.3680043.9.7278.1';\n}\n\n// local generated uid counter\nlet _uidCount = 0;\n\n/**\n * Writer rule.\n */\nexport class WriterRule {\n  /**\n   * Rule action: `copy`, `remove`, `clear` or `replace`.\n   *\n   * @type {string}\n   */\n  action;\n  /**\n   * Optional value to use for replace action.\n   *\n   * @type {any|undefined}\n   */\n  value;\n\n  /**\n   * @param {string} action The rule action.\n   */\n  constructor(action) {\n    this.action = action;\n  }\n}\n\n/**\n * Possible writer actions.\n *\n * @type {Object<string, Function>}\n */\nconst writerActions = {\n  copy: function (item) {\n    return item;\n  },\n  remove: function () {\n    return null;\n  },\n  clear: function (item) {\n    item.value = [];\n    return item;\n  },\n  replace: function (item, value) {\n    item.value = [value];\n    return item;\n  }\n};\n\n/**\n * Get simple (non official) DICOM anonymisation rules.\n *\n * @returns {Object<string, WriterRule>} The rules.\n */\nexport function getDefaultAnonymisationRules() {\n  return {\n    default: {action: 'copy', value: null},\n    PatientName: {action: 'replace', value: 'Anonymized'}, // tag\n    'Meta Element': {action: 'copy', value: null}, // group '0002'\n    Acquisition: {action: 'copy', value: null}, // group '0018'\n    'Image Presentation': {action: 'copy', value: null}, // group '0028'\n    Procedure: {action: 'copy', value: null}, // group '0040'\n    'Pixel Data': {action: 'copy', value: null} // group '7fe0'\n  };\n}\n\n/**\n * Get a UID for a DICOM tag.\n *\n * Note: Use {@link https://github.com/uuidjs/uuid}?\n *\n * Ref:\n * - {@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/chapter_9.html},\n * - {@link http://dicomiseasy.blogspot.com/2011/12/chapter-4-dicom-objects-in-chapter-3.html},\n * - {@link https://stackoverflow.com/questions/46304306/how-to-generate-unique-dicom-uid}.\n *\n * @param {string} tagName The input tag.\n * @returns {string} The corresponding UID.\n */\nexport function getUID(tagName) {\n  const prefix = getDwvUIDPrefix() + '.';\n  let uid = '';\n  if (tagName === 'ImplementationClassUID') {\n    uid = prefix + getDwvVersion();\n  } else {\n    // date (only numbers), do not keep milliseconds\n    const date = (new Date()).toISOString().replace(/\\D/g, '');\n    const datePart = '.' + date.substring(0, 14);\n    // count\n    _uidCount += 1;\n    const countPart = '.' + _uidCount;\n\n    // uid = prefix . tag . date . count\n    uid = prefix;\n\n    // limit tag part to not exceed 64 length\n    const nonTagLength = prefix.length + countPart.length + datePart.length;\n    const leni = Math.min(tagName.length, 64 - nonTagLength);\n    if (leni > 1) {\n      let tagNumber = '';\n      for (let i = 0; i < leni; ++i) {\n        tagNumber += tagName.charCodeAt(i);\n      }\n      uid += tagNumber.substring(0, leni);\n    }\n\n    // finish\n    uid += datePart + countPart;\n  }\n  return uid;\n}\n\n/**\n * Return true if the input number is even.\n *\n * @param {number} number The number to check.\n * @returns {boolean} True is the number is even.\n */\nfunction isEven(number) {\n  return number % 2 === 0;\n}\n\n/**\n * Is the input VR a VR that stores data in a typed array.\n * TODO: include ox and xs?\n *\n * @param {string} vr The element VR.\n * @returns {boolean} True if the VR is a typed array one.\n */\nfunction isTypedArrayVr(vr) {\n  const vrType = vrTypes[vr];\n  return typeof vrType !== 'undefined' &&\n    vrType !== 'string';\n}\n\n/**\n * Is the input VR a string VR.\n *\n * @param {string} vr The element VR.\n * @returns {boolean} True if the VR is a string one.\n */\nfunction isStringVr(vr) {\n  const vrType = vrTypes[vr];\n  return typeof vrType !== 'undefined' &&\n    vrType === 'string';\n}\n\n/**\n * Is the input VR a VR that could need padding.\n *\n * See {@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_6.2.html}.\n *\n * @param {string} vr The element VR.\n * @returns {boolean} True if the VR needs padding.\n */\nfunction isVrToPad(vr) {\n  return isStringVr(vr) || vr === 'OB';\n}\n\n/**\n * Get the VR specific padding value.\n *\n * @param {string} vr The element VR.\n * @returns {string} The value used to pad.\n */\nfunction getVrPad(vr) {\n  let pad = '';\n  if (isStringVr(vr)) {\n    if (vr === 'UI') {\n      pad = '\\0';\n    } else {\n      pad = ' ';\n    }\n  }\n  return pad;\n}\n\n/**\n * Push a value at the end of an input Uint8Array.\n *\n * @param {Array|Uint8Array} arr The input array.\n * @param {Array|Uint8Array} value The value to push.\n * @returns {Uint8Array} The new array.\n */\nfunction uint8ArrayPush(arr, value) {\n  const newArr = new Uint8Array(arr.length + 1);\n  newArr.set(arr);\n  newArr.set(value, arr.length);\n  return newArr;\n}\n\n/**\n * Pad an input OB value.\n *\n * @param {Array|Uint8Array} value The input value.\n * @returns {Array|Uint8Array} The padded input.\n */\nfunction padOBValue(value) {\n  if (value !== null &&\n    typeof value !== 'undefined' &&\n    typeof value.length !== 'undefined') {\n    // calculate size and pad if needed\n    if (value.length !== 0 &&\n      typeof value[0].length !== 'undefined') {\n      // handle array of array\n      let size = 0;\n      for (let i = 0; i < value.length; ++i) {\n        size += value[i].length;\n      }\n      if (!isEven(size)) {\n        value[value.length - 1] = uint8ArrayPush(\n          value[value.length - 1], [0]);\n      }\n    } else {\n      if (!isEven(value.length)) {\n        value = uint8ArrayPush(value, [0]);\n      }\n    }\n  } else {\n    throw new Error('Cannot pad undefined or null OB value.');\n  }\n  // uint8ArrayPush may create a new array so we\n  // need to return it\n  return value;\n}\n\n/**\n * Helper method to flatten an array of typed arrays to 2D typed array.\n *\n * @param {Array} initialArray Array of typed arrays.\n * @returns {object} A typed array containing all values.\n */\nfunction flattenArrayOfTypedArrays(initialArray) {\n  const initialArrayLength = initialArray.length;\n  const arrayLength = initialArray[0].length;\n  // If this is not a array of arrays, just return the initial one:\n  if (typeof arrayLength === 'undefined') {\n    return initialArray;\n  }\n\n  const flattenendArrayLength = initialArrayLength * arrayLength;\n\n  const flattenedArray = new initialArray[0].constructor(flattenendArrayLength);\n\n  for (let i = 0; i < initialArrayLength; i++) {\n    const indexFlattenedArray = i * arrayLength;\n    flattenedArray.set(initialArray[i], indexFlattenedArray);\n  }\n  return flattenedArray;\n}\n\n/**\n * Default text encoder.\n */\nclass DefaultTextEncoder {\n  /**\n   * Encode an input string.\n   *\n   * @param {string} str The string to encode.\n   * @returns {Uint8Array} The encoded string.\n   */\n  encode(str) {\n    const result = new Uint8Array(str.length);\n    for (let i = 0, leni = str.length; i < leni; ++i) {\n      result[i] = str.charCodeAt(i);\n    }\n    return result;\n  }\n}\n\n/**\n * Small list of used tag keys.\n */\nconst TagKeys = {\n  TransferSyntax: '00020010',\n  SpecificCharacterSet: '00080005',\n  BitsAllocated: '00280100',\n};\n\n/**\n * DICOM writer.\n *\n * @example\n * // add link to html\n * const link = document.createElement(\"a\");\n * link.appendChild(document.createTextNode(\"download\"));\n * const div = document.getElementById(\"dwv\");\n * div.appendChild(link);\n * // XMLHttpRequest onload callback\n * const onload = function (event) {\n *   const parser = new dwv.DicomParser();\n *   parser.parse(event.target.response);\n *   // create writer\n *   const writer = new dwv.DicomWriter();\n *   // get buffer using default rules\n *   const dicomBuffer = writer.getBuffer(parser.getDicomElements());\n *   // create blob\n *   const blob = new Blob([dicomBuffer], {type: 'application/dicom'});\n *   // add blob to download link\n *   link.href = URL.createObjectURL(blob);\n *   link.download = \"anonym.dcm\";\n * };\n * // DICOM file request\n * const request = new XMLHttpRequest();\n * const url = 'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm';\n * request.open('GET', url);\n * request.responseType = 'arraybuffer';\n * request.onload = onload;\n * request.send();\n */\nexport class DicomWriter {\n\n  /**\n   * Flag to use VR=UN for private sequences, default to false\n   * (mainly used in tests).\n   *\n   * @type {boolean}\n   */\n  #useUnVrForPrivateSq = false;\n\n  /**\n   * Flag to activate or not the vr=UN tag check and fix\n   * if present in the dictionary. Default to true.\n   *\n   * @type {boolean}\n   */\n  #fixUnknownVR = true;\n\n  /**\n   * Default rules: just copy.\n   *\n   * @type {Object<string, WriterRule>}\n   */\n  #defaultRules = {\n    default: {action: 'copy', value: null}\n  };\n\n  /**\n   * Writing rules.\n   *\n   * @type {Object<string, WriterRule>}\n   */\n  #rules = this.#defaultRules;\n\n  /**\n   * List of compulsory tags keys.\n   *\n   * @type {string[]}\n   */\n  #compulsoryTags = [];\n\n  /**\n   * Default text encoder.\n   *\n   * @type {DefaultTextEncoder}\n   */\n  #defaultTextEncoder = new DefaultTextEncoder();\n\n  /**\n   * Special text encoder.\n   *\n   * @type {DefaultTextEncoder|TextEncoder}\n   */\n  #textEncoder = this.#defaultTextEncoder;\n\n  /**\n   * Set the use UN VR for private sequence flag.\n   *\n   * @param {boolean} flag True to use UN VR.\n   */\n  setUseUnVrForPrivateSq(flag) {\n    this.#useUnVrForPrivateSq = flag;\n  }\n\n  /**\n   * Set the vr=UN check and fix flag.\n   *\n   * @param {boolean} flag True to activate the check and fix.\n   */\n  setFixUnknownVR(flag) {\n    this.#fixUnknownVR = flag;\n  }\n\n  /**\n   * Set the writing rules.\n   * List of writer rules indexed by either `default`,\n   *   tagKey, tagName or groupName.\n   * Each DICOM element will be checked to see if a rule is applicable.\n   * First checked by tagKey, tagName and then by groupName,\n   * if nothing is found the default rule is applied.\n   *\n   * @param {Object<string, WriterRule>} rules The input rules.\n   * @param {boolean} [addMissingTags] If true, explicit tags that\n   *   have replace rule and a value will be\n   *   added if missing. Defaults to false.\n   */\n  setRules(rules, addMissingTags) {\n    this.#rules = rules;\n\n    // default compulsory list is empty\n    this.#compulsoryTags = [];\n\n    // use replace rule tags as compulsory tags\n    if (addMissingTags) {\n      const keys = Object.keys(rules);\n      for (const key of keys) {\n        const rule = rules[key];\n        if (rule.action === 'replace' &&\n          typeof rule.value !== 'undefined' &&\n          rule.value !== null) {\n          // check if key really exists\n          let isKey = false;\n          if (key.length === 8) {\n            const tag = getTagFromKey(key);\n            isKey = typeof tag.getNameFromDictionary() !== 'undefined';\n          }\n          // get tag key, rules can use key or tag name\n          let tagKey;\n          if (isKey) {\n            tagKey = key;\n          } else {\n            // try tag name\n            const tag = getTagFromDictionary(key);\n            if (typeof tag !== 'undefined') {\n              tagKey = tag.getKey();\n            }\n          }\n          // add to list\n          if (typeof tagKey !== 'undefined') {\n            this.#compulsoryTags.push(tagKey);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Encode string data.\n   *\n   * @param {string} str The string to encode.\n   * @returns {Uint8Array} The encoded string.\n   */\n  #encodeString(str) {\n    return this.#defaultTextEncoder.encode(str);\n  }\n\n  /**\n   * Encode data as a UTF-8.\n   *\n   * @param {string} str The string to write.\n   * @returns {Uint8Array} The encoded string.\n   */\n  #encodeSpecialString(str) {\n    return this.#textEncoder.encode(str);\n  }\n\n  /**\n   * Use a TextEncoder instead of the default text decoder.\n   */\n  useSpecialTextEncoder() {\n    /**\n     * The text encoder.\n     *\n     * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder}.\n     *\n     * @external TextEncoder\n     */\n    this.#textEncoder = new TextEncoder();\n  }\n\n  /**\n   * Get the element to write according to the class rules.\n   * Priority order: tagName, groupName, default.\n   *\n   * @param {DataElement} element The element to check.\n   * @returns {DataElement|null} The element to write, can be null.\n   */\n  getElementToWrite(element) {\n    // get group and tag string name\n    const groupName = element.tag.getGroupName();\n    const tagName = element.tag.getNameFromDictionary();\n\n    // apply rules:\n    let rule;\n    if (typeof this.#rules[element.tag.getKey()] !== 'undefined') {\n      // 1. tag itself\n      rule = this.#rules[element.tag.getKey()];\n    } else if (typeof tagName !== 'undefined' &&\n      typeof this.#rules[tagName] !== 'undefined') {\n      // 2. tag name\n      rule = this.#rules[tagName];\n    } else if (typeof this.#rules[groupName] !== 'undefined') {\n      // 3. group name\n      rule = this.#rules[groupName];\n    } else {\n      // 4. default\n      rule = this.#rules['default'];\n    }\n    // apply action on element and return\n    return writerActions[rule.action](element, rule.value);\n  }\n\n  /**\n   * Write a list of items.\n   *\n   * @param {DataWriter} writer The raw data writer.\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} items The list of items to write.\n   * @param {boolean} isImplicit Is the DICOM VR implicit?\n   * @returns {number} The new offset position.\n   */\n  #writeDataElementItems(\n    writer, byteOffset, items, isImplicit) {\n    let item;\n    for (let i = 0; i < items.length; ++i) {\n      item = items[i];\n      if (item.length === 0) {\n        continue;\n      }\n      // item element (create new to not modify original)\n      let undefinedLength = false;\n      const itemTag = item.find((subItem) => isItemTag(subItem.tag));\n      if (typeof itemTag !== 'undefined' &&\n        typeof itemTag.undefinedLength !== 'undefined') {\n        undefinedLength = itemTag.undefinedLength;\n      }\n      const itemElement = new DataElement('NONE');\n      itemElement.vl = undefinedLength ? 0xffffffff : itemTag.vl,\n      itemElement.tag = getItemTag();\n      itemElement.value = [];\n      byteOffset = this.#writeDataElement(\n        writer, itemElement, byteOffset, isImplicit);\n      // write rest\n      for (const subItem of item) {\n        if (!isItemTag(subItem.tag) &&\n          !isItemDelimitationItemTag(subItem.tag)) {\n          byteOffset = this.#writeDataElement(\n            writer, subItem, byteOffset, isImplicit);\n        }\n      }\n      // item delimitation\n      if (undefinedLength) {\n        const itemDelimElement = new DataElement('NONE');\n        itemDelimElement.vl = 0;\n        itemDelimElement.tag = getItemDelimitationItemTag();\n        itemDelimElement.value = [];\n        byteOffset = this.#writeDataElement(\n          writer, itemDelimElement, byteOffset, isImplicit);\n      }\n    }\n\n    // return new offset\n    return byteOffset;\n  }\n\n  /**\n   * Write data with a specific Value Representation (VR).\n   *\n   * @param {DataWriter} writer The raw data writer.\n   * @param {DataElement} element The element to write.\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} value The array to write.\n   * @param {boolean} isImplicit Is the DICOM VR implicit?\n   * @returns {number} The new offset position.\n   */\n  #writeDataElementValue(\n    writer, element, byteOffset, value, isImplicit) {\n\n    const startOffset = byteOffset;\n\n    if (element.vr === 'NONE') {\n      // nothing to do!\n    } else if (value instanceof Uint8Array) {\n      // binary data has been expanded 8 times at read\n      if (value.length === 8 * element.vl) {\n        byteOffset = writer.writeBinaryArray(byteOffset, value);\n      } else {\n        byteOffset = writer.writeUint8Array(byteOffset, value);\n      }\n    } else if (value instanceof Int8Array) {\n      byteOffset = writer.writeInt8Array(byteOffset, value);\n    } else if (value instanceof Uint16Array) {\n      byteOffset = writer.writeUint16Array(byteOffset, value);\n    } else if (value instanceof Int16Array) {\n      byteOffset = writer.writeInt16Array(byteOffset, value);\n    } else if (value instanceof Uint32Array) {\n      byteOffset = writer.writeUint32Array(byteOffset, value);\n    } else if (value instanceof Int32Array) {\n      byteOffset = writer.writeInt32Array(byteOffset, value);\n    } else if (value instanceof BigUint64Array) {\n      byteOffset = writer.writeUint64Array(byteOffset, value);\n    } else if (value instanceof BigInt64Array) {\n      byteOffset = writer.writeInt64Array(byteOffset, value);\n    } else {\n      // switch according to VR if input type is undefined\n      const vrType = vrTypes[element.vr];\n      if (typeof vrType !== 'undefined') {\n        if (vrType === 'Uint8') {\n          byteOffset = writer.writeUint8Array(byteOffset, value);\n        } else if (vrType === 'Uint16') {\n          byteOffset = writer.writeUint16Array(byteOffset, value);\n        } else if (vrType === 'Int16') {\n          byteOffset = writer.writeInt16Array(byteOffset, value);\n        } else if (vrType === 'Uint32') {\n          byteOffset = writer.writeUint32Array(byteOffset, value);\n        } else if (vrType === 'Int32') {\n          byteOffset = writer.writeInt32Array(byteOffset, value);\n        } else if (vrType === 'Uint64') {\n          byteOffset = writer.writeUint64Array(byteOffset, value);\n        } else if (vrType === 'Int64') {\n          byteOffset = writer.writeInt64Array(byteOffset, value);\n        } else if (vrType === 'Float32') {\n          byteOffset = writer.writeFloat32Array(byteOffset, value);\n        } else if (vrType === 'Float64') {\n          byteOffset = writer.writeFloat64Array(byteOffset, value);\n        } else if (vrType === 'string') {\n          byteOffset = writer.writeUint8Array(byteOffset, value);\n        } else {\n          throw new Error('Unknown VR type: ' + vrType);\n        }\n      } else if (element.vr === 'SQ') {\n        byteOffset = this.#writeDataElementItems(\n          writer, byteOffset, value, isImplicit);\n      } else if (element.vr === 'AT') {\n        for (let i = 0; i < value.length; ++i) {\n          const hexString = value[i] + '';\n          const hexString1 = hexString.substring(1, 5);\n          const hexString2 = hexString.substring(6, 10);\n          const dec1 = parseInt(hexString1, 16);\n          const dec2 = parseInt(hexString2, 16);\n          const atValue = [dec1, dec2];\n          byteOffset = writer.writeUint16Array(byteOffset, atValue);\n        }\n      } else if (element.vr === 'xs') {\n        // TODO would be better to use pixelRepresentation in if\n        if (value instanceof Int16Array) {\n          byteOffset = writer.writeInt16Array(byteOffset, value);\n        } else {\n          byteOffset = writer.writeUint16Array(byteOffset, value);\n        }\n      } else {\n        logger.warn('Unknown VR: ' + element.vr);\n      }\n    }\n\n    if (element.vr !== 'SQ' && element.vr !== 'NONE') {\n      const diff = byteOffset - startOffset;\n      if (diff !== element.vl) {\n        let message = 'Offset difference and VL are not equal: ' +\n          diff + ' != ' + element.vl;\n        message += ' (';\n        if (typeof element.tag !== 'undefined') {\n          message += element.tag + ', ';\n        }\n        message += 'vr:' + element.vr + ')';\n        logger.warn(message);\n      }\n    }\n\n    // return new offset\n    return byteOffset;\n  }\n\n  /**\n   * Write a pixel data element.\n   *\n   * @param {DataWriter} writer The raw data writer.\n   * @param {DataElement} element The element to write.\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} value The array to write.\n   * @param {boolean} isImplicit Is the DICOM VR implicit?\n   * @returns {number} The new offset position.\n   */\n  #writePixelDataElementValue(\n    writer, element, byteOffset, value, isImplicit) {\n    // undefined length flag\n    let undefinedLength = false;\n    if (typeof element.undefinedLength !== 'undefined') {\n      undefinedLength = element.undefinedLength;\n    }\n    // explicit length\n    if (!undefinedLength) {\n      let finalValue = value[0];\n      // flatten multi frame\n      if (value.length > 1) {\n        finalValue = flattenArrayOfTypedArrays(value);\n      }\n      // write\n      byteOffset = this.#writeDataElementValue(\n        writer, element, byteOffset, finalValue, isImplicit);\n    } else {\n      // pixel data as sequence\n      const item = {};\n      // first item: basic offset table\n      item['FFFEE000'] = {\n        tag: getItemTag(),\n        vr: 'NONE',\n        vl: 0,\n        value: []\n      };\n      // data\n      for (let i = 0; i < value.length; ++i) {\n        item[i] = {\n          tag: getItemTag(),\n          vr: element.vr,\n          vl: value[i].length,\n          value: value[i]\n        };\n      }\n      // write\n      byteOffset = this.#writeDataElementItems(\n        writer, byteOffset, [item], isImplicit);\n    }\n\n    // return new offset\n    return byteOffset;\n  }\n\n  /**\n   * Write a data element.\n   *\n   * @param {DataWriter} writer The raw data writer.\n   * @param {DataElement} element The DICOM data element to write.\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {boolean} isImplicit Is the DICOM VR implicit?\n   * @returns {number} The new offset position.\n   */\n  #writeDataElement(\n    writer, element, byteOffset, isImplicit) {\n    const isTagWithVR = element.tag.isWithVR();\n    const is32bitVL = (isImplicit || !isTagWithVR)\n      ? true : is32bitVLVR(element.vr);\n    // group\n    byteOffset = writer.writeHex(byteOffset, element.tag.getGroup());\n    // element\n    byteOffset = writer.writeHex(byteOffset, element.tag.getElement());\n    // VR\n    let vr = element.vr;\n    // use VR=UN for private sequence\n    if (this.#useUnVrForPrivateSq &&\n      element.tag.isPrivate() &&\n      vr === 'SQ') {\n      logger.warn('Write element using VR=UN for private sequence.');\n      vr = 'UN';\n    }\n    if (isTagWithVR && !isImplicit) {\n      byteOffset = writer.writeUint8Array(byteOffset, this.#encodeString(vr));\n      // reserved 2 bytes for 32bit VL\n      if (is32bitVL) {\n        byteOffset += 2;\n      }\n    }\n\n    let undefinedLengthSequence = false;\n    if (element.vr === 'SQ' ||\n      isPixelDataTag(element.tag)) {\n      if (typeof element.undefinedLength !== 'undefined') {\n        undefinedLengthSequence = element.undefinedLength;\n      }\n    }\n    let undefinedLengthItem = false;\n    if (isItemTag(element.tag)) {\n      if (typeof element.undefinedLength !== 'undefined') {\n        undefinedLengthItem = element.undefinedLength;\n      }\n    }\n\n    // update vl for sequence or item with undefined length\n    let vl = element.vl;\n    if (undefinedLengthSequence || undefinedLengthItem) {\n      vl = 0xffffffff;\n    }\n    // VL\n    if (is32bitVL) {\n      byteOffset = writer.writeUint32(byteOffset, vl);\n    } else {\n      byteOffset = writer.writeUint16(byteOffset, vl);\n    }\n\n    // value\n    let value = element.value;\n    // check value\n    if (typeof value === 'undefined') {\n      value = [];\n    }\n    // write\n    if (isPixelDataTag(element.tag)) {\n      byteOffset = this.#writePixelDataElementValue(\n        writer, element, byteOffset, value, isImplicit);\n    } else {\n      byteOffset = this.#writeDataElementValue(\n        writer, element, byteOffset, value, isImplicit);\n    }\n\n    // sequence delimitation item for sequence with undefined length\n    if (undefinedLengthSequence) {\n      const seqDelimElement = new DataElement('NONE');\n      seqDelimElement.vl = 0;\n      seqDelimElement.tag = getSequenceDelimitationItemTag();\n      seqDelimElement.value = [];\n      byteOffset = this.#writeDataElement(\n        writer, seqDelimElement, byteOffset, isImplicit);\n    }\n\n    // return new offset\n    return byteOffset;\n  }\n\n  /**\n   * Get the ArrayBuffer corresponding to input DICOM elements.\n   *\n   * @param {Object<string, DataElement>} dataElements The elements to write.\n   * @returns {ArrayBuffer} The elements as a buffer.\n   */\n  getBuffer(dataElements) {\n    // Transfer Syntax\n    const syntax = dataElements[TagKeys.TransferSyntax].value[0];\n    const isImplicit = isImplicitTransferSyntax(syntax);\n    const isBigEndian = isBigEndianTransferSyntax(syntax);\n    // Specific CharacterSet\n    if (typeof dataElements[TagKeys.SpecificCharacterSet] !== 'undefined') {\n      const oldscs = dataElements[TagKeys.SpecificCharacterSet].value[0];\n      // force UTF-8 if not default character set\n      if (typeof oldscs !== 'undefined' && oldscs !== 'ISO-IR 6') {\n        logger.debug('Change charset to UTF, was: ' + oldscs);\n        this.useSpecialTextEncoder();\n        dataElements[TagKeys.SpecificCharacterSet].value = ['ISO_IR 192'];\n      }\n    }\n    // Bits Allocated (for image data)\n    let bitsAllocated;\n    if (typeof dataElements[TagKeys.BitsAllocated] !== 'undefined') {\n      bitsAllocated = dataElements[TagKeys.BitsAllocated].value[0];\n    }\n\n    // calculate buffer size and split elements (meta and non meta)\n    let totalSize = 128 + 4; // DICM\n    let localSize = 0;\n    const metaElements = [];\n    const rawElements = [];\n    let element;\n    let groupName;\n    let metaLength = 0;\n    // FileMetaInformationGroupLength\n    const fmiglTag = getFileMetaInformationGroupLengthTag();\n    // FileMetaInformationVersion\n    const fmivTag = new Tag('0002', '0001');\n    // ImplementationClassUID\n    const icUIDTag = new Tag('0002', '0012');\n    // ImplementationVersionName\n    const ivnTag = new Tag('0002', '0013');\n\n    // missing tag list: start as a copy of compulsory\n    const missingTags = this.#compulsoryTags.slice();\n\n    // loop through elements to get the buffer size\n    const keys = Object.keys(dataElements);\n    for (let i = 0, leni = keys.length; i < leni; ++i) {\n      const originalElement = dataElements[keys[i]];\n      originalElement.tag = getTagFromKey(keys[i]);\n      element = this.getElementToWrite(originalElement);\n      if (element !== null &&\n        !fmiglTag.equals(element.tag) &&\n        !fmivTag.equals(element.tag) &&\n        !icUIDTag.equals(element.tag) &&\n        !ivnTag.equals(element.tag)) {\n        localSize = 0;\n\n        // check if compulsory tag, if present remove from missing list\n        const index = missingTags.indexOf(element.tag.getKey());\n        if (index !== -1) {\n          missingTags.splice(index, 1);\n        }\n\n        // XB7 2020-04-17\n        // Check if UN can be converted to correct VR.\n        // This check must be done BEFORE calculating totalSize,\n        // otherwise there may be extra null bytes at the end of the file\n        // (dcmdump may crash because of these bytes)\n        if (this.#fixUnknownVR) {\n          checkAndFixUnknownVR(element, !isBigEndian);\n        }\n\n        // update value and vl\n        this.#setElementValue(\n          element, element.value, isImplicit, bitsAllocated);\n\n        // tag group name\n        groupName = element.tag.getGroupName();\n\n        // prefix\n        if (groupName === 'Meta Element') {\n          localSize += getDataElementPrefixByteSize(element.vr, false);\n        } else {\n          localSize += getDataElementPrefixByteSize(\n            element.vr, isImplicit);\n        }\n\n        // value\n        localSize += element.vl;\n\n        // sort elements\n        if (groupName === 'Meta Element') {\n          metaElements.push(element);\n          metaLength += localSize;\n        } else {\n          rawElements.push(element);\n        }\n\n        // add to total size\n        totalSize += localSize;\n      }\n    }\n\n    // add compulsory tags to output data if not present\n    for (const key of missingTags) {\n      const tag = getTagFromKey(key);\n      const dataElement = new DataElement(tag.getVrFromDictionary());\n      dataElement.tag = tag;\n      // rules are indexed by key or tag name\n      let value;\n      if (typeof this.#rules[key] !== 'undefined') {\n        value = this.#rules[key].value;\n      } else {\n        const name = tag.getNameFromDictionary();\n        value = this.#rules[name].value;\n      }\n      // add element\n      let size = getDataElementPrefixByteSize(dataElement.vr, isImplicit);\n      size += this.#setElementValue(dataElement, [value], isImplicit);\n      rawElements.push(dataElement);\n      totalSize += size;\n    }\n\n    // FileMetaInformationVersion\n    const fmiv = getDataElement('FileMetaInformationVersion');\n    let fmivSize = getDataElementPrefixByteSize(fmiv.vr, false);\n    fmivSize += this.#setElementValue(fmiv, [0, 1], false);\n    metaElements.push(fmiv);\n    metaLength += fmivSize;\n    totalSize += fmivSize;\n    // ImplementationClassUID\n    const icUID = getDataElement('ImplementationClassUID');\n    let icUIDSize = getDataElementPrefixByteSize(icUID.vr, false);\n    const icUIDValue =\n      getUID('ImplementationClassUID').replace('-beta', '.99');\n    icUIDSize += this.#setElementValue(icUID, [icUIDValue], false);\n    metaElements.push(icUID);\n    metaLength += icUIDSize;\n    totalSize += icUIDSize;\n    // ImplementationVersionName\n    const ivn = getDataElement('ImplementationVersionName');\n    let ivnSize = getDataElementPrefixByteSize(ivn.vr, false);\n    const dwvVersion = getDwvVersion().replace('-beta', '.99');\n    const ivnValue = 'DWV_' + dwvVersion;\n    ivnSize += this.#setElementValue(ivn, [ivnValue], false);\n    metaElements.push(ivn);\n    metaLength += ivnSize;\n    totalSize += ivnSize;\n\n    // sort elements\n    const elemSortFunc = function (a, b) {\n      return tagCompareFunction(a.tag, b.tag);\n    };\n    metaElements.sort(elemSortFunc);\n    rawElements.sort(elemSortFunc);\n\n    // create the FileMetaInformationGroupLength element\n    const fmigl = getDataElement('FileMetaInformationGroupLength');\n    let fmiglSize = getDataElementPrefixByteSize(fmigl.vr, false);\n    fmiglSize += this.#setElementValue(\n      fmigl, new Uint32Array([metaLength]), false);\n    totalSize += fmiglSize;\n\n    // create buffer\n    const buffer = new ArrayBuffer(totalSize);\n    const metaWriter = new DataWriter(buffer);\n    const dataWriter = new DataWriter(buffer, !isBigEndian);\n\n    let offset = 128;\n    // DICM\n    offset = metaWriter.writeUint8Array(offset, this.#encodeString('DICM'));\n    // FileMetaInformationGroupLength\n    offset = this.#writeDataElement(metaWriter, fmigl, offset, false);\n    // write meta\n    for (let j = 0, lenj = metaElements.length; j < lenj; ++j) {\n      offset = this.#writeDataElement(\n        metaWriter, metaElements[j], offset, false);\n    }\n\n    // check meta position\n    const preambleSize = 128 + 4;\n    const metaOffset = preambleSize + fmiglSize + metaLength;\n    if (offset !== metaOffset) {\n      logger.warn('Bad size calculation... meta offset: ' + offset +\n        ', calculated size:' + metaOffset +\n        ' (diff:' + (offset - metaOffset) + ')');\n    }\n\n    // write non meta\n    for (let k = 0, lenk = rawElements.length; k < lenk; ++k) {\n      offset = this.#writeDataElement(\n        dataWriter, rawElements[k], offset, isImplicit);\n    }\n\n    // check final position\n    if (offset !== totalSize) {\n      logger.warn('Bad size calculation... final offset: ' + offset +\n        ', calculated size:' + totalSize +\n        ' (diff:' + (offset - totalSize) + ')');\n    }\n    // return\n    return buffer;\n  }\n\n  /**\n   * Set a DICOM element value according to its VR (Value Representation).\n   *\n   * @param {DataElement} element The DICOM element to set the value.\n   * @param {object} value The value to set.\n   * @param {boolean} isImplicit Does the data use implicit VR?\n   * @param {number} [bitsAllocated] Bits allocated used for pixel data.\n   * @returns {number} The total element size.\n   */\n  #setElementValue(\n    element, value, isImplicit, bitsAllocated) {\n    // byte size of the element\n    let size = 0;\n    // special sequence case\n    if (element.vr === 'SQ') {\n\n      if (value !== null && value !== 0) {\n        const newItems = [];\n\n        // explicit or undefined length sequence\n        let undefinedLength = false;\n        if (typeof element.undefinedLength !== 'undefined') {\n          undefinedLength = element.undefinedLength;\n          delete element.undefinedLength;\n        }\n\n        // items\n        for (let i = 0; i < value.length; ++i) {\n          const oldItemElements = value[i];\n          const newItemElements = [];\n          let subSize = 0;\n\n          // check data\n          if (oldItemElements === null || oldItemElements === 0) {\n            continue;\n          }\n\n          // possible local bitsAllocated\n          let sqBitsAllocated = bitsAllocated;\n          const dataElement = oldItemElements[TagKeys.BitsAllocated];\n          if (typeof dataElement !== 'undefined' &&\n            typeof dataElement.value !== 'undefined') {\n            sqBitsAllocated = dataElement.value[0];\n          }\n\n          // elements\n          const itemKeys = Object.keys(oldItemElements);\n          for (let j = 0, lenj = itemKeys.length; j < lenj; ++j) {\n            const itemKey = itemKeys[j];\n            const subElement = oldItemElements[itemKey];\n            subElement.tag = getTagFromKey(itemKey);\n\n            if (isItemTag(subElement.tag)) {\n              continue;\n            }\n            // set item value\n            subSize += this.#setElementValue(\n              subElement, subElement.value, isImplicit, sqBitsAllocated);\n            newItemElements.push(subElement);\n            // add prefix size\n            subSize += getDataElementPrefixByteSize(\n              subElement.vr, isImplicit);\n          }\n\n          // add item element (used to store its size)\n          const itemElement = {\n            tag: getItemTag(),\n            vr: 'NONE',\n            vl: subSize,\n            value: []\n          };\n          if (undefinedLength) {\n            itemElement.undefinedLength = undefinedLength;\n          }\n          newItemElements.push(itemElement);\n          subSize += getDataElementPrefixByteSize(\n            itemElement.vr, isImplicit);\n\n          // add item delimitation size\n          if (undefinedLength) {\n            subSize += getDataElementPrefixByteSize(\n              'NONE', isImplicit);\n          }\n\n          // sort\n          const elemSortFunc = function (a, b) {\n            return tagCompareFunction(a.tag, b.tag);\n          };\n          newItemElements.sort(elemSortFunc);\n\n          size += subSize;\n          newItems.push(newItemElements);\n        }\n\n        // add sequence delimitation size\n        if (undefinedLength) {\n          size += getDataElementPrefixByteSize('NONE', isImplicit);\n        }\n\n        // update sequence element\n        element.value = newItems;\n        element.vl = size;\n        if (undefinedLength) {\n          element.undefinedLength = undefinedLength;\n        }\n      }\n    } else {\n      // pad if necessary\n      if (isVrToPad(element.vr)) {\n        const padStr = getVrPad(element.vr);\n        // encode string\n        // TODO: not sure for UN...\n        if (isStringVr(element.vr)) {\n          let pad;\n          if (isCharSetStringVR(element.vr)) {\n            value = this.#encodeSpecialString(value.join('\\\\'));\n            pad = this.#encodeSpecialString(padStr);\n          } else {\n            value = this.#encodeString(value.join('\\\\'));\n            pad = this.#encodeString(padStr);\n          }\n          if (!isEven(value.length)) {\n            value = uint8ArrayPush(value, pad);\n          }\n        } else if (element.vr === 'OB') {\n          value = padOBValue(value);\n        }\n      }\n\n      // calculate byte size\n      size = 0;\n      if (element.vr === 'AT') {\n        size = 4 * value.length;\n      } else if (element.vr === 'xs') {\n        size = value.length * Uint16Array.BYTES_PER_ELEMENT;\n      } else if (isTypedArrayVr(element.vr) || element.vr === 'ox') {\n        if (isPixelDataTag(element.tag) &&\n          Array.isArray(value)) {\n          size = 0;\n          for (let b = 0; b < value.length; ++b) {\n            size += value[b].length;\n          }\n        } else {\n          size = value.length;\n        }\n\n        // convert size to bytes\n        const vrType = vrTypes[element.vr];\n        if (isPixelDataTag(element.tag) || element.vr === 'ox') {\n          if (element.undefinedLength) {\n            const itemPrefixSize =\n              getDataElementPrefixByteSize('NONE', isImplicit);\n            // offset table\n            size += itemPrefixSize;\n            // pixel items\n            size += itemPrefixSize * value.length;\n            // add sequence delimitation size\n            size += itemPrefixSize;\n          } else {\n            // use bitsAllocated for pixel data\n            // no need to multiply for 8 bits\n            if (typeof bitsAllocated !== 'undefined') {\n              if (bitsAllocated === 1) {\n                // binary data\n                size /= 8;\n              } else if (bitsAllocated === 16) {\n                size *= Uint16Array.BYTES_PER_ELEMENT;\n              }\n            }\n          }\n        } else if (typeof vrType !== 'undefined') {\n          const bpe = getBpeForVrType(vrType);\n          if (typeof bpe !== 'undefined') {\n            size *= bpe;\n          } else {\n            throw new Error('Unknown bytes per element for VR type: ' + vrType);\n          }\n        } else {\n          throw new Error('Unsupported element: ' + element.vr);\n        }\n      } else {\n        size = value.length;\n      }\n\n      element.value = value;\n      element.vl = size;\n    }\n\n    // return the size of that data\n    return size;\n  }\n\n} // class DicomWriter\n\n/**\n * Fix for broken DICOM elements: replace \"UN\" with correct VR if the\n * element exists in dictionary.\n *\n * @param {DataElement} element The DICOM element.\n * @param {boolean} [isLittleEndian] Flag to tell if the data is little\n *   or big endian (default: true).\n */\nfunction checkAndFixUnknownVR(element, isLittleEndian) {\n  if (element.vr === 'UN') {\n    const dictVr = element.tag.getVrFromDictionary();\n    if (typeof dictVr !== 'undefined' && element.vr !== dictVr) {\n      element.vr = dictVr;\n      // cast typed array value from Uint8 to vr type\n      const vrType = vrTypes[element.vr];\n      if (typeof vrType !== 'undefined' &&\n        vrType !== 'Uint8' &&\n        vrType !== 'string') {\n        const data = getUint8ToVrValue(\n          element.value, element.vr, isLittleEndian);\n        if (typeof data !== 'undefined') {\n          element.value = data;\n        }\n      }\n      logger.info('Element ' + element.tag.getGroup() +\n        ' ' + element.tag.getElement() +\n        ' VR changed from UN to ' + element.vr);\n    }\n  }\n}\n\n/**\n * Get the casted typed array value from Uint8 to vr type.\n *\n * @param {object} value The value to cast.\n * @param {string} vr The DICOM element VR.\n * @param {boolean} [isLittleEndian] Flag to tell if the data is little\n *   or big endian (default: true).\n * @returns {object} The element value casted to the vr type.\n */\nfunction getUint8ToVrValue(value, vr, isLittleEndian) {\n  let data;\n  if (typeof value.buffer === 'undefined') {\n    return data;\n  }\n  const reader = new DataReader(value.buffer, isLittleEndian);\n  const offset = value.byteOffset;\n  const vl = value.length; // size before cast\n  const vrType = vrTypes[vr];\n  if (vrType === 'Uint16') {\n    data = reader.readUint16Array(offset, vl);\n  } else if (vrType === 'Uint32') {\n    data = reader.readUint32Array(offset, vl);\n  } else if (vrType === 'Uint64') {\n    data = reader.readUint64Array(offset, vl);\n  } else if (vrType === 'Int16') {\n    data = Array.from(reader.readInt16Array(offset, vl));\n  } else if (vrType === 'Int32') {\n    data = Array.from(reader.readInt32Array(offset, vl));\n  } else if (vrType === 'Int64') {\n    data = reader.readInt64Array(offset, vl);\n  } else if (vrType === 'Float32') {\n    data = Array.from(reader.readFloat32Array(offset, vl));\n  } else if (vrType === 'Float64') {\n    data = Array.from(reader.readFloat64Array(offset, vl));\n  }\n  return data;\n}\n\n/**\n * Get a DICOM element from its tag name (value set separatly).\n *\n * @param {string} tagName The string tag name.\n * @returns {DataElement} The DICOM element.\n */\nfunction getDataElement(tagName) {\n  const tag = getTagFromDictionary(tagName);\n  const element = new DataElement(tag.getVrFromDictionary());\n  element.tag = tag;\n  return element;\n}\n\n/**\n * Get the number of bytes per element for a given VR type.\n *\n * @param {string} vrType The VR type as defined in the dictionary.\n * @returns {number} The bytes per element.\n */\nfunction getBpeForVrType(vrType) {\n  let bpe;\n  if (vrType === 'Uint8') {\n    bpe = Uint8Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Uint16') {\n    bpe = Uint16Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Int16') {\n    bpe = Int16Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Uint32') {\n    bpe = Uint32Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Int32') {\n    bpe = Int32Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Float32') {\n    bpe = Float32Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Float64') {\n    bpe = Float64Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Uint64') {\n    bpe = BigUint64Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Int64') {\n    bpe = BigInt64Array.BYTES_PER_ELEMENT;\n  }\n  return bpe;\n}\n\n/**\n * Get the DICOM elements from a 'simple' DICOM tags object.\n * The input object is a simplified version of the oficial DICOM json with\n * tag names instead of keys and direct values (no value property) for\n * simple tags. See synthetic test data (in tests/dicom) for examples.\n *\n * @param {Object<string, any>} simpleTags The 'simple' DICOM\n *   tags object.\n * @returns {Object<string, DataElement>} The DICOM elements.\n */\nexport function getElementsFromJSONTags(simpleTags) {\n  const keys = Object.keys(simpleTags);\n  const dataElements = {};\n  for (let k = 0, len = keys.length; k < len; ++k) {\n    // get the DICOM element definition from its name\n    const tag = getTagFromDictionary(keys[k]);\n    if (typeof tag === 'undefined') {\n      continue;\n    }\n    const vr = tag.getVrFromDictionary();\n    // tag value\n    let value;\n    let undefinedLength = false;\n    const simpleTag = simpleTags[keys[k]];\n    if (vr === 'SQ') {\n      const items = [];\n      if (typeof simpleTag.undefinedLength !== 'undefined') {\n        undefinedLength = simpleTag.undefinedLength;\n      }\n      if (typeof simpleTag.value !== 'undefined' &&\n        simpleTag.value !== null) {\n        for (let i = 0; i < simpleTag.value.length; ++i) {\n          items.push(getElementsFromJSONTags(simpleTag.value[i]));\n        }\n      } else {\n        logger.trace('Undefined or null simpleTag SQ value.');\n      }\n      value = items;\n    } else {\n      if (Array.isArray(simpleTag)) {\n        value = simpleTag;\n      } else {\n        value = [simpleTag];\n      }\n    }\n    // create element\n    const dataElement = new DataElement(vr);\n    dataElement.tag = tag;\n    dataElement.value = value;\n    if (undefinedLength) {\n      dataElement.undefinedLength = undefinedLength;\n    }\n    // store\n    dataElements[tag.getKey()] = dataElement;\n  }\n  // return\n  // @ts-expect-error\n  return dataElements;\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * DICOM code tag keys.\n */\nconst TagKeys = {\n  CodeValue: '00080100',\n  CodingSchemeDesignator: '00080102',\n  CodeMeaning: '00080104',\n  LongCodeValue: '00080119',\n  URNCodeValue: '00080120'\n};\n\n/**\n * DICOM code: item of a basic code sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_8.8.html}.\n */\nexport class DicomCode {\n  /**\n   * Code meaning.\n   *\n   * @type {string}\n   */\n  meaning;\n  /**\n   * Code value.\n   *\n   * @type {string|undefined}\n   */\n  value;\n  /**\n   * Long code value.\n   *\n   * @type {string|undefined}\n   */\n  longValue;\n  /**\n   * URN code value.\n   *\n   * @type {string|undefined}\n   */\n  urnValue;\n  /**\n   * Coding scheme designator.\n   *\n   * @type {string|undefined}\n   */\n  schemeDesignator;\n\n  /**\n   * @param {string} meaning The code meaning.\n   */\n  constructor(meaning) {\n    this.meaning = meaning;\n  }\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The code as string.\n   */\n  toString() {\n    return '(' + this.value + ', ' +\n      this.schemeDesignator + ', \\'' +\n      this.meaning + '\\')';\n  }\n}\n\n/**\n * Check if two code objects are equal.\n *\n * @param {DicomCode} code1 The first code.\n * @param {DicomCode} code2 The second code.\n * @returns {boolean} True if both codes are equal.\n */\nexport function isEqualCode(code1, code2) {\n  return Object.keys(code1).length === Object.keys(code2).length &&\n  Object.keys(code1).every(key =>\n    Object.prototype.hasOwnProperty.call(code2, key) &&\n    code1[key] === code2[key]\n  );\n}\n\n/**\n * Get a code object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {DicomCode} A code object.\n */\nexport function getCode(dataElements) {\n  // meaning -> CodeMeaning (type1)\n  const code = new DicomCode(dataElements[TagKeys.CodeMeaning].value[0]);\n  // value -> CodeValue (type1C)\n  // longValue -> LongCodeValue (type1C)\n  // urnValue -> URNCodeValue (type1C)\n  if (typeof dataElements[TagKeys.CodeValue] !== 'undefined') {\n    code.value = dataElements[TagKeys.CodeValue].value[0];\n  } else if (typeof dataElements[TagKeys.LongCodeValue] !== 'undefined') {\n    code.longValue = dataElements[TagKeys.LongCodeValue].value[0];\n  } else if (typeof dataElements[TagKeys.URNCodeValue] !== 'undefined') {\n    code.urnValue = dataElements[TagKeys.URNCodeValue].value[0];\n  } else {\n    throw new Error(\n      'Invalid code with no value, no long value and no urn value.');\n  }\n  // schemeDesignator -> CodingSchemeDesignator (type1C)\n  if (typeof code.value !== 'undefined' ||\n    typeof code.longValue !== 'undefined') {\n    if (typeof dataElements[TagKeys.CodingSchemeDesignator] !== 'undefined') {\n      code.schemeDesignator =\n        dataElements[TagKeys.CodingSchemeDesignator].value[0];\n    } else {\n      throw new Error(\n        'No coding sheme designator when code value or long value is present');\n    }\n  }\n  return code;\n}\n\n/**\n * Get a simple dicom element item from a code object.\n *\n * @param {DicomCode} code The code object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomCodeItem(code) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n  // value\n  if (typeof code.value !== 'undefined') {\n    item.CodeValue = code.value;\n  } else if (typeof code.longValue !== 'undefined') {\n    item.LongCodeValue = code.longValue;\n  } else if (typeof code.urnValue !== 'undefined') {\n    item.URNCodeValue = code.urnValue;\n  }\n  // CodingSchemeDesignator\n  if (typeof code.schemeDesignator !== 'undefined') {\n    item.CodingSchemeDesignator = code.schemeDesignator;\n  }\n  // CodeMeaning\n  item.CodeMeaning = code.meaning;\n  // return\n  return item;\n}\n\n/**\n * DICOM codes.\n * List: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part16/chapter_d.html}.\n */\nconst DcmCodes = {\n  111030: 'Image Region',\n  112039: 'Tracking Identifier',\n  112040: 'Tracking Unique Identifier',\n  113048: 'Pixel by pixel Maximum',\n  113049: 'Pixel by pixel mean',\n  113051: 'Pixel by pixel Minimum',\n  113061: 'Standard Deviation',\n  113076: 'Segmentation',\n  121055: 'Path',\n  121207: 'Height',\n  121322: 'Source image for image processing operation',\n  121324: 'Source Image',\n  122438: 'Reference Points',\n  125007: 'Measurement Group',\n  125309: 'Short label',\n  128773: 'Reference Geometry'\n};\n\n/**\n * SNOMED-CT codes.\n * List: {@link https://browser.ihtsdotools.org}.\n */\nconst SctCodes = {\n  1483009: 'Angle',\n  42798000: 'Area',\n  103355008: 'Width',\n  103339001: 'Long axis',\n  103340004: 'Short axis',\n  131190003: 'Radius',\n  261665006: 'Unknown',\n  410668003: 'Length',\n  718499004: 'Color'\n};\n\n/**\n * UCUM codes.\n * Definition: {@link https://unitsofmeasure.org/ucum}.\n * List: {@link https://ucum.nlm.nih.gov/ucum-lhc/demo.html}.\n */\nconst UcumCodes = {\n  1: 'No units',\n  mm: 'Millimeter',\n  deg: 'Degree - plane angle',\n  cm2: 'Square centimeter',\n  'cm2/ml': 'Square centimeter per milliliter',\n  '/cm': 'Per centimeter',\n  'g/ml': 'Gram per milliliter',\n  'g/ml{SUVbw}': 'Standardized Uptake Value body weight',\n  'mg/ml': 'Milligram per milliliter',\n  'umol/ml': 'Micromole per milliliter',\n  'Bq/ml': 'Becquerels per milliliter',\n  'mg/min/ml': 'Milligrams per minute per milliliter',\n  'umol/min/ml': 'Micromole per minute per milliliter',\n  'ml/min/g': 'Milliliter per minute per gram',\n  'ml/g': 'Milliliter per gram',\n  'ml/min/ml': 'Milliliter per minute per milliliter',\n  'ml/ml': 'Milliliter per milliliter',\n  '%': 'Percentage',\n  '[hnsf\\'U]': 'Hounsfield unit',\n  '10*23/ml': 'Electron density',\n  '{counts}': 'Counts',\n  '{counts}/s': 'Counts per second',\n  '{propcounts}': 'Proportional to counts',\n  '{propcounts}/s': 'Proportional to counts per second',\n};\n\n/**\n * Get a DICOM code from a value (~id).\n *\n * @param {string} value The code value.\n * @param {string} scheme The scheme designator.\n * @returns {DicomCode|undefined} The DICOM code.\n */\nfunction getDicomCode(value, scheme) {\n  let meaning;\n  if (scheme === 'DCM') {\n    meaning = DcmCodes[value];\n  } else if (scheme === 'SCT') {\n    meaning = SctCodes[value];\n  } else if (scheme === 'UCUM') {\n    meaning = UcumCodes[value];\n  }\n  let code;\n  if (typeof meaning !== 'undefined') {\n    code = new DicomCode(meaning);\n    code.schemeDesignator = scheme;\n    code.value = value;\n  }\n  return code;\n}\n\n/**\n * Get a measurement group DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getMeasurementGroupCode() {\n  return getDicomCode('125007', 'DCM');\n}\n\n/**\n * Get an image region DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getImageRegionCode() {\n  return getDicomCode('111030', 'DCM');\n}\n\n/**\n * Get a reference geometry DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getReferenceGeometryCode() {\n  return getDicomCode('128773', 'DCM');\n}\n\n/**\n * Get a path DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getPathCode() {\n  return getDicomCode('121055', 'DCM');\n}\n\n/**\n * Get a source image DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getSourceImageCode() {\n  return getDicomCode('121324', 'DCM');\n}\n\n/**\n * Get a tracking identifier DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getTrackingIdentifierCode() {\n  return getDicomCode('112039', 'DCM');\n}\n\n/**\n * Get a segmentation DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getSegmentationCode() {\n  return getDicomCode('113076', 'DCM');\n}\n\n/**\n * Get a source image for processing DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getSourceImageForProcessingCode() {\n  return getDicomCode('121322', 'DCM');\n}\n\n/**\n * Get a short label DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getShortLabelCode() {\n  return getDicomCode('125309', 'DCM');\n}\n\n/**\n * Get a reference points DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getReferencePointsCode() {\n  return getDicomCode('122438', 'DCM');\n}\n\n/**\n * Get a colour DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getColourCode() {\n  return getDicomCode('718499004', 'SCT');\n}\n\n/**\n * Quantification name to dictionary item.\n */\nconst QuantificationName2DictItem = {\n  angle: {key: '1483009', scheme: 'SCT'},\n  length: {key: '410668003', scheme: 'SCT'},\n  surface: {key: '42798000', scheme: 'SCT'},\n  height: {key: '121207', scheme: 'DCM'},\n  width: {key: '103355008', scheme: 'SCT'},\n  radius: {key: '131190003', scheme: 'SCT'},\n  a: {key: '103339001', scheme: 'SCT'},\n  b: {key: '103340004', scheme: 'SCT'},\n  min: {key: '113051', scheme: 'DCM'},\n  max: {key: '113048', scheme: 'DCM'},\n  mean: {key: '113049', scheme: 'DCM'},\n  stddev: {key: '113061', scheme: 'DCM'},\n  // median\n  // 25th percentile\n  // 75th percentile\n};\n\n/**\n * Get a concept name DICOM code.\n *\n * @param {string} name The measurment name as defined\n *   in a quantification object.\n * @returns {DicomCode|undefined} The code.\n */\nexport function getConceptNameCode(name) {\n  const item = QuantificationName2DictItem[name];\n  let code;\n  if (typeof item !== 'undefined') {\n    code = getDicomCode(item.key, item.scheme);\n  }\n  return code;\n}\n\n/**\n * Get the DICOM code for a quantification name.\n *\n * @param {DicomCode} code The Dicom code.\n * @returns {string|undefined} The quantification name.\n */\nexport function getQuantificationName(code) {\n  let name;\n  for (const propKey in QuantificationName2DictItem) {\n    const item = QuantificationName2DictItem[propKey];\n    if (item.scheme === code.schemeDesignator &&\n      item.key === code.value) {\n      name = propKey;\n      break;\n    }\n  }\n  return name;\n}\n\n/**\n * Quantification unit to UCUM key. Associated tags:\n * - Rescale type {@link https://dicom.innolitics.com/ciods/computed-radiography-image/modality-lut/00281054},\n * - Units {@link https://dicom.innolitics.com/ciods/positron-emission-tomography-image/pet-series/00541001}.\n * - SUV {@link https://dicom.nema.org/medical/dicom/current/output/chtml/part16/sect_CID_85.html}.\n */\nconst QuantificationUnit2UcumKey = {\n  'unit.mm': 'mm',\n  'unit.cm2': 'cm2',\n  'unit.degree': 'deg',\n  // OD optical density\n  HU: '[hnsf\\'U]',\n  // US: '1', // duplicates 'NONE'\n  MGML: 'mg/ml',\n  // Z_EFF Effective Atomic Number (i.e., Effective-Z)\n  ED: '10*23/ml',\n  // EDW Electron density normalized\n  // HU_MOD Modified Hounsfield Unit\n  PCT: '%',\n  CNTS: '{counts}',\n  NONE: '1',\n  CM2: 'cm2',\n  CM2ML: 'cm2/ml',\n  PCNT: '%',\n  CPS: '{counts}/s',\n  BQML: 'Bq/ml',\n  MGMINML: 'mg/min/ml',\n  UMOLMINML: 'umol/min/ml',\n  MLMING: 'ml/min/g',\n  MLG: 'ml/g',\n  '1CM': '/cm',\n  UMOLML: 'umol/ml',\n  PROPCNTS: '{propcounts}',\n  PROPCPS: '{propcounts}/s',\n  MLMINML: 'ml/min/ml',\n  MLML: 'ml/ml',\n  GML: 'g/ml',\n  //STDDEV\n  SUV: 'g/ml{SUVbw}',\n};\n\n/**\n * Get a measurement units DICOM code.\n *\n * @param {string} name The unit name as defined in a quantification object.\n * @returns {DicomCode|undefined} The code.\n */\nexport function getMeasurementUnitsCode(name) {\n  const key = QuantificationUnit2UcumKey[name];\n  let code;\n  if (typeof key !== 'undefined') {\n    code = getDicomCode(key, 'UCUM');\n  } else if (typeof key === 'undefined') {\n    // no unit\n    code = getDicomCode('1', 'UCUM');\n  }\n  return code;\n}\n\n/**\n * Get a quantification unit name.\n *\n * @param {DicomCode} code The code to get the unit from.\n * @returns {string} The quantification unit.\n */\nexport function getQuantificationUnit(code) {\n  let unit;\n  for (const propKey in QuantificationUnit2UcumKey) {\n    const ucumKey = QuantificationUnit2UcumKey[propKey];\n    if (code.schemeDesignator === 'UCUM' &&\n      ucumKey === code.value) {\n      unit = propKey;\n      break;\n    }\n  }\n  return unit;\n}\n","import {\n  isEqualRgb,\n  cielabToSrgb,\n  uintLabToLab,\n  labToUintLab,\n  srgbToCielab\n} from '../utils/colour';\nimport {\n  getCode,\n  getDicomCodeItem\n} from './dicomCode';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {RGB} from '../utils/colour';\nimport {DataElement} from './dataElement';\nimport {DicomCode} from './dicomCode';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  SegmentNumber: '00620004',\n  SegmentLabel: '00620005',\n  SegmentAlgorithmType: '00620008',\n  SegmentAlgorithmName: '00620009',\n  RecommendedDisplayGrayscaleValue: '0062000C',\n  RecommendedDisplayCIELabValue: '0062000D',\n  SegmentedPropertyCategoryCodeSequence: '00620003',\n  SegmentedPropertyTypeCodeSequence: '0062000F',\n  TrackingID: '00620020',\n  TrackingUID: '00620021'\n};\n\n/**\n * DICOM (mask) segment: item of a SegmentSequence (0062,0002).\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.8.20.4.html}.\n */\nexport class MaskSegment {\n  /**\n   * Segment number (0062,0004).\n   *\n   * @type {number}\n   */\n  number;\n  /**\n   * Segment label (0062,0005).\n   *\n   * @type {string}\n   */\n  label;\n  /**\n   * Segment algorithm type (0062,0008).\n   *\n   * @type {string}\n   */\n  algorithmType;\n  /**\n   * Segment algorithm name (0062,0009).\n   *\n   * @type {string|undefined}\n   */\n  algorithmName;\n  /**\n   * Segment display value as simple value.\n   *\n   * @type {number|undefined}\n   */\n  displayValue;\n  /**\n   * Segment display value as RGB colour ({r,g,b}).\n   *\n   * @type {RGB|undefined}\n   */\n  displayRGBValue;\n  /**\n   * Segment property code: specific property\n   * the segment represents (0062,000F).\n   *\n   * @type {DicomCode|undefined}\n   */\n  propertyTypeCode;\n  /**\n   * Segment property category code: general category\n   * of the property the segment represents (0062,0003).\n   *\n   * @type {DicomCode|undefined}\n   */\n  propertyCategoryCode;\n  /**\n   * Segment tracking UID (0062,0021).\n   *\n   * @type {string|undefined}\n   */\n  trackingUid;\n  /**\n   * Segment tracking id: text label for the UID (0062,0020).\n   *\n   * @type {string|undefined}\n   */\n  trackingId;\n\n  /**\n   * @param {number} number The segment number.\n   * @param {string} label The segment label.\n   * @param {string} algorithmType The segment number.\n   */\n  constructor(number, label, algorithmType) {\n    this.number = number;\n    this.label = label;\n    this.algorithmType = algorithmType;\n  }\n}\n\n/**\n * Get a segment object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {MaskSegment} A segment object.\n */\nexport function getSegment(dataElements) {\n  // number -> SegmentNumber (type1)\n  // label -> SegmentLabel (type1)\n  // algorithmType -> SegmentAlgorithmType (type1)\n  const segment = new MaskSegment(\n    dataElements[TagKeys.SegmentNumber].value[0],\n    dataElements[TagKeys.SegmentLabel]\n      ? dataElements[TagKeys.SegmentLabel].value[0] : 'n/a',\n    dataElements[TagKeys.SegmentAlgorithmType].value[0]\n  );\n  // algorithmName -> SegmentAlgorithmName (type1C)\n  if (typeof dataElements[TagKeys.SegmentAlgorithmName] !== 'undefined') {\n    segment.algorithmName = dataElements[TagKeys.SegmentAlgorithmName].value[0];\n  }\n  // // required if type is not MANUAL\n  // if (segment.algorithmType !== 'MANUAL' &&\n  //   (typeof segment.algorithmName === 'undefined' ||\n  //   segment.algorithmName.length === 0)) {\n  //   throw new Error('Empty algorithm name for non MANUAL algorithm type.');\n  // }\n  // displayValue ->\n  // - RecommendedDisplayGrayscaleValue\n  // - RecommendedDisplayCIELabValue converted to RGB\n  if (typeof dataElements[TagKeys.RecommendedDisplayGrayscaleValue] !==\n    'undefined') {\n    segment.displayValue =\n      dataElements[TagKeys.RecommendedDisplayGrayscaleValue].value[0];\n  } else if (typeof dataElements[TagKeys.RecommendedDisplayCIELabValue] !==\n    'undefined') {\n    const cielabElement =\n      dataElements[TagKeys.RecommendedDisplayCIELabValue].value;\n    const rgb = cielabToSrgb(uintLabToLab({\n      l: cielabElement[0],\n      a: cielabElement[1],\n      b: cielabElement[2]\n    }));\n    segment.displayRGBValue = rgb;\n  }\n  // Segmented Property Category Code Sequence (type1, only one)\n  if (typeof dataElements[TagKeys.SegmentedPropertyCategoryCodeSequence] !==\n    'undefined') {\n    segment.propertyCategoryCode =\n      getCode(\n        dataElements[TagKeys.SegmentedPropertyCategoryCodeSequence].value[0]\n      );\n  } else {\n    throw new Error('Missing Segmented Property Category Code Sequence.');\n  }\n  // Segmented Property Type Code Sequence (type1)\n  if (typeof dataElements[TagKeys.SegmentedPropertyTypeCodeSequence] !==\n    'undefined') {\n    segment.propertyTypeCode =\n      getCode(dataElements[TagKeys.SegmentedPropertyTypeCodeSequence].value[0]);\n  } else {\n    throw new Error('Missing Segmented Property Type Code Sequence.');\n  }\n  // tracking Id and UID (type1C)\n  if (typeof dataElements[TagKeys.TrackingID] !== 'undefined') {\n    segment.trackingId = dataElements[TagKeys.TrackingID].value[0];\n    segment.trackingUid = dataElements[TagKeys.TrackingUID].value[0];\n  }\n\n  return segment;\n}\n\n/**\n * Check if two segment objects are equal.\n *\n * @param {MaskSegment} seg1 The first segment.\n * @param {MaskSegment} seg2 The second segment.\n * @returns {boolean} True if both segment are equal.\n */\nexport function isEqualSegment(seg1, seg2) {\n  // basics\n  if (typeof seg1 === 'undefined' ||\n    typeof seg2 === 'undefined' ||\n    seg1 === null ||\n    seg2 === null) {\n    return false;\n  }\n  let isEqual = seg1.number === seg2.number &&\n    seg1.label === seg2.label &&\n    seg1.algorithmType === seg2.algorithmType;\n  // display value\n  if (typeof seg1.displayRGBValue !== 'undefined' &&\n    typeof seg2.displayRGBValue !== 'undefined') {\n    isEqual = isEqual &&\n      isEqualRgb(seg1.displayRGBValue, seg2.displayRGBValue);\n  } else if (typeof seg1.displayValue !== 'undefined' &&\n    typeof seg2.displayValue !== 'undefined') {\n    isEqual = isEqual &&\n      seg1.displayValue === seg2.displayValue;\n  } else {\n    isEqual = false;\n  }\n  // algorithmName\n  if (typeof seg1.algorithmName !== 'undefined') {\n    if (typeof seg2.algorithmName === 'undefined') {\n      isEqual = false;\n    } else {\n      isEqual = isEqual &&\n        seg1.algorithmName === seg2.algorithmName;\n    }\n  }\n\n  return isEqual;\n}\n\n/**\n * Check if two segment objects are similar: either the\n * number or the displayValue are equal.\n *\n * @param {MaskSegment} seg1 The first segment.\n * @param {MaskSegment} seg2 The second segment.\n * @returns {boolean} True if both segment are similar.\n */\nexport function isSimilarSegment(seg1, seg2) {\n  // basics\n  if (typeof seg1 === 'undefined' ||\n    typeof seg2 === 'undefined' ||\n    seg1 === null ||\n    seg2 === null) {\n    return false;\n  }\n  let isSimilar = seg1.number === seg2.number;\n  // display value\n  if (typeof seg1.displayRGBValue !== 'undefined' &&\n    typeof seg2.displayRGBValue !== 'undefined') {\n    isSimilar = isSimilar ||\n      isEqualRgb(seg1.displayRGBValue, seg2.displayRGBValue);\n  } else if (typeof seg1.displayValue !== 'undefined' &&\n    typeof seg2.displayValue !== 'undefined') {\n    isSimilar = isSimilar ||\n      seg1.displayValue === seg2.displayValue;\n  } else {\n    isSimilar = false;\n  }\n\n  return isSimilar;\n}\n\n/**\n * Get a dicom simple tag from a segment object.\n *\n * @param {MaskSegment} segment The segment object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSegmentItem(segment) {\n  let algoType = segment.algorithmType;\n  if (algoType === undefined) {\n    algoType = 'MANUAL';\n  }\n  // dicom item (tags are in group/element order)\n  const segmentItem = {\n    SegmentNumber: segment.number,\n    SegmentLabel: segment.label,\n    SegmentAlgorithmType: algoType\n  };\n  // SegmentAlgorithmName\n  if (algoType !== 'MANUAL' && segment.algorithmName !== undefined) {\n    segmentItem.SegmentAlgorithmName = segment.algorithmName;\n  }\n  // RecommendedDisplay value\n  if (segment.displayRGBValue) {\n    const cieLab = labToUintLab(srgbToCielab(segment.displayRGBValue));\n    segmentItem.RecommendedDisplayCIELabValue = [\n      Math.round(cieLab.l),\n      Math.round(cieLab.a),\n      Math.round(cieLab.b)\n    ];\n  } else {\n    segmentItem.RecommendedDisplayGrayscaleValue = segment.displayValue;\n  }\n  // SegmentedPropertyCategoryCodeSequence\n  if (segment.propertyCategoryCode) {\n    segmentItem.SegmentedPropertyCategoryCodeSequence = {\n      value: [getDicomCodeItem(segment.propertyCategoryCode)]\n    };\n  }\n  // SegmentedPropertyTypeCodeSequence\n  if (segment.propertyTypeCode) {\n    segmentItem.SegmentedPropertyTypeCodeSequence = {\n      value: [getDicomCodeItem(segment.propertyTypeCode)]\n    };\n  }\n  // tracking\n  if (segment.trackingId) {\n    segmentItem.TrackingID = segment.trackingId;\n    segmentItem.TrackingUID = segment.trackingUid;\n  }\n  // return\n  return segmentItem;\n}\n","import {getSpacingFromMeasure} from './dicomElementsWrapper';\nimport {logger} from '../utils/logger';\nimport {arrayEquals} from '../utils/array';\nimport {\n  getDicomCodeItem,\n  getSegmentationCode,\n  getSourceImageForProcessingCode\n} from './dicomCode';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\nimport {Spacing} from '../image/spacing';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  DerivationImageSequence: '00089124',\n  SourceImageSequence: '00082112',\n  ReferencedSOPClassUID: '00081150',\n  ReferencedSOPInstanceUID: '00081155',\n  FrameContentSequence: '00209111',\n  DimensionIndexValue: '00209157',\n  SegmentIdentificationSequence: '0062000A',\n  ReferencedSegmentNumber: '0062000B',\n  PlanePositionSequence: '00209113',\n  ImagePosition: '00200032',\n  PlaneOrientationSequence: '00209116',\n  ImageOrientation: '00200037',\n  PixelMeasuresSequence: '00289110'\n};\n\n/**\n * DICOM segment frame info: item of a\n *  PerframeFunctionalGroupsSequence (5200,9230).\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.7.6.16.html}.\n */\nexport class DicomSegmentFrameInfo {\n  /**\n   * The dimension index.\n   *\n   * @type {number[]}\n   */\n  dimIndex;\n  /**\n   * The frame image position patient.\n   *\n   * @type {number[]}\n   */\n  imagePosPat;\n  /**\n   * List of derivation images.\n   *\n   * @type {Array}\n   */\n  derivationImages;\n  /**\n   * The reference segment number.\n   *\n   * @type {number}\n   */\n  refSegmentNumber;\n\n  /**\n   * The frame image orientation.\n   *\n   * @type {number[]|undefined}\n   */\n  imageOrientationPatient;\n  /**\n   * The frame spacing.\n   *\n   * @type {Spacing|undefined}\n   */\n  spacing;\n\n  /**\n   * @param {number[]} dimIndex The dimension index.\n   * @param {number[]} imagePosPat The frame image position patient.\n   * @param {Array} derivationImages List of derivation images.\n   * @param {number} refSegmentNumber The reference segment number.\n   */\n  constructor(dimIndex, imagePosPat, derivationImages, refSegmentNumber) {\n    this.dimIndex = dimIndex;\n    this.imagePosPat = imagePosPat;\n    this.derivationImages = derivationImages;\n    this.refSegmentNumber = refSegmentNumber;\n  }\n}\n\n/**\n * Get a frame information object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {DicomSegmentFrameInfo} A frame information object.\n */\nexport function getSegmentFrameInfo(dataElements) {\n  // Derivation Image Sequence\n  const derivationImages = [];\n  if (typeof dataElements[TagKeys.DerivationImageSequence] !== 'undefined') {\n    const derivationImageSq =\n      dataElements[TagKeys.DerivationImageSequence].value;\n    // Source Image Sequence\n    for (let i = 0; i < derivationImageSq.length; ++i) {\n      const sourceImages = [];\n      if (typeof derivationImageSq[i][TagKeys.SourceImageSequence] !==\n        'undefined') {\n        const sourceImageSq =\n          derivationImageSq[i][TagKeys.SourceImageSequence].value;\n        for (let j = 0; j < sourceImageSq.length; ++j) {\n          const sourceImage = {};\n          // Referenced SOP Class UID\n          if (typeof sourceImageSq[j][TagKeys.ReferencedSOPClassUID] !==\n            'undefined') {\n            sourceImage.referencedSOPClassUID =\n              sourceImageSq[j][TagKeys.ReferencedSOPClassUID].value[0];\n          }\n          // Referenced SOP Instance UID\n          if (typeof sourceImageSq[j][TagKeys.ReferencedSOPInstanceUID] !==\n            'undefined') {\n            sourceImage.referencedSOPInstanceUID =\n              sourceImageSq[j][TagKeys.ReferencedSOPInstanceUID].value[0];\n          }\n          sourceImages.push(sourceImage);\n        }\n      }\n      derivationImages.push({\n        sourceImages: sourceImages\n      });\n    }\n  }\n  // Frame Content Sequence (required, only one)\n  const frameContentSq = dataElements[TagKeys.FrameContentSequence].value;\n  // Dimension Index Value\n  const dimIndex = frameContentSq[0][TagKeys.DimensionIndexValue].value;\n  // Segment Identification Sequence (required, only one)\n  const segmentIdSq = dataElements[TagKeys.SegmentIdentificationSequence].value;\n  // Referenced Segment Number\n  const refSegmentNumber =\n    parseInt(segmentIdSq[0][TagKeys.ReferencedSegmentNumber].value[0], 0);\n  // Plane Position Sequence (required, only one)\n  const planePosSq = dataElements[TagKeys.PlanePositionSequence].value;\n  // Image Position (Patient) (conditionally required)\n  const imagePosPat = planePosSq[0][TagKeys.ImagePosition].value;\n  for (let p = 0; p < imagePosPat.length; ++p) {\n    imagePosPat[p] = parseFloat(imagePosPat[p]);\n  }\n  const frameInfo = new DicomSegmentFrameInfo(\n    dimIndex,\n    imagePosPat,\n    derivationImages,\n    refSegmentNumber\n  );\n  // Plane Orientation Sequence\n  if (typeof dataElements[TagKeys.PlaneOrientationSequence] !== 'undefined') {\n    const framePlaneOrientationSeq =\n      dataElements[TagKeys.PlaneOrientationSequence];\n    if (framePlaneOrientationSeq.value.length !== 0) {\n      // should only be one Image Orientation (Patient)\n      const frameImageOrientation =\n        framePlaneOrientationSeq.value[0][TagKeys.ImageOrientation].value;\n      if (typeof frameImageOrientation !== 'undefined') {\n        frameInfo.imageOrientationPatient = frameImageOrientation;\n      }\n    }\n  }\n  // Pixel Measures Sequence\n  if (typeof dataElements[TagKeys.PixelMeasuresSequence] !== 'undefined') {\n    const framePixelMeasuresSeq = dataElements[TagKeys.PixelMeasuresSequence];\n    if (framePixelMeasuresSeq.value.length !== 0) {\n      // should only be one\n      const frameSpacing =\n        getSpacingFromMeasure(framePixelMeasuresSeq.value[0]);\n      if (typeof frameSpacing !== 'undefined') {\n        frameInfo.spacing = frameSpacing;\n      }\n    } else {\n      logger.warn(\n        'No shared functional group pixel measure sequence items.');\n    }\n  }\n\n  return frameInfo;\n}\n\n/**\n * Check if two frame info objects are equal.\n *\n * @param {DicomSegmentFrameInfo} dsfi1 The first frame info.\n * @param {DicomSegmentFrameInfo} dsfi2 The second frame info.\n * @returns {boolean} True if both frame info are equal.\n */\nexport function isEqualSegmentFrameInfo(dsfi1, dsfi2) {\n  // basics\n  if (typeof dsfi1 === 'undefined' ||\n    typeof dsfi2 === 'undefined' ||\n    dsfi1 === null ||\n    dsfi2 === null) {\n    return false;\n  }\n  let isEqual =\n    arrayEquals(dsfi1.dimIndex, dsfi2.dimIndex) &&\n    arrayEquals(dsfi1.imagePosPat, dsfi2.imagePosPat) &&\n    dsfi1.refSegmentNumber === dsfi2.refSegmentNumber;\n\n  isEqual = isEqual &&\n    dsfi1.derivationImages.length === dsfi2.derivationImages.length;\n  for (let i = 0; i < dsfi1.derivationImages.length; ++i) {\n    const derivationImage1 = dsfi1.derivationImages[i];\n    const derivationImage2 = dsfi2.derivationImages[i];\n    isEqual = isEqual &&\n      derivationImage1.sourceImages.length ===\n        derivationImage2.sourceImages.length;\n    for (let j = 0; j < derivationImage1.length; ++j) {\n      const sourceImage1 = derivationImage1.sourceImages[j];\n      const sourceImage2 = derivationImage2.sourceImages[j];\n      isEqual = isEqual &&\n        sourceImage1.referencedSOPClassUID ===\n          sourceImage2.referencedSOPClassUID &&\n        sourceImage1.referencedSOPInstanceUID ===\n          sourceImage2.referencedSOPInstanceUID;\n    }\n  }\n\n  return isEqual;\n}\n\n/**\n * Get a dicom item from a frame information object.\n *\n * @param {object} frameInfo The frame information object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSegmentFrameInfoItem(frameInfo) {\n  const item = {\n    FrameContentSequence: {\n      value: [\n        {\n          DimensionIndexValues: frameInfo.dimIndex\n        }\n      ]\n    },\n    PlanePositionSequence: {\n      value: [\n        {\n          ImagePositionPatient: frameInfo.imagePosPat\n        }\n      ]\n    },\n    SegmentIdentificationSequence: {\n      value: [\n        {\n          ReferencedSegmentNumber: frameInfo.refSegmentNumber\n        }\n      ]\n    }\n  };\n  // optional DerivationImageSequence\n  if (frameInfo.derivationImages !== undefined) {\n    const sourceImgPurposeOfReferenceCode =\n      getDicomCodeItem(getSourceImageForProcessingCode());\n    const segDerivationCode =\n      getDicomCodeItem(getSegmentationCode());\n\n    const derivationImageItems = [];\n    for (const derivationImage of frameInfo.derivationImages) {\n      const sourceImages = [];\n      for (const sourceImage of derivationImage.sourceImages) {\n        sourceImages.push({\n          PurposeOfReferenceCodeSequence: {\n            value: [sourceImgPurposeOfReferenceCode]\n          },\n          ReferencedSOPClassUID: sourceImage.referencedSOPClassUID,\n          ReferencedSOPInstanceUID: sourceImage.referencedSOPInstanceUID\n        });\n      }\n\n      derivationImageItems.push({\n        DerivationCodeSequence: {\n          value: [segDerivationCode]\n        },\n        SourceImageSequence: {\n          value: sourceImages\n        }\n      });\n    }\n\n    item.DerivationImageSequence = {\n      value: derivationImageItems\n    };\n  }\n\n  return item;\n}\n","import {\n  dateToDateObj,\n  getDicomDate,\n  dateToTimeObj,\n  getDicomTime,\n} from '../dicom/dicomDate';\nimport {safeGet} from '../dicom/dataElement';\nimport {\n  getImage2DSize,\n  getSpacingFromMeasure,\n  getDimensionOrganization,\n  getDicomMeasureItem,\n  getDicomPlaneOrientationItem\n} from '../dicom/dicomElementsWrapper';\nimport {Tag} from '../dicom/dicomTag';\nimport {getElementsFromJSONTags} from '../dicom/dicomWriter';\nimport {\n  getSegment,\n  getDicomSegmentItem,\n} from '../dicom/dicomSegment';\nimport {\n  getSegmentFrameInfo,\n  getDicomSegmentFrameInfoItem\n} from '../dicom/dicomSegmentFrameInfo';\nimport {transferSyntaxKeywords} from '../dicom/dictionary';\nimport {Image} from '../image/image';\nimport {Geometry} from '../image/geometry';\nimport {Point, Point3D} from '../math/point';\nimport {Vector3D} from '../math/vector';\nimport {Index} from '../math/index';\nimport {Matrix33, REAL_WORLD_EPSILON} from '../math/matrix';\nimport {logger} from '../utils/logger';\nimport {arraySortEquals} from '../utils/array';\nimport {Size} from './size';\nimport {ColourMap} from './luts';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from '../dicom/dataElement';\nimport {MaskSegment} from '../dicom/dicomSegment';\n/* eslint-enable no-unused-vars */\n\n/**\n * @typedef {Object<string, DataElement>} DataElements\n */\n\n/**\n * Check two position patients for equality.\n *\n * @param {*} pos1 The first position patient.\n * @param {*} pos2 The second position patient.\n * @returns {boolean} True is equal.\n */\nfunction equalPosPat(pos1, pos2) {\n  return JSON.stringify(pos1) === JSON.stringify(pos2);\n}\n\n/**\n * @callback compareFn\n * @param {object} a The first object.\n * @param {object} b The first object.\n * @returns {number} >0 to sort a after b, <0 to sort a before b,\n *   0 to not change order.\n */\n\n/**\n * Get a position patient compare function accroding to an\n * input orientation.\n *\n * @param {Matrix33} orientation The orientation matrix.\n * @returns {compareFn} The position compare function.\n */\nfunction getComparePosPat(orientation) {\n  const invOrientation = orientation.getInverse();\n  return function (pos1, pos2) {\n    const p1 = invOrientation.multiplyArray3D(pos1);\n    const p2 = invOrientation.multiplyArray3D(pos2);\n    return p1[2] - p2[2];\n  };\n}\n\n/**\n * Merge two tag lists.\n *\n * @param {object} tags1 Base list, will be modified.\n * @param {object} tags2 List to merge.\n */\nfunction mergeTags(tags1, tags2) {\n  const keys2 = Object.keys(tags2);\n  for (const tagName2 of keys2) {\n    if (tags1[tagName2] !== undefined) {\n      logger.trace('Overwritting tag: ' + tagName2);\n    }\n    tags1[tagName2] = tags2[tagName2];\n  }\n}\n\n/**\n * Check that a DICOM tag definition is present in a parsed element.\n *\n * @param {DataElements} dataElements The root dicom element.\n * @param {object} tagDefinition The tag definition as {name, tag, type, enum}.\n */\nfunction checkTag(dataElements, tagDefinition) {\n  const element = dataElements[tagDefinition.tag];\n  // check null and undefined\n  if (tagDefinition.type === 1 || tagDefinition.type === 2) {\n    if (typeof element === 'undefined') {\n      throw new Error('Missing or empty ' + tagDefinition.name);\n    }\n  } else {\n    if (typeof element === 'undefined') {\n      // non mandatory value, exit\n      return;\n    }\n  }\n  let includes = false;\n  let tagValue;\n  if (element.value.length === 1) {\n    tagValue = element.value[0];\n  } else {\n    tagValue = element.value;\n  }\n  if (Array.isArray(tagValue)) {\n    for (let i = 0; i < tagDefinition.enum.length; ++i) {\n      if (!Array.isArray(tagDefinition.enum[i])) {\n        throw new Error('Cannot compare array and non array tag value.');\n      }\n      if (arraySortEquals(tagDefinition.enum[i], tagValue)) {\n        includes = true;\n        break;\n      }\n    }\n  } else {\n    includes = tagDefinition.enum.includes(tagValue);\n  }\n  if (!includes) {\n    throw new Error(\n      'Unsupported ' + tagDefinition.name + ' value: ' + tagValue);\n  }\n}\n\n/**\n * Create ROI slice buffers.\n *\n * @param {Image} image The mask image.\n * @param {MaskSegment[]} segments The mask segments.\n * @param {number} sliceOffset The slice offset.\n * @returns {object} The ROI slice image buffers.\n */\nfunction createRoiSliceBuffers(\n  image,\n  segments,\n  sliceOffset\n) {\n  // create binary mask buffers\n  const geometry = image.getGeometry();\n  const size = geometry.getSize();\n  const sliceSize = size.getDimSize(2);\n  const buffers = {};\n  for (let o = 0; o < sliceSize; ++o) {\n    const inputOffset = sliceOffset + o;\n    const pixelValue = image.getValueAtOffset(inputOffset);\n    for (const segment of segments) {\n      const segmentIndex = segment.number - 1;\n      if (pixelValue === segment.number) {\n        if (buffers[segmentIndex] === undefined) {\n          buffers[segmentIndex] = new Uint8Array(sliceSize);\n        }\n        buffers[segmentIndex][o] = 1;\n      }\n    }\n  }\n  return buffers;\n}\n\n/**\n * Create ROI buffers.\n *\n * @param {Image} image The mask image.\n * @param {MaskSegment[]} segments The mask segments.\n * @returns {object} The ROI buffers.\n */\nfunction createRoiBuffers(image, segments) {\n  const geometry = image.getGeometry();\n  const size = geometry.getSize();\n\n  // image buffer to multi frame\n  const sliceSize = size.getDimSize(2);\n  const roiBuffers = {};\n  for (let k = 0; k < size.get(2); ++k) {\n    const sliceOffset = k * sliceSize;\n    // create slice buffers\n    const buffers = createRoiSliceBuffers(image, segments, sliceOffset);\n    // store slice buffers\n    const keys0 = Object.keys(buffers);\n    for (const key0 of keys0) {\n      if (roiBuffers[key0] === undefined) {\n        roiBuffers[key0] = {};\n      }\n      // ordering by slice index (follows posPat)\n      roiBuffers[key0][k] = buffers[key0];\n    }\n  }\n  return roiBuffers;\n}\n\n/**\n * List of DICOM Seg required tags.\n */\nconst RequiredDicomSegTags = [\n  {\n    name: 'TransferSyntaxUID',\n    tag: '00020010',\n    type: '1',\n    enum: [\n      transferSyntaxKeywords.ImplicitVRLittleEndian,\n      transferSyntaxKeywords.ExplicitVRLittleEndian,\n      transferSyntaxKeywords.ExplicitVRBigEndian\n    ]\n  },\n  {\n    name: 'MediaStorageSOPClassUID',\n    tag: '00020002',\n    type: '1',\n    enum: ['1.2.840.10008.5.1.4.1.1.66.4']\n  },\n  {\n    name: 'SOPClassUID',\n    tag: '00020002',\n    type: '1',\n    enum: ['1.2.840.10008.5.1.4.1.1.66.4']\n  },\n  {\n    name: 'Modality',\n    tag: '00080060',\n    type: '1',\n    enum: ['SEG']\n  },\n  {\n    name: 'SegmentationType',\n    tag: '00620001',\n    type: '1',\n    enum: ['BINARY']\n  },\n  {\n    name: 'DimensionOrganizationType',\n    tag: '00209311',\n    type: '3',\n    enum: ['3D']\n  },\n  {\n    name: 'ImageType',\n    tag: '00080008',\n    type: '1',\n    enum: [['DERIVED', 'PRIMARY']]\n  },\n  {\n    name: 'SamplesPerPixel',\n    tag: '00280002',\n    type: '1',\n    enum: [1]\n  },\n  {\n    name: 'PhotometricInterpretation',\n    tag: '00280004',\n    type: '1',\n    enum: ['MONOCHROME2']\n  },\n  {\n    name: 'PixelRepresentation',\n    tag: '00280103',\n    type: '1',\n    enum: [0]\n  },\n  {\n    name: 'BitsAllocated',\n    tag: '00280100',\n    type: '1',\n    enum: [1]\n  },\n  {\n    name: 'BitsStored',\n    tag: '00280101',\n    type: '1',\n    enum: [1]\n  },\n  {\n    name: 'HighBit',\n    tag: '00280102',\n    type: '1',\n    enum: [0]\n  },\n];\n\n/**\n * Get the default DICOM seg tags as an object.\n *\n * @returns {object} The default tags.\n */\nexport function getDefaultDicomSegJson() {\n  const tags = {};\n  for (let i = 0; i < RequiredDicomSegTags.length; ++i) {\n    const reqTag = RequiredDicomSegTags[i];\n    tags[reqTag.name] = reqTag.enum[0];\n  }\n  return tags;\n}\n\n/**\n * Mask {@link Image} factory.\n */\nexport class MaskFactory {\n\n  /**\n   * Possible warning created by checkElements.\n   *\n   * @type {string|undefined}\n   */\n  #warning;\n\n  /**\n   * Get a warning string if elements are not as expected.\n   * Created by checkElements.\n   *\n   * @returns {string|undefined} The warning.\n   */\n  getWarning() {\n    return this.#warning;\n  }\n\n  /**\n   * Check dicom elements.\n   *\n   * @param {Object<string, DataElement>} _dicomElements The DICOM tags.\n   * @returns {string|undefined} A possible warning.\n   * @throws Error for missing or wrong data.\n   */\n  checkElements(_dicomElements) {\n    // does nothing\n    return;\n  }\n\n  /**\n   * Get an {@link Image} object from the read DICOM file.\n   *\n   * @param {Object<string, DataElement>} dataElements The DICOM tags.\n   * @param {Uint8Array | Int8Array |\n   *   Uint16Array | Int16Array |\n   *   Uint32Array | Int32Array} pixelBuffer The pixel buffer.\n   * @returns {Image} A new Image.\n   * @throws Error for missing or wrong data.\n   */\n  create(dataElements, pixelBuffer) {\n    // check required and supported tags\n    for (let d = 0; d < RequiredDicomSegTags.length; ++d) {\n      checkTag(dataElements, RequiredDicomSegTags[d]);\n    }\n\n    // image size\n    const size2D = getImage2DSize(dataElements);\n    const size = new Size([size2D[0], size2D[1], 1]);\n\n    const sliceSize = size.getTotalSize();\n\n    // frames\n    let frames = 1;\n    const framesElem = dataElements['00280008'];\n    if (typeof framesElem !== 'undefined') {\n      frames = parseInt(framesElem.value[0], 10);\n    }\n\n    if (frames !== pixelBuffer.length / sliceSize) {\n      throw new Error(\n        'Buffer and numberOfFrames meta are not equal.' +\n        frames + ' ' + pixelBuffer.length / sliceSize);\n    }\n\n    // Dimension Organization and Index\n    const dimension = getDimensionOrganization(dataElements);\n\n    // Segment Sequence\n    const segSequence = dataElements['00620002'];\n    if (typeof segSequence === 'undefined') {\n      throw new Error('Missing or empty segmentation sequence');\n    }\n    const segments = [];\n    // segment number is unique and starts at 1, use 0 as background\n    const redLut = [0];\n    const greenLut = [0];\n    const blueLut = [0];\n    for (let i = 0; i < segSequence.value.length; ++i) {\n      const segment = getSegment(segSequence.value[i]);\n      if (typeof segment.displayRGBValue !== 'undefined') {\n        // add palette colour\n        redLut[segment.number] = segment.displayRGBValue.r;\n        greenLut[segment.number] = segment.displayRGBValue.g;\n        blueLut[segment.number] = segment.displayRGBValue.b;\n      }\n      // store\n      segments.push(segment);\n    }\n\n    let hasDisplayRGBValue = false;\n    let paletteColourMap;\n    if (redLut.length > 1) {\n      hasDisplayRGBValue = true;\n      paletteColourMap = new ColourMap(redLut, greenLut, blueLut);\n    }\n\n    // Shared Functional Groups Sequence\n    let spacing;\n    let imageOrientationPatient;\n    const sharedFunctionalGroupsSeq = dataElements['52009229'];\n    if (typeof sharedFunctionalGroupsSeq !== 'undefined') {\n      // should be only one\n      const funcGroup0 = sharedFunctionalGroupsSeq.value[0];\n      // Plane Orientation Sequence\n      if (typeof funcGroup0['00209116'] !== 'undefined') {\n        const planeOrientationSeq = funcGroup0['00209116'];\n        if (planeOrientationSeq.value.length !== 0) {\n          // should be only one\n          imageOrientationPatient =\n            planeOrientationSeq.value[0]['00200037'].value;\n        } else {\n          logger.warn(\n            'No shared functional group plane orientation sequence items.');\n        }\n      }\n      // Pixel Measures Sequence\n      if (typeof funcGroup0['00289110'] !== 'undefined') {\n        const pixelMeasuresSeq = funcGroup0['00289110'];\n        if (pixelMeasuresSeq.value.length !== 0) {\n          // should be only one\n          spacing = getSpacingFromMeasure(pixelMeasuresSeq.value[0]);\n        } else {\n          logger.warn(\n            'No shared functional group pixel measure sequence items.');\n        }\n      }\n    }\n\n    const includesPosPat = function (arr, val) {\n      return arr.some(function (arrVal) {\n        return equalPosPat(val, arrVal);\n      });\n    };\n\n    const findIndexPosPat = function (arr, val) {\n      return arr.findIndex(function (arrVal) {\n        return equalPosPat(val, arrVal);\n      });\n    };\n\n    // Per-frame Functional Groups Sequence\n    const perFrameFuncGroupSequence = dataElements['52009230'];\n    if (typeof perFrameFuncGroupSequence === 'undefined') {\n      throw new Error('Missing or empty per frame functional sequence');\n    }\n    if (frames !== perFrameFuncGroupSequence.value.length) {\n      throw new Error(\n        'perFrameFuncGroupSequence meta and numberOfFrames are not equal.');\n    }\n    // create frame info object from per frame func\n    const frameInfos = [];\n    for (let j = 0; j < perFrameFuncGroupSequence.value.length; ++j) {\n      frameInfos.push(\n        getSegmentFrameInfo(perFrameFuncGroupSequence.value[j]));\n    }\n\n    // check frame infos\n    const framePosPats = [];\n    for (let ii = 0; ii < frameInfos.length; ++ii) {\n      if (!includesPosPat(framePosPats, frameInfos[ii].imagePosPat)) {\n        framePosPats.push(frameInfos[ii].imagePosPat);\n      }\n      // store orientation if needed, avoid multi\n      if (typeof frameInfos[ii].imageOrientationPatient !== 'undefined') {\n        if (typeof imageOrientationPatient === 'undefined') {\n          imageOrientationPatient = frameInfos[ii].imageOrientationPatient;\n        } else {\n          if (!arraySortEquals(\n            imageOrientationPatient, frameInfos[ii].imageOrientationPatient)) {\n            throw new Error('Unsupported multi orientation dicom seg.');\n          }\n        }\n      }\n      // store spacing if needed, avoid multi\n      if (typeof frameInfos[ii].spacing !== 'undefined') {\n        if (typeof spacing === 'undefined') {\n          spacing = frameInfos[ii].spacing;\n        } else {\n          if (!spacing.equals(frameInfos[ii].spacing)) {\n            throw new Error('Unsupported multi resolution dicom seg.');\n          }\n        }\n      }\n    }\n\n    // check spacing and orientation\n    if (typeof spacing === 'undefined') {\n      throw new Error('No spacing found for DICOM SEG');\n    }\n    if (spacing.length() !== 3) {\n      throw new Error('Incomplete spacing found for DICOM SEG');\n    }\n    if (typeof imageOrientationPatient === 'undefined') {\n      throw new Error('No imageOrientationPatient found for DICOM SEG');\n    }\n    if (imageOrientationPatient.length !== 6) {\n      throw new Error('Incomplete imageOrientationPatient found for DICOM SEG');\n    }\n\n    // orientation\n    const rowCosines = new Vector3D(\n      parseFloat(imageOrientationPatient[0]),\n      parseFloat(imageOrientationPatient[1]),\n      parseFloat(imageOrientationPatient[2]));\n    const colCosines = new Vector3D(\n      parseFloat(imageOrientationPatient[3]),\n      parseFloat(imageOrientationPatient[4]),\n      parseFloat(imageOrientationPatient[5]));\n    const normal = rowCosines.crossProduct(colCosines);\n    /* eslint-disable @stylistic/js/array-element-newline */\n    const orientationMatrix = new Matrix33([\n      rowCosines.getX(), colCosines.getX(), normal.getX(),\n      rowCosines.getY(), colCosines.getY(), normal.getY(),\n      rowCosines.getZ(), colCosines.getZ(), normal.getZ()\n    ]);\n    /* eslint-enable @stylistic/js/array-element-newline */\n\n    // sort positions patient\n    framePosPats.sort(getComparePosPat(orientationMatrix));\n\n    const point3DFromArray = function (arr) {\n      return new Point3D(arr[0], arr[1], arr[2]);\n    };\n\n    // frame origins\n    const frameOrigins = [];\n    for (let n = 0; n < framePosPats.length; ++n) {\n      frameOrigins.push(point3DFromArray(framePosPats[n]));\n    }\n\n    // tmp geometry with correct spacing but only one slice\n    const tmpGeometry = new Geometry(\n      [frameOrigins[0]], size, spacing, orientationMatrix);\n\n    // origin distance test\n    // TODO: maybe use sliceSpacing / 10\n    const isAboveEpsilon = function (value) {\n      let res = value > REAL_WORLD_EPSILON;\n      if (res) {\n        // try larger epsilon\n        res = value > REAL_WORLD_EPSILON * 10;\n        if (!res) {\n          // warn if epsilon < value < epsilon * 10\n          logger.warn(\n            'Using larger real world epsilon in SEG pos pat adding'\n          );\n        } else {\n          res = value > REAL_WORLD_EPSILON * 100;\n          if (!res) {\n            // warn if epsilon < value < epsilon * 100\n            logger.warn(\n              'Using larger+ real world epsilon in SEG pos pat adding'\n            );\n          }\n        }\n      }\n      return res;\n    };\n\n    // add possibly missing posPats\n    const posPats = [];\n    posPats.push(framePosPats[0]);\n    let sliceIndex = 0;\n    for (let g = 1; g < framePosPats.length; ++g) {\n      ++sliceIndex;\n      let index = new Index([0, 0, sliceIndex]);\n      let point = tmpGeometry.indexToWorld(index).get3D();\n      const frameOrigin = frameOrigins[g];\n      // check if more pos pats are needed\n      let dist = frameOrigin.getDistance(point);\n      const distPrevious = dist;\n      // TODO: good threshold?\n      while (isAboveEpsilon(dist)) {\n        logger.debug('Adding intermediate pos pats for DICOM seg at ' +\n          point.toString());\n        posPats.push([point.getX(), point.getY(), point.getZ()]);\n        ++sliceIndex;\n        index = new Index([0, 0, sliceIndex]);\n        point = tmpGeometry.indexToWorld(index).get3D();\n        dist = frameOrigin.getDistance(point);\n        if (dist > distPrevious) {\n          throw new Error(\n            'Test distance is increasing when adding intermediate pos pats');\n        }\n      }\n      // add frame pos pat\n      posPats.push(framePosPats[g]);\n    }\n\n    // as many slices as posPats\n    const numberOfSlices = posPats.length;\n\n    // final geometry\n    const geometry = new Geometry(\n      [frameOrigins[0]], size, spacing, orientationMatrix);\n    const uids = ['0'];\n    for (let m = 1; m < numberOfSlices; ++m) {\n      geometry.appendOrigin(point3DFromArray(posPats[m]), m);\n      uids.push(m.toString());\n    }\n\n    const getFindSegmentFunc = function (number) {\n      return function (item) {\n        return item.number === number;\n      };\n    };\n\n    // create output buffer\n    const buffer =\n      // @ts-ignore\n      new pixelBuffer.constructor(sliceSize * numberOfSlices);\n    buffer.fill(0);\n    // merge frame buffers\n    let sliceOffset = null;\n    let frameOffset = null;\n    for (let f = 0; f < frameInfos.length; ++f) {\n      // get the slice index from the position in the posPat array\n      sliceIndex = findIndexPosPat(posPats, frameInfos[f].imagePosPat);\n      frameOffset = sliceSize * f;\n      sliceOffset = sliceSize * sliceIndex;\n      // get the frame display value\n      const frameSegment = segments.find(\n        getFindSegmentFunc(frameInfos[f].refSegmentNumber)\n      );\n      for (let l = 0; l < sliceSize; ++l) {\n        if (pixelBuffer[frameOffset + l] !== 0) {\n          const offset = sliceOffset + l;\n          if (hasDisplayRGBValue) {\n            buffer[offset] = frameSegment.number;\n          } else {\n            buffer[offset] = frameSegment.displayValue;\n          }\n        }\n      }\n    }\n\n    // create image\n    const image = new Image(geometry, buffer, uids);\n    if (hasDisplayRGBValue) {\n      image.setPhotometricInterpretation('PALETTE COLOR');\n      image.setPaletteColourMap(paletteColourMap);\n    }\n    // meta information\n    const meta = getDefaultDicomSegJson();\n    const safeGetLocal = function (key) {\n      return safeGet(dataElements, key);\n    };\n    // Study\n    meta.StudyDate = safeGetLocal('00080020');\n    meta.StudyTime = safeGetLocal('00080030');\n    meta.StudyInstanceUID = safeGetLocal('0020000D');\n    meta.StudyID = safeGetLocal('00200010');\n    // Series\n    meta.SeriesDate = safeGetLocal('00080021');\n    meta.SeriesTime = safeGetLocal('00080031');\n    meta.SeriesInstanceUID = safeGetLocal('0020000E');\n    meta.SeriesNumber = safeGetLocal('00200011');\n    // ReferringPhysicianName\n    meta.ReferringPhysicianName = safeGetLocal('00080090');\n    // patient info\n    meta.PatientName = safeGetLocal('00100010');\n    meta.PatientID = safeGetLocal('00100020');\n    meta.PatientBirthDate = safeGetLocal('00100030');\n    meta.PatientSex = safeGetLocal('00100040');\n    // Enhanced General Equipment Module\n    meta.Manufacturer = safeGetLocal('00080070');\n    meta.ManufacturerModelName = safeGetLocal('00081090');\n    meta.DeviceSerialNumber = safeGetLocal('00181000');\n    meta.SoftwareVersions = safeGetLocal('00181020');\n    // dicom seg dimension\n    meta.DimensionOrganizationSequence = dimension.organizations;\n    meta.DimensionIndexSequence = dimension.indices;\n    // custom\n    meta.custom = {\n      segments: segments,\n      frameInfos: frameInfos,\n      SOPInstanceUID: dataElements['00080018'].value[0]\n    };\n\n    // number of files: in this case equal to number slices,\n    //   used to calculate buffer size\n    meta.numberOfFiles = numberOfSlices;\n    // FrameOfReferenceUID (optional)\n    const frameOfReferenceUID = dataElements['00200052'];\n    if (frameOfReferenceUID) {\n      meta.FrameOfReferenceUID = frameOfReferenceUID.value[0];\n    }\n    // LossyImageCompression (optional)\n    const lossyImageCompression = dataElements['00282110'];\n    if (lossyImageCompression) {\n      meta.LossyImageCompression = lossyImageCompression.value[0];\n    }\n\n    image.setMeta(meta);\n\n    return image;\n  }\n\n  /**\n   * Convert a mask image into a DICOM segmentation object.\n   *\n   * @param {Image} image The mask image.\n   * @param {MaskSegment[]} segments The mask segments.\n   * @param {Image} sourceImage The source image.\n   * @param {Object<string, any>} [extraTags] Optional list of extra tags.\n   * @returns {Object<string, DataElement>} A list of dicom elements.\n   */\n  toDicom(\n    image,\n    segments,\n    sourceImage,\n    extraTags\n  ) {\n    // original image tags\n    const tags = image.getMeta();\n\n    // use image segments if not provided as input\n    if (segments === undefined) {\n      segments = tags.segments;\n    }\n\n    const geometry = image.getGeometry();\n    const size = geometry.getSize();\n\n    // (not in meta)\n    tags.Rows = size.get(1);\n    tags.Columns = size.get(0);\n    // update content tags\n    const now = new Date();\n    tags.ContentDate = getDicomDate(dateToDateObj(now));\n    tags.ContentTime = getDicomTime(dateToTimeObj(now));\n\n    // keep source image StudyInstanceUID\n    if (sourceImage !== undefined) {\n      tags.StudyInstanceUID = (sourceImage.getMeta()).StudyInstanceUID;\n    }\n\n    // segments\n    const segmentItems = [];\n    for (const segment of segments) {\n      segmentItems.push(getDicomSegmentItem(segment));\n    }\n    tags.SegmentSequence = {\n      value: segmentItems\n    };\n\n    // Shared Functional Groups Sequence\n    tags.SharedFunctionalGroupsSequence = {\n      value: [\n        {\n          PlaneOrientationSequence: {\n            value: [getDicomPlaneOrientationItem(geometry.getOrientation())]\n          },\n          PixelMeasuresSequence: {\n            value: [getDicomMeasureItem(geometry.getSpacing())]\n          }\n        }\n      ]\n    };\n\n    // image buffer to multi frame\n    const roiBuffers = createRoiBuffers(image, segments);\n\n    const frameInfos = [];\n\n    // flatten buffer array\n    const finalBuffers = [];\n    const referencedSOPs = [];\n    for (const segment of segments) {\n      const number40 = segment.number;\n      const number4 = number40 - 1;\n      // check if buffer has values\n      if (roiBuffers[number4] === undefined) {\n        continue;\n      }\n      const keys1 = Object.keys(roiBuffers[number4]);\n      // revert slice order\n      for (let k1 = keys1.length - 1; k1 >= 0; --k1) {\n        const key1 = Number.parseInt(keys1[k1], 10);\n        finalBuffers.push(roiBuffers[number4][key1]);\n        // frame info\n        const posPat = image.getGeometry().getOrigins()[key1];\n        const posPatArray = [posPat.getX(), posPat.getY(), posPat.getZ()];\n        const frameInfo = {\n          dimIndex: [number40, keys1.length - k1],\n          imagePosPat: posPatArray,\n          refSegmentNumber: number40\n        };\n        // derivation image info\n        if (sourceImage !== undefined) {\n          const sourceGeometry = sourceImage.getGeometry();\n          const sourceIndex = sourceGeometry.worldToIndex(\n            new Point([posPat.getX(), posPat.getY(), posPat.getZ()])\n          );\n          frameInfo.derivationImages = [\n            {\n              sourceImages: [\n                {\n                  referencedSOPInstanceUID:\n                    sourceImage.getImageUid(sourceIndex),\n                  referencedSOPClassUID:\n                    (sourceImage.getMeta()).SOPClassUID\n                }\n              ]\n            }\n          ];\n          // store as tag\n          referencedSOPs.push({\n            ReferencedSOPInstanceUID:\n              sourceImage.getImageUid(sourceIndex),\n            ReferencedSOPClassUID:\n              (sourceImage.getMeta()).SOPClassUID\n          });\n        }\n        frameInfos.push(frameInfo);\n      }\n    }\n\n    tags.NumberOfFrames = finalBuffers.length.toString();\n\n    // frame infos\n    const frameInfosTag = [];\n    for (const frameInfo of frameInfos) {\n      frameInfosTag.push(getDicomSegmentFrameInfoItem(frameInfo));\n    }\n    tags.PerFrameFunctionalGroupsSequence = {\n      value: frameInfosTag\n    };\n\n    // also store referenced SOPs in ReferencedSeriesSequence\n    if (sourceImage !== undefined) {\n      const refSeriesTag = [];\n      refSeriesTag.push({\n        ReferencedInstanceSequence: {\n          value: referencedSOPs\n        },\n        SeriesInstanceUID: (sourceImage.getMeta()).SeriesInstanceUID\n      });\n      tags.ReferencedSeriesSequence = {\n        value: refSeriesTag\n      };\n    }\n\n    // merge extra tags if provided\n    if (extraTags !== undefined) {\n      mergeTags(tags, extraTags);\n    }\n\n    // convert JSON to DICOM element object\n    const dicomElements = getElementsFromJSONTags(tags);\n\n    // pixel value length: divide by 8 to trigger binary write\n    const sliceSize = size.getDimSize(2);\n    const pixVl = (finalBuffers.length * sliceSize) / 8;\n    const de = new DataElement('OB');\n    de.tag = new Tag('7FE0', '0010');\n    de.vl = pixVl;\n    de.value = finalBuffers;\n    dicomElements['7FE00010'] = de;\n\n    return dicomElements;\n  }\n\n} // class MaskFactory\n","import {Index} from '../math/index';\nimport {Point3D} from '../math/point';\nimport {logger} from '../utils/logger';\nimport {arrayContains} from '../utils/array';\nimport {getTypedArray} from '../dicom/dicomParser';\nimport {ListenerHandler} from '../utils/listen';\nimport {valueRange} from './iterator';\nimport {RescaleSlopeAndIntercept} from './rsi';\nimport {ImageFactory} from './imageFactory';\nimport {MaskFactory} from './maskFactory';\nimport {isMonochrome} from '../dicom/dicomElementsWrapper';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Geometry} from './geometry';\nimport {Matrix33} from '../math/matrix';\nimport {NumberRange} from '../math/stats';\nimport {DataElement} from '../dicom/dataElement';\nimport {RGB} from '../utils/colour';\nimport {ColourMap} from './luts';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get the slice index of an input slice into a volume geometry.\n *\n * @param {Geometry} volumeGeometry The volume geometry.\n * @param {Geometry} sliceGeometry The slice geometry.\n * @returns {Index} The index of the slice in the volume geomtry.\n */\nfunction getSliceIndex(volumeGeometry, sliceGeometry) {\n  // possible time\n  const timeId = sliceGeometry.getInitialTime();\n  // index values\n  const values = [];\n  // x, y\n  values.push(0);\n  values.push(0);\n  // z\n  values.push(volumeGeometry.getSliceIndex(sliceGeometry.getOrigin(), timeId));\n  // time\n  if (typeof timeId !== 'undefined') {\n    values.push(timeId);\n  }\n  // return index\n  return new Index(values);\n}\n\n/**\n * Create an Image from DICOM elements.\n *\n * @param {Object<string, DataElement>} elements The DICOM elements.\n * @returns {Image} The Image object.\n */\nexport function createImage(elements) {\n  const factory = new ImageFactory();\n  return factory.create(\n    elements,\n    elements['7FE00010'].value[0],\n    1\n  );\n}\n\n/**\n * Create a mask Image from DICOM elements.\n *\n * @param {Object<string, DataElement>} elements The DICOM elements.\n * @returns {Image} The mask Image object.\n */\nexport function createMaskImage(elements) {\n  const factory = new MaskFactory();\n  return factory.create(\n    elements,\n    elements['7FE00010'].value[0]\n  );\n}\n\n/**\n * Image class.\n * Usable once created, optional are:\n * - rescale slope and intercept (default 1:0),\n * - photometric interpretation (default MONOCHROME2),\n * - planar configuration (default RGBRGB...).\n *\n * @example\n * // XMLHttpRequest onload callback\n * const onload = function (event) {\n *   // parse the dicom buffer\n *   const dicomParser = new dwv.DicomParser();\n *   dicomParser.parse(event.target.response);\n *   // create the image object\n *   const image = dwv.createImage(dicomParser.getDicomElements());\n *   // result div\n *   const div = document.getElementById('dwv');\n *   // display the image size\n *   const size = image.getGeometry().getSize();\n *   div.appendChild(document.createTextNode(\n *     'Size: ' + size.toString() +\n *     ' (should be 256,256,1)'));\n *   // break line\n *   div.appendChild(document.createElement('br'));\n *   // display a pixel value\n *   div.appendChild(document.createTextNode(\n *     'Pixel @ [128,40,0]: ' +\n *     image.getRescaledValue(128,40,0) +\n *     ' (should be 101)'));\n * };\n * // DICOM file request\n * const request = new XMLHttpRequest();\n * const url = 'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm';\n * request.open('GET', url);\n * request.responseType = 'arraybuffer';\n * request.onload = onload;\n * request.send();\n */\nexport class Image {\n\n  /**\n   * Data geometry.\n   *\n   * @type {Geometry}\n   */\n  #geometry;\n\n  /**\n   * List of compatible typed arrays.\n   *\n   * @typedef {(\n   *   Uint8Array | Int8Array |\n   *   Uint16Array | Int16Array |\n   *   Uint32Array | Int32Array\n   * )} TypedArray\n   */\n\n  /**\n   * Data buffer.\n   *\n   * @type {TypedArray}\n   */\n  #buffer;\n\n  /**\n   * Image UIDs.\n   *\n   * @type {string[]}\n   */\n  #imageUids;\n\n  /**\n   * Constant rescale slope and intercept (default).\n   *\n   * @type {RescaleSlopeAndIntercept}\n   */\n  #rsi = new RescaleSlopeAndIntercept(1, 0);\n\n  /**\n   * Varying rescale slope and intercept.\n   *\n   * @type {RescaleSlopeAndIntercept[]}\n   */\n  #rsis = null;\n\n  /**\n   * Flag to know if the RSIs are all identity (1,0).\n   *\n   * @type {boolean}\n   */\n  #isIdentityRSI = true;\n\n  /**\n   * Flag to know if the RSIs are all equals.\n   *\n   * @type {boolean}\n   */\n  #isConstantRSI = true;\n\n  /**\n   * Photometric interpretation (MONOCHROME, RGB...).\n   *\n   * @type {string}\n   */\n  #photometricInterpretation = 'MONOCHROME2';\n\n  /**\n   * Palette colour map.\n   *\n   * @type {ColourMap}\n   */\n  #paletteColourMap;\n\n  /**\n   * Planar configuration for RGB data (`0:RGBRGBRGBRGB...` or\n   *   `1:RRR...GGG...BBB...`).\n   *\n   * @type {number}\n   */\n  #planarConfiguration = 0;\n\n  /**\n   * Number of components.\n   *\n   * @type {number}\n   */\n  #numberOfComponents;\n\n  /**\n   * Meta information.\n   *\n   * @type {Object<string, any>}\n   */\n  #meta = {};\n\n  /**\n   * Data range.\n   *\n   * @type {NumberRange}\n   */\n  #dataRange = null;\n\n  /**\n   * Rescaled data range.\n   *\n   * @type {NumberRange}\n   */\n  #rescaledDataRange = null;\n\n  /**\n   * Histogram.\n   *\n   * @type {Array}\n   */\n  #histogram = null;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * @param {Geometry} geometry The geometry of the image.\n   * @param {TypedArray} buffer The image data as a one dimensional buffer.\n   * @param {string[]} [imageUids] An array of Uids indexed to slice number.\n   */\n  constructor(geometry, buffer, imageUids) {\n    this.#geometry = geometry;\n    this.#buffer = buffer;\n    this.#imageUids = imageUids;\n\n    this.#numberOfComponents = this.#buffer.length / (\n      this.#geometry.getSize().getTotalSize());\n  }\n\n  /**\n   * Get the image UID at a given index.\n   *\n   * @param {Index} [index] The index at which to get the id.\n   * @returns {string} The UID.\n   */\n  getImageUid(index) {\n    let uid = this.#imageUids[0];\n    if (this.#imageUids.length !== 1 && typeof index !== 'undefined') {\n      uid = this.#imageUids[this.getSecondaryOffset(index)];\n    }\n    return uid;\n  }\n\n  /**\n   * Get the image origin for a image UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {Point3D|undefined} The origin.\n   */\n  getOriginForImageUid(uid) {\n    let origin;\n    const uidIndex = this.#imageUids.indexOf(uid);\n    if (uidIndex !== -1) {\n      const origins = this.getGeometry().getOrigins();\n      origin = origins[uidIndex];\n    }\n    return origin;\n  }\n\n  /**\n   * Check if the image includes an UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {boolean} True if present.\n   */\n  includesImageUid(uid) {\n    return this.#imageUids.includes(uid);\n  }\n\n  /**\n   * Check if this image includes the input uids.\n   *\n   * @param {string[]} uids UIDs to test for presence.\n   * @returns {boolean} True if all uids are in this image uids.\n   */\n  containsImageUids(uids) {\n    return arrayContains(this.#imageUids, uids);\n  }\n\n  /**\n   * Get the geometry of the image.\n   *\n   * @returns {Geometry} The geometry.\n   */\n  getGeometry() {\n    return this.#geometry;\n  }\n\n  /**\n   * Get the data buffer of the image.\n   *\n   * @todo Dangerous...\n   * @returns {TypedArray} The data buffer of the image.\n   */\n  getBuffer() {\n    return this.#buffer;\n  }\n\n  /**\n   * Can the image values be quantified?\n   *\n   * @returns {boolean} True if only one component.\n   */\n  canQuantify() {\n    return this.getNumberOfComponents() === 1;\n  }\n\n  /**\n   * Can window and level be applied to the data?\n   *\n   * @returns {boolean} True if the data is monochrome.\n   * @deprecated Since v0.33, please use isMonochrome instead.\n   */\n  canWindowLevel() {\n    return this.isMonochrome();\n  }\n\n  /**\n   * Is the data monochrome.\n   *\n   * @returns {boolean} True if the data is monochrome.\n   */\n  isMonochrome() {\n    return isMonochrome(this.getPhotometricInterpretation());\n  }\n\n  /**\n   * Can the data be scrolled?\n   *\n   * @param {Matrix33} viewOrientation The view orientation.\n   * @returns {boolean} True if the data has a third dimension greater than one\n   *   after applying the view orientation.\n   */\n  canScroll(viewOrientation) {\n    const size = this.getGeometry().getSize();\n    // also check the numberOfFiles in case we are in the middle of a load\n    let nFiles = 1;\n    if (typeof this.#meta.numberOfFiles !== 'undefined') {\n      nFiles = this.#meta.numberOfFiles;\n    }\n    return size.canScroll(viewOrientation) || nFiles !== 1;\n  }\n\n  /**\n   * Get the secondary offset max.\n   *\n   * @returns {number} The maximum offset.\n   */\n  #getSecondaryOffsetMax() {\n    return this.#geometry.getSize().getTotalSize(2);\n  }\n\n  /**\n   * Get the secondary offset: an offset that takes into account\n   *   the slice and above dimension numbers.\n   *\n   * @param {Index} index The index.\n   * @returns {number} The offset.\n   */\n  getSecondaryOffset(index) {\n    return this.#geometry.getSize().indexToOffset(index, 2);\n  }\n\n  /**\n   * Get the rescale slope and intercept.\n   *\n   * @param {Index} [index] The index (only needed for non constant rsi).\n   * @returns {RescaleSlopeAndIntercept} The rescale slope and intercept.\n   */\n  getRescaleSlopeAndIntercept(index) {\n    let res = this.#rsi;\n    if (!this.isConstantRSI()) {\n      if (typeof index === 'undefined') {\n        throw new Error('Cannot get non constant RSI with empty slice index.');\n      }\n      const offset = this.getSecondaryOffset(index);\n      if (typeof this.#rsis[offset] !== 'undefined') {\n        res = this.#rsis[offset];\n      } else {\n        logger.warn('undefined non constant rsi at ' + offset);\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Get the rsi at a specified (secondary) offset.\n   *\n   * @param {number} offset The desired (secondary) offset.\n   * @returns {RescaleSlopeAndIntercept} The coresponding rsi.\n   */\n  #getRescaleSlopeAndInterceptAtOffset(offset) {\n    return this.#rsis[offset];\n  }\n\n  /**\n   * Set the rescale slope and intercept.\n   *\n   * @param {RescaleSlopeAndIntercept} inRsi The input rescale\n   *   slope and intercept.\n   * @param {number} [offset] The rsi offset (only needed for non constant rsi).\n   */\n  setRescaleSlopeAndIntercept(inRsi, offset) {\n    // update identity flag\n    this.#isIdentityRSI = this.#isIdentityRSI && inRsi.isID();\n    // update constant flag\n    if (!this.#isConstantRSI) {\n      if (typeof offset === 'undefined') {\n        throw new Error(\n          'Cannot store non constant RSI with empty slice index.');\n      }\n      this.#rsis.splice(offset, 0, inRsi);\n    } else {\n      if (!this.#rsi.equals(inRsi)) {\n        if (typeof offset === 'undefined') {\n          // no slice index, replace existing\n          this.#rsi = inRsi;\n        } else {\n          // first non constant rsi\n          this.#isConstantRSI = false;\n          // switch to non constant mode\n          this.#rsis = [];\n          // initialise RSIs\n          for (let i = 0, leni = this.#getSecondaryOffsetMax(); i < leni; ++i) {\n            this.#rsis.push(this.#rsi);\n          }\n          // store\n          this.#rsi = null;\n          this.#rsis.splice(offset, 0, inRsi);\n        }\n      }\n    }\n  }\n\n  /**\n   * Are all the RSIs identity (1,0).\n   *\n   * @returns {boolean} True if they are.\n   */\n  isIdentityRSI() {\n    return this.#isIdentityRSI;\n  }\n\n  /**\n   * Are all the RSIs equal.\n   *\n   * @returns {boolean} True if they are.\n   */\n  isConstantRSI() {\n    return this.#isConstantRSI;\n  }\n\n  /**\n   * Get the photometricInterpretation of the image.\n   *\n   * @returns {string} The photometricInterpretation of the image.\n   */\n  getPhotometricInterpretation() {\n    return this.#photometricInterpretation;\n  }\n\n  /**\n   * Set the photometricInterpretation of the image.\n   *\n   * @param {string} interp The photometricInterpretation of the image.\n   */\n  setPhotometricInterpretation(interp) {\n    this.#photometricInterpretation = interp;\n  }\n\n  /**\n   * Set the palette colour map.\n   *\n   * @param {ColourMap} map The colour map.\n   */\n  setPaletteColourMap(map) {\n    this.#paletteColourMap = map;\n    // fire imagecontentchange\n    this.#fireEvent({type: 'imagecontentchange'});\n  }\n\n  /**\n   * Get the palette colour map.\n   *\n   * @returns {ColourMap} The colour map.\n   */\n  getPaletteColourMap() {\n    return this.#paletteColourMap;\n  }\n\n  /**\n   * Update the palette colour map.\n   *\n   * @param {number} index The index to change the colour of.\n   * @param {RGB} colour The colour to use at index.\n   */\n  updatePaletteColourMap(index, colour) {\n    this.#paletteColourMap.red[index] = colour.r;\n    this.#paletteColourMap.green[index] = colour.g;\n    this.#paletteColourMap.blue[index] = colour.b;\n    // fire imagecontentchange\n    this.#fireEvent({type: 'imagecontentchange'});\n  }\n\n  /**\n   * Get the planarConfiguration of the image.\n   *\n   * @returns {number} The planarConfiguration of the image.\n   */\n  getPlanarConfiguration() {\n    return this.#planarConfiguration;\n  }\n\n  /**\n   * Set the planarConfiguration of the image.\n   *\n   * @param {number} config The planarConfiguration of the image.\n   */\n  setPlanarConfiguration(config) {\n    this.#planarConfiguration = config;\n  }\n\n  /**\n   * Get the numberOfComponents of the image.\n   *\n   * @returns {number} The numberOfComponents of the image.\n   */\n  getNumberOfComponents() {\n    return this.#numberOfComponents;\n  }\n\n  /**\n   * Get the meta information of the image.\n   *\n   * @returns {Object<string, any>} The meta information of the image.\n   */\n  getMeta() {\n    return this.#meta;\n  }\n\n  /**\n   * Set the meta information of the image.\n   *\n   * @param {Object<string, any>} rhs The meta information of the image.\n   */\n  setMeta(rhs) {\n    this.#meta = rhs;\n  }\n\n  /**\n   * Get value at offset. Warning: No size check...\n   *\n   * @param {number} offset The desired offset.\n   * @returns {number} The value at offset.\n   */\n  getValueAtOffset(offset) {\n    return this.#buffer[offset];\n  }\n\n  /**\n   * Get the offsets where the buffer equals the input value.\n   * Loops through the whole volume, can get long for big data...\n   *\n   * @param {number|RGB} value The value to check.\n   * @returns {number[]} The list of offsets.\n   */\n  getOffsets(value) {\n    // value to array\n    let bufferValue;\n    if (typeof value === 'number') {\n      if (this.#numberOfComponents !== 1) {\n        throw new Error(\n          'Number of components is not 1 for getting single value.');\n      }\n      bufferValue = [value];\n    } else if (typeof value.r !== 'undefined' &&\n      typeof value.g !== 'undefined' &&\n      typeof value.b !== 'undefined') {\n      if (this.#numberOfComponents !== 3) {\n        throw new Error(\n          'Number of components is not 3 for getting RGB value.');\n      }\n      bufferValue = [value.r, value.g, value.b];\n    }\n\n    // main loop\n    const offsets = [];\n    let equal;\n    for (let i = 0; i < this.#buffer.length; i = i + this.#numberOfComponents) {\n      equal = true;\n      for (let j = 0; j < this.#numberOfComponents; ++j) {\n        if (this.#buffer[i + j] !== bufferValue[j]) {\n          equal = false;\n          break;\n        }\n      }\n      if (equal) {\n        offsets.push(i);\n      }\n    }\n    return offsets;\n  }\n\n  /**\n   * Check if the input values are in the buffer.\n   * Could loop through the whole volume, can get long for big data...\n   *\n   * @param {Array} values The values to check.\n   * @returns {boolean[]} A list of booleans for each input value,\n   *   set to true if the value is present in the buffer.\n   */\n  hasValues(values) {\n    // check input\n    if (typeof values === 'undefined' ||\n      values.length === 0) {\n      return [];\n    }\n    // final array value\n    const finalValues = [];\n    for (let v1 = 0; v1 < values.length; ++v1) {\n      if (this.#numberOfComponents === 1) {\n        finalValues.push([values[v1]]);\n      } else if (this.#numberOfComponents === 3) {\n        finalValues.push([\n          values[v1].r,\n          values[v1].g,\n          values[v1].b\n        ]);\n      }\n    }\n    // find callback\n    let equalFunc;\n    if (this.#numberOfComponents === 1) {\n      equalFunc = function (a, b) {\n        return a[0] === b[0];\n      };\n    } else if (this.#numberOfComponents === 3) {\n      equalFunc = function (a, b) {\n        return a[0] === b[0] &&\n          a[1] === b[1] &&\n          a[2] === b[2];\n      };\n    }\n    const getEqualCallback = function (value) {\n      return function (item) {\n        return equalFunc(item, value);\n      };\n    };\n    // main loop\n    const res = new Array(values.length);\n    res.fill(false);\n    const valuesToFind = finalValues.slice();\n    let equal;\n    let indicesToRemove;\n    for (let i = 0, leni = this.#buffer.length;\n      i < leni; i = i + this.#numberOfComponents) {\n      indicesToRemove = [];\n      for (let v = 0; v < valuesToFind.length; ++v) {\n        equal = true;\n        // check value(s)\n        for (let j = 0; j < this.#numberOfComponents; ++j) {\n          if (this.#buffer[i + j] !== valuesToFind[v][j]) {\n            equal = false;\n            break;\n          }\n        }\n        // if found, store answer and add to indices to remove\n        if (equal) {\n          const valIndex = finalValues.findIndex(\n            getEqualCallback(valuesToFind[v]));\n          res[valIndex] = true;\n          indicesToRemove.push(v);\n        }\n      }\n      // remove found values\n      for (let r = 0; r < indicesToRemove.length; ++r) {\n        valuesToFind.splice(indicesToRemove[r], 1);\n      }\n      // exit if no values to find\n      if (valuesToFind.length === 0) {\n        break;\n      }\n    }\n    // return\n    return res;\n  }\n\n  /**\n   * Clone the image.\n   *\n   * @returns {Image} A clone of this image.\n   */\n  clone() {\n    // clone the image buffer\n    const clonedBuffer = this.#buffer.slice(0);\n    // create the image copy\n    const copy = new Image(this.getGeometry(), clonedBuffer, this.#imageUids);\n    // copy the RSI(s)\n    if (this.isConstantRSI()) {\n      copy.setRescaleSlopeAndIntercept(this.getRescaleSlopeAndIntercept());\n    } else {\n      for (let i = 0; i < this.#getSecondaryOffsetMax(); ++i) {\n        copy.setRescaleSlopeAndIntercept(\n          this.#getRescaleSlopeAndInterceptAtOffset(i), i);\n      }\n    }\n    // copy extras\n    copy.setPhotometricInterpretation(this.getPhotometricInterpretation());\n    copy.setPlanarConfiguration(this.getPlanarConfiguration());\n    copy.setMeta(this.getMeta());\n    // return\n    return copy;\n  }\n\n  /**\n   * Re-allocate buffer memory to an input size.\n   *\n   * @param {number} size The new size.\n   */\n  #realloc(size) {\n    // save buffer\n    let tmpBuffer = this.#buffer;\n    // create new\n    this.#buffer = getTypedArray(\n      this.#buffer.BYTES_PER_ELEMENT * 8,\n      this.#meta.IsSigned ? 1 : 0,\n      size);\n    if (this.#buffer === null) {\n      throw new Error('Cannot reallocate data for image.');\n    }\n    // put old in new\n    this.#buffer.set(tmpBuffer);\n    // clean\n    tmpBuffer = null;\n  }\n\n  /**\n   * Append a slice to the image.\n   *\n   * @param {Image} rhs The slice to append.\n   * @fires Image#imagegeometrychange\n   */\n  appendSlice(rhs) {\n    // check input\n    if (rhs === null) {\n      throw new Error('Cannot append null slice');\n    }\n    const rhsSize = rhs.getGeometry().getSize();\n    let size = this.#geometry.getSize();\n    if (rhsSize.get(2) !== 1) {\n      throw new Error('Cannot append more than one slice');\n    }\n    if (size.get(0) !== rhsSize.get(0)) {\n      throw new Error('Cannot append a slice with different number of columns');\n    }\n    if (size.get(1) !== rhsSize.get(1)) {\n      throw new Error('Cannot append a slice with different number of rows');\n    }\n    if (!this.#geometry.getOrientation().equals(\n      rhs.getGeometry().getOrientation(), 0.0001)) {\n      throw new Error('Cannot append a slice with different orientation');\n    }\n    if (this.#photometricInterpretation !==\n      rhs.getPhotometricInterpretation()) {\n      throw new Error(\n        'Cannot append a slice with different photometric interpretation');\n    }\n    // all meta should be equal\n    for (const key in this.#meta) {\n      if (key === 'windowPresets' || key === 'numberOfFiles' ||\n        key === 'custom') {\n        continue;\n      }\n      if (this.#meta[key] !== rhs.getMeta()[key]) {\n        throw new Error('Cannot append a slice with different ' + key +\n          ': ' + this.#meta[key] + ' != ' + rhs.getMeta()[key]);\n      }\n    }\n\n    // update ranges\n    const rhsRange = rhs.getDataRange();\n    const range = this.getDataRange();\n    this.#dataRange = {\n      min: Math.min(rhsRange.min, range.min),\n      max: Math.max(rhsRange.max, range.max),\n    };\n    const rhsResRange = rhs.getRescaledDataRange();\n    const resRange = this.getRescaledDataRange();\n    this.#rescaledDataRange = {\n      min: Math.min(rhsResRange.min, resRange.min),\n      max: Math.max(rhsResRange.max, resRange.max),\n    };\n\n    // possible time\n    const timeId = rhs.getGeometry().getInitialTime();\n\n    // append frame if needed\n    let isNewFrame = false;\n    if (typeof timeId !== 'undefined' &&\n      !this.#geometry.hasSlicesAtTime(timeId)) {\n      // update grometry\n      this.appendFrame(timeId, rhs.getGeometry().getOrigin());\n      // update size\n      size = this.#geometry.getSize();\n      // update flag\n      isNewFrame = true;\n    }\n\n    // get slice index\n    const index = getSliceIndex(this.#geometry, rhs.getGeometry());\n\n    // calculate slice size\n    const sliceSize = this.#numberOfComponents * size.getDimSize(2);\n\n    // create full buffer if not done yet\n    if (typeof this.#meta.numberOfFiles === 'undefined') {\n      throw new Error('Missing number of files for buffer manipulation.');\n    }\n    const fullBufferSize = sliceSize * this.#meta.numberOfFiles;\n    if (this.#buffer.length !== fullBufferSize) {\n      this.#realloc(fullBufferSize);\n    }\n\n    // slice index\n    const sliceIndex = index.get(2);\n\n    // slice index including possible 4D\n    let fullSliceIndex = sliceIndex;\n    if (typeof timeId !== 'undefined') {\n      fullSliceIndex +=\n        this.#geometry.getCurrentNumberOfSlicesBeforeTime(timeId);\n    }\n    // offset of the input slice\n    const indexOffset = fullSliceIndex * sliceSize;\n    const maxOffset =\n      this.#geometry.getCurrentTotalNumberOfSlices() * sliceSize;\n    // move content if needed\n    if (indexOffset < maxOffset) {\n      this.#buffer.set(\n        this.#buffer.subarray(indexOffset, maxOffset),\n        indexOffset + sliceSize\n      );\n    }\n    // add new slice content\n    this.#buffer.set(rhs.getBuffer(), indexOffset);\n\n    // update geometry\n    if (!isNewFrame) {\n      this.#geometry.appendOrigin(\n        rhs.getGeometry().getOrigin(), sliceIndex, timeId);\n    }\n    // update rsi\n    // (rhs should just have one rsi)\n    this.setRescaleSlopeAndIntercept(\n      rhs.getRescaleSlopeAndIntercept(), fullSliceIndex);\n\n    // current number of images\n    const numberOfImages = this.#imageUids.length;\n\n    // insert sop instance UIDs\n    this.#imageUids.splice(fullSliceIndex, 0, rhs.getImageUid());\n\n    // update window presets\n    if (typeof this.#meta.windowPresets !== 'undefined') {\n      const windowPresets = this.#meta.windowPresets;\n      const rhsPresets = rhs.getMeta().windowPresets;\n      const keys = Object.keys(rhsPresets);\n      let pkey = null;\n      for (let i = 0; i < keys.length; ++i) {\n        pkey = keys[i];\n        const rhsPreset = rhsPresets[pkey];\n        const windowPreset = windowPresets[pkey];\n        if (typeof windowPreset !== 'undefined') {\n          // if not set or false, check perslice\n          if (typeof windowPreset.perslice === 'undefined' ||\n            windowPreset.perslice === false) {\n            // if different preset.wl, mark it as perslice\n            if (!windowPreset.wl[0].equals(rhsPreset.wl[0])) {\n              windowPreset.perslice = true;\n              // fill wl array with copy of wl[0]\n              // (loop on number of images minus the existing one)\n              for (let j = 0; j < numberOfImages - 1; ++j) {\n                windowPreset.wl.push(windowPreset.wl[0]);\n              }\n            }\n          }\n          // store (first) rhs preset.wl if needed\n          if (typeof windowPreset.perslice !== 'undefined' &&\n            windowPreset.perslice === true) {\n            windowPresets[pkey].wl.splice(\n              fullSliceIndex, 0, rhsPreset.wl[0]);\n          }\n        } else {\n          // if not defined (it should be), store all\n          windowPresets[pkey] = rhsPresets[pkey];\n        }\n      }\n    }\n    /**\n     * Image geometry change event.\n     *\n     * @event Image#imagegeometrychange\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    this.#fireEvent({\n      type: 'imagegeometrychange'\n    });\n  }\n\n  /**\n   * Append a frame buffer to the image.\n   *\n   * @param {object} frameBuffer The frame buffer to append.\n   * @param {number} frameIndex The frame index.\n   */\n  appendFrameBuffer(frameBuffer, frameIndex) {\n    // create full buffer if not done yet\n    const size = this.#geometry.getSize();\n    const frameSize = this.#numberOfComponents * size.getDimSize(2);\n    if (typeof this.#meta.numberOfFiles === 'undefined') {\n      throw new Error('Missing number of files for frame buffer manipulation.');\n    }\n    const fullBufferSize = frameSize * this.#meta.numberOfFiles;\n    if (this.#buffer.length !== fullBufferSize) {\n      this.#realloc(fullBufferSize);\n    }\n    // check index\n    if (frameIndex >= this.#meta.numberOfFiles) {\n      logger.warn('Ignoring frame at index ' + frameIndex +\n        ' (size: ' + this.#meta.numberOfFiles + ')');\n      return;\n    }\n    // append\n    this.#buffer.set(frameBuffer, frameSize * frameIndex);\n    // update geometry\n    this.appendFrame(frameIndex, new Point3D(0, 0, 0));\n  }\n\n  /**\n   * Append a frame to the image.\n   *\n   * @param {number} time The frame time value.\n   * @param {Point3D} origin The origin of the frame.\n   */\n  appendFrame(time, origin) {\n    this.#geometry.appendFrame(origin, time);\n    /**\n     * Append frame event.\n     *\n     * @event Image#appendframe\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    this.#fireEvent({\n      type: 'appendframe'\n    });\n    // memory will be updated at the first appendSlice or appendFrameBuffer\n  }\n\n  /**\n   * Get the data range.\n   *\n   * @returns {NumberRange} The data range.\n   */\n  getDataRange() {\n    if (!this.#dataRange) {\n      this.#dataRange = this.calculateDataRange();\n    }\n    return this.#dataRange;\n  }\n\n  /**\n   * Get the rescaled data range.\n   *\n   * @returns {NumberRange} The rescaled data range.\n   */\n  getRescaledDataRange() {\n    if (!this.#rescaledDataRange) {\n      this.#rescaledDataRange = this.calculateRescaledDataRange();\n    }\n    return this.#rescaledDataRange;\n  }\n\n  /**\n   * Get the histogram.\n   *\n   * @returns {Array} The histogram.\n   */\n  getHistogram() {\n    if (!this.#histogram) {\n      const res = this.calculateHistogram();\n      this.#dataRange = res.dataRange;\n      this.#rescaledDataRange = res.rescaledDataRange;\n      this.#histogram = res.histogram;\n    }\n    return this.#histogram;\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  // ****************************************\n  // image data modifiers... carefull...\n  // ****************************************\n\n  /**\n   * Set the inner buffer values at given offsets.\n   *\n   * @param {number[]} offsets List of offsets where to set the data.\n   * @param {number|RGB} value The value to set at the given offsets.\n   * @fires Image#imagecontentchange\n   */\n  setAtOffsets(offsets, value) {\n    // value to array\n    let bufferValue;\n    if (typeof value === 'number') {\n      if (this.#numberOfComponents !== 1) {\n        throw new Error(\n          'Number of components is not 1 for setting single value.');\n      }\n      bufferValue = [value];\n    } else if (typeof value.r !== 'undefined' &&\n      typeof value.g !== 'undefined' &&\n      typeof value.b !== 'undefined') {\n      if (this.#numberOfComponents !== 3) {\n        throw new Error(\n          'Number of components is not 3 for setting RGB value.');\n      }\n      bufferValue = [value.r, value.g, value.b];\n    }\n\n    let offset;\n    for (let i = 0, leni = offsets.length; i < leni; ++i) {\n      offset = offsets[i];\n      for (let j = 0; j < this.#numberOfComponents; ++j) {\n        this.#buffer[offset + j] = bufferValue[j];\n      }\n    }\n    // fire imagecontentchange\n    this.#fireEvent({type: 'imagecontentchange'});\n  }\n\n  /**\n   * Set the inner buffer values at given offsets.\n   *\n   * @param {number[][]} offsetsLists List of offset lists where\n   *   to set the data.\n   * @param {number} value The value to set at the given offsets.\n   * @returns {Array} A list of objects representing the original values before\n   *  replacing them.\n   * @fires Image#imagecontentchange\n   */\n  setAtOffsetsAndGetOriginals(offsetsLists, value) {\n    const originalValuesLists = [];\n\n    // update and store\n    for (let j = 0; j < offsetsLists.length; ++j) {\n      const offsets = offsetsLists[j];\n      // first value\n      let offset = offsets[0];\n      let previousValue = this.#buffer[offset];\n      // original value storage\n      const originalValues = [];\n      originalValues.push({\n        index: 0,\n        value: previousValue\n      });\n      for (let i = 0; i < offsets.length; ++i) {\n        offset = offsets[i];\n        const currentValue = this.#buffer[offset];\n        // check if new value\n        if (previousValue !== currentValue) {\n          // store new value\n          originalValues.push({\n            index: i,\n            value: currentValue\n          });\n          previousValue = currentValue;\n        }\n        // write update value\n        this.#buffer[offset] = value;\n      }\n      originalValuesLists.push(originalValues);\n    }\n    // fire imagecontentchange\n    this.#fireEvent({type: 'imagecontentchange'});\n    return originalValuesLists;\n  }\n\n  /**\n   * Set the inner buffer values at given offsets.\n   *\n   * @param {number[][]} offsetsLists List of offset lists\n   *   where to set the data.\n   * @param {number|Array} value The value to set at the given offsets.\n   * @fires Image#imagecontentchange\n   */\n  setAtOffsetsWithIterator(offsetsLists, value) {\n    const isValueArray = Array.isArray(value);\n\n    for (let j = 0; j < offsetsLists.length; ++j) {\n      const offsets = offsetsLists[j];\n      let iterator;\n      if (isValueArray) {\n        // input value is a list of iterators\n        // created by setAtOffsetsAndGetOriginals\n        iterator = valueRange(\n          value[j], offsets.length);\n      } else {\n        // input value is a simple color\n        iterator = valueRange(\n          [{index: 0, value: value}], offsets.length);\n      }\n\n      // set values\n      let ival = iterator.next();\n      while (!ival.done) {\n        const offset = offsets[ival.index];\n        this.#buffer[offset] = ival.value;\n        ival = iterator.next();\n      }\n    }\n    /**\n     * Image content change event.\n     *\n     * @event Image#imagecontentchange\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    this.#fireEvent({type: 'imagecontentchange'});\n  }\n\n  /**\n   * Get the value of the image at a specific coordinate.\n   *\n   * @param {number} i The X index.\n   * @param {number} j The Y index.\n   * @param {number} k The Z index.\n   * @param {number} f The frame number.\n   * @returns {number} The value at the desired position.\n   * Warning: No size check...\n   */\n  getValue(i, j, k, f) {\n    const frame = (f || 0);\n    const index = new Index([i, j, k, frame]);\n    return this.getValueAtOffset(\n      this.getGeometry().getSize().indexToOffset(index));\n  }\n\n  /**\n   * Get the value of the image at a specific index.\n   *\n   * @param {Index} index The index.\n   * @returns {number} The value at the desired position.\n   * Warning: No size check...\n   */\n  getValueAtIndex(index) {\n    return this.getValueAtOffset(\n      this.getGeometry().getSize().indexToOffset(index));\n  }\n\n  /**\n   * Get the rescaled value of the image at a specific position.\n   *\n   * @param {number} i The X index.\n   * @param {number} j The Y index.\n   * @param {number} k The Z index.\n   * @param {number} f The frame number.\n   * @returns {number} The rescaled value at the desired position.\n   * Warning: No size check...\n   */\n  getRescaledValue(i, j, k, f) {\n    if (typeof f === 'undefined') {\n      f = 0;\n    }\n    let val = this.getValue(i, j, k, f);\n    if (!this.isIdentityRSI()) {\n      if (this.isConstantRSI()) {\n        val = this.getRescaleSlopeAndIntercept().apply(val);\n      } else {\n        const values = [i, j, k, f];\n        const index = new Index(values);\n        val = this.getRescaleSlopeAndIntercept(index).apply(val);\n      }\n    }\n    return val;\n  }\n\n  /**\n   * Get the rescaled value of the image at a specific index.\n   *\n   * @param {Index} index The index.\n   * @returns {number} The rescaled value at the desired position.\n   * Warning: No size check...\n   */\n  getRescaledValueAtIndex(index) {\n    return this.getRescaledValueAtOffset(\n      this.getGeometry().getSize().indexToOffset(index)\n    );\n  }\n\n  /**\n   * Get the rescaled value of the image at a specific offset.\n   *\n   * @param {number} offset The desired offset.\n   * @returns {number} The rescaled value at the desired offset.\n   * Warning: No size check...\n   */\n  getRescaledValueAtOffset(offset) {\n    let val = this.getValueAtOffset(offset);\n    if (!this.isIdentityRSI()) {\n      if (this.isConstantRSI()) {\n        val = this.getRescaleSlopeAndIntercept().apply(val);\n      } else {\n        const index = this.getGeometry().getSize().offsetToIndex(offset);\n        val = this.getRescaleSlopeAndIntercept(index).apply(val);\n      }\n    }\n    return val;\n  }\n\n  /**\n   * Calculate the data range of the image.\n   * WARNING: for speed reasons, only calculated on the first frame...\n   *\n   * @returns {object} The range {min, max}.\n   */\n  calculateDataRange() {\n    let min = this.getValueAtOffset(0);\n    let max = min;\n    let value = 0;\n    const size = this.getGeometry().getSize();\n    let leni = size.getTotalSize();\n    // max to 3D\n    if (size.length() >= 3) {\n      leni = size.getDimSize(3);\n    }\n    for (let i = 0; i < leni; ++i) {\n      value = this.getValueAtOffset(i);\n      if (value > max) {\n        max = value;\n      }\n      if (value < min) {\n        min = value;\n      }\n    }\n    // return\n    return {min: min, max: max};\n  }\n\n  /**\n   * Calculate the rescaled data range of the image.\n   * WARNING: for speed reasons, only calculated on the first frame...\n   *\n   * @returns {object} The range {min, max}.\n   */\n  calculateRescaledDataRange() {\n    if (this.isIdentityRSI()) {\n      return this.getDataRange();\n    } else if (this.isConstantRSI()) {\n      const range = this.getDataRange();\n      const resmin = this.getRescaleSlopeAndIntercept().apply(range.min);\n      const resmax = this.getRescaleSlopeAndIntercept().apply(range.max);\n      return {\n        min: ((resmin < resmax) ? resmin : resmax),\n        max: ((resmin > resmax) ? resmin : resmax)\n      };\n    } else {\n      let rmin = this.getRescaledValueAtOffset(0);\n      let rmax = rmin;\n      let rvalue = 0;\n      const size = this.getGeometry().getSize();\n      let leni = size.getTotalSize();\n      // max to 3D\n      if (size.length() === 3) {\n        leni = size.getDimSize(3);\n      }\n      for (let i = 0; i < leni; ++i) {\n        rvalue = this.getRescaledValueAtOffset(i);\n        if (rvalue > rmax) {\n          rmax = rvalue;\n        }\n        if (rvalue < rmin) {\n          rmin = rvalue;\n        }\n      }\n      // return\n      return {min: rmin, max: rmax};\n    }\n  }\n\n  /**\n   * Calculate the histogram of the image.\n   *\n   * @returns {object} The histogram, data range and rescaled data range.\n   */\n  calculateHistogram() {\n    const size = this.getGeometry().getSize();\n    const histo = [];\n    let min = this.getValueAtOffset(0);\n    let max = min;\n    let value = 0;\n    let rmin = this.getRescaledValueAtOffset(0);\n    let rmax = rmin;\n    let rvalue = 0;\n    for (let i = 0, leni = size.getTotalSize(); i < leni; ++i) {\n      value = this.getValueAtOffset(i);\n      if (value > max) {\n        max = value;\n      }\n      if (value < min) {\n        min = value;\n      }\n      rvalue = this.getRescaledValueAtOffset(i);\n      if (rvalue > rmax) {\n        rmax = rvalue;\n      }\n      if (rvalue < rmin) {\n        rmin = rvalue;\n      }\n      histo[rvalue] = (histo[rvalue] || 0) + 1;\n    }\n    // set data range\n    const dataRange = {min: min, max: max};\n    const rescaledDataRange = {min: rmin, max: rmax};\n    // generate data for plotting\n    const histogram = [];\n    for (let b = rmin; b <= rmax; ++b) {\n      histogram.push([b, (histo[b] || 0)]);\n    }\n    // return\n    return {\n      dataRange: dataRange,\n      rescaledDataRange: rescaledDataRange,\n      histogram: histogram\n    };\n  }\n\n  /**\n   * Convolute the image with a given 2D kernel.\n   *\n   * Note: Uses raw buffer values.\n   *\n   * @param {number[]} weights The weights of the 2D kernel as a 3x3 matrix.\n   * @returns {Image} The convoluted image.\n   */\n  convolute2D(weights) {\n    if (weights.length !== 9) {\n      throw new Error(\n        'The convolution matrix does not have a length of 9; it has ' +\n        weights.length);\n    }\n\n    const newImage = this.clone();\n    const newBuffer = newImage.getBuffer();\n\n    const imgSize = this.getGeometry().getSize();\n    const dimOffset = imgSize.getDimSize(2) * this.getNumberOfComponents();\n    for (let k = 0; k < imgSize.get(2); ++k) {\n      this.convoluteBuffer(weights, newBuffer, k * dimOffset);\n    }\n\n    return newImage;\n  }\n\n  /**\n   * Convolute an image buffer with a given 2D kernel.\n   *\n   * Note: Uses raw buffer values.\n   *\n   * @param {number[]} weights The weights of the 2D kernel as a 3x3 matrix.\n   * @param {TypedArray} buffer The buffer to convolute.\n   * @param {number} startOffset The index to start at.\n   */\n  convoluteBuffer(\n    weights, buffer, startOffset) {\n    const imgSize = this.getGeometry().getSize();\n    const ncols = imgSize.get(0);\n    const nrows = imgSize.get(1);\n    const ncomp = this.getNumberOfComponents();\n\n    // number of component and planar configuration vars\n    let factor = 1;\n    let componentOffset = 1;\n    if (ncomp === 3) {\n      if (this.getPlanarConfiguration() === 0) {\n        factor = 3;\n      } else {\n        componentOffset = imgSize.getDimSize(2);\n      }\n    }\n\n    // allow special indent for matrices\n    /*jshint indent:false */\n\n    // default weight offset matrix\n    const wOff = [];\n    wOff[0] = (-ncols - 1) * factor;\n    wOff[1] = (-ncols) * factor;\n    wOff[2] = (-ncols + 1) * factor;\n    wOff[3] = -factor;\n    wOff[4] = 0;\n    wOff[5] = 1 * factor;\n    wOff[6] = (ncols - 1) * factor;\n    wOff[7] = (ncols) * factor;\n    wOff[8] = (ncols + 1) * factor;\n\n    // border weight offset matrices\n    // borders are extended (see http://en.wikipedia.org/wiki/Kernel_%28image_processing%29)\n\n    // i=0, j=0\n    const wOff00 = [];\n    wOff00[0] = wOff[4]; wOff00[1] = wOff[4]; wOff00[2] = wOff[5];\n    wOff00[3] = wOff[4]; wOff00[4] = wOff[4]; wOff00[5] = wOff[5];\n    wOff00[6] = wOff[7]; wOff00[7] = wOff[7]; wOff00[8] = wOff[8];\n    // i=0, j=*\n    const wOff0x = [];\n    wOff0x[0] = wOff[1]; wOff0x[1] = wOff[1]; wOff0x[2] = wOff[2];\n    wOff0x[3] = wOff[4]; wOff0x[4] = wOff[4]; wOff0x[5] = wOff[5];\n    wOff0x[6] = wOff[7]; wOff0x[7] = wOff[7]; wOff0x[8] = wOff[8];\n    // i=0, j=nrows\n    const wOff0n = [];\n    wOff0n[0] = wOff[1]; wOff0n[1] = wOff[1]; wOff0n[2] = wOff[2];\n    wOff0n[3] = wOff[4]; wOff0n[4] = wOff[4]; wOff0n[5] = wOff[5];\n    wOff0n[6] = wOff[4]; wOff0n[7] = wOff[4]; wOff0n[8] = wOff[5];\n\n    // i=*, j=0\n    const wOffx0 = [];\n    wOffx0[0] = wOff[3]; wOffx0[1] = wOff[4]; wOffx0[2] = wOff[5];\n    wOffx0[3] = wOff[3]; wOffx0[4] = wOff[4]; wOffx0[5] = wOff[5];\n    wOffx0[6] = wOff[6]; wOffx0[7] = wOff[7]; wOffx0[8] = wOff[8];\n    // i=*, j=* -> wOff\n    // i=*, j=nrows\n    const wOffxn = [];\n    wOffxn[0] = wOff[0]; wOffxn[1] = wOff[1]; wOffxn[2] = wOff[2];\n    wOffxn[3] = wOff[3]; wOffxn[4] = wOff[4]; wOffxn[5] = wOff[5];\n    wOffxn[6] = wOff[3]; wOffxn[7] = wOff[4]; wOffxn[8] = wOff[5];\n\n    // i=ncols, j=0\n    const wOffn0 = [];\n    wOffn0[0] = wOff[3]; wOffn0[1] = wOff[4]; wOffn0[2] = wOff[4];\n    wOffn0[3] = wOff[3]; wOffn0[4] = wOff[4]; wOffn0[5] = wOff[4];\n    wOffn0[6] = wOff[6]; wOffn0[7] = wOff[7]; wOffn0[8] = wOff[7];\n    // i=ncols, j=*\n    const wOffnx = [];\n    wOffnx[0] = wOff[0]; wOffnx[1] = wOff[1]; wOffnx[2] = wOff[1];\n    wOffnx[3] = wOff[3]; wOffnx[4] = wOff[4]; wOffnx[5] = wOff[4];\n    wOffnx[6] = wOff[6]; wOffnx[7] = wOff[7]; wOffnx[8] = wOff[7];\n    // i=ncols, j=nrows\n    const wOffnn = [];\n    wOffnn[0] = wOff[0]; wOffnn[1] = wOff[1]; wOffnn[2] = wOff[1];\n    wOffnn[3] = wOff[3]; wOffnn[4] = wOff[4]; wOffnn[5] = wOff[4];\n    wOffnn[6] = wOff[3]; wOffnn[7] = wOff[4]; wOffnn[8] = wOff[4];\n\n    // restore indent for rest of method\n    /*jshint indent:4 */\n\n    // loop vars\n    let pixelOffset = startOffset;\n    let newValue = 0;\n    let wOffFinal = [];\n    for (let c = 0; c < ncomp; ++c) {\n      // component offset\n      pixelOffset += c * componentOffset;\n      for (let j = 0; j < nrows; ++j) {\n        for (let i = 0; i < ncols; ++i) {\n          wOffFinal = wOff;\n          // special border cases\n          if (i === 0 && j === 0) {\n            wOffFinal = wOff00;\n          } else if (i === 0 && j === (nrows - 1)) {\n            wOffFinal = wOff0n;\n          } else if (i === (ncols - 1) && j === 0) {\n            wOffFinal = wOffn0;\n          } else if (i === (ncols - 1) && j === (nrows - 1)) {\n            wOffFinal = wOffnn;\n          } else if (i === 0 && j !== (nrows - 1) && j !== 0) {\n            wOffFinal = wOff0x;\n          } else if (i === (ncols - 1) && j !== (nrows - 1) && j !== 0) {\n            wOffFinal = wOffnx;\n          } else if (i !== 0 && i !== (ncols - 1) && j === 0) {\n            wOffFinal = wOffx0;\n          } else if (i !== 0 && i !== (ncols - 1) && j === (nrows - 1)) {\n            wOffFinal = wOffxn;\n          }\n          // calculate the weighed sum of the source image pixels that\n          // fall under the convolution matrix\n          newValue = 0;\n          for (let wi = 0; wi < 9; ++wi) {\n            newValue += this.getValueAtOffset(\n              pixelOffset + wOffFinal[wi]) * weights[wi];\n          }\n          buffer[pixelOffset] = newValue;\n          // increment pixel offset\n          pixelOffset += factor;\n        }\n      }\n    }\n  }\n\n  /**\n   * Transform an image using a specific operator.\n   * WARNING: no size check!\n   *\n   * @param {Function} operator The operator to use when transforming.\n   * @returns {Image} The transformed image.\n   * Note: Uses the raw buffer values.\n   */\n  transform(operator) {\n    const newImage = this.clone();\n    const newBuffer = newImage.getBuffer();\n    for (let i = 0, leni = newBuffer.length; i < leni; ++i) {\n      newBuffer[i] = operator(newImage.getValueAtOffset(i));\n    }\n    return newImage;\n  }\n\n  /**\n   * Compose this image with another one and using a specific operator.\n   * WARNING: no size check!\n   *\n   * @param {Image} rhs The image to compose with.\n   * @param {Function} operator The operator to use when composing.\n   * @returns {Image} The composed image.\n   * Note: Uses the raw buffer values.\n   */\n  compose(rhs, operator) {\n    const newImage = this.clone();\n    const newBuffer = newImage.getBuffer();\n    for (let i = 0, leni = newBuffer.length; i < leni; ++i) {\n      // using the operator on the local buffer, i.e. the\n      // latest (not original) data\n      newBuffer[i] = Math.floor(\n        operator(this.getValueAtOffset(i), rhs.getValueAtOffset(i))\n      );\n    }\n    return newImage;\n  }\n\n} // class Image\n","import {custom} from '../app/custom';\nimport {View} from './view';\nimport {WindowLevel} from './windowLevel';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {DataElement} from '../dicom/dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * List of default window level presets.\n *\n * @type {Object.<string, Object.<string, WindowLevel>>}\n */\nconst defaultWlPresets = {\n  CT: {\n    mediastinum: new WindowLevel(40, 400),\n    lung: new WindowLevel(-500, 1500),\n    bone: new WindowLevel(500, 2000),\n    brain: new WindowLevel(40, 80),\n    head: new WindowLevel(90, 350)\n  }\n};\n\n/**\n * {@link View} factory.\n */\nexport class ViewFactory {\n\n  /**\n   * Get an View object from the read DICOM file.\n   *\n   * @param {Object<string, DataElement>} dataElements The DICOM tags.\n   * @param {Image} image The associated image.\n   * @returns {View} The new View.\n   */\n  create(dataElements, image) {\n    // view\n    const view = new View(image);\n\n    // default color map\n    if (image.getPhotometricInterpretation() === 'MONOCHROME1') {\n      view.setColourMap('invPlain');\n    }\n\n    // window level presets\n    let windowPresets = {};\n    // image presets\n    if (typeof image.getMeta().windowPresets !== 'undefined') {\n      windowPresets = image.getMeta().windowPresets;\n    }\n    // min/max\n    // Not filled yet since it is stil too costly to calculate min/max\n    // for each slice... It will be filled at first use\n    // (see view.setWindowLevelPreset).\n    // Order is important, if no wl from DICOM, this will be the default.\n    windowPresets.minmax = {name: 'minmax'};\n    // optional modality presets\n    const modality = image.getMeta().Modality;\n    let wlPresets;\n    if (typeof custom.wlPresets !== 'undefined' &&\n      typeof custom.wlPresets[modality] !== 'undefined') {\n      wlPresets = custom.wlPresets[modality];\n    } else {\n      wlPresets = defaultWlPresets[modality];\n    }\n    for (const key in wlPresets) {\n      const preset = wlPresets[key];\n      windowPresets[key] = {\n        wl: [new WindowLevel(preset.center, preset.width)],\n        name: key\n      };\n    }\n\n    // store\n    view.setWindowPresets(windowPresets);\n\n    // initialise the view\n    view.init();\n\n    return view;\n  }\n\n} // class ViewFactory\n","import {Index} from '../math/index';\nimport {ModalityLut} from './modalityLut';\nimport {WindowLut} from './windowLut';\nimport {luts} from './luts';\nimport {VoiLut} from './voiLut';\nimport {WindowLevel} from './windowLevel';\nimport {generateImageDataMonochrome} from './viewMonochrome';\nimport {generateImageDataPaletteColor} from './viewPaletteColor';\nimport {generateImageDataRgb} from './viewRgb';\nimport {generateImageDataYbrFull} from './viewYbrFull';\nimport {ViewFactory} from './viewFactory';\nimport {isIdentityMat33} from '../math/matrix';\nimport {getSliceIterator} from '../image/iterator';\nimport {ListenerHandler} from '../utils/listen';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {RescaleSlopeAndIntercept} from './rsi';\nimport {ColourMap} from './luts';\nimport {Matrix33} from '../math/matrix';\nimport {\n  Point,\n  Point3D\n} from '../math/point';\nimport {DataElement} from '../dicom/dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * List of view event names.\n *\n * @type {string[]}\n */\nexport const viewEventNames = [\n  'wlchange',\n  'wlpresetadd',\n  'colourmapchange',\n  'positionchange',\n  'opacitychange',\n  'alphafuncchange'\n];\n\n/**\n * Create a View from DICOM elements and image.\n *\n * @param {Object<string, DataElement>} elements The DICOM elements.\n * @param {Image} image The associated image.\n * @returns {View} The View object.\n */\nexport function createView(elements, image) {\n  const factory = new ViewFactory();\n  return factory.create(elements, image);\n}\n\n/**\n * View class.\n *\n * Need to set the window lookup table once created\n * (either directly or with helper methods).\n *\n * @example\n * // XMLHttpRequest onload callback\n * const onload = function (event) {\n *   // parse the dicom buffer\n *   const dicomParser = new dwv.DicomParser();\n *   dicomParser.parse(event.target.response);\n *   // create the image object\n *   const image = dwv.createImage(dicomParser.getDicomElements());\n *   // create the view\n *   const view = dwv.createView(dicomParser.getDicomElements(), image);\n *   // setup canvas\n *   const canvas = document.createElement('canvas');\n *   canvas.width = 256;\n *   canvas.height = 256;\n *   const ctx = canvas.getContext(\"2d\");\n *   // update the image data\n *   const imageData = ctx.createImageData(256, 256);\n *   view.generateImageData(imageData);\n *   ctx.putImageData(imageData, 0, 0);\n *   // update html\n *   const div = document.getElementById('dwv');\n *   div.appendChild(canvas);;\n * };\n * // DICOM file request\n * const request = new XMLHttpRequest();\n * const url = 'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm';\n * request.open('GET', url);\n * request.responseType = 'arraybuffer';\n * request.onload = onload;\n * request.send();\n */\nexport class View {\n\n  /**\n   * The associated image.\n   *\n   * @type {Image}\n   */\n  #image;\n\n  /**\n   * Window lookup tables, indexed per Rescale Slope and Intercept (RSI).\n   *\n   * @type {WindowLut}\n   */\n  #windowLut;\n\n  /**\n   * Flag for image constant RSI.\n   *\n   * @type {boolean}\n   */\n  #isConstantRSI;\n\n  /**\n   * Window presets.\n   * Minmax will be filled at first use (see view.setWindowLevelPreset).\n   *\n   * @type {object}\n   */\n  #windowPresets = {minmax: {name: 'minmax'}};\n\n  /**\n   * Current window preset name.\n   *\n   * @type {string}\n   */\n  #currentPresetName = null;\n\n  /**\n   * Current window level.\n   *\n   * @type {WindowLevel}\n   */\n  #currentWl;\n\n  /**\n   * Colour map name.\n   *\n   * @type {string}\n   */\n  #colourMapName = 'plain';\n\n  /**\n   * Current position as a Point.\n   * Store position and not index to stay geometry independent.\n   *\n   * @type {Point}\n   */\n  #currentPosition = null;\n\n  /**\n   * View orientation. Undefined will use the original slice ordering.\n   *\n   * @type {Matrix33}\n   */\n  #orientation;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * @param {Image} image The associated image.\n   */\n  constructor(image) {\n    this.#image = image;\n\n    // listen to appendframe event to update the current position\n    //   to add the extra dimension\n    this.#image.addEventListener('appendframe', () => {\n      // update current position if first appendFrame\n      const index = this.getCurrentIndex();\n      if (index.length() === 3) {\n        // add dimension\n        const values = index.getValues();\n        values.push(0);\n        this.setCurrentIndex(new Index(values));\n      }\n    });\n  }\n\n  /**\n   * Get the associated image.\n   *\n   * @returns {Image} The associated image.\n   */\n  getImage() {\n    return this.#image;\n  }\n\n  /**\n   * Set the associated image.\n   *\n   * @param {Image} inImage The associated image.\n   */\n  setImage(inImage) {\n    this.#image = inImage;\n  }\n\n  /**\n   * Get the view orientation.\n   *\n   * @returns {Matrix33} The orientation matrix.\n   */\n  getOrientation() {\n    return this.#orientation;\n  }\n\n  /**\n   * Set the view orientation.\n   *\n   * @param {Matrix33} mat33 The orientation matrix.\n   */\n  setOrientation(mat33) {\n    this.#orientation = mat33;\n  }\n\n  /**\n   * Initialise the view: set initial index.\n   */\n  init() {\n    this.setInitialIndex();\n  }\n\n  /**\n   * Set the initial index to the middle position.\n   */\n  setInitialIndex() {\n    const geometry = this.#image.getGeometry();\n    const size = geometry.getSize();\n    const values = new Array(size.length());\n    values.fill(0);\n    // middle\n    values[0] = Math.floor(size.get(0) / 2);\n    values[1] = Math.floor(size.get(1) / 2);\n    values[2] = Math.floor(size.get(2) / 2);\n    this.setCurrentIndex(new Index(values), true);\n  }\n\n  /**\n   * Get the milliseconds per frame from frame rate.\n   *\n   * @param {number} recommendedDisplayFrameRate Recommended Display Frame Rate.\n   * @returns {number} The milliseconds per frame.\n   */\n  getPlaybackMilliseconds(recommendedDisplayFrameRate) {\n    if (!recommendedDisplayFrameRate) {\n      // Default to 10 FPS if none is found in the meta\n      recommendedDisplayFrameRate = 10;\n    }\n    // round milliseconds per frame to nearest whole number\n    return Math.round(1000 / recommendedDisplayFrameRate);\n  }\n\n  /**\n   * Per value alpha function.\n   *\n   * @param {number[]|number} _value The pixel value.\n   *   Can be a number for monochrome data or an array for RGB data.\n   * @param {number} _index The index of the value.\n   * @returns {number} The coresponding alpha [0,255].\n   */\n  #alphaFunction = function (_value, _index) {\n    // default always returns fully visible\n    return 0xff;\n  };\n\n  /**\n   * @callback alphaFn\n   * @param {number[]|number} value The pixel value.\n   * @param {number} index The values' index.\n   * @returns {number} The opacity of the input value.\n   */\n\n  /**\n   * Get the alpha function.\n   *\n   * @returns {alphaFn} The function.\n   */\n  getAlphaFunction() {\n    return this.#alphaFunction;\n  }\n\n  /**\n   * Set alpha function.\n   *\n   * @param {alphaFn} func The function.\n   * @fires View#alphafuncchange\n   */\n  setAlphaFunction(func) {\n    this.#alphaFunction = func;\n    /**\n     * Alpha func change event.\n     *\n     * @event View#alphafuncchange\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    this.#fireEvent({\n      type: 'alphafuncchange'\n    });\n  }\n\n  /**\n   * Get the window LUT of the image.\n   * Warning: can be undefined in no window/level was set.\n   *\n   * @returns {WindowLut} The window LUT of the image.\n   * @fires View#wlchange\n   */\n  #getCurrentWindowLut() {\n    // special case for 'perslice' presets\n    if (this.#currentPresetName &&\n      typeof this.#windowPresets[this.#currentPresetName] !== 'undefined' &&\n      typeof this.#windowPresets[this.#currentPresetName].perslice !==\n        'undefined' &&\n      this.#windowPresets[this.#currentPresetName].perslice === true) {\n      // check position\n      if (!this.getCurrentIndex()) {\n        this.setInitialIndex();\n      }\n      // get the slice window level\n      const currentIndex = this.getCurrentIndex();\n      const offset = this.#image.getSecondaryOffset(currentIndex);\n      const currentPreset = this.#windowPresets[this.#currentPresetName];\n      const sliceWl = currentPreset.wl[offset];\n      // set window level: will send a change event, mark it as silent as\n      // this change is always triggered by a position change\n      this.setWindowLevel(sliceWl, this.#currentPresetName, true);\n    }\n\n    // if no current, use first id\n    if (typeof this.#currentWl === 'undefined') {\n      this.setWindowLevelPresetById(0, true);\n    }\n\n    // get the window lut\n    if (typeof this.#isConstantRSI === 'undefined' ||\n      this.#image.isConstantRSI() !== this.#isConstantRSI) {\n      this.#isConstantRSI = this.#image.isConstantRSI();\n      // set or update windowLut if isConstantRSI has changed\n      // (can be different at first slice and after having loaded\n      //  the full volume...)\n      let rsi;\n      let isDiscrete;\n      if (this.#isConstantRSI) {\n        rsi = this.#image.getRescaleSlopeAndIntercept();\n        isDiscrete = true;\n      } else {\n        rsi = new RescaleSlopeAndIntercept(1, 0);\n        isDiscrete = false;\n      }\n      // create the rescale lookup table\n      const modalityLut = new ModalityLut(\n        rsi,\n        this.#image.getMeta().BitsStored);\n      // create the window lookup table\n      this.#windowLut = new WindowLut(\n        modalityLut,\n        this.#image.getMeta().IsSigned,\n        isDiscrete);\n    }\n\n    // update VOI lut if not present or its window level\n    // is different from the current one\n    const voiLut = this.#windowLut.getVoiLut();\n    let voiLutWl;\n    if (typeof voiLut !== 'undefined') {\n      voiLutWl = voiLut.getWindowLevel();\n    }\n    if (typeof voiLut === 'undefined' ||\n      !this.#currentWl.equals(voiLutWl)) {\n      // set lut window level\n      const voiLut = new VoiLut(this.#currentWl);\n      this.#windowLut.setVoiLut(voiLut);\n    }\n\n    // return\n    return this.#windowLut;\n  }\n\n  /**\n   * Get the window presets.\n   *\n   * @returns {object} The window presets.\n   */\n  getWindowPresets() {\n    return this.#windowPresets;\n  }\n\n  /**\n   * Get the window presets names.\n   *\n   * @returns {string[]} The list of window presets names.\n   */\n  getWindowPresetsNames() {\n    return Object.keys(this.#windowPresets);\n  }\n\n  /**\n   * Set the window presets.\n   *\n   * @param {object} presets The window presets.\n   */\n  setWindowPresets(presets) {\n    this.#windowPresets = presets;\n  }\n\n  /**\n   * Add window presets to the existing ones.\n   *\n   * @param {object} presets The window presets.\n   */\n  addWindowPresets(presets) {\n    const keys = Object.keys(presets);\n    let key = null;\n    for (let i = 0; i < keys.length; ++i) {\n      key = keys[i];\n      if (typeof this.#windowPresets[key] !== 'undefined') {\n        if (typeof this.#windowPresets[key].perslice !== 'undefined' &&\n          this.#windowPresets[key].perslice === true) {\n          throw new Error('Cannot add perslice preset');\n        } else {\n          // update existing\n          this.#windowPresets[key] = presets[key];\n        }\n      } else {\n        // add new\n        this.#windowPresets[key] = presets[key];\n        // fire event\n        /**\n         * Window/level add preset event.\n         *\n         * @event View#wlpresetadd\n         * @type {object}\n         * @property {string} type The event type.\n         * @property {string} name The name of the preset.\n         */\n        this.#fireEvent({\n          type: 'wlpresetadd',\n          name: key\n        });\n      }\n    }\n  }\n\n  /**\n   * Get the current window level preset name.\n   *\n   * @returns {string} The preset name.\n   */\n  getCurrentWindowPresetName() {\n    return this.#currentPresetName;\n  }\n\n  /**\n   * Get the colour map of the image.\n   *\n   * @returns {string} The colour map name.\n   */\n  getColourMap() {\n    return this.#colourMapName;\n  }\n\n  /**\n   * Get the colour map object.\n   *\n   * @returns {ColourMap} The colour map.\n   */\n  #getColourMapLut() {\n    return luts[this.#colourMapName];\n  }\n\n  /**\n   * Set the colour map of the image.\n   *\n   * @param {string} name The colour map name.\n   * @fires View#colourmapchange\n   */\n  setColourMap(name) {\n    // check if we have it\n    if (!luts[name]) {\n      throw new Error('Unknown colour map: \\'' + name + '\\'');\n    }\n\n    this.#colourMapName = name;\n\n    /**\n     * Color change event.\n     *\n     * @event View#colourmapchange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} value The changed value.\n     */\n    this.#fireEvent({\n      type: 'colourmapchange',\n      value: [name]\n    });\n  }\n\n  /**\n   * Get the current position.\n   *\n   * @returns {Point} The current position.\n   */\n  getCurrentPosition() {\n    return this.#currentPosition;\n  }\n\n  /**\n   * Get the current index.\n   *\n   * @returns {Index} The current index.\n   */\n  getCurrentIndex() {\n    const position = this.getCurrentPosition();\n    if (!position) {\n      return null;\n    }\n    const geometry = this.getImage().getGeometry();\n    return geometry.worldToIndex(position);\n  }\n\n  /**\n   * Get the SOP image UID of the current image.\n   *\n   * @returns {string} The UID.\n   */\n  getCurrentImageUid() {\n    return this.#image.getImageUid(this.getCurrentIndex());\n  }\n\n  /**\n   * Get the image origin for a image UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {Point3D|undefined} The origin.\n   */\n  getOriginForImageUid(uid) {\n    return this.#image.getOriginForImageUid(uid);\n  }\n\n  /**\n   * Check if the image includes an UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {boolean} True if present.\n   */\n  includesImageUid(uid) {\n    return this.#image.includesImageUid(uid);\n  }\n\n  /**\n   * Check if the current position (default) or\n   * the provided position is in bounds.\n   *\n   * @param {Point} [position] Optional position.\n   * @returns {boolean} True is the position is in bounds.\n   */\n  isPositionInBounds(position) {\n    if (typeof position === 'undefined') {\n      position = this.#currentPosition;\n    }\n    const geometry = this.#image.getGeometry();\n    const index = geometry.worldToIndex(position);\n    const dirs = [this.getScrollDimIndex()];\n    if (index.length() === 4) {\n      dirs.push(3);\n    }\n    return geometry.isIndexInBounds(index, dirs);\n  }\n\n  /**\n   * Get the first origin or at a given position.\n   *\n   * @param {Point} [position] Optional position.\n   * @returns {Point3D} The origin.\n   */\n  getOrigin(position) {\n    const geometry = this.#image.getGeometry();\n    let originIndex = 0;\n    if (typeof position !== 'undefined') {\n      const index = geometry.worldToIndex(position);\n      // index is reoriented, 2 is scroll index\n      originIndex = index.get(2);\n    }\n    return geometry.getOrigins()[originIndex];\n  }\n\n  /**\n   * Set the current position via an index.\n   *\n   * @param {Index} index The new index.\n   * @param {boolean} [silent] Flag to fire event or not.\n   * @returns {boolean} False if not in bounds.\n   * @fires View#positionchange\n   */\n  setCurrentIndex(index, silent) {\n    const geometry = this.#image.getGeometry();\n    const position = geometry.indexToWorld(index);\n    return this.setCurrentPosition(position, silent);\n  }\n\n  /**\n   * Set current position.\n   *\n   * @param {Point} position The new position.\n   * @param {boolean} [silent] Flag to fire event or not.\n   * @returns {boolean} False if not in bounds.\n   * @fires View#positionchange\n   */\n  setCurrentPosition(position, silent) {\n    // check input\n    if (typeof silent === 'undefined') {\n      silent = false;\n    }\n\n    const geometry = this.#image.getGeometry();\n    const index = geometry.worldToIndex(position);\n\n    // check if possible\n    const dirs = [this.getScrollDimIndex()];\n    if (index.length() === 4) {\n      dirs.push(3);\n    }\n    if (!geometry.isIndexInBounds(index, dirs)) {\n      this.#currentPosition = position;\n      if (!silent) {\n        // fire event with valid: false\n        this.#fireEvent({\n          type: 'positionchange',\n          value: [\n            index.getValues(),\n            position.getValues(),\n          ],\n          valid: false\n        });\n      }\n\n      // do no send invalid positionchange event: avoid empty repaint\n      return false;\n    }\n\n    // calculate diff dims before updating internal\n    let diffDims = null;\n    let currentIndex = null;\n    if (this.getCurrentPosition()) {\n      currentIndex = this.getCurrentIndex();\n    }\n    if (currentIndex) {\n      if (currentIndex.canCompare(index)) {\n        diffDims = currentIndex.compare(index);\n      } else {\n        diffDims = [];\n        const minLen = Math.min(currentIndex.length(), index.length());\n        for (let i = 0; i < minLen; ++i) {\n          if (currentIndex.get(i) !== index.get(i)) {\n            diffDims.push(i);\n          }\n        }\n        const maxLen = Math.max(currentIndex.length(), index.length());\n        for (let j = minLen; j < maxLen; ++j) {\n          diffDims.push(j);\n        }\n      }\n    } else {\n      diffDims = [];\n      for (let k = 0; k < index.length(); ++k) {\n        diffDims.push(k);\n      }\n    }\n\n    // assign\n    this.#currentPosition = position;\n\n    if (!silent) {\n      /**\n       * Position change event.\n       *\n       * @event View#positionchange\n       * @type {object}\n       * @property {Array} value The changed value as [index, pixelValue].\n       * @property {number[]} diffDims An array of modified indices.\n       */\n      const posEvent = {\n        type: 'positionchange',\n        value: [\n          index.getValues(),\n          position.getValues(),\n        ],\n        diffDims: diffDims,\n        data: {\n          imageUid: this.#image.getImageUid(index)\n        }\n      };\n\n      // add value if possible\n      if (this.#image.canQuantify()) {\n        const pixValue = this.#image.getRescaledValueAtIndex(index);\n        posEvent.value.push(pixValue);\n      }\n\n      // fire\n      this.#fireEvent(posEvent);\n    }\n\n    // all good\n    return true;\n  }\n\n  /**\n   * Set the view window/level.\n   *\n   * @param {WindowLevel} wl The window and level.\n   * @param {string} [name] Associated preset name, defaults to 'manual'.\n   * Warning: uses the latest set rescale LUT or the default linear one.\n   * @param {boolean} [silent] Flag to launch events with skipGenerate.\n   * @fires View#wlchange\n   */\n  setWindowLevel(wl, name, silent) {\n    // check input\n    if (typeof name === 'undefined') {\n      name = 'manual';\n    }\n    if (name !== 'manual' &&\n      typeof this.#windowPresets[name] === 'undefined') {\n      throw new Error('Unknown window level preset: \\'' + name + '\\'');\n    }\n    if (typeof silent === 'undefined') {\n      silent = false;\n    }\n\n    // check if new wl\n    const isNewWl = !wl.equals(this.#currentWl);\n    // check if new name\n    const isNewName = this.#currentPresetName !== name;\n\n    // compare to previous if present\n    if (isNewWl || isNewName) {\n      // assign\n      this.#currentWl = wl;\n      this.#currentPresetName = name;\n\n      // update manual\n      if (name === 'manual') {\n        if (typeof this.#windowPresets[name] !== 'undefined') {\n          this.#windowPresets[name].wl[0] = wl;\n        } else {\n          // add if not present\n          this.addWindowPresets({\n            manual: {\n              wl: [wl],\n              name: 'manual'\n            }\n          });\n        }\n      }\n\n      /**\n       * Window/level change event.\n       *\n       * @event View#wlchange\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {Array} value The changed value.\n       * @property {number} wc The new window center value.\n       * @property {number} ww The new window wdth value.\n       * @property {boolean} skipGenerate Flag to skip view generation.\n       */\n      this.#fireEvent({\n        type: 'wlchange',\n        value: [wl.center, wl.width, name],\n        wc: wl.center,\n        ww: wl.width,\n        skipGenerate: silent\n      });\n    }\n  }\n\n  /**\n   * Get the window/level.\n   *\n   * @returns {WindowLevel} The window and level.\n   */\n  getWindowLevel() {\n    // same as #currentWl...\n    const windowLut = this.#getCurrentWindowLut();\n    return windowLut.getVoiLut().getWindowLevel();\n  }\n\n  /**\n   * Set the window level to the preset with the input name.\n   *\n   * @param {string} name The name of the preset to activate.\n   * @param {boolean} [silent] Flag to launch events with skipGenerate.\n   */\n  setWindowLevelPreset(name, silent) {\n    const preset = this.getWindowPresets()[name];\n    if (typeof preset === 'undefined') {\n      throw new Error('Unknown window level preset: \\'' + name + '\\'');\n    }\n    // special min/max\n    if (name === 'minmax' && typeof preset.wl === 'undefined') {\n      preset.wl = [this.getWindowLevelMinMax()];\n    }\n    // default to first\n    let wl = preset.wl[0];\n    // check if 'perslice' case\n    if (typeof preset.perslice !== 'undefined' &&\n      preset.perslice === true) {\n      const offset = this.#image.getSecondaryOffset(this.getCurrentIndex());\n      wl = preset.wl[offset];\n    }\n    // set w/l\n    this.setWindowLevel(wl, name, silent);\n  }\n\n  /**\n   * Set the window level to the preset with the input id.\n   *\n   * @param {number} id The id of the preset to activate.\n   * @param {boolean} [silent] Flag to launch events with skipGenerate.\n   */\n  setWindowLevelPresetById(id, silent) {\n    const keys = Object.keys(this.getWindowPresets());\n    this.setWindowLevelPreset(keys[id], silent);\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  /**\n   * Get the image window/level that covers the full data range.\n   * Warning: uses the latest set rescale LUT or the default linear one.\n   *\n   * @returns {WindowLevel} A min/max window level.\n   */\n  getWindowLevelMinMax() {\n    const range = this.getImage().getRescaledDataRange();\n    const min = range.min;\n    const max = range.max;\n    let width = max - min;\n    // full black / white images, defaults to 1.\n    if (width < 1) {\n      logger.warn('Zero or negative window width, defaulting to one.');\n      width = 1;\n    }\n    const center = min + width / 2;\n    return new WindowLevel(center, width);\n  }\n\n  /**\n   * Set the image window/level to cover the full data range.\n   * Warning: uses the latest set rescale LUT or the default linear one.\n   */\n  setWindowLevelMinMax() {\n    // calculate center and width\n    const wl = this.getWindowLevelMinMax();\n    // set window level\n    this.setWindowLevel(wl, 'minmax');\n  }\n\n  /**\n   * Generate display image data to be given to a canvas.\n   *\n   * @param {ImageData} data The iamge data to fill in.\n   * @param {Index} index Optional index at which to generate,\n   *   otherwise generates at current index.\n   */\n  generateImageData(data, index) {\n    // check index\n    if (typeof index === 'undefined') {\n      if (!this.getCurrentIndex()) {\n        this.setInitialIndex();\n      }\n      index = this.getCurrentIndex();\n    }\n\n    const image = this.getImage();\n    const isRescaled = !image.isConstantRSI();\n    const iterator = getSliceIterator(\n      image, index, isRescaled, this.getOrientation());\n\n    const photoInterpretation = image.getPhotometricInterpretation();\n    switch (photoInterpretation) {\n    case 'MONOCHROME1':\n    case 'MONOCHROME2':\n      generateImageDataMonochrome(\n        data,\n        iterator,\n        this.getAlphaFunction(),\n        this.#getCurrentWindowLut(),\n        this.#getColourMapLut()\n      );\n      break;\n\n    case 'PALETTE COLOR':\n      generateImageDataPaletteColor(\n        data,\n        iterator,\n        this.getAlphaFunction(),\n        image.getPaletteColourMap(),\n        image.getMeta().BitsStored === 16\n      );\n      break;\n\n    case 'RGB':\n      generateImageDataRgb(\n        data,\n        iterator,\n        this.getAlphaFunction()\n      );\n      break;\n\n    case 'YBR_FULL':\n      generateImageDataYbrFull(\n        data,\n        iterator,\n        this.getAlphaFunction()\n      );\n      break;\n\n    default:\n      throw new Error(\n        'Unsupported photometric interpretation: ' + photoInterpretation);\n    }\n  }\n\n  /**\n   * Get the scroll dimension index.\n   *\n   * @returns {number} The index.\n   */\n  getScrollDimIndex() {\n    let index = null;\n    const orientation = this.getOrientation();\n    if (typeof orientation !== 'undefined') {\n      index = orientation.getThirdColMajorDirection();\n    } else {\n      index = 2;\n    }\n    return index;\n  }\n\n  /**\n   * Is this view in the same orientation as the image aquisition.\n   *\n   * @returns {boolean} True if in aquisition plane.\n   */\n  isAquisitionOrientation() {\n    return isIdentityMat33(this.#orientation);\n  }\n\n} // class View\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {WindowLut} from './windowLut';\nimport {ColourMap} from './luts';\n/* eslint-enable no-unused-vars */\n\n/**\n * Generate image data for 'MONOCHROME*' photometric interpretation.\n *\n * @param {ImageData} array The array to store the outut data.\n * @param {object} iterator Position iterator.\n * @param {Function} alphaFunc The alpha function.\n * @param {WindowLut} windowLut The window/level LUT.\n * @param {ColourMap} colourMap The colour map.\n */\nexport function generateImageDataMonochrome(\n  array,\n  iterator,\n  alphaFunc,\n  windowLut,\n  colourMap) {\n  let index = 0;\n  let pxValue = 0;\n  let ival = iterator.next();\n  while (!ival.done) {\n    // pixel value\n    pxValue = windowLut.getValue(ival.value);\n    // store data\n    array.data[index] = colourMap.red[pxValue];\n    array.data[index + 1] = colourMap.green[pxValue];\n    array.data[index + 2] = colourMap.blue[pxValue];\n    array.data[index + 3] = alphaFunc(ival.value, ival.index);\n    // increment\n    index += 4;\n    ival = iterator.next();\n  }\n}\n","import {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {ColourMap} from './luts';\n/* eslint-enable no-unused-vars */\n\n/**\n * Generate image data for 'PALETTE COLOR' photometric interpretation.\n *\n * @param {ImageData} array The array to store the outut data.\n * @param {object} iterator Position iterator.\n * @param {Function} alphaFunc The alpha function.\n * @param {ColourMap} colourMap The colour map.\n * @param {boolean} is16BitsStored Flag to know if the data is 16bits.\n */\nexport function generateImageDataPaletteColor(\n  array,\n  iterator,\n  alphaFunc,\n  colourMap,\n  is16BitsStored) {\n  // right shift 8\n  const to8 = function (value) {\n    return value >> 8;\n  };\n\n  if (is16BitsStored) {\n    logger.info('Scaling 16bits data to 8bits.');\n  }\n\n  let index = 0;\n  let pxValue = 0;\n  let ival = iterator.next();\n  while (!ival.done) {\n    // pixel value\n    pxValue = ival.value;\n    // store data\n    // TODO check pxValue fits in lut\n    if (is16BitsStored) {\n      array.data[index] = to8(colourMap.red[pxValue]);\n      array.data[index + 1] = to8(colourMap.green[pxValue]);\n      array.data[index + 2] = to8(colourMap.blue[pxValue]);\n    } else {\n      array.data[index] = colourMap.red[pxValue];\n      array.data[index + 1] = colourMap.green[pxValue];\n      array.data[index + 2] = colourMap.blue[pxValue];\n    }\n    array.data[index + 3] = alphaFunc(pxValue, ival.index);\n    // increment\n    index += 4;\n    ival = iterator.next();\n  }\n}\n","/**\n * Generate image data for 'RGB' photometric interpretation.\n *\n * @param {ImageData} array The array to store the outut data.\n * @param {object} iterator Position iterator.\n * @param {Function} alphaFunc The alpha function.\n */\nexport function generateImageDataRgb(\n  array,\n  iterator,\n  alphaFunc) {\n  let index = 0;\n  let ival = iterator.next();\n  while (!ival.done) {\n    // store data\n    array.data[index] = ival.value[0];\n    array.data[index + 1] = ival.value[1];\n    array.data[index + 2] = ival.value[2];\n    array.data[index + 3] = alphaFunc(ival.value, ival.index);\n    // increment\n    index += 4;\n    ival = iterator.next();\n  }\n}\n","import {ybrToRgb} from '../utils/colour';\n\n/**\n * Generate image data for 'YBR_FULL' photometric interpretation.\n *\n * @param {ImageData} array The array to store the outut data.\n * @param {object} iterator Position iterator.\n * @param {Function} alphaFunc The alpha function.\n */\nexport function generateImageDataYbrFull(\n  array,\n  iterator,\n  alphaFunc) {\n  let index = 0;\n  let rgb = null;\n  let ival = iterator.next();\n  while (!ival.done) {\n    // convert ybr to rgb\n    rgb = ybrToRgb(ival.value[0], ival.value[1], ival.value[2]);\n    // store data\n    array.data[index] = rgb.r;\n    array.data[index + 1] = rgb.g;\n    array.data[index + 2] = rgb.b;\n    array.data[index + 3] = alphaFunc(ival.value, ival.index);\n    // increment\n    index += 4;\n    ival = iterator.next();\n  }\n}\n","import {Vector3D} from '../math/vector';\nimport {Point3D, Point2D} from '../math/point';\nimport {isIdentityMat33} from '../math/matrix';\nimport {\n  getCosinesFromOrientation,\n  getTargetOrientation\n} from '../math/orientation';\nimport {getOrientedArray3D, getDeOrientedArray3D} from './geometry';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point} from '../math/point';\nimport {Index} from '../math/index';\nimport {Geometry} from '../image/geometry';\nimport {Matrix33} from '../math/matrix';\nimport {Spacing} from './spacing';\nimport {Scalar2D, Scalar3D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Plane geometry helper.\n */\nexport class PlaneHelper {\n\n  /**\n   * The image geometry.\n   *\n   * @type {Geometry}\n   */\n  #imageGeometry;\n\n  /**\n   * The associated spacing.\n   *\n   * @type {Spacing}\n   */\n  #spacing;\n\n  /**\n   * The image orientation.\n   *\n   * @type {Matrix33}\n   */\n  #imageOrientation;\n\n  /**\n   * The viewe orientation.\n   *\n   * @type {Matrix33}\n   */\n  #viewOrientation;\n\n  /**\n   * The target orientation.\n   *\n   * @type {Matrix33}\n   */\n  #targetOrientation;\n\n  /**\n   * @param {Geometry} imageGeometry The image geometry.\n   * @param {Matrix33} viewOrientation The view orientation.\n   */\n  constructor(imageGeometry, viewOrientation) {\n    this.#imageGeometry = imageGeometry;\n    this.#spacing = imageGeometry.getRealSpacing();\n    this.#imageOrientation = imageGeometry.getOrientation();\n    this.#viewOrientation = viewOrientation;\n\n    this.#targetOrientation = getTargetOrientation(\n      this.#imageOrientation, viewOrientation);\n  }\n\n  /**\n   * Get the view orientation.\n   *\n   * @returns {Matrix33} The orientation matrix.\n   */\n  getViewOrientation() {\n    return this.#viewOrientation;\n  }\n\n  /**\n   * Get the target orientation.\n   *\n   * @returns {Matrix33} The orientation matrix.\n   */\n  getTargetOrientation() {\n    return this.#targetOrientation;\n  }\n\n  /**\n   * Get a 3D offset from a plane one.\n   *\n   * @param {Scalar2D} offset2D The plane offset as {x,y}.\n   * @returns {Vector3D} The 3D world offset.\n   */\n  getOffset3DFromPlaneOffset(offset2D) {\n    // make 3D\n    const planeOffset = new Vector3D(\n      offset2D.x, offset2D.y, 0);\n    // de-orient\n    const pixelOffset = this.getTargetDeOrientedVector3D(planeOffset);\n    // ~indexToWorld\n    return new Vector3D(\n      pixelOffset.getX() * this.#spacing.get(0),\n      pixelOffset.getY() * this.#spacing.get(1),\n      pixelOffset.getZ() * this.#spacing.get(2));\n  }\n\n  /**\n   * Get a plane offset from a 3D one.\n   *\n   * @param {Scalar3D} offset3D The 3D offset as {x,y,z}.\n   * @returns {Scalar2D} The plane offset as {x,y}.\n   */\n  getPlaneOffsetFromOffset3D(offset3D) {\n    // ~worldToIndex\n    const pixelOffset = new Vector3D(\n      offset3D.x / this.#spacing.get(0),\n      offset3D.y / this.#spacing.get(1),\n      offset3D.z / this.#spacing.get(2));\n    // orient\n    const planeOffset = this.getTargetOrientedVector3D(pixelOffset);\n    // make 2D\n    return {\n      x: planeOffset.getX(),\n      y: planeOffset.getY()\n    };\n  }\n\n  /**\n   * Orient an input vector from real to target space.\n   *\n   * @param {Vector3D} vector The input vector.\n   * @returns {Vector3D} The oriented vector.\n   */\n  getTargetOrientedVector3D(vector) {\n    let planeVector = vector;\n    if (typeof this.#targetOrientation !== 'undefined') {\n      planeVector =\n        this.#targetOrientation.getInverse().multiplyVector3D(vector);\n    }\n    return planeVector;\n  }\n\n  /**\n   * De-orient an input vector from target to real space.\n   *\n   * @param {Vector3D} planeVector The input vector.\n   * @returns {Vector3D} The de-orienteded vector.\n   */\n  getTargetDeOrientedVector3D(planeVector) {\n    let vector = planeVector;\n    if (typeof this.#targetOrientation !== 'undefined') {\n      vector = this.#targetOrientation.multiplyVector3D(planeVector);\n    }\n    return vector;\n  }\n\n  /**\n   * De-orient an input point from target to real space.\n   *\n   * @param {Point3D} planePoint The input point.\n   * @returns {Point3D} The de-orienteded point.\n   */\n  getTargetDeOrientedPoint3D(planePoint) {\n    let point = planePoint;\n    if (typeof this.#targetOrientation !== 'undefined') {\n      point = this.#targetOrientation.multiplyPoint3D(planePoint);\n    }\n    return point;\n  }\n\n  /**\n   * Orient an input vector from target to image space.\n   *\n   * @param {Vector3D} planeVector The input vector.\n   * @returns {Vector3D} The orienteded vector.\n   */\n  getImageOrientedVector3D(planeVector) {\n    let vector = planeVector;\n    if (typeof this.#viewOrientation !== 'undefined') {\n      // image oriented => view de-oriented\n      const values = getDeOrientedArray3D(\n        [\n          planeVector.getX(),\n          planeVector.getY(),\n          planeVector.getZ()\n        ],\n        this.#viewOrientation);\n      vector = new Vector3D(\n        values[0],\n        values[1],\n        values[2]\n      );\n    }\n    return vector;\n  }\n\n  /**\n   * Orient an input point from target to image space.\n   *\n   * @param {Point3D} planePoint The input vector.\n   * @returns {Point3D} The orienteded vector.\n   */\n  getImageOrientedPoint3D(planePoint) {\n    let point = planePoint;\n    if (typeof this.#viewOrientation !== 'undefined') {\n      // image oriented => view de-oriented\n      const values = getDeOrientedArray3D(\n        [\n          planePoint.getX(),\n          planePoint.getY(),\n          planePoint.getZ()\n        ],\n        this.#viewOrientation);\n      point = new Point3D(\n        values[0],\n        values[1],\n        values[2]\n      );\n    }\n    return point;\n  }\n\n  /**\n   * De-orient an input vector from image to target space.\n   *\n   * @param {Vector3D} vector The input vector.\n   * @returns {Vector3D} The de-orienteded vector.\n   */\n  getImageDeOrientedVector3D(vector) {\n    let planeVector = vector;\n    if (typeof this.#viewOrientation !== 'undefined') {\n      // image de-oriented => view oriented\n      const orientedValues = getOrientedArray3D(\n        [\n          vector.getX(),\n          vector.getY(),\n          vector.getZ()\n        ],\n        this.#viewOrientation);\n      planeVector = new Vector3D(\n        orientedValues[0],\n        orientedValues[1],\n        orientedValues[2]\n      );\n    }\n    return planeVector;\n  }\n\n  /**\n   * De-orient an input point from image to target space.\n   *\n   * @param {Point3D} point The input point.\n   * @returns {Point3D} The de-orienteded point.\n   */\n  getImageDeOrientedPoint3D(point) {\n    let planePoint = point;\n    if (typeof this.#viewOrientation !== 'undefined') {\n      // image de-oriented => view oriented\n      const orientedValues = getOrientedArray3D(\n        [\n          point.getX(),\n          point.getY(),\n          point.getZ()\n        ],\n        this.#viewOrientation);\n      planePoint = new Point3D(\n        orientedValues[0],\n        orientedValues[1],\n        orientedValues[2]\n      );\n    }\n    return planePoint;\n  }\n\n  /**\n   * Get a world position from a 2D plane position.\n   *\n   * @param {Point2D} point2D The plane point.\n   * @param {number} k The slice index.\n   * @returns {Point3D} The world position.\n   */\n  getPositionFromPlanePoint(point2D, k) {\n    const planePoint = new Point3D(point2D.getX(), point2D.getY(), k);\n    // de-orient\n    const point = this.getImageOrientedPoint3D(planePoint);\n    // ~indexToWorld to not loose precision\n    return this.#imageGeometry.pointToWorld(point);\n  }\n\n  /**\n   * Get a 2D plane position from a world position.\n   *\n   * @param {Point} point The world position.\n   * @returns {Point3D} The plane point.\n   */\n  getPlanePointFromPosition(point) {\n    const point3D = this.#imageGeometry.worldToPoint(point);\n    return this.getImageDeOrientedPoint3D(point3D);\n  }\n\n  /**\n   * Get the cosines of this plane.\n   *\n   * @returns {number[]} The 2 cosines vectors (3D).\n   */\n  getCosines() {\n    return getCosinesFromOrientation(this.#targetOrientation);\n  }\n\n  /**\n   * Get a list of points that define the plane at input position,\n   *   given this classes orientation.\n   *\n   * @param {Point} position The position.\n   * @returns {Point3D[]} An origin and 2 cosines vectors.\n   */\n  getPlanePoints(position) {\n    // snap to grid\n    const index = this.worldToIndex(position);\n    const snapPosition = this.indexToWorld(index);\n    // get plane point\n    const planePoint = this.getPlanePointFromPosition(snapPosition);\n    // get origin\n    const planeOrigin = this.getPositionFromPlanePoint(\n      new Point2D(0, 0), planePoint.getZ());\n    // find image origin\n    const origins = this.#imageGeometry.getOrigins();\n    const closestOriginIndex = planeOrigin.getClosest(origins);\n    const imageOrigin = origins[closestOriginIndex];\n\n    // use image origin for scroll to cope with\n    // possible irregular slice spacing\n    const pValues = planeOrigin.getValues();\n    const iValues = imageOrigin.getValues();\n    const scrollDimIndex = this.getNativeScrollDimIndex();\n    pValues[scrollDimIndex] = iValues[scrollDimIndex];\n\n    // plane cosines\n    const cosines = this.getCosines();\n\n    return [\n      new Point3D(pValues[0], pValues[1], pValues[2]),\n      new Point3D(cosines[0], cosines[1], cosines[2]),\n      new Point3D(cosines[3], cosines[4], cosines[5])\n    ];\n  }\n\n  /**\n   * Image world to index.\n   *\n   * @param {Point} point The input point.\n   * @returns {Index} The corresponding index.\n   */\n  worldToIndex(point) {\n    return this.#imageGeometry.worldToIndex(point);\n  }\n\n  /**\n   * Image index to world.\n   *\n   * @param {Index} index The input index.\n   * @returns {Point} The corresponding point.\n   */\n  indexToWorld(index) {\n    return this.#imageGeometry.indexToWorld(index);\n  }\n\n  /**\n   * Is this view in the same orientation as the image aquisition.\n   *\n   * @returns {boolean} True if in aquisition plane.\n   */\n  isAquisitionOrientation() {\n    return isIdentityMat33(this.#viewOrientation);\n  }\n\n  /**\n   * Reorder values to follow target orientation.\n   *\n   * @param {Scalar3D} values Values as {x,y,z}.\n   * @returns {Scalar3D} Reoriented values as {x,y,z}.\n   */\n  getTargetOrientedPositiveXYZ(values) {\n    const orientedValues = getOrientedArray3D(\n      [\n        values.x,\n        values.y,\n        values.z\n      ],\n      this.#targetOrientation);\n    return {\n      x: orientedValues[0],\n      y: orientedValues[1],\n      z: orientedValues[2]\n    };\n  }\n\n  /**\n   * Get the (view) scroll dimension index.\n   *\n   * @returns {number} The index.\n   */\n  getScrollDimIndex() {\n    let index = null;\n    if (typeof this.#viewOrientation !== 'undefined') {\n      index = this.#viewOrientation.getThirdColMajorDirection();\n    } else {\n      index = 2;\n    }\n    return index;\n  }\n\n  /**\n   * Get the native (image) scroll dimension index.\n   *\n   * @returns {number} The index.\n   */\n  getNativeScrollDimIndex() {\n    let index = null;\n    if (typeof this.#imageOrientation !== 'undefined') {\n      index = this.#imageOrientation.getThirdColMajorDirection();\n    } else {\n      index = 2;\n    }\n    return index;\n  }\n\n} // class PlaneHelper\n","import {mergeGeometries} from './geometry';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point} from '../math/point';\nimport {Index} from '../math/index';\nimport {View} from './view';\nimport {Geometry} from './geometry';\n/* eslint-enable no-unused-vars */\n\nclass ViewPositionAccessor {\n  /**\n   * @type {View}\n   */\n  #view;\n  /**\n   * @param {View} view The view.\n   */\n  constructor(view) {\n    this.#view = view;\n  }\n  /**\n   * Get the current position.\n   *\n   * @returns {Point} The position.\n   */\n  getCurrentPosition() {\n    return this.#view.getCurrentPosition();\n  }\n  /**\n   * Set the current position.\n   *\n   * @param {Point} position The position.\n   * @param {boolean} [silent] Flag to fire event or not.\n   * @returns {boolean} True if possible and in bounds.\n   */\n  setCurrentPosition(position, silent) {\n    let res = false;\n    if (typeof position !== 'undefined') {\n      res = this.#view.setCurrentPosition(position, silent);\n    }\n    return res;\n  }\n}\n\n/**\n * Position helper.\n */\nexport class PositionHelper {\n\n  /**\n   * @type {ViewPositionAccessor}\n   */\n  #positionAccessor;\n\n  /**\n   * @type {Geometry}\n   */\n  #geometry;\n\n  /**\n   * @type {number}\n   */\n  #scrollDimIndex;\n\n  /**\n   * @param {View} view The associated view.\n   */\n  constructor(view) {\n    this.#positionAccessor = new ViewPositionAccessor(view);\n    this.#geometry = view.getImage().getGeometry();\n    this.#scrollDimIndex = view.getScrollDimIndex();\n  }\n\n  /**\n   * Get the geometry.\n   *\n   * @returns {Geometry} The geometry.\n   */\n  getGeometry() {\n    return this.#geometry;\n  }\n\n  /**\n   * Get the scroll index.\n   *\n   * @returns {number} The scroll index.\n   */\n  getScrollDimIndex() {\n    return this.#scrollDimIndex;\n  }\n\n  /**\n   * Get the maximum dimension value.\n   *\n   * @param {number} dim The dimension.\n   * @returns {number} The maximum value.\n   */\n  getMaximumDimValue(dim) {\n    return this.#geometry.getSize().get(dim) - 1;\n  }\n\n  /**\n   * Get the maximum scroll value.\n   *\n   * @returns {number} The maximum value.\n   */\n  getMaximumScrollValue() {\n    return this.getMaximumDimValue(this.#scrollDimIndex);\n  }\n\n  /**\n   * Get the current position.\n   *\n   * @returns {Point} The current position.\n   */\n  getCurrentPosition() {\n    return this.#positionAccessor.getCurrentPosition();\n  }\n\n  /**\n   * Get the value at dimension index for the current position.\n   *\n   * @param {number} dim The dimension.\n   * @returns {number} The value.\n   */\n  getCurrentPositionDimValue(dim) {\n    return this.getCurrentIndex().get(dim);\n  }\n\n  /**\n   * Get the value at scroll index for the current position.\n   *\n   * @returns {number} The value.\n   */\n  getCurrentPositionScrollValue() {\n    return this.getCurrentPositionDimValue(this.#scrollDimIndex);\n  }\n\n  /**\n   * Get the current position updated at the provided dimension index\n   *   with the input value.\n   *\n   * @param {number} dim The dimension.\n   * @param {number} value The value to used at dimension index.\n   * @returns {Point} The position.\n   */\n  getCurrentPositionAtDimValue(dim, value) {\n    const values = this.getCurrentIndex().getValues();\n    values[dim] = value;\n    return this.#geometry.indexToWorld(new Index(values));\n  }\n\n  /**\n   * Get the current position updated at scroll index with the input value.\n   *\n   * @param {number} value The value to use at scroll index.\n   * @returns {Point} The position.\n   */\n  getCurrentPositionAtScrollValue(value) {\n    return this.getCurrentPositionAtDimValue(this.#scrollDimIndex, value);\n  }\n\n  /**\n   * Get the current index.\n   *\n   * @returns {Index} The current index.\n   */\n  getCurrentIndex() {\n    return this.#geometry.worldToIndex(this.getCurrentPosition());\n  }\n\n  /**\n   * Set the current position.\n   *\n   * @param {Point} position The position.\n   * @param {boolean} [silent] Flag to fire event or not.\n   * @returns {boolean} True if possible and in bounds.\n   */\n  setCurrentPosition(position, silent) {\n    let res = false;\n    if (typeof position !== 'undefined') {\n      res = this.#positionAccessor.setCurrentPosition(position, silent);\n    }\n    return res;\n  }\n\n  /**\n   * Set the current position only if it is in the geometry bounds.\n   *\n   * @param {Point} position The position.\n   * @param {boolean} [silent] Flag to fire event or not.\n   * @returns {boolean} True if possible and in bounds.\n   */\n  setCurrentPositionSafe(position, silent) {\n    let res = false;\n    if (this.isPositionInBounds(position)) {\n      res = this.setCurrentPosition(position, silent);\n    }\n    return res;\n  }\n\n  /**\n   * Merge with another helper.\n   *\n   * @param {PositionHelper} rhs The helper to merge with this one.\n   */\n  merge(rhs) {\n    // check compatibility\n    if (this.#scrollDimIndex !== rhs.getScrollDimIndex()) {\n      throw new Error(\n        'Cannot merge helper of a view with different orientation'\n      );\n    }\n    // merge geometries\n    this.#geometry = mergeGeometries(this.#geometry, rhs.getGeometry());\n  }\n\n  /**\n   * Check if the current position (default) or\n   * the provided position is in bounds.\n   *\n   * @param {Point} position Optional position.\n   * @returns {boolean} True is the position is in bounds.\n   */\n  isPositionInBounds(position) {\n    const index = this.#geometry.worldToIndex(position);\n    const dirs = [this.#scrollDimIndex];\n    if (index.length() === 4) {\n      dirs.push(3);\n    }\n    return this.#geometry.isIndexInBounds(index, dirs);\n  }\n\n  /**\n   * Get the current position incremented in the input direction.\n   *\n   * @param {number} dim The direction in which to increment.\n   * @returns {Point} The resulting point.\n   */\n  getIncrementPosition(dim) {\n    const nextIndex = this.getCurrentIndex().next(dim);\n    return this.#geometry.indexToWorld(nextIndex);\n  }\n\n  /**\n   * Get the current position decremented in the input direction.\n   *\n   * @param {number} dim The direction in which to decrement.\n   * @returns {Point} The resulting point.\n   */\n  getDecrementPosition(dim) {\n    const previousIndex = this.getCurrentIndex().previous(dim);\n    return this.#geometry.indexToWorld(previousIndex);\n  }\n\n  /**\n   * Increment the current position along the provided dim.\n   *\n   * @param {number} dim The direction in which to increment.\n   * @returns {boolean} True if possible and in bounds.\n   */\n  incrementPosition(dim) {\n    return this.setCurrentPositionSafe(this.getIncrementPosition(dim));\n  }\n\n  /**\n   * Decrement the current position along the provided dim.\n   *\n   * @param {number} dim The direction in which to decrement.\n   * @returns {boolean} True if possible and in bounds.\n   */\n  decrementPosition(dim) {\n    return this.setCurrentPositionSafe(this.getDecrementPosition(dim));\n  }\n\n  /**\n   * Increment the current position along the scroll dimension.\n   *\n   * @returns {boolean} True if possible and in bounds.\n   */\n  incrementPositionAlongScroll() {\n    return this.incrementPosition(this.#scrollDimIndex);\n  }\n\n  /**\n   * Decrement the current position along the scroll dimension.\n   *\n   * @returns {boolean} True if possible and in bounds.\n   */\n  decrementPositionAlongScroll() {\n    return this.decrementPosition(this.#scrollDimIndex);\n  }\n\n}","import {Index} from '../math/index';\nimport {Vector3D} from '../math/vector';\nimport {Point3D} from '../math/point';\nimport {isIdentityMat33} from '../math/matrix';\nimport {Size} from '../image/size';\nimport {Spacing} from '../image/spacing';\nimport {Image} from '../image/image';\nimport {Geometry} from '../image/geometry';\nimport {PlaneHelper} from '../image/planeHelper';\nimport {\n  getSliceIterator,\n  getIteratorValues,\n  getRegionSliceIterator,\n  getVariableRegionSliceIterator\n} from '../image/iterator';\nimport {PositionHelper} from '../image/positionHelper';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {View} from '../image/view';\nimport {WindowLevel} from '../image/windowLevel';\nimport {Point, Point2D} from '../math/point';\nimport {Scalar2D} from '../math/scalar';\nimport {Matrix33} from '../math/matrix';\nimport {ViewLayer} from '../gui/viewLayer';\n/* eslint-enable no-unused-vars */\n\n/**\n * View controller.\n */\nexport class ViewController {\n\n  /**\n   * Associated View.\n   *\n   * @type {View}\n   */\n  #view;\n\n  /**\n   * Plane helper.\n   *\n   * @type {PlaneHelper}\n   */\n  #planeHelper;\n\n  /**\n   * Position helper.\n   *\n   * @type {PositionHelper}\n   */\n  #positionHelper;\n\n  /**\n   * Third dimension player ID (created by setInterval).\n   *\n   * @type {number|undefined}\n   */\n  #playerID;\n\n  /**\n   * Is DICOM seg mask flag.\n   *\n   * @type {boolean}\n   */\n  #isMask = false;\n\n  /**\n   * @param {View} view The associated view.\n   */\n  constructor(view) {\n    // check view\n    if (typeof view.getImage() === 'undefined') {\n      throw new Error('View does not have an image, cannot setup controller');\n    }\n\n    this.#view = view;\n\n    // setup the plane helper\n    this.#planeHelper = new PlaneHelper(\n      view.getImage().getGeometry(),\n      view.getOrientation()\n    );\n\n    // position helper\n    this.#positionHelper = new PositionHelper(view);\n\n    // mask segment helper\n    if (view.getImage().getMeta().Modality === 'SEG') {\n      this.#isMask = true;\n    }\n  }\n\n  /**\n   * Get the plane helper.\n   *\n   * @returns {PlaneHelper} The helper.\n   */\n  getPlaneHelper() {\n    return this.#planeHelper;\n  }\n\n  /**\n   * Check is the associated image is a mask.\n   *\n   * @returns {boolean} True if the associated image is a mask.\n   */\n  isMask() {\n    return this.#isMask;\n  }\n\n  /**\n   * Initialise the controller.\n   */\n  initialise() {\n    // set window/level to first preset\n    this.setWindowLevelPresetById(0);\n    // default position\n    this.setCurrentPosition(this.getPositionFromPlanePoint(\n      new Point2D(0, 0)\n    ));\n  }\n\n  /**\n   * Get the image modality.\n   *\n   * @returns {string} The modality.\n   */\n  getModality() {\n    return this.#view.getImage().getMeta().Modality;\n  }\n\n  /**\n   * Get the window/level presets names.\n   *\n   * @returns {string[]} The presets names.\n   */\n  getWindowLevelPresetsNames() {\n    return this.#view.getWindowPresetsNames();\n  }\n\n  /**\n   * Add window/level presets to the view.\n   *\n   * @param {object} presets A preset object.\n   * @returns {object} The list of presets.\n   */\n  addWindowLevelPresets(presets) {\n    return this.#view.addWindowPresets(presets);\n  }\n\n  /**\n   * Set the window level to the preset with the input name.\n   *\n   * @param {string} name The name of the preset to activate.\n   */\n  setWindowLevelPreset(name) {\n    this.#view.setWindowLevelPreset(name);\n  }\n\n  /**\n   * Set the window level to the preset with the input id.\n   *\n   * @param {number} id The id of the preset to activate.\n   */\n  setWindowLevelPresetById(id) {\n    this.#view.setWindowLevelPresetById(id);\n  }\n\n  /**\n   * Check if the controller is playing.\n   *\n   * @returns {boolean} True if the controler is playing.\n   */\n  isPlaying() {\n    return (typeof this.#playerID !== 'undefined');\n  }\n\n  /**\n   * Get the position helper.\n   *\n   * @returns {PositionHelper} The helper.\n   */\n  getPositionHelper() {\n    return this.#positionHelper;\n  }\n\n  /**\n   * Get the current position.\n   *\n   * @returns {Point} The position.\n   */\n  getCurrentPosition() {\n    return this.#positionHelper.getCurrentPosition();\n  }\n\n  /**\n   * Get the current index.\n   *\n   * @returns {Index} The current index.\n   */\n  getCurrentIndex() {\n    return this.#positionHelper.getCurrentIndex();\n  }\n\n  /**\n   * Get the SOP image UID of the current image.\n   *\n   * @returns {string} The UID.\n   */\n  getCurrentImageUid() {\n    return this.#view.getCurrentImageUid();\n  }\n\n  /**\n   * Get the image origin for a image UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {Point3D|undefined} The origin.\n   */\n  getOriginForImageUid(uid) {\n    return this.#view.getOriginForImageUid(uid);\n  }\n\n  /**\n   * Check if the image includes an UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {boolean} True if present.\n   */\n  includesImageUid(uid) {\n    return this.#view.includesImageUid(uid);\n  }\n\n  /**\n   * Get the current oriented index.\n   *\n   * @returns {Index} The index.\n   */\n  getCurrentOrientedIndex() {\n    let res = this.getCurrentIndex();\n    if (typeof this.#view.getOrientation() !== 'undefined') {\n      // view oriented => image de-oriented\n      const vector = this.#planeHelper.getImageDeOrientedVector3D(\n        new Vector3D(res.get(0), res.get(1), res.get(2))\n      );\n      res = new Index([\n        vector.getX(), vector.getY(), vector.getZ()\n      ]);\n    }\n    return res;\n  }\n\n  /**\n   * Get the scroll dimension index.\n   *\n   * @returns {number} The index.\n   */\n  getScrollDimIndex() {\n    return this.#view.getScrollDimIndex();\n  }\n\n  /**\n   * Get the current index scroll value.\n   *\n   * @returns {number} The value.\n   */\n  getCurrentIndexScrollValue() {\n    return this.getCurrentIndex().get(this.#view.getScrollDimIndex());\n  }\n\n  /**\n   * Get the first origin or at a given position.\n   *\n   * @param {Point} [position] Optional position.\n   * @returns {Point3D} The origin.\n   */\n  getOrigin(position) {\n    return this.#view.getOrigin(position);\n  }\n\n  /**\n   * Is this view in the same orientation as the image aquisition.\n   *\n   * @returns {boolean} True if in aquisition plane.\n   */\n  isAquisitionOrientation() {\n    return this.#view.isAquisitionOrientation();\n  }\n\n  /**\n   * Get a list of points that define the plane at input position,\n   *   given this classes orientation.\n   *\n   * @param {Point} position The position.\n   * @returns {Point3D[]} An origin and 2 cosines vectors.\n   */\n  getPlanePoints(position) {\n    return this.#planeHelper.getPlanePoints(position);\n  }\n\n  /**\n   * Get the current scroll position value.\n   *\n   * @returns {number} The value.\n   */\n  getCurrentScrollPosition() {\n    const scrollDimIndex = this.#view.getScrollDimIndex();\n    return this.#view.getCurrentPosition().get(scrollDimIndex);\n  }\n\n  /**\n   * Generate display image data to be given to a canvas.\n   *\n   * @param {ImageData} array The array to fill in.\n   * @param {Index} [index] Optional index at which to generate,\n   *   otherwise generates at current index.\n   */\n  generateImageData(array, index) {\n    this.#view.generateImageData(array, index);\n  }\n\n  /**\n   * Set the associated image.\n   *\n   * @param {Image} img The associated image.\n   */\n  setImage(img) {\n    this.#view.setImage(img);\n  }\n\n  /**\n   * Get the current view (2D) spacing.\n   *\n   * @returns {Scalar2D} The spacing as a 2D array.\n   */\n  get2DSpacing() {\n    const spacing = this.#view.getImage().getGeometry().getSpacing(\n      this.#view.getOrientation());\n    return spacing.get2D();\n  }\n\n  /**\n   * Get the image rescaled value at the input position.\n   *\n   * @param {Point} position The input position.\n   * @returns {number|undefined} The image value or undefined if out of bounds\n   *   or no quantifiable (for ex RGB).\n   */\n  getRescaledImageValue(position) {\n    const image = this.#view.getImage();\n    if (!image.canQuantify()) {\n      return;\n    }\n    const geometry = image.getGeometry();\n    const index = geometry.worldToIndex(position);\n    let value;\n    if (geometry.isIndexInBounds(index)) {\n      value = image.getRescaledValueAtIndex(index);\n    }\n    return value;\n  }\n\n  /**\n   * Get the image pixel unit.\n   *\n   * @returns {string} The unit.\n   */\n  getPixelUnit() {\n    return this.#view.getImage().getMeta().pixelUnit;\n  }\n\n  /**\n   * Extract a slice from an image at the given index and orientation.\n   *\n   * @param {Image} image The image to parse.\n   * @param {Index} index The index at which to get the\n   *   image values.\n   * @param {boolean} isRescaled Flag for rescaled values (default false).\n   * @param {Matrix33} orientation The desired orientation.\n   * @returns {Image} The extracted slice.\n   */\n  #getSlice(image, index, isRescaled, orientation) {\n    // generate slice values\n    const sliceIter = getSliceIterator(\n      image,\n      index,\n      isRescaled,\n      orientation\n    );\n    const sliceValues = getIteratorValues(sliceIter);\n    // oriented geometry\n    const orientedSize = image.getGeometry().getSize(orientation);\n    const sizeValues = orientedSize.getValues();\n    sizeValues[2] = 1;\n    const sliceSize = new Size(sizeValues);\n    const orientedSpacing = image.getGeometry().getSpacing(orientation);\n    const spacingValues = orientedSpacing.getValues();\n    spacingValues[2] = 1;\n    const sliceSpacing = new Spacing(spacingValues);\n    const sliceOrigin = new Point3D(0, 0, 0);\n    const sliceGeometry =\n      new Geometry([sliceOrigin], sliceSize, sliceSpacing);\n    // slice image\n    // @ts-ignore\n    return new Image(sliceGeometry, sliceValues);\n  }\n\n  /**\n   * Get some values from the associated image in a region.\n   *\n   * @param {Point2D} min Minimum point.\n   * @param {Point2D} max Maximum point.\n   * @param {Index} index The index at which to get the\n   *   image values (combined with min/max).\n   * @returns {Array} A list of values.\n   */\n  getImageRegionValues(min, max, index) {\n    let image = this.#view.getImage();\n    const orientation = this.#view.getOrientation();\n    let imageIndex = index;\n    let rescaled = true;\n\n    // create oriented slice if needed\n    if (!isIdentityMat33(orientation)) {\n      image = this.#getSlice(image, imageIndex, rescaled, orientation);\n      // update position\n      imageIndex = new Index([0, 0, 0]);\n      rescaled = false;\n    }\n\n    // get region values\n    const iter = getRegionSliceIterator(\n      image, imageIndex, rescaled, min, max);\n    let values = [];\n    if (iter) {\n      values = getIteratorValues(iter);\n    }\n    return values;\n  }\n\n  /**\n   * Get some values from the associated image in variable regions.\n   *\n   * @param {number[][][]} regions A list of [x, y] pairs (min, max).\n   * @param {Index} index The index at which to get the\n   *   image values (combined with regions min/max).\n   * @returns {Array} A list of values.\n   */\n  getImageVariableRegionValues(regions, index) {\n    let image = this.#view.getImage();\n    const orientation = this.#view.getOrientation();\n    let imageIndex = index;\n    let rescaled = true;\n\n    // create oriented slice if needed\n    if (!isIdentityMat33(orientation)) {\n      image = this.#getSlice(image, imageIndex, rescaled, orientation);\n      // update position\n      imageIndex = new Index([0, 0, 0]);\n      rescaled = false;\n    }\n\n    // get region values\n    const iter = getVariableRegionSliceIterator(\n      image, imageIndex, rescaled, regions);\n    let values = [];\n    if (iter) {\n      values = getIteratorValues(iter);\n    }\n    return values;\n  }\n\n  /**\n   * Can the image values be quantified?\n   *\n   * @returns {boolean} True if possible.\n   */\n  canQuantifyImage() {\n    return this.#view.getImage().canQuantify();\n  }\n\n  /**\n   * Can window and level be applied to the data?\n   *\n   * @returns {boolean} True if possible.\n   * @deprecated Since v0.33, please use isMonochrome instead.\n   */\n  canWindowLevel() {\n    return this.isMonochrome();\n  }\n\n  /**\n   * Is the data monochrome.\n   *\n   * @returns {boolean} True if the data is monochrome.\n   */\n  isMonochrome() {\n    return this.#view.getImage().isMonochrome();\n  }\n\n  /**\n   * Can the data be scrolled?\n   *\n   * @returns {boolean} True if the data has either the third dimension\n   * or above greater than one.\n   */\n  canScroll() {\n    return this.#view.getImage().canScroll(this.#view.getOrientation());\n  }\n\n  /**\n   * Get the oriented image size.\n   *\n   * @returns {Size} The size.\n   */\n  getImageSize() {\n    return this.#view.getImage().getGeometry().getSize(\n      this.#view.getOrientation());\n  }\n\n\n  /**\n   * Is the data size larger than one in the given dimension?\n   *\n   * @param {number} dim The dimension.\n   * @returns {boolean} True if the image size is larger than one\n   *   in the given dimension.\n   */\n  moreThanOne(dim) {\n    return this.getImageSize().moreThanOne(dim);\n  }\n\n  /**\n   * Get the image world (mm) 2D size.\n   *\n   * @returns {Scalar2D} The 2D size as {x,y}.\n   */\n  getImageWorldSize() {\n    const geometry = this.#view.getImage().getGeometry();\n    const size = geometry.getSize(this.#view.getOrientation()).get2D();\n    const spacing = geometry.getSpacing(this.#view.getOrientation()).get2D();\n    return {\n      x: size.x * spacing.x,\n      y: size.y * spacing.y\n    };\n  }\n\n  /**\n   * Get the image rescaled data range.\n   *\n   * @returns {object} The range as {min, max}.\n   */\n  getImageRescaledDataRange() {\n    return this.#view.getImage().getRescaledDataRange();\n  }\n\n  /**\n   * Compare the input meta data to the associated image one.\n   *\n   * @param {object} meta The meta data.\n   * @returns {boolean} True if the associated image has equal meta data.\n   */\n  equalImageMeta(meta) {\n    const imageMeta = this.#view.getImage().getMeta();\n    // loop through input meta keys\n    const metaKeys = Object.keys(meta);\n    for (let i = 0; i < metaKeys.length; ++i) {\n      const metaKey = metaKeys[i];\n      if (typeof imageMeta[metaKey] === 'undefined') {\n        return false;\n      }\n      if (imageMeta[metaKey] !== meta[metaKey]) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  /**\n   * Check if the current position (default) or\n   * the provided position is in bounds.\n   *\n   * @param {Point} [position] Optional position.\n   * @returns {boolean} True is the position is in bounds.\n   */\n  isPositionInBounds(position) {\n    return this.#view.isPositionInBounds(position);\n  }\n\n  /**\n   * Set the current position.\n   *\n   * @param {Point} pos The position.\n   * @param {boolean} [silent] If true, does not fire a\n   *   positionchange event.\n   * @returns {boolean} False if not in bounds.\n   */\n  setCurrentPosition(pos, silent) {\n    return this.#view.setCurrentPosition(pos, silent);\n  }\n\n  /**\n   * Get a world position from a 2D plane position.\n   *\n   * @param {Point2D} point2D The input point.\n   * @param {number} [k] Optional slice index,\n   *   if undefined, uses the current one.\n   * @returns {Point} The associated position.\n   */\n  getPositionFromPlanePoint(point2D, k) {\n    // keep third direction\n    if (typeof k === 'undefined') {\n      k = this.getCurrentIndexScrollValue();\n    }\n    const planePoint = new Point3D(point2D.getX(), point2D.getY(), k);\n    // de-orient\n    const point = this.#planeHelper.getImageOrientedPoint3D(planePoint);\n    // ~indexToWorld to not loose precision\n    const geometry = this.#view.getImage().getGeometry();\n    const point3D = geometry.pointToWorld(point);\n    // merge with current position to keep extra dimensions\n    return this.getCurrentPosition().mergeWith3D(point3D);\n  }\n\n  /**\n   * Get a 2D plane position from a world position.\n   *\n   * @param {Point} point The 3D position.\n   * @returns {Point2D} The 2D position.\n   */\n  getPlanePositionFromPosition(point) {\n    // orient\n    const geometry = this.#view.getImage().getGeometry();\n    // ~worldToIndex to not loose precision\n    const point3D = geometry.worldToPoint(point);\n    const planePoint = this.#planeHelper.getImageDeOrientedPoint3D(point3D);\n    // return\n    return new Point2D(\n      planePoint.getX(),\n      planePoint.getY(),\n    );\n  }\n\n  /**\n   * Get the index of a world position.\n   *\n   * @param {Point} point The 3D position.\n   * @returns {Index} The index.\n   */\n  getIndexFromPosition(point) {\n    // orient\n    const geometry = this.#view.getImage().getGeometry();\n    // ~worldToIndex to not loose precision\n    return geometry.worldToIndex(point);\n  }\n\n  /**\n   * Set the current index.\n   *\n   * @param {Index} index The index.\n   * @param {boolean} [silent] If true, does not fire a positionchange event.\n   * @returns {boolean} False if not in bounds.\n   */\n  setCurrentIndex(index, silent) {\n    return this.#view.setCurrentIndex(index, silent);\n  }\n\n  /**\n   * Get a plane 3D position from a plane 2D position: does not compensate\n   *   for the image origin. Needed for setting the scale center...\n   *\n   * @param {Point2D} point2D The 2D position.\n   * @returns {Point3D} The 3D point.\n   */\n  getPlanePositionFromPlanePoint(point2D) {\n    // keep third direction\n    const k = this.getCurrentIndexScrollValue();\n    const planePoint = new Point3D(point2D.getX(), point2D.getY(), k);\n    // de-orient\n    const point = this.#planeHelper.getTargetDeOrientedPoint3D(planePoint);\n    // ~indexToWorld to not loose precision\n    const geometry = this.#view.getImage().getGeometry();\n    const spacing = geometry.getRealSpacing();\n    return new Point3D(\n      point.getX() * spacing.get(0),\n      point.getY() * spacing.get(1),\n      point.getZ() * spacing.get(2));\n  }\n\n  /**\n   * Get a 3D offset from a plane one.\n   *\n   * @param {Scalar2D} offset2D The plane offset as {x,y}.\n   * @returns {Vector3D} The 3D world offset.\n   */\n  getOffset3DFromPlaneOffset(offset2D) {\n    return this.#planeHelper.getOffset3DFromPlaneOffset(offset2D);\n  }\n\n  /**\n   * Scroll play: loop through all slices.\n   */\n  play() {\n    // ensure data is scrollable: dim >= 3\n    if (!this.canScroll()) {\n      return;\n    }\n    if (typeof this.#playerID === 'undefined') {\n      const image = this.#view.getImage();\n      const recommendedDisplayFrameRate =\n        image.getMeta().RecommendedDisplayFrameRate;\n      const milliseconds = this.#view.getPlaybackMilliseconds(\n        recommendedDisplayFrameRate);\n      const size = image.getGeometry().getSize();\n      const canScroll3D = size.canScroll3D();\n\n      this.#playerID = window.setInterval(() => {\n        let canDoMore = false;\n        if (canScroll3D) {\n          canDoMore = this.#positionHelper.incrementPositionAlongScroll();\n        } else {\n          canDoMore = this.#positionHelper.incrementPosition(3);\n        }\n        // end of scroll, loop back\n        if (!canDoMore) {\n          const pos1 = this.getCurrentIndex();\n          const values = pos1.getValues();\n          const orientation = this.#view.getOrientation();\n          if (canScroll3D) {\n            values[orientation.getThirdColMajorDirection()] = 0;\n          } else {\n            values[3] = 0;\n          }\n          const index = new Index(values);\n          const geometry = this.#view.getImage().getGeometry();\n          this.setCurrentPosition(geometry.indexToWorld(index));\n        }\n      }, milliseconds);\n    } else {\n      this.stop();\n    }\n  }\n\n  /**\n   * Stop scroll playing.\n   */\n  stop() {\n    if (typeof this.#playerID !== 'undefined') {\n      clearInterval(this.#playerID);\n      this.#playerID = undefined;\n    }\n  }\n\n  /**\n   * Get the window/level.\n   *\n   * @returns {WindowLevel} The window and level.\n   */\n  getWindowLevel() {\n    return this.#view.getWindowLevel();\n  }\n\n  /**\n   * Get the current window level preset name.\n   *\n   * @returns {string} The preset name.\n   */\n  getCurrentWindowPresetName() {\n    return this.#view.getCurrentWindowPresetName();\n  }\n\n  /**\n   * Set the window and level.\n   *\n   * @param {WindowLevel} wl The window and level.\n   */\n  setWindowLevel(wl) {\n    this.#view.setWindowLevel(wl);\n  }\n\n  /**\n   * Get the colour map.\n   *\n   * @returns {string} The colour map name.\n   */\n  getColourMap() {\n    return this.#view.getColourMap();\n  }\n\n  /**\n   * Set the colour map.\n   *\n   * @param {string} name The colour map name.\n   */\n  setColourMap(name) {\n    this.#view.setColourMap(name);\n  }\n\n  /**\n   * @callback alphaFn\n   * @param {number[]|number} value The pixel value.\n   * @param {number} index The values' index.\n   * @returns {number} The opacity of the input value.\n   */\n\n  /**\n   * Set the view per value alpha function.\n   *\n   * @param {alphaFn} func The function.\n   */\n  setViewAlphaFunction(func) {\n    this.#view.setAlphaFunction(func);\n  }\n\n  /**\n   * Bind the view image to the provided layer.\n   *\n   * @param {ViewLayer} viewLayer The layer to bind.\n   */\n  bindImageAndLayer(viewLayer) {\n    const image = this.#view.getImage();\n    image.addEventListener('imagecontentchange',\n      viewLayer.onimagecontentchange\n    );\n    image.addEventListener('imagegeometrychange',\n      viewLayer.onimagegeometrychange\n    );\n  }\n\n  /**\n   * Unbind the view image to the provided layer.\n   *\n   * @param {ViewLayer} viewLayer The layer to bind.\n   */\n  unbindImageAndLayer(viewLayer) {\n    const image = this.#view.getImage();\n    image.removeEventListener('imagecontentchange',\n      viewLayer.onimagecontentchange\n    );\n    image.removeEventListener('imagegeometrychange',\n      viewLayer.onimagegeometrychange\n    );\n  }\n\n} // class ViewController\n","import {logger} from '../utils/logger';\nimport {Point2D} from '../math/point';\n\n/**\n * List of interaction event names.\n */\nexport const InteractionEventNames = [\n  'mousedown',\n  'mousemove',\n  'mouseup',\n  'mouseout',\n  'wheel',\n  'dblclick',\n  'touchstart',\n  'touchmove',\n  'touchend'\n];\n\n/**\n * Get the positions (without the parent offset) of a list of touch events.\n *\n * @param {Array} touches The list of touch events.\n * @returns {Point2D[]} The list of positions of the touch events.\n */\nfunction getTouchesPositions(touches) {\n  // get the touch offset from all its parents\n  let offsetLeft = 0;\n  let offsetTop = 0;\n  if (touches.length !== 0 &&\n    typeof touches[0].target !== 'undefined') {\n    let offsetParent = touches[0].target.offsetParent;\n    while (offsetParent) {\n      if (!isNaN(offsetParent.offsetLeft)) {\n        offsetLeft += offsetParent.offsetLeft;\n      }\n      if (!isNaN(offsetParent.offsetTop)) {\n        offsetTop += offsetParent.offsetTop;\n      }\n      offsetParent = offsetParent.offsetParent;\n    }\n  } else {\n    logger.debug('No touch target offset parent.');\n  }\n  // set its position\n  const positions = [];\n  for (let i = 0; i < touches.length; ++i) {\n    positions.push(new Point2D(\n      touches[i].pageX - offsetLeft,\n      touches[i].pageY - offsetTop\n    ));\n  }\n  return positions;\n}\n\n/**\n * Get the offsets of an input touch event.\n *\n * @param {object} event The event to get the offset from.\n * @returns {Point2D[]} The array of points.\n */\nexport function getTouchPoints(event) {\n  let positions = [];\n  if (typeof event.targetTouches !== 'undefined' &&\n    event.targetTouches.length !== 0) {\n    // see https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/targetTouches\n    positions = getTouchesPositions(event.targetTouches);\n  } else if (typeof event.changedTouches !== 'undefined' &&\n    event.changedTouches.length !== 0) {\n    // see https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/changedTouches\n    positions = getTouchesPositions(event.changedTouches);\n  }\n  return positions;\n}\n\n/**\n * Get the offset of an input mouse event.\n *\n * @param {object} event The event to get the offset from.\n * @returns {Point2D} The 2D point.\n */\nexport function getMousePoint(event) {\n  // offsetX/Y: the offset in the X coordinate of the mouse pointer\n  // between that event and the padding edge of the target node\n  // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/offsetX\n  // https://caniuse.com/mdn-api_mouseevent_offsetx\n  return new Point2D(\n    event.offsetX,\n    event.offsetY\n  );\n}\n\n/**\n * Test if a canvas with the input size can be created.\n *\n * Ref:\n * - {@link https://github.com/ivmartel/dwv/issues/902},\n * - {@link https://github.com/jhildenbiddle/canvas-size/blob/v1.2.4/src/canvas-test.js}.\n *\n * @param {number} width The canvas width.\n * @param {number} height The canvas height.\n * @returns {boolean} True is the canvas can be created.\n */\nexport function canCreateCanvas(width, height) {\n  // test canvas with input size\n  const testCvs = document.createElement('canvas');\n  testCvs.width = width;\n  testCvs.height = height;\n  // crop canvas to speed up test\n  const cropCvs = document.createElement('canvas');\n  cropCvs.width = 1;\n  cropCvs.height = 1;\n  // contexts\n  const testCtx = testCvs.getContext('2d');\n  const cropCtx = cropCvs.getContext('2d');\n  // set data\n  if (testCtx) {\n    testCtx.fillRect(width - 1, height - 1, 1, 1);\n    // Render the test pixel in the bottom-right corner of the\n    // test canvas in the top-left of the 1x1 crop canvas. This\n    // dramatically reducing the time for getImageData to complete.\n    cropCtx.drawImage(testCvs, width - 1, height - 1, 1, 1, 0, 0, 1, 1);\n  }\n  // Verify image data (alpha component, Pass = 255, Fail = 0)\n  return cropCtx && cropCtx.getImageData(0, 0, 1, 1).data[3] !== 0;\n}\n","import {Index} from '../math/index';\nimport {ListenerHandler} from '../utils/listen';\nimport {viewEventNames} from '../image/view';\nimport {ViewController} from '../app/viewController';\nimport {Point2D} from '../math/point';\nimport {\n  canCreateCanvas,\n  InteractionEventNames\n} from './generic';\nimport {getScaledOffset} from './layerGroup';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Vector3D} from '../math/vector';\nimport {Point, Point3D} from '../math/point';\nimport {Scalar2D, Scalar3D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * View layer.\n */\nexport class ViewLayer {\n\n  /**\n   * Container div.\n   *\n   * @type {HTMLElement}\n   */\n  #containerDiv;\n\n  /**\n   * The view controller.\n   *\n   * @type {ViewController}\n   */\n  #viewController = null;\n\n  /**\n   * The main display canvas.\n   *\n   * @type {object}\n   */\n  #canvas = null;\n\n  /**\n   * The offscreen canvas: used to store the raw, unscaled pixel data.\n   *\n   * @type {object}\n   */\n  #offscreenCanvas = null;\n\n  /**\n   * The associated CanvasRenderingContext2D.\n   *\n   * @type {object}\n   */\n  #context = null;\n\n  /**\n   * Flag to know if the current position is valid.\n   *\n   * @type {boolean}\n   */\n  #isValidPosition = true;\n\n  /**\n   * The image data array.\n   *\n   * @type {ImageData}\n   */\n  #imageData = null;\n\n  /**\n   * The layer base size as {x,y}.\n   *\n   * @type {Scalar2D}\n   */\n  #baseSize;\n\n  /**\n   * The layer base spacing as {x,y}.\n   *\n   * @type {Scalar2D}\n   */\n  #baseSpacing;\n\n  /**\n   * The layer opacity.\n   *\n   * @type {number}\n   */\n  #opacity = 1;\n\n  /**\n   * The layer scale.\n   *\n   * @type {Scalar2D}\n   */\n  #scale = {x: 1, y: 1};\n\n  /**\n   * The layer fit scale.\n   *\n   * @type {Scalar2D}\n   */\n  #fitScale = {x: 1, y: 1};\n\n  /**\n   * The layer flip scale.\n   *\n   * @type {Scalar3D}\n   */\n  #flipScale = {x: 1, y: 1, z: 1};\n\n  /**\n   * The layer offset.\n   *\n   * @type {Scalar2D}\n   */\n  #offset = {x: 0, y: 0};\n\n  /**\n   * The base layer offset.\n   *\n   * @type {Scalar2D}\n   */\n  #baseOffset = {x: 0, y: 0};\n\n  /**\n   * The view offset.\n   *\n   * @type {Scalar2D}\n   */\n  #viewOffset = {x: 0, y: 0};\n\n  /**\n   * The zoom offset.\n   *\n   * @type {Scalar2D}\n   */\n  #zoomOffset = {x: 0, y: 0};\n\n  /**\n   * The flip offset.\n   *\n   * @type {Scalar2D}\n   */\n  #flipOffset = {x: 0, y: 0};\n\n  /**\n   * Data update flag.\n   *\n   * @type {boolean}\n   */\n  #needsDataUpdate = null;\n\n  /**\n   * The associated data id.\n   *\n   * @type {string}\n   */\n  #dataId;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Image smoothing flag.\n   *\n   * See: {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingEnabled}.\n   *\n   * @type {boolean}\n   */\n  #imageSmoothing = false;\n\n  /**\n   * Layer group origin.\n   *\n   * @type {Point3D}\n   */\n  #layerGroupOrigin;\n\n  /**\n   * Layer group first origin.\n   *\n   * @type {Point3D}\n   */\n  #layerGroupOrigin0;\n\n  /**\n   * @param {HTMLElement} containerDiv The layer div, its id will be used\n   *   as this layer id.\n   */\n  constructor(containerDiv) {\n    this.#containerDiv = containerDiv;\n    // specific css class name\n    this.#containerDiv.className += ' viewLayer';\n  }\n\n  /**\n   * Get the associated data id.\n   *\n   * @returns {string} The data id.\n   */\n  getDataId() {\n    return this.#dataId;\n  }\n\n  /**\n   * Get the layer scale.\n   *\n   * @returns {Scalar2D} The scale as {x,y}.\n   */\n  getScale() {\n    return this.#scale;\n  }\n\n  /**\n   * Get the layer zoom offset without the fit scale.\n   *\n   * @returns {Scalar2D} The offset as {x,y}.\n   */\n  getAbsoluteZoomOffset() {\n    return {\n      x: this.#zoomOffset.x * this.#fitScale.x,\n      y: this.#zoomOffset.y * this.#fitScale.y\n    };\n  }\n\n  /**\n   * Set the imageSmoothing flag value.\n   *\n   * @param {boolean} flag True to enable smoothing.\n   */\n  setImageSmoothing(flag) {\n    this.#imageSmoothing = flag;\n  }\n\n  /**\n   * Set the associated view.\n   *\n   * @param {object} view The view.\n   * @param {string} dataId The associated data id.\n   */\n  setView(view, dataId) {\n    this.#dataId = dataId;\n    // local listeners\n    view.addEventListener('wlchange', this.#onWLChange);\n    view.addEventListener('colourmapchange', this.#onColourMapChange);\n    view.addEventListener('positionchange', this.#onPositionChange);\n    view.addEventListener('alphafuncchange', this.#onAlphaFuncChange);\n    // view events\n    for (let j = 0; j < viewEventNames.length; ++j) {\n      view.addEventListener(viewEventNames[j], this.#fireEvent);\n    }\n    // create view controller\n    this.#viewController = new ViewController(view);\n    // bind layer and image\n    this.bindImage();\n  }\n\n  /**\n   * Get the view controller.\n   *\n   * @returns {ViewController} The controller.\n   */\n  getViewController() {\n    return this.#viewController;\n  }\n\n  /**\n   * Get the canvas image data.\n   *\n   * @returns {object} The image data.\n   */\n  getImageData() {\n    return this.#imageData;\n  }\n\n  /**\n   * Handle an image set event.\n   *\n   * @param {object} event The event.\n   * @function\n   */\n  onimageset = (event) => {\n    // event.value = [index, image]\n    if (this.#dataId === event.dataid) {\n      this.#viewController.setImage(event.value[0]);\n      this.#setBaseSize(this.#viewController.getImageSize().get2D());\n      this.#needsDataUpdate = true;\n    }\n  };\n\n  /**\n   * Bind this layer to the view image.\n   */\n  bindImage() {\n    if (this.#viewController) {\n      this.#viewController.bindImageAndLayer(this);\n    }\n  }\n\n  /**\n   * Unbind this layer to the view image.\n   */\n  unbindImage() {\n    if (this.#viewController) {\n      this.#viewController.unbindImageAndLayer(this);\n    }\n  }\n\n  /**\n   * Handle an image content change event.\n   *\n   * @param {object} event The event.\n   * @function\n   */\n  onimagecontentchange = (event) => {\n    // event.value = [index]\n    if (this.#dataId === event.dataid) {\n      this.#isValidPosition = this.#viewController.isPositionInBounds();\n      // flag update and draw\n      this.#needsDataUpdate = true;\n      this.draw();\n    }\n  };\n\n  /**\n   * Handle an image change event.\n   *\n   * @param {object} event The event.\n   * @function\n   */\n  onimagegeometrychange = (event) => {\n    // event.value = [index]\n    if (this.#dataId === event.dataid) {\n      const vcSize = this.#viewController.getImageSize().get2D();\n      if (this.#baseSize.x !== vcSize.x ||\n        this.#baseSize.y !== vcSize.y) {\n        // size changed, recalculate base offset\n        // in case origin changed\n        if (typeof this.#layerGroupOrigin !== 'undefined' &&\n          typeof this.#layerGroupOrigin0 !== 'undefined') {\n          const origin0 = this.#viewController.getOrigin();\n          const scrollOffset = this.#layerGroupOrigin0.minus(origin0);\n          const origin = this.#viewController.getOrigin(\n            this.#viewController.getCurrentPosition()\n          );\n          const planeOffset = this.#layerGroupOrigin.minus(origin);\n          this.setBaseOffset(scrollOffset, planeOffset);\n        }\n        // update base size\n        this.#setBaseSize(vcSize);\n        // flag update and draw\n        this.#needsDataUpdate = true;\n        this.draw();\n      }\n    }\n  };\n\n  // common layer methods [start] ---------------\n\n  /**\n   * Get the id of the layer.\n   *\n   * @returns {string} The string id.\n   */\n  getId() {\n    return this.#containerDiv.id;\n  }\n\n  /**\n   * Remove the HTML element from the DOM.\n   */\n  removeFromDOM() {\n    this.#containerDiv.remove();\n  }\n\n  /**\n   * Get the layer base size (without scale).\n   *\n   * @returns {Scalar2D} The size as {x,y}.\n   */\n  getBaseSize() {\n    return this.#baseSize;\n  }\n\n  /**\n   * Get the image world (mm) 2D size.\n   *\n   * @returns {Scalar2D} The 2D size as {x,y}.\n   */\n  getImageWorldSize() {\n    return this.#viewController.getImageWorldSize();\n  }\n\n  /**\n   * Get the layer opacity.\n   *\n   * @returns {number} The opacity ([0:1] range).\n   */\n  getOpacity() {\n    return this.#opacity;\n  }\n\n  /**\n   * Set the layer opacity.\n   *\n   * @param {number} alpha The opacity ([0:1] range).\n   */\n  setOpacity(alpha) {\n    if (alpha === this.#opacity) {\n      return;\n    }\n\n    this.#opacity = Math.min(Math.max(alpha, 0), 1);\n\n    /**\n     * Opacity change event.\n     *\n     * @event App#opacitychange\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    const event = {\n      type: 'opacitychange',\n      value: [this.#opacity]\n    };\n    this.#fireEvent(event);\n  }\n\n  /**\n   * Add a flip offset along the layer X axis.\n   */\n  addFlipOffsetX() {\n    this.#flipOffset.x += this.#canvas.width / this.#scale.x;\n    this.#offset.x += this.#flipOffset.x;\n  }\n\n  /**\n   * Add a flip offset along the layer Y axis.\n   */\n  addFlipOffsetY() {\n    this.#flipOffset.y += this.#canvas.height / this.#scale.y;\n    this.#offset.y += this.#flipOffset.y;\n  }\n\n  /**\n   * Flip the scale along the layer X axis.\n   */\n  flipScaleX() {\n    this.#flipScale.x *= -1;\n  }\n\n  /**\n   * Flip the scale along the layer Y axis.\n   */\n  flipScaleY() {\n    this.#flipScale.y *= -1;\n  }\n\n  /**\n   * Flip the scale along the layer Z axis.\n   */\n  flipScaleZ() {\n    this.#flipScale.z *= -1;\n  }\n\n  /**\n   * Set the layer scale.\n   *\n   * @param {Scalar3D} newScale The scale as {x,y,z}.\n   * @param {Point3D} [center] The scale center.\n   */\n  setScale(newScale, center) {\n    const helper = this.#viewController.getPlaneHelper();\n    const orientedNewScale = helper.getTargetOrientedPositiveXYZ({\n      x: newScale.x * this.#flipScale.x,\n      y: newScale.y * this.#flipScale.y,\n      z: newScale.z * this.#flipScale.z,\n    });\n    const finalNewScale = {\n      x: this.#fitScale.x * orientedNewScale.x,\n      y: this.#fitScale.y * orientedNewScale.y\n    };\n\n    if (Math.abs(newScale.x) === 1 &&\n      Math.abs(newScale.y) === 1 &&\n      Math.abs(newScale.z) === 1) {\n      // reset zoom offset for scale=1\n      const resetOffset = {\n        x: this.#offset.x - this.#zoomOffset.x,\n        y: this.#offset.y - this.#zoomOffset.y\n      };\n      // store new offset\n      this.#zoomOffset = {x: 0, y: 0};\n      this.#offset = resetOffset;\n    } else {\n      if (typeof center !== 'undefined') {\n        let worldCenter = helper.getPlaneOffsetFromOffset3D({\n          x: center.getX(),\n          y: center.getY(),\n          z: center.getZ()\n        });\n        // center was obtained with viewLayer.displayToMainPlanePos\n        // compensated for baseOffset\n        // TODO: justify...\n        worldCenter = {\n          x: worldCenter.x + this.#baseOffset.x,\n          y: worldCenter.y + this.#baseOffset.y\n        };\n\n        const newOffset = getScaledOffset(\n          this.#offset, this.#scale, finalNewScale, worldCenter);\n\n        const newZoomOffset = {\n          x: this.#zoomOffset.x + newOffset.x - this.#offset.x,\n          y: this.#zoomOffset.y + newOffset.y - this.#offset.y\n        };\n        // store new offset\n        this.#zoomOffset = newZoomOffset;\n        this.#offset = newOffset;\n      }\n    }\n\n    // store new scale\n    this.#scale = finalNewScale;\n  }\n\n  /**\n   * Initialise the layer scale.\n   *\n   * @param {Scalar3D} newScale The scale as {x,y,z}.\n   * @param {Scalar2D} absoluteZoomOffset The zoom offset as {x,y}\n   *   without the fit scale (as provided by getAbsoluteZoomOffset).\n   */\n  initScale(newScale, absoluteZoomOffset) {\n    const helper = this.#viewController.getPlaneHelper();\n    const orientedNewScale = helper.getTargetOrientedPositiveXYZ({\n      x: newScale.x * this.#flipScale.x,\n      y: newScale.y * this.#flipScale.y,\n      z: newScale.z * this.#flipScale.z,\n    });\n    const finalNewScale = {\n      x: this.#fitScale.x * orientedNewScale.x,\n      y: this.#fitScale.y * orientedNewScale.y\n    };\n    this.#scale = finalNewScale;\n\n    this.#zoomOffset = {\n      x: absoluteZoomOffset.x / this.#fitScale.x,\n      y: absoluteZoomOffset.y / this.#fitScale.y\n    };\n    this.#offset = {\n      x: this.#offset.x + this.#zoomOffset.x,\n      y: this.#offset.y + this.#zoomOffset.y\n    };\n  }\n\n  /**\n   * Set the base layer offset. Updates the layer offset.\n   *\n   * @param {Vector3D} scrollOffset The scroll offset vector.\n   * @param {Vector3D} planeOffset The plane offset vector.\n   * @param {Point3D} [layerGroupOrigin] The layer group origin.\n   * @param {Point3D} [layerGroupOrigin0] The layer group first origin.\n   * @returns {boolean} True if the offset was updated.\n   */\n  setBaseOffset(\n    scrollOffset, planeOffset,\n    layerGroupOrigin, layerGroupOrigin0) {\n    const helper = this.#viewController.getPlaneHelper();\n    const scrollDimIndex = helper.getNativeScrollDimIndex();\n    const newOffset = helper.getPlaneOffsetFromOffset3D({\n      x: scrollDimIndex === 0 ? scrollOffset.getX() : planeOffset.getX(),\n      y: scrollDimIndex === 1 ? scrollOffset.getY() : planeOffset.getY(),\n      z: scrollDimIndex === 2 ? scrollOffset.getZ() : planeOffset.getZ(),\n    });\n    const needsUpdate = this.#baseOffset.x !== newOffset.x ||\n      this.#baseOffset.y !== newOffset.y;\n    // store layer group origins\n    if (typeof layerGroupOrigin !== 'undefined' &&\n      typeof layerGroupOrigin0 !== 'undefined') {\n      this.#layerGroupOrigin = layerGroupOrigin;\n      this.#layerGroupOrigin0 = layerGroupOrigin0;\n    }\n    // reset offset if needed\n    if (needsUpdate) {\n      this.#offset = {\n        x: this.#offset.x - this.#baseOffset.x + newOffset.x,\n        y: this.#offset.y - this.#baseOffset.y + newOffset.y\n      };\n      this.#baseOffset = newOffset;\n    }\n    return needsUpdate;\n  }\n\n  /**\n   * Set the layer offset.\n   *\n   * @param {Scalar3D} newOffset The offset as {x,y,z}.\n   */\n  setOffset(newOffset) {\n    const helper = this.#viewController.getPlaneHelper();\n    const planeNewOffset = helper.getPlaneOffsetFromOffset3D(newOffset);\n    this.#offset = {\n      x: planeNewOffset.x +\n        this.#viewOffset.x +\n        this.#baseOffset.x +\n        this.#zoomOffset.x +\n        this.#flipOffset.x,\n      y: planeNewOffset.y +\n        this.#viewOffset.y +\n        this.#baseOffset.y +\n        this.#zoomOffset.y +\n        this.#flipOffset.y\n    };\n  }\n\n  /**\n   * Transform a display position to a 2D index.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {Index} The equivalent 2D index.\n   */\n  displayToPlaneIndex(point2D) {\n    const planePos = this.displayToPlanePos(point2D);\n    return new Index([\n      Math.floor(planePos.getX()),\n      Math.floor(planePos.getY())\n    ]);\n  }\n\n  /**\n   * Remove scale from a display position.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {Point2D} The de-scaled point.\n   */\n  displayToPlaneScale(point2D) {\n    return new Point2D(\n      point2D.getX() / this.#scale.x,\n      point2D.getY() / this.#scale.y\n    );\n  }\n\n  /**\n   * Get a plane position from a display position.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {Point2D} The plane position.\n   */\n  displayToPlanePos(point2D) {\n    const deScaled = this.displayToPlaneScale(point2D);\n    return new Point2D(\n      deScaled.getX() + this.#offset.x,\n      deScaled.getY() + this.#offset.y\n    );\n  }\n\n  /**\n   * Get a display position from a plane position.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {Point2D} The display position, can be individually\n   *   undefined if out of bounds.\n   */\n  planePosToDisplay(point2D) {\n    let posX =\n      (point2D.getX() - this.#offset.x + this.#baseOffset.x) * this.#scale.x;\n    let posY =\n      (point2D.getY() - this.#offset.y + this.#baseOffset.y) * this.#scale.y;\n    // check if in bounds\n    if (posX < 0 || posX >= this.#canvas.width) {\n      posX = undefined;\n    }\n    if (posY < 0 || posY >= this.#canvas.height) {\n      posY = undefined;\n    }\n    return new Point2D(posX, posY);\n  }\n\n  /**\n   * Get a main plane position from a display position.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {Point2D} The main plane position.\n   */\n  displayToMainPlanePos(point2D) {\n    const planePos = this.displayToPlanePos(point2D);\n    return new Point2D(\n      planePos.getX() - this.#baseOffset.x,\n      planePos.getY() - this.#baseOffset.y\n    );\n  }\n\n  /**\n   * Display the layer.\n   *\n   * @param {boolean} flag Whether to display the layer or not.\n   */\n  display(flag) {\n    this.#containerDiv.style.display = flag ? '' : 'none';\n  }\n\n  /**\n   * Check if the layer is visible.\n   *\n   * @returns {boolean} True if the layer is visible.\n   */\n  isVisible() {\n    return this.#containerDiv.style.display === '';\n  }\n\n  /**\n   * Draw the content (imageData) of the layer.\n   * The imageData variable needs to be set.\n   *\n   * @fires App#renderstart\n   * @fires App#renderend\n   */\n  draw() {\n    // skip for non valid position\n    if (!this.#isValidPosition) {\n      return;\n    }\n\n    /**\n     * Render start event.\n     *\n     * @event App#renderstart\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    let event = {\n      type: 'renderstart',\n      layerid: this.getId(),\n      dataid: this.getDataId()\n    };\n    this.#fireEvent(event);\n\n    // update data if needed\n    if (this.#needsDataUpdate) {\n      this.#updateImageData();\n    }\n\n    // context opacity\n    this.#context.globalAlpha = this.#opacity;\n\n    // clear context\n    this.clear();\n\n    // draw the cached canvas on the context\n    // transform takes as input a, b, c, d, e, f to create\n    // the transform matrix (column-major order):\n    // [ a c e ]\n    // [ b d f ]\n    // [ 0 0 1 ]\n    this.#context.setTransform(\n      this.#scale.x,\n      0,\n      0,\n      this.#scale.y,\n      -1 * this.#offset.x * this.#scale.x,\n      -1 * this.#offset.y * this.#scale.y\n    );\n\n    // disable smoothing (set just before draw, could be reset by resize)\n    this.#context.imageSmoothingEnabled = this.#imageSmoothing;\n    // draw image\n    this.#context.drawImage(this.#offscreenCanvas, 0, 0);\n\n    /**\n     * Render end event.\n     *\n     * @event App#renderend\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    event = {\n      type: 'renderend',\n      layerid: this.getId(),\n      dataid: this.getDataId()\n    };\n    this.#fireEvent(event);\n  }\n\n  /**\n   * Initialise the layer: set the canvas and context.\n   *\n   * @param {Scalar2D} size The image size as {x,y}.\n   * @param {Scalar2D} spacing The image spacing as {x,y}.\n   * @param {number} alpha The initial data opacity.\n   */\n  initialise(size, spacing, alpha) {\n    // set locals\n    this.#baseSpacing = spacing;\n    this.#opacity = Math.min(Math.max(alpha, 0), 1);\n\n    // create canvas\n    // (canvas size is set in fitToContainer)\n    this.#canvas = document.createElement('canvas');\n    this.#containerDiv.appendChild(this.#canvas);\n\n    // check that the getContext method exists\n    if (!this.#canvas.getContext) {\n      alert('Error: no canvas.getContext method.');\n      return;\n    }\n    // get the 2D context\n    this.#context = this.#canvas.getContext('2d');\n    if (!this.#context) {\n      alert('Error: failed to get the 2D context.');\n      return;\n    }\n\n    // off screen canvas\n    this.#offscreenCanvas = document.createElement('canvas');\n\n    // set base size: needs an existing context and off screen canvas\n    this.#setBaseSize(size);\n\n    // update data on first draw\n    this.#needsDataUpdate = true;\n  }\n\n  /**\n   * Set the base size of the layer.\n   *\n   * @param {Scalar2D} size The size as {x,y}.\n   */\n  #setBaseSize(size) {\n    // check canvas creation\n    if (!canCreateCanvas(size.x, size.y)) {\n      throw new Error('Cannot create canvas with size ' +\n        size.x + ', ' + size.y);\n    }\n\n    // set local\n    this.#baseSize = size;\n\n    // off screen canvas\n    this.#offscreenCanvas.width = this.#baseSize.x;\n    this.#offscreenCanvas.height = this.#baseSize.y;\n    // original empty image data array\n    this.#context.clearRect(0, 0, this.#baseSize.x, this.#baseSize.y);\n    this.#imageData = this.#context.createImageData(\n      this.#baseSize.x, this.#baseSize.y);\n  }\n\n  /**\n   * Fit the layer to its parent container.\n   *\n   * @param {Scalar2D} containerSize The fit size as {x,y}.\n   * @param {number} divToWorldSizeRatio The div to world size ratio.\n   * @param {Scalar2D} fitOffset The fit offset as {x,y}.\n   */\n  fitToContainer(containerSize, divToWorldSizeRatio, fitOffset) {\n    let needsDraw = false;\n\n    // set canvas size if different from previous\n    if (this.#canvas.width !== containerSize.x ||\n      this.#canvas.height !== containerSize.y) {\n      if (!canCreateCanvas(containerSize.x, containerSize.y)) {\n        throw new Error('Cannot resize canvas ' +\n          containerSize.x + ', ' + containerSize.y);\n      }\n      // canvas size change triggers canvas reset\n      this.#canvas.width = containerSize.x;\n      this.#canvas.height = containerSize.y;\n      // update draw flag\n      needsDraw = true;\n    }\n\n    // fit scale\n    const divToImageSizeRatio = {\n      x: divToWorldSizeRatio * this.#baseSpacing.x,\n      y: divToWorldSizeRatio * this.#baseSpacing.y\n    };\n    // #scale = inputScale * fitScale * flipScale\n    // flipScale does not change here, we can omit it\n    // newScale = (#scale / fitScale) * newFitScale\n    const newScale = {\n      x: this.#scale.x * divToImageSizeRatio.x / this.#fitScale.x,\n      y: this.#scale.y * divToImageSizeRatio.y / this.#fitScale.y\n    };\n\n    // set scales if different from previous\n    if (this.#scale.x !== newScale.x ||\n      this.#scale.y !== newScale.y) {\n      this.#fitScale = divToImageSizeRatio;\n      this.#scale = newScale;\n      // update draw flag\n      needsDraw = true;\n    }\n\n    // view offset\n    const newViewOffset = {\n      x: fitOffset.x / divToImageSizeRatio.x,\n      y: fitOffset.y / divToImageSizeRatio.y\n    };\n    // flip offset\n    const scaledImageSize = {\n      x: containerSize.x / divToImageSizeRatio.x,\n      y: containerSize.y / divToImageSizeRatio.y\n    };\n    const newFlipOffset = {\n      x: this.#flipOffset.x !== 0 ? scaledImageSize.x : 0,\n      y: this.#flipOffset.y !== 0 ? scaledImageSize.y : 0,\n    };\n\n    // set offsets if different from previous\n    if (this.#viewOffset.x !== newViewOffset.x ||\n      this.#viewOffset.y !== newViewOffset.y ||\n      this.#flipOffset.x !== newFlipOffset.x ||\n      this.#flipOffset.y !== newFlipOffset.y) {\n      // update global offset\n      this.#offset = {\n        x: this.#offset.x +\n          newViewOffset.x - this.#viewOffset.x +\n          newFlipOffset.x - this.#flipOffset.x,\n        y: this.#offset.y +\n          newViewOffset.y - this.#viewOffset.y +\n          newFlipOffset.y - this.#flipOffset.y,\n      };\n      // update private local offsets\n      this.#flipOffset = newFlipOffset;\n      this.#viewOffset = newViewOffset;\n      // update draw flag\n      needsDraw = true;\n    }\n\n    // draw if needed\n    if (needsDraw) {\n      this.draw();\n    }\n  }\n\n  /**\n   * Enable and listen to container interaction events.\n   */\n  bindInteraction() {\n    // allow pointer events\n    this.#containerDiv.style.pointerEvents = 'auto';\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      const eventName = names[i];\n      const passive = eventName !== 'wheel';\n      this.#containerDiv.addEventListener(\n        eventName, this.#fireEvent, {passive: passive});\n    }\n  }\n\n  /**\n   * Disable and stop listening to container interaction events.\n   */\n  unbindInteraction() {\n    // disable pointer events\n    this.#containerDiv.style.pointerEvents = 'none';\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      this.#containerDiv.removeEventListener(names[i], this.#fireEvent);\n    }\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    event.srclayerid = this.getId();\n    event.dataid = this.#dataId;\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  // common layer methods [end] ---------------\n\n  /**\n   * Update the canvas image data.\n   */\n  #updateImageData() {\n    // generate image data\n    this.#viewController.generateImageData(this.#imageData);\n    // pass the data to the off screen canvas\n    this.#offscreenCanvas.getContext('2d').putImageData(this.#imageData, 0, 0);\n    // update data flag\n    this.#needsDataUpdate = false;\n  }\n\n  /**\n   * Handle window/level change.\n   *\n   * @param {object} event The event fired when changing the window/level.\n   */\n  #onWLChange = (event) => {\n    // generate and draw if no skip flag\n    const skip = typeof event.skipGenerate !== 'undefined' &&\n      event.skipGenerate === true;\n    if (!skip) {\n      this.#needsDataUpdate = true;\n      this.draw();\n    }\n  };\n\n  /**\n   * Handle colour map change.\n   *\n   * @param {object} event The event fired when changing the colour map.\n   */\n  #onColourMapChange = (event) => {\n    const skip = typeof event.skipGenerate !== 'undefined' &&\n      event.skipGenerate === true;\n    if (!skip) {\n      this.#needsDataUpdate = true;\n      this.draw();\n    }\n  };\n\n  /**\n   * Handle position change.\n   *\n   * @param {object} event The event fired when changing the position.\n   */\n  #onPositionChange = (event) => {\n    const skip = typeof event.skipGenerate !== 'undefined' &&\n      event.skipGenerate === true;\n    if (!skip) {\n      let valid = true;\n      if (typeof event.valid !== 'undefined') {\n        valid = event.valid;\n      }\n      // clear for non valid events\n      if (!valid) {\n        // clear only once\n        if (this.#isValidPosition) {\n          this.#isValidPosition = false;\n          this.clear();\n        }\n      } else {\n        // 3D dimensions\n        const dims3D = [0, 1, 2];\n        // remove scroll index\n        const indexScrollDimIndex =\n          dims3D.indexOf(this.#viewController.getScrollDimIndex());\n        dims3D.splice(indexScrollDimIndex, 1);\n        // remove non scroll index from diff dims\n        const diffDims = event.diffDims.filter(function (item) {\n          return dims3D.indexOf(item) === -1;\n        });\n        // update if we have something left\n        if (diffDims.length !== 0 || !this.#isValidPosition) {\n          // reset valid flag\n          this.#isValidPosition = true;\n          // reset update flag\n          this.#needsDataUpdate = true;\n          this.draw();\n        }\n      }\n    }\n  };\n\n  /**\n   * Handle alpha function change.\n   *\n   * @param {object} event The event fired when changing the function.\n   */\n  #onAlphaFuncChange = (event) => {\n    const skip = typeof event.skipGenerate !== 'undefined' &&\n      event.skipGenerate === true;\n    if (!skip) {\n      this.#needsDataUpdate = true;\n      this.draw();\n    }\n  };\n\n  /**\n   * Set the current position.\n   *\n   * @param {Point} position The new position.\n   * @param {Index} _index The new index.\n   * @returns {boolean} True if the position was updated.\n   */\n  setCurrentPosition(position, _index) {\n    return this.#viewController.setCurrentPosition(position);\n  }\n\n  /**\n   * Clear the context.\n   */\n  clear() {\n    // clear the context: reset the transform first\n    // store the current transformation matrix\n    this.#context.save();\n    // use the identity matrix while clearing the canvas\n    this.#context.setTransform(1, 0, 0, 1, 0, 0);\n    this.#context.clearRect(0, 0, this.#canvas.width, this.#canvas.height);\n    // restore the transform\n    this.#context.restore();\n  }\n\n} // ViewLayer class\n","import {getLayerDetailsFromEvent} from '../gui/layerGroup';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get a normalised spin speed in the Y direction to try to support\n * trackpads (small and large deltaY) and mouse wheel (large deltaY).\n * Should return 1 or -1 for a single mouse wheel tick.\n *\n * @param {object} event The wheel event.\n * @returns {number} The normalised spin Y.\n */\nfunction getSpinY(event) {\n  // (notes of 03/2024)\n\n  // firefox seems to change the value of deltaY\n  // if you ask for deltaMode before (?????)\n\n  // deltaY (for a single mouse wheel tick):\n  // - chrome: [linux] 120, [mac]: 4\n  // - firefox: [linux] 132, [mac]: 16\n\n  // wheelDelta (for a single mouse wheel tick):\n  // - chrome: [linux] 120, [mac]: 240\n  // - firefox: [linux] 120, [mac]: 48\n\n  // -> using wheelDelta for mouse wheel detection as\n  //    it is consistently larger than trackpad scroll\n\n  // wheelDeltaY and deltaY do not go in the same direction,\n  // using -deltaY so that they do...\n\n  if (typeof event.wheelDeltaY === 'undefined') {\n    //logger.warn('No wheel delta, scroll could be tricky...);\n    return -event.deltaY;\n  } else {\n    const threshold = 45;\n    if (event.wheelDeltaY > threshold) {\n      return 1;\n    } else if (event.wheelDeltaY < -threshold) {\n      return -1;\n    } else {\n      return -event.deltaY / 60;\n    }\n  }\n}\n\n/**\n * Class to sum wheel events and know if that sum\n * corresponds to a 'tick'.\n */\nclass ScrollSum {\n  /**\n   * The scroll sum.\n   *\n   * @type {number}\n   */\n  #sum = 0;\n\n  /**\n   * Get the scroll sum.\n   *\n   * @returns {number} The scroll sum.\n   */\n  getSum() {\n    return this.#sum;\n  }\n\n  /**\n   * Add scroll.\n   *\n   * @param {object} event The wheel event.\n   */\n  add(event) {\n    this.#sum += getSpinY(event);\n  }\n\n  /**\n   * Clear the scroll sum.\n   */\n  clear() {\n    this.#sum = 0;\n  }\n\n  /**\n   * Does the accumulated scroll correspond to a 'tick'.\n   *\n   * @returns {boolean} True if the sum corresponds to a 'tick'.\n   */\n  isTick() {\n    return Math.abs(this.#sum) >= 1;\n  }\n}\n\n/**\n * Scroll wheel class: provides a wheel event handler\n *   that scroll the corresponding data.\n */\nexport class ScrollWheel {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Accumulated scroll.\n   *\n   * @type {ScrollSum}\n   */\n  #scrollSum = new ScrollSum();\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {WheelEvent} event The mouse wheel event.\n   */\n  wheel(event) {\n    this.#scrollSum.add(event);\n    const up = this.#scrollSum.getSum() >= 0;\n\n    // exit if no tick\n    if (!this.#scrollSum.isTick()) {\n      return;\n    } else {\n      this.#scrollSum.clear();\n    }\n\n    // prevent default page scroll\n    event.preventDefault();\n\n    const layerDetails = getLayerDetailsFromEvent(event);\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    const positionHelper = layerGroup.getPositionHelper();\n\n    if (layerGroup.canScroll()) {\n      if (up) {\n        positionHelper.incrementPositionAlongScroll();\n      } else {\n        positionHelper.decrementPositionAlongScroll();\n      }\n    } else if (layerGroup.moreThanOne(3)) {\n      if (up) {\n        positionHelper.incrementPosition(3);\n      } else {\n        positionHelper.decrementPosition(3);\n      }\n    }\n  }\n\n} // ScrollWheel class\n","import {Point2D} from './point';\nimport {\n  isSimilar,\n  REAL_WORLD_EPSILON,\n} from './matrix';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {ViewController} from '../app/viewController';\nimport {Scalar2D} from './scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Line shape.\n */\nexport class Line {\n\n  /**\n   * Line begin point.\n   *\n   * @type {Point2D}\n   */\n  #begin;\n\n  /**\n   * Line end point.\n   *\n   * @type {Point2D}\n   */\n  #end;\n\n  /**\n   * @param {Point2D} begin A Point2D representing the beginning\n   *   of the line.\n   * @param {Point2D} end A Point2D representing the end of the line.\n   */\n  constructor(begin, end) {\n    this.#begin = begin;\n    this.#end = end;\n  }\n\n  /**\n   * Get the begin point of the line.\n   *\n   * @returns {Point2D} The beginning point of the line.\n   */\n  getBegin() {\n    return this.#begin;\n  }\n\n  /**\n   * Get the end point of the line.\n   *\n   * @returns {Point2D} The ending point of the line.\n   */\n  getEnd() {\n    return this.#end;\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Line} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.getBegin().equals(rhs.getBegin()) &&\n      this.getEnd().equals(rhs.getEnd());\n  }\n\n  /**\n   * Get the line delta in the X direction.\n   *\n   * @returns {number} The delta in the X direction.\n   */\n  getDeltaX() {\n    return this.getEnd().getX() - this.getBegin().getX();\n  }\n\n  /**\n   * Get the line delta in the Y direction.\n   *\n   * @returns {number} The delta in the Y direction.\n   */\n  getDeltaY() {\n    return this.getEnd().getY() - this.getBegin().getY();\n  }\n\n  /**\n   * Get the length of the line.\n   *\n   * @returns {number} The length of the line.\n   */\n  getLength() {\n    return Math.sqrt(\n      this.getDeltaX() * this.getDeltaX() +\n      this.getDeltaY() * this.getDeltaY()\n    );\n  }\n\n  /**\n   * Get the length of the line according to a  spacing.\n   *\n   * @param {Scalar2D} spacing2D The 2D spacing.\n   * @returns {number} The length of the line with spacing\n   *  or null for null spacings.\n   */\n  getWorldLength(spacing2D) {\n    let wlen = null;\n    if (spacing2D !== null) {\n      const dxs = this.getDeltaX() * spacing2D.x;\n      const dys = this.getDeltaY() * spacing2D.y;\n      wlen = Math.sqrt(dxs * dxs + dys * dys);\n    }\n    return wlen;\n  }\n\n  /**\n   * Get the mid point of the line.\n   *\n   * @returns {Point2D} The mid point of the line.\n   */\n  getMidpoint() {\n    return new Point2D(\n      (this.getBegin().getX() + this.getEnd().getX()) / 2,\n      (this.getBegin().getY() + this.getEnd().getY()) / 2\n    );\n  }\n\n  /**\n   * Get the centroid of the line.\n   *\n   * @returns {Point2D} THe centroid point.\n   */\n  getCentroid() {\n    return this.getMidpoint();\n  }\n\n  /**\n   * Get the slope of the line.\n   *\n   * @returns {number} The slope of the line.\n   */\n  getSlope() {\n    return this.getDeltaY() / this.getDeltaX();\n  }\n\n  /**\n   * Get the intercept of the line.\n   *\n   * @returns {number} The slope of the line.\n   */\n  getIntercept() {\n    return (\n      this.getEnd().getX() * this.getBegin().getY() -\n      this.getBegin().getX() * this.getEnd().getY()\n    ) / this.getDeltaX();\n  }\n\n  /**\n   * Get the inclination of the line.\n   *\n   * @returns {number} The inclination of the line.\n   */\n  getInclination() {\n    // tan(theta) = slope\n    const angle =\n      Math.atan2(this.getDeltaY(), this.getDeltaX()) * 180 / Math.PI;\n    // shift?\n    return 180 - angle;\n  }\n\n  /**\n   * Quantify a line according to view information.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   * @returns {object} A quantification object.\n   */\n  quantify(viewController) {\n    const quant = {};\n    // length\n    const spacing2D = viewController.get2DSpacing();\n    const length = this.getWorldLength(spacing2D);\n    if (length !== null) {\n      quant.length = {value: length, unit: 'unit.mm'};\n    }\n    // return\n    return quant;\n  }\n\n} // Line class\n\n/**\n * Get the angle between two lines in degree.\n *\n * @param {Line} line0 The first line.\n * @param {Line} line1 The second line.\n * @returns {number} The angle.\n */\nexport function getAngle(line0, line1) {\n  const dx0 = line0.getDeltaX();\n  const dy0 = line0.getDeltaY();\n  const dx1 = line1.getDeltaX();\n  const dy1 = line1.getDeltaY();\n  // dot = ||a||*||b||*cos(theta)\n  const dot = dx0 * dx1 + dy0 * dy1;\n  // cross = ||a||*||b||*sin(theta)\n  const det = dx0 * dy1 - dy0 * dx1;\n  // tan = sin / cos\n  const angle = Math.atan2(det, dot) * 180 / Math.PI;\n  // complementary angle\n  // shift?\n  return 360 - (180 - angle);\n}\n\n/**\n * Check if two lines are orthogonal.\n *\n * @param {Line} line0 The first line.\n * @param {Line} line1 The second line.\n * @returns {boolean} True if both lines are orthogonal.\n */\nexport function areOrthogonal(line0, line1) {\n  const dx0 = line0.getDeltaX();\n  const dy0 = line0.getDeltaY();\n  const dx1 = line1.getDeltaX();\n  const dy1 = line1.getDeltaY();\n  // dot = ||a||*||b||*cos(theta)\n  return (dx0 * dx1 + dy0 * dy1) === 0;\n}\n\n/**\n * Check if a point is in a line coordinate range.\n *\n * @param {Point2D} point The input point.\n * @param {Line} line The input line.\n * @returns {boolean} True if the input point is in the line coordinate range.\n */\nexport function isPointInLineRange(point, line) {\n  const minX = Math.min(line.getBegin().getX(), line.getEnd().getX());\n  const maxX = Math.max(line.getBegin().getX(), line.getEnd().getX());\n  const minY = Math.min(line.getBegin().getY(), line.getEnd().getY());\n  const maxY = Math.max(line.getBegin().getY(), line.getEnd().getY());\n  return point.getX() >= minX &&\n    point.getX() <= maxX &&\n    point.getY() >= minY &&\n    point.getY() <= maxY;\n}\n\n/**\n * Get a perpendicular line to an input one at a given point.\n *\n * @param {Line} line The line to be perpendicular to.\n * @param {Point2D} point The middle point of the perpendicular line.\n * @param {number} length The length of the perpendicular line.\n * @param {Scalar2D} [spacing] Optional image spacing, default to [1,1].\n * @returns {Line} The perpendicular line.\n */\nexport function getPerpendicularLine(line, point, length, spacing) {\n  if (typeof spacing === 'undefined') {\n    spacing = {x: 1, y: 1};\n  }\n  const sx2 = spacing.x * spacing.x;\n  const sy2 = spacing.y * spacing.y;\n  // a0 * a1 = -1 (in square space)\n  const perpSlope = -sx2 / (sy2 * line.getSlope());\n  // y0 = a1*x0 + b1 -> b1 = y0 - a1*x0\n  const prepIntercept = point.getY() - perpSlope * point.getX();\n  // return\n  return getLineFromEquation(perpSlope, prepIntercept, point, length, spacing);\n}\n\n/**\n * Get a perpendicular line to an input one at a given distance\n *   of its begin point.\n *\n * @param {Line} line The line to be perpendicular to.\n * @param {number} distance The distance to the input line begin point.\n * @param {number} length The length of the perpendicular line.\n * @param {Scalar2D} [spacing] Optional image spacing, default to [1,1].\n * @returns {Line} The perpendicular line.\n */\nexport function getPerpendicularLineAtDistance(\n  line, distance, length, spacing) {\n  // get a line along the input one and centered on begin point\n  const lineFromEq = getLineFromEquation(\n    line.getSlope(),\n    line.getIntercept(),\n    line.getBegin(),\n    distance,\n    spacing\n  );\n  // select the point on the input line\n  let startPoint;\n  if (isPointInLineRange(lineFromEq.getBegin(), line)) {\n    startPoint = lineFromEq.getBegin();\n  } else {\n    startPoint = lineFromEq.getEnd();\n  }\n  // use it as base for a perpendicular line\n  return getPerpendicularLine(line, startPoint, length, spacing);\n}\n\n/**\n * Get a line from an equation, a middle point and a length.\n *\n * @param {number} slope The line slope.\n * @param {number} intercept The line intercept.\n * @param {Point2D} point The middle point of the line.\n * @param {number} length The line length.\n * @param {Scalar2D} [spacing] Optional image spacing, default to [1,1].\n * @returns {Line} The resulting line.\n */\nexport function getLineFromEquation(slope, intercept, point, length, spacing) {\n  if (typeof spacing === 'undefined') {\n    spacing = {x: 1, y: 1};\n  }\n  // begin point\n  let beginX = 0;\n  let beginY = 0;\n  // end point\n  let endX = 0;\n  let endY = 0;\n\n  if (isSimilar(slope, 0, REAL_WORLD_EPSILON)) {\n    // slope = ~0 -> horizontal input line\n    beginX = point.getX() - length / (2 * spacing.x);\n    beginY = point.getY();\n    endX = point.getX() + length / (2 * spacing.x);\n    endY = point.getY();\n  } else if (Math.abs(slope) > 1e6) {\n    // slope = ~(+/-)Infinity -> vertical input line\n    beginX = point.getX();\n    beginY = point.getY() - length / (2 * spacing.y);\n    endX = point.getX();\n    endY = point.getY() + length / (2 * spacing.y);\n  } else {\n    const sx2 = spacing.x * spacing.x;\n    const sy2 = spacing.y * spacing.y;\n\n    // 1. [length] sx^2 * (x - x0)^2 + sy^2 * (y - y0)^2 = d^2\n    // 2. [slope] a = (y - y0) / (x - x0) -> y - y0 = a*(x - x0)\n    // ->  sx^2 * (x - x0)^2 + sy^2 * a^2 * (x - x0)^2 = d^2\n    // ->  (x - x0)^2 = d^2 / (sx^2 + sy^2 * a^2)\n    // -> x = x0 +- d / sqrt(sx^2 + sy^2 * a^2)\n\n    // length is the distance between begin and end,\n    // point is half way between both -> d = length / 2\n    const dx = length / (2 * Math.sqrt(sx2 + sy2 * slope * slope));\n\n    // begin point\n    beginX = point.getX() - dx;\n    beginY = slope * beginX + intercept;\n    // end point\n    endX = point.getX() + dx;\n    endY = slope * endX + intercept;\n  }\n  return new Line(\n    new Point2D(beginX, beginY),\n    new Point2D(endX, endY));\n}\n","// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DrawLayer} from '../gui/drawLayer';\nimport {Annotation} from '../image/annotation';\nimport {DrawController} from '../app/drawController';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get the display name of the input shape.\n *\n * @param {Konva.Shape} shape The Konva shape.\n * @returns {string} The display name.\n */\nexport function getShapeDisplayName(shape) {\n  let displayName = 'shape';\n  if (shape instanceof Konva.Line) {\n    if (shape.points().length === 4) {\n      displayName = 'line';\n    } else if (shape.points().length === 6) {\n      displayName = 'protractor';\n    } else {\n      displayName = 'roi';\n    }\n  } else if (shape instanceof Konva.Rect) {\n    displayName = 'rectangle';\n  } else if (shape instanceof Konva.Ellipse) {\n    displayName = 'ellipse';\n  }\n  // return\n  return displayName;\n}\n\n/**\n * Add annotation command.\n */\nexport class AddAnnotationCommand {\n  /**\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * @type {DrawController}\n   */\n  #drawController;\n\n  /**\n   * @param {Annotation} annotation The annotation to add.\n   * @param {DrawController} drawController The associated draw controller.\n   */\n  constructor(annotation, drawController) {\n    this.#annotation = annotation;\n    this.#drawController = drawController;\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'AddAnnotation-' + this.#annotation.id;\n  }\n\n  /**\n   * Execute the command.\n   */\n  execute() {\n    this.#drawController.addAnnotation(this.#annotation);\n  }\n\n  /**\n   * Undo the command.\n   */\n  undo() {\n    this.#drawController.removeAnnotation(this.#annotation.id);\n  }\n}\n\n/**\n * Remove annotation command.\n */\nexport class RemoveAnnotationCommand {\n  /**\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * @type {DrawController}\n   */\n  #drawController;\n\n  /**\n   * @param {Annotation} annotation The annotation to remove.\n   * @param {DrawController} drawController The associated draw controller.\n   */\n  constructor(annotation, drawController) {\n    this.#annotation = annotation;\n    this.#drawController = drawController;\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'RemoveAnnotation-' + this.#annotation.id;\n  }\n\n  /**\n   * Execute the command.\n   */\n  execute() {\n    this.#drawController.removeAnnotation(this.#annotation.id);\n  }\n\n  /**\n   * Undo the command.\n   */\n  undo() {\n    this.#drawController.addAnnotation(this.#annotation);\n  }\n}\n\n/**\n * Update annotation command.\n */\nexport class UpdateAnnotationCommand {\n  /**\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * @type {DrawController}\n   */\n  #drawController;\n\n  /**\n   * Original annotation properties.\n   *\n   * @type {object}\n   */\n  #originalProps;\n\n  /**\n   * New annotation properties.\n   *\n   * @type {object}\n   */\n  #newProps;\n\n  /**\n   * @param {Annotation} annotation The annotation to update.\n   * @param {object} originaProps The original annotation properties.\n   * @param {object} newProps The new annotation properties.\n   * @param {DrawController} drawController The associated draw controller.\n   */\n  constructor(annotation, originaProps, newProps, drawController) {\n    this.#annotation = annotation;\n    this.#drawController = drawController;\n    this.#originalProps = originaProps;\n    this.#newProps = newProps;\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'UpdateAnnotation-' + this.#annotation.id;\n  }\n\n  /**\n   * Execute the command.\n   */\n  execute() {\n    const keys = Object.keys(this.#newProps);\n    for (const key of keys) {\n      this.#annotation[key] = this.#newProps[key];\n    }\n    this.#drawController.updateAnnotation(this.#annotation, keys);\n  }\n\n  /**\n   * Undo the command.\n   */\n  undo() {\n    const keys = Object.keys(this.#originalProps);\n    for (const key of keys) {\n      this.#annotation[key] = this.#originalProps[key];\n    }\n    this.#drawController.updateAnnotation(this.#annotation, keys);\n  }\n}\n/**\n * Draw group command.\n *\n * TODO: remove.\n */\nexport class DrawGroupCommand {\n\n  /**\n   * The group to draw.\n   *\n   * @type {Konva.Group}\n   */\n  #group;\n\n  /**\n   * The shape display name.\n   *\n   * @type {string}\n   */\n  #name;\n\n  /**\n   * The draw layer.\n   *\n   * @type {DrawLayer}\n   */\n  #layer;\n\n  /**\n   * Flag to send events.\n   *\n   * @type {boolean}\n   */\n  #isSilent;\n\n  /**\n   * The group parent.\n   *\n   * @type {object}\n   */\n  #parent;\n\n  /**\n   * @param {Konva.Group} group The group draw.\n   * @param {string} name The shape display name.\n   * @param {DrawLayer} layer The layer where to draw the group.\n   * @param {boolean} [silent] Whether to send a creation event or not.\n   */\n  constructor(group, name, layer, silent) {\n    this.#group = group;\n    this.#name = name;\n    this.#layer = layer;\n    this.#isSilent = (typeof silent === 'undefined') ? false : silent;\n    this.#parent = group.getParent();\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'Draw-' + this.#name;\n  }\n\n  /**\n   * Execute the command.\n   *\n   * @fires DrawGroupCommand#drawcreate\n   */\n  execute() {\n    // add the group to the parent (in case of undo/redo)\n    this.#parent.add(this.#group);\n    // draw\n    this.#layer.getKonvaLayer().draw();\n    // callback\n    if (!this.#isSilent) {\n      /**\n       * Draw create event.\n       *\n       * @event DrawGroupCommand#drawcreate\n       * @type {object}\n       * @property {string} id The id of the created draw.\n       * @property {string} srclayerid The id of the layer of the draw.\n       * @property {string} dataid The associated data id.\n       */\n      this.onExecute({\n        type: 'drawcreate',\n        id: this.#group.id(),\n        srclayerid: this.#layer.getId(),\n        dataid: this.#layer.getDataId()\n      });\n    }\n  }\n\n  /**\n   * Undo the command.\n   *\n   * @fires DeleteGroupCommand#drawdelete\n   */\n  undo() {\n    // remove the group from the parent layer\n    this.#group.remove();\n    // draw\n    this.#layer.getKonvaLayer().draw();\n    // callback\n    this.onUndo({\n      type: 'drawdelete',\n      id: this.#group.id(),\n      srclayerid: this.#layer.getId(),\n      dataid: this.#layer.getDataId()\n    });\n  }\n\n  /**\n   * Handle an execute event.\n   *\n   * @param {object} _event The execute event with type and id.\n   */\n  onExecute(_event) {\n    // default does nothing.\n  }\n\n  /**\n   * Handle an undo event.\n   *\n   * @param {object} _event The undo event with type and id.\n   */\n  onUndo(_event) {\n    // default does nothing.\n  }\n\n} // DrawGroupCommand class\n","import {getShadowColour} from '../utils/colour';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Scalar2D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Style class.\n */\nexport class Style {\n  /**\n   * Font size.\n   *\n   * @type {number}\n   */\n  #fontSize = 10;\n\n  /**\n   * Font family.\n   *\n   * @type {string}\n   */\n  #fontFamily = 'Verdana';\n\n  /**\n   * Text colour.\n   *\n   * @type {string}\n   */\n  #textColour = '#fff';\n\n  /**\n   * Line colour.\n   *\n   * @type {string}\n   */\n  #lineColour = '#ffff80';\n\n  /**\n   * Base scale.\n   *\n   * @type {Scalar2D}\n   */\n  #baseScale = {x: 1, y: 1};\n\n  /**\n   * Zoom scale.\n   *\n   * @type {Scalar2D}\n   */\n  #zoomScale = {x: 1, y: 1};\n\n  /**\n   * Stroke width.\n   *\n   * @type {number}\n   */\n  #strokeWidth = 2;\n\n  /**\n   * Shadow offset.\n   *\n   * @type {Scalar2D}\n   */\n  #shadowOffset = {x: 0.25, y: 0.25};\n\n  /**\n   * Tag opacity.\n   *\n   * @type {number}\n   */\n  #tagOpacity = 0.2;\n\n  /**\n   * Text padding.\n   *\n   * @type {number}\n   */\n  #textPadding = 3;\n\n  /**\n   * Get the font family.\n   *\n   * @returns {string} The font family.\n   */\n  getFontFamily() {\n    return this.#fontFamily;\n  }\n\n  /**\n   * Get the font size.\n   *\n   * @returns {number} The font size.\n   */\n  getFontSize() {\n    return this.#fontSize;\n  }\n\n  /**\n   * Get the stroke width.\n   *\n   * @returns {number} The stroke width.\n   */\n  getStrokeWidth() {\n    return this.#strokeWidth;\n  }\n\n  /**\n   * Get the text colour.\n   *\n   * @returns {string} The text colour.\n   */\n  getTextColour() {\n    return this.#textColour;\n  }\n\n  /**\n   * Get the line colour.\n   *\n   * @returns {string} The line colour.\n   */\n  getLineColour() {\n    return this.#lineColour;\n  }\n\n  /**\n   * Set the line colour.\n   *\n   * @param {string} colour The line colour.\n   */\n  setLineColour(colour) {\n    this.#lineColour = colour;\n  }\n\n  /**\n   * Set the base scale.\n   *\n   * @param {Scalar2D} scale The scale as {x,y}.\n   */\n  setBaseScale(scale) {\n    this.#baseScale = scale;\n  }\n\n  /**\n   * Set the zoom scale.\n   *\n   * @param {Scalar2D} scale The scale as {x,y}.\n   */\n  setZoomScale(scale) {\n    this.#zoomScale = scale;\n  }\n\n  /**\n   * Get the base scale.\n   *\n   * @returns {Scalar2D} The scale as {x,y}.\n   */\n  getBaseScale() {\n    return this.#baseScale;\n  }\n\n  /**\n   * Get the zoom scale.\n   *\n   * @returns {Scalar2D} The scale as {x,y}.\n   */\n  getZoomScale() {\n    return this.#zoomScale;\n  }\n\n  /**\n   * Scale an input value using the base scale.\n   *\n   * @param {number} value The value to scale.\n   * @returns {number} The scaled value.\n   */\n  scale(value) {\n    // TODO: 2D?\n    return value / this.#baseScale.x;\n  }\n\n  /**\n   * Apply zoom scale on an input value.\n   *\n   * @param {number} value The value to scale.\n   * @returns {Scalar2D} The scaled value as {x,y}.\n   */\n  applyZoomScale(value) {\n    return {\n      x: value / this.#zoomScale.x,\n      y: value / this.#zoomScale.y\n    };\n  }\n\n  /**\n   * Multiply an input value by the zoom ratio (zx/zy).\n   *\n   * @param {number} value The value to scale.\n   * @returns {number} The scaled value.\n   */\n  applyZoomRatio(value) {\n    return value * this.#zoomScale.x / this.#zoomScale.y;\n  }\n\n  /**\n   * Get the shadow offset.\n   *\n   * @returns {Scalar2D} The offset as {x,y}.\n   */\n  getShadowOffset() {\n    return this.#shadowOffset;\n  }\n\n  /**\n   * Get the tag opacity.\n   *\n   * @returns {number} The opacity.\n   */\n  getTagOpacity() {\n    return this.#tagOpacity;\n  }\n\n  /**\n   * Get the text padding.\n   *\n   * @returns {number} The padding.\n   */\n  getTextPadding() {\n    return this.#textPadding;\n  }\n\n  /**\n   * Get the font definition string.\n   *\n   * @returns {string} The font definition string.\n   */\n  getFontStr() {\n    return ('normal ' + this.getFontSize() + 'px sans-serif');\n  }\n\n  /**\n   * Get the line height.\n   *\n   * @returns {number} The line height.\n   */\n  getLineHeight() {\n    return (this.getFontSize() + this.getFontSize() / 5);\n  }\n\n  /**\n   * Get the font size scaled to the display.\n   *\n   * @returns {number} The scaled font size.\n   */\n  getScaledFontSize() {\n    return this.scale(this.getFontSize());\n  }\n\n  /**\n   * Get the stroke width scaled to the display.\n   *\n   * @returns {number} The scaled stroke width.\n   */\n  getScaledStrokeWidth() {\n    return this.scale(this.getStrokeWidth());\n  }\n\n  /**\n   * Get the shadow line colour.\n   *\n   * @returns {string} The shadow line colour.\n   */\n  getShadowLineColour() {\n    return getShadowColour(this.getLineColour());\n  }\n\n} // class Style\n","import {Point2D} from '../math/point';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Scalar2D} from '../math/scalar';\nimport {Style} from '../gui/style';\n// external\nimport Konva from 'konva';\n/* eslint-enable no-unused-vars */\n\n/**\n * List of default label texts.\n *\n * @type {Object.<string, Object.<string, string>>}\n */\nexport const defaultLabelTexts = {\n  arrow: {\n    '*': ''\n  },\n  circle: {\n    '*': '{surface}'\n  },\n  ellipse: {\n    '*': '{surface}'\n  },\n  protractor: {\n    '*': '{angle}'\n  },\n  rectangle: {\n    '*': '{surface}'\n  },\n  roi: {\n    '*': ''\n  },\n  ruler: {\n    '*': '{length}'\n  }\n};\n\n/**\n * Is an input node's name 'label'.\n *\n * @param {Konva.Node} node A Konva node.\n * @returns {boolean} True if the node's name is 'label'.\n */\nexport function isNodeNameLabel(node) {\n  return node.name() === 'label';\n}\n\n/**\n * Is an input node's name 'shape'.\n *\n * @param {Konva.Node} node A Konva node.\n * @returns {boolean} True if the node's name is 'shape'.\n */\nexport function isNodeNameShape(node) {\n  return node.name() === 'shape';\n}\n\n/**\n * Is an input node a position node.\n *\n * @param {Konva.Node} node A Konva node.\n * @returns {boolean} True if the node's name is 'position-group'.\n */\nexport function isPositionNode(node) {\n  return node.name() === 'position-group';\n}\n\n/**\n * Get a Konva.Line shape from a group.\n *\n * @param {Konva.Group} group The group to look into.\n * @returns {Konva.Line|undefined} The shape.\n */\nexport function getLineShape(group) {\n  const kshape = group.getChildren(isNodeNameShape)[0];\n  if (!(kshape instanceof Konva.Line)) {\n    return;\n  }\n  return kshape;\n}\n\n/**\n * Get a Konva.Ellipse anchor shape from a group.\n *\n * @param {Konva.Group} group The group to look into.\n * @param {number} index The anchor index.\n * @returns {Konva.Ellipse|undefined} The anchor shape.\n */\nexport function getAnchorShape(group, index) {\n  const kshape = group.getChildren(function (node) {\n    return node.id() === 'anchor' + index;\n  })[0];\n  if (!(kshape instanceof Konva.Ellipse)) {\n    return;\n  }\n  return kshape;\n}\n\n/**\n * @callback testFn\n * @param {Konva.Node} node The node.\n * @returns {boolean} True if the node passes the test.\n */\n\n/**\n * Get a lambda to check a node's id.\n *\n * @param {string} id The id to check.\n * @returns {testFn} A function to check a node's id.\n */\nexport function isNodeWithId(id) {\n  return function (node) {\n    return node.id() === id;\n  };\n}\n\n/**\n * Draw Debug flag.\n */\nexport const DRAW_DEBUG = false;\n\n/**\n * Get the default anchor shape.\n *\n * @param {number} x The X position.\n * @param {number} y The Y position.\n * @param {string} id The shape id.\n * @param {Style} style The application style.\n * @returns {Konva.Ellipse} The default anchor shape.\n */\nexport function getDefaultAnchor(x, y, id, style) {\n  const radius = style.applyZoomScale(6);\n  const absRadius = {\n    x: Math.abs(radius.x),\n    y: Math.abs(radius.y)\n  };\n  return new Konva.Ellipse({\n    x: x,\n    y: y,\n    stroke: '#999',\n    fill: 'rgba(100,100,100,0.7',\n    strokeWidth: style.getStrokeWidth(),\n    strokeScaleEnabled: false,\n    radius: absRadius,\n    radiusX: absRadius.x,\n    radiusY: absRadius.y,\n    name: 'anchor',\n    id: id.toString(),\n    dragOnTop: false,\n    draggable: true,\n    visible: false\n  });\n}\n\n/**\n * Get an anchor index from its id.\n *\n * @param {string} id The anchor id as 'anchor#'.\n * @returns {number} The anchor index.\n */\nexport function getAnchorIndex(id) {\n  // 'anchor'.length = 6\n  return parseInt(id.substring(6), 10);\n}\n\n/**\n * Bound a node position.\n *\n * @param {Konva.Node} node The node to bound the position.\n * @param {Point2D} min The minimum position.\n * @param {Point2D} max The maximum position.\n * @returns {boolean} True if the position was corrected.\n */\nfunction boundNodePosition(node, min, max) {\n  let changed = false;\n  if (node.x() < min.getX()) {\n    node.x(min.getX());\n    changed = true;\n  } else if (node.x() > max.getX()) {\n    node.x(max.getX());\n    changed = true;\n  }\n  if (node.y() < min.getY()) {\n    node.y(min.getY());\n    changed = true;\n  } else if (node.y() > max.getY()) {\n    node.y(max.getY());\n    changed = true;\n  }\n  return changed;\n}\n\n/**\n * Get a shape top left position range.\n *\n * @param {Scalar2D} stageSize The stage size as {x,y}.\n * @param {Konva.Shape} shape The shape to evaluate.\n * @returns {object} The range as {min, max}.\n */\nexport function getShapePositionRange(stageSize, shape) {\n  const min = new Point2D(0, 0);\n  const max = new Point2D(\n    stageSize.x - Math.abs(shape.width()),\n    stageSize.y - Math.abs(shape.height())\n  );\n\n  return {min: min, max: max};\n}\n\n/**\n * Is an input shape top left position in the input range.\n *\n * @param {Konva.Shape} shape The shape to evaluate.\n * @param {Point2D} min The minimum top left position.\n * @param {Point2D} max The maximum top left position.\n * @returns {boolean} True if in range.\n */\nexport function isShapeInRange(shape, min, max) {\n  // use client rect to get the shape's top left position\n  const boundRect = shape.getClientRect({relativeTo: shape.getParent()});\n  return boundRect.x > min.getX() &&\n    boundRect.x < max.getX() &&\n    boundRect.y > min.getY() &&\n    boundRect.y < max.getY();\n}\n\n/**\n * Validate an anchor position.\n *\n * @param {Scalar2D} stageSize The stage size {x,y}.\n * @param {Konva.Shape} anchor The anchor to evaluate.\n * @returns {boolean} True if the position was corrected.\n */\nexport function validateAnchorPosition(stageSize, anchor) {\n  const group = anchor.getParent();\n\n  const min = new Point2D(\n    -group.x(),\n    -group.y()\n  );\n  const max = new Point2D(\n    stageSize.x - group.x(),\n    stageSize.y - group.y()\n  );\n\n  return boundNodePosition(anchor, min, max);\n}\n","import {logger} from '../utils/logger';\nimport {UpdateAnnotationCommand} from './drawCommands';\nimport {validateAnchorPosition} from './drawBounds';\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {DrawLayer} from '../gui/drawLayer';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Draw shape editor.\n */\nexport class DrawShapeEditor {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Event callback.\n   *\n   * @type {Function}\n   */\n  #eventCallback;\n\n  /**\n   * @param {App} app The associated application.\n   * @param {Function} eventCallback Event callback.\n   */\n  constructor(app, eventCallback) {\n    this.#app = app;\n    this.#eventCallback = eventCallback;\n  }\n\n  /**\n   * Current shape factory.\n   *\n   * @type {object}\n   */\n  #currentFactory = null;\n\n  /**\n   * Edited shape.\n   *\n   * @type {Konva.Shape}\n   */\n  #shape = null;\n\n  /**\n   * Associated draw layer. Used to bound anchor move.\n   *\n   * @type {DrawLayer}\n   */\n  #drawLayer;\n\n  /**\n   * The associated annotation.\n   *\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * Active flag.\n   *\n   * @type {boolean}\n   */\n  #isActive = false;\n\n  /**\n   * @callback eventFn\n   * @param {object} event The event.\n   */\n\n  /**\n   * Set the shape to edit.\n   *\n   * @param {Konva.Shape} inshape The shape to edit.\n   * @param {DrawLayer} drawLayer The associated draw layer.\n   * @param {Annotation} annotation The associated annotation.\n   */\n  setShape(inshape, drawLayer, annotation) {\n    this.#shape = inshape;\n    this.#drawLayer = drawLayer;\n    this.#annotation = annotation;\n\n    if (this.#shape) {\n      // remove old anchors\n      this.#removeAnchors();\n\n      this.#currentFactory = annotation.getFactory();\n      if (this.#currentFactory === null) {\n        throw new Error('Could not find a factory to update shape.');\n      }\n\n      // add new anchors\n      this.#addAnchors();\n    }\n  }\n\n  /**\n   * Get the edited shape.\n   *\n   * @returns {Konva.Shape} The edited shape.\n   */\n  getShape() {\n    return this.#shape;\n  }\n\n  /**\n   * Get the edited annotation.\n   *\n   * @returns {Annotation} The annotation.\n   */\n  getAnnotation() {\n    return this.#annotation;\n  }\n\n  /**\n   * Get the active flag.\n   *\n   * @returns {boolean} The active flag.\n   */\n  isActive() {\n    return this.#isActive;\n  }\n\n  /**\n   * Enable the editor. Redraws the layer.\n   */\n  enable() {\n    this.#isActive = true;\n    if (this.#shape) {\n      this.#setAnchorsVisible(true);\n      if (this.#shape.getLayer()) {\n        this.#shape.getLayer().draw();\n      }\n    }\n  }\n\n  /**\n   * Disable the editor. Redraws the layer.\n   */\n  disable() {\n    this.#isActive = false;\n    if (this.#shape) {\n      this.#setAnchorsVisible(false);\n      if (this.#shape.getLayer()) {\n        this.#shape.getLayer().draw();\n      }\n    }\n  }\n\n  /**\n   * Reset the editor.\n   */\n  reset() {\n    this.#shape = undefined;\n    this.#drawLayer = undefined;\n    this.#annotation = undefined;\n  }\n\n  /**\n   * Reset the anchors.\n   */\n  resetAnchors() {\n    // remove previous controls\n    this.#removeAnchors();\n    // add anchors\n    this.#addAnchors();\n    // set them visible\n    this.#setAnchorsVisible(true);\n  }\n\n  /**\n   * Apply a function on all anchors.\n   *\n   * @param {object} func A f(shape) function.\n   */\n  #applyFuncToAnchors(func) {\n    if (this.#shape && this.#shape.getParent()) {\n      const anchors = this.#shape.getParent().find('.anchor');\n      anchors.forEach(func);\n    }\n  }\n\n  /**\n   * Set anchors visibility.\n   *\n   * @param {boolean} flag The visible flag.\n   */\n  #setAnchorsVisible(flag) {\n    this.#applyFuncToAnchors(function (anchor) {\n      anchor.visible(flag);\n    });\n  }\n\n  /**\n   * Set anchors active.\n   *\n   * @param {boolean} flag The active (on/off) flag.\n   */\n  setAnchorsActive(flag) {\n    let func = null;\n    if (flag) {\n      func = (anchor) => {\n        this.#setAnchorOn(anchor);\n      };\n    } else {\n      func = (anchor) => {\n        this.#setAnchorOff(anchor);\n      };\n    }\n    this.#applyFuncToAnchors(func);\n  }\n\n  /**\n   * Remove anchors.\n   */\n  #removeAnchors() {\n    this.#applyFuncToAnchors(function (anchor) {\n      anchor.remove();\n    });\n  }\n\n  /**\n   * Add the shape anchors.\n   */\n  #addAnchors() {\n    // exit if no shape or no layer\n    if (!this.#shape || !this.#shape.getLayer()) {\n      return;\n    }\n    // get shape group\n    const group = this.#shape.getParent();\n\n    // activate and add anchors to group\n    const anchors =\n      this.#currentFactory.getAnchors(this.#shape, this.#app.getStyle());\n    for (let i = 0; i < anchors.length; ++i) {\n      // set anchor on\n      this.#setAnchorOn(anchors[i]);\n      // add the anchor to the group\n      group.add(anchors[i]);\n    }\n  }\n\n  /**\n   * Set the anchor on listeners.\n   *\n   * @param {Konva.Ellipse} anchor The anchor to set on.\n   */\n  #setAnchorOn(anchor) {\n    let originalProps;\n\n    // drag start listener\n    anchor.on('dragstart.edit', (event) => {\n      // prevent bubbling upwards\n      event.cancelBubble = true;\n      // store original properties\n      originalProps = {\n        mathShape: this.#annotation.mathShape,\n        referencePoints: this.#annotation.referencePoints\n      };\n    });\n    // drag move listener\n    anchor.on('dragmove.edit', (event) => {\n      const anchor = event.target;\n      if (!(anchor instanceof Konva.Shape)) {\n        return;\n      }\n      // validate the anchor position\n      validateAnchorPosition(this.#drawLayer.getBaseSize(), anchor);\n      if (typeof this.#currentFactory.constrainAnchorMove !== 'undefined') {\n        this.#currentFactory.constrainAnchorMove(anchor);\n      }\n\n      // udpate annotation\n      this.#currentFactory.updateAnnotationOnAnchorMove(\n        this.#annotation, anchor);\n      // udpate shape\n      this.#currentFactory.updateShapeGroupOnAnchorMove(\n        this.#annotation, anchor, this.#app.getStyle());\n\n      // redraw\n      if (anchor.getLayer()) {\n        anchor.getLayer().draw();\n      } else {\n        logger.warn('No layer to draw the anchor!');\n      }\n      // prevent bubbling upwards\n      event.cancelBubble = true;\n    });\n    // drag end listener\n    anchor.on('dragend.edit', (event) => {\n      // update annotation command\n      const newProps = {\n        mathShape: this.#annotation.mathShape,\n        referencePoints: this.#annotation.referencePoints\n      };\n      const command = new UpdateAnnotationCommand(\n        this.#annotation,\n        originalProps,\n        newProps,\n        this.#drawLayer.getDrawController()\n      );\n      // add command to undo stack\n      this.#app.addToUndoStack(command);\n      // fire event manually since command is not executed\n      this.#eventCallback({\n        type: 'annotationupdate',\n        data: this.#annotation,\n        dataid: this.#drawLayer.getDataId(),\n        keys: Object.keys(newProps)\n      });\n      // update original properties\n      originalProps = {\n        mathShape: newProps.mathShape,\n        referencePoints: newProps.referencePoints\n      };\n\n      // prevent bubbling upwards\n      event.cancelBubble = true;\n    });\n    // mouse down listener\n    anchor.on('mousedown touchstart', (event) => {\n      const anchor = event.target;\n      anchor.moveToTop();\n    });\n    // mouse over styling\n    anchor.on('mouseover.edit', (event) => {\n      const anchor = event.target;\n      if (!(anchor instanceof Konva.Shape)) {\n        return;\n      }\n      // style is handled by the group\n      anchor.stroke('#ddd');\n      if (anchor.getLayer()) {\n        anchor.getLayer().draw();\n      } else {\n        logger.warn('No layer to draw the anchor!');\n      }\n    });\n    // mouse out styling\n    anchor.on('mouseout.edit', (event) => {\n      const anchor = event.target;\n      if (!(anchor instanceof Konva.Shape)) {\n        return;\n      }\n      // style is handled by the group\n      anchor.stroke('#999');\n      if (anchor.getLayer()) {\n        anchor.getLayer().draw();\n      } else {\n        logger.warn('No layer to draw the anchor!');\n      }\n    });\n  }\n\n  /**\n   * Set the anchor off listeners.\n   *\n   * @param {Konva.Ellipse} anchor The anchor to set off.\n   */\n  #setAnchorOff(anchor) {\n    anchor.off('dragstart.edit');\n    anchor.off('dragmove.edit');\n    anchor.off('dragend.edit');\n    anchor.off('mousedown touchstart');\n    anchor.off('mouseover.edit');\n    anchor.off('mouseout.edit');\n  }\n\n} // class Editor\n","import Konva from 'konva';\n\n/* eslint-disable no-unused-vars */\nimport {Scalar2D} from '../math/scalar';\nimport {DrawLayer} from '../gui/drawLayer';\n/* eslint-enable no-unused-vars */\n\nexport class DrawTrash {\n  /**\n   * Trash draw: a cross.\n   *\n   * @type {Konva.Group}\n   */\n  #trash;\n\n  constructor() {\n    this.createTrashIcon();\n\n  }\n\n  /**\n   * Creates the trash icon o positionates it.\n   */\n  createTrashIcon() {\n    this.#trash = new Konva.Group();\n    // first line of the cross\n    const trashLine1 = new Konva.Line({\n      points: [-10, -10, 10, 10],\n      stroke: 'red'\n    });\n    // second line of the cross\n    const trashLine2 = new Konva.Line({\n      points: [10, -10, -10, 10],\n      stroke: 'red'\n    });\n    this.#trash.width(20);\n    this.#trash.height(20);\n    this.#trash.add(trashLine1);\n    this.#trash.add(trashLine2);\n  }\n\n  /**\n   *\n   * Activates the trash, by showing the icon into the layer draw layer.\n   *\n   * @param {DrawLayer} drawLayer The draw layer where to draw.\n   */\n  activate(drawLayer) {\n    const stage = drawLayer.getKonvaStage();\n    const scale = stage.scale();\n    const konvaLayer = drawLayer.getKonvaLayer();\n    const invscale = {x: 1 / scale.x, y: 1 / scale.y};\n    this.#trash.x(stage.offset().x + (stage.width() / (2 * scale.x)));\n    this.#trash.y(stage.offset().y + (stage.height() / (15 * scale.y)));\n    this.#trash.scale(invscale);\n    konvaLayer.add(this.#trash);\n    // draw\n    konvaLayer.draw();\n  }\n\n  /**\n   *\n   * Change colour on trash over.\n   *\n   * @param {Scalar2D} eventPosition The event drag move position.\n   * @param {Konva.Group} shapeGroup The shape group whose colour\n   *   must be change.\n   * @param {string} originalShapeColour The original shape colour.\n   */\n  changeChildrenColourOnTrashHover(eventPosition,\n    shapeGroup, originalShapeColour) {\n    if (this.isOverTrash(eventPosition)) {\n      this.changeGroupChildrenColour(this.#trash, 'orange');\n      this.changeGroupChildrenColour(shapeGroup, 'red');\n      return;\n\n    }\n    this.changeGroupChildrenColour(this.#trash, 'red');\n    this.changeGroupChildrenColour(shapeGroup, originalShapeColour);\n  }\n\n  /**\n   * Change colour on trash out.\n   *\n   * @param {Konva.Group} group The group whose colour must be change.\n   * @param {string} colour The new colour to be set.\n   */\n  changeGroupChildrenColour(group, colour) {\n    group.getChildren().forEach(function (tshape) {\n      if (tshape instanceof Konva.Shape &&\n        typeof tshape.stroke !== 'undefined') {\n        tshape.stroke(colour);\n      }\n    });\n  }\n\n  /**\n   * Removes the trash from the draw layer.\n   */\n  remove() {\n    this.#trash.remove();\n  }\n\n  /**\n   * Determines if the event is over trash.\n   *\n   * @param {Scalar2D} eventPosition The event position.\n   * @returns {boolean} True if the event is over trash.\n   */\n  isOverTrash(eventPosition) {\n    const trashHalfWidth =\n        this.#trash.width() * Math.abs(this.#trash.scaleX()) / 2;\n    const trashHalfHeight =\n        this.#trash.height() * Math.abs(this.#trash.scaleY()) / 2;\n    return Math.abs(eventPosition.x - this.#trash.x()) < trashHalfWidth &&\n        Math.abs(eventPosition.y - this.#trash.y()) < trashHalfHeight;\n  }\n\n}","import {custom} from '../app/custom';\nimport {\n  getMousePoint,\n} from '../gui/generic';\nimport {\n  RemoveAnnotationCommand,\n  UpdateAnnotationCommand\n} from './drawCommands';\nimport {\n  isNodeNameShape,\n  isNodeNameLabel,\n  getShapePositionRange,\n  isShapeInRange\n} from './drawBounds';\nimport {DrawShapeEditor} from './drawShapeEditor';\nimport {DrawTrash} from './drawTrash';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {Scalar2D} from '../math/scalar';\nimport {DrawLayer} from '../gui/drawLayer';\nimport {Annotation} from '../image/annotation';\nimport {Point2D} from '../math/point';\n/* eslint-enable no-unused-vars */\n\n/**\n * Open a dialogue to edit roi data. Defaults to window.prompt.\n *\n * @param {Annotation} annotation The roi data.\n * @param {Function} callback The callback to launch on dialogue exit.\n */\nfunction defaultOpenRoiDialog(annotation, callback) {\n  const textExpr = prompt('Label', annotation.textExpr);\n  if (textExpr !== null) {\n    annotation.textExpr = textExpr;\n    callback(annotation);\n  }\n}\n\n/**\n * Draw shape handler: handle action on existing shapes.\n */\nexport class DrawShapeHandler {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Shape editor.\n   *\n   * @type {DrawShapeEditor}\n   */\n  #shapeEditor;\n\n  /**\n   * Trash draw: a cross.\n   *\n   * @type {DrawTrash}\n   */\n  #trash;\n\n  /**\n   * Mouse cursor.\n   *\n   * @type {string}\n   */\n  #mouseOverCursor = 'pointer';\n\n  /**\n   * Original mouse cursor.\n   *\n   * @type {string}\n   */\n  #originalCursor;\n\n  /**\n   * Shape with mouse over.\n   *\n   * @type {Konva.Group}\n   */\n  #mouseOverShapeGroup;\n\n  /**\n   * Event callback.\n   *\n   * @type {Function}\n   */\n  #eventCallback;\n\n  /**\n   * @callback eventFn\n   * @param {object} event The event.\n   */\n\n  /**\n   * @param {App} app The associated application.\n   * @param {Function} eventCallback Event callback.\n   */\n  constructor(app, eventCallback) {\n    this.#app = app;\n    this.#eventCallback = eventCallback;\n    this.#shapeEditor = new DrawShapeEditor(app, eventCallback);\n    this.#trash = new DrawTrash();\n  }\n\n  /**\n   * Set the draw editor shape.\n   *\n   * @param {Konva.Shape} shape The shape to edit.\n   * @param {DrawLayer} drawLayer The layer the shape belongs to.\n   */\n  setEditorShape(shape, drawLayer) {\n    const drawController = drawLayer.getDrawController();\n    if (shape &&\n      shape instanceof Konva.Shape &&\n      shape !== this.#shapeEditor.getShape() &&\n      drawController.isAnnotationGroupEditable()) {\n      // disable\n      this.#shapeEditor.disable();\n      // set shape\n      this.#shapeEditor.setShape(\n        shape,\n        drawLayer,\n        drawLayer.getDrawController().getAnnotation(shape.getParent().id()));\n      // enable\n      this.#shapeEditor.enable();\n    }\n  }\n\n  /**\n   * Get the currently edited shape group.\n   *\n   * @returns {Konva.Group|undefined} The edited group.\n   */\n  getEditorShapeGroup() {\n    let res;\n    if (this.#shapeEditor.isActive()) {\n      res = this.#shapeEditor.getShape().getParent();\n      if (!(res instanceof Konva.Group)) {\n        return;\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Get the currently edited annotation.\n   *\n   * @returns {Annotation|undefined} The edited annotation.\n   */\n  getEditorAnnotation() {\n    let res;\n    if (this.#shapeEditor.isActive()) {\n      res = this.#shapeEditor.getAnnotation();\n    }\n    return res;\n  }\n\n  /**\n   * Disable and reset the shape editor.\n   */\n  disableAndResetEditor() {\n    this.#shapeEditor.disable();\n    this.#shapeEditor.reset();\n  }\n\n  /**\n   * Get the real position from an event.\n   * TODO: use layer method?\n   *\n   * @param {Scalar2D} index The input index as {x,y}.\n   * @param {DrawLayer} drawLayer The origin draw layer.\n   * @returns {Scalar2D} The real position in the image as {x,y}.\n   */\n  #getRealPosition(index, drawLayer) {\n    const stage = drawLayer.getKonvaStage();\n    return {\n      x: stage.offset().x + index.x / stage.scale().x,\n      y: stage.offset().y + index.y / stage.scale().y\n    };\n  }\n\n  /**\n   * Store specific mouse over cursor.\n   *\n   * @param {string} cursor The cursor name.\n   */\n  storeMouseOverCursor(cursor) {\n    this.#mouseOverCursor = cursor;\n  }\n\n  /**\n   * Handle shape group mouseover.\n   */\n  #onMouseOverShapeGroup() {\n    // mouse cursor\n    this.#originalCursor = document.body.style.cursor;\n    document.body.style.cursor = this.#mouseOverCursor;\n    // shape opacity\n    this.#mouseOverShapeGroup.opacity(0.75);\n  }\n\n  /**\n   * Handle shape group mouseout.\n   */\n  onMouseOutShapeGroup() {\n    // mouse cursor\n    if (typeof this.#originalCursor !== 'undefined') {\n      document.body.style.cursor = this.#originalCursor;\n      this.#originalCursor = undefined;\n    }\n    // shape opacity\n    if (typeof this.#mouseOverShapeGroup !== 'undefined') {\n      this.#mouseOverShapeGroup.opacity(1);\n    }\n  }\n\n  /**\n   * Add shape group mouse over and out listeners: updates\n   *   shape group opacity and cursor.\n   *\n   * @param {Konva.Group} shapeGroup The shape group.\n   */\n  #addShapeOverListeners(shapeGroup) {\n    // handle mouse over\n    shapeGroup.on('mouseover', () => {\n      this.#mouseOverShapeGroup = shapeGroup;\n      this.#onMouseOverShapeGroup();\n    });\n\n    // handle mouse out\n    shapeGroup.on('mouseout', () => {\n      this.onMouseOutShapeGroup();\n      this.#mouseOverShapeGroup = undefined;\n    });\n  }\n\n  /**\n   * Remove shape group mouse over and out listeners.\n   *\n   * @param {Konva.Group} shapeGroup The shape group.\n   */\n  #removeShapeOverListeners(shapeGroup) {\n    shapeGroup.off('mouseover');\n    shapeGroup.off('mouseout');\n  }\n\n  /**\n   * Add shape group listeners.\n   *\n   * @param {Konva.Group} shapeGroup The shape group to set on.\n   * @param {Annotation} annotation The associated annotation.\n   * @param {DrawLayer} drawLayer The origin draw layer.\n   */\n  addShapeGroupListeners(shapeGroup, annotation, drawLayer) {\n    // shape mouse over\n    this.#addShapeOverListeners(shapeGroup);\n\n    // make shape draggable\n    this.#addShapeListeners(shapeGroup, annotation, drawLayer);\n\n    // make label draggable\n    this.#addLabelListeners(shapeGroup, annotation, drawLayer);\n\n    // double click handling: update annotation text\n    shapeGroup.on('dblclick', () => {\n      // original text expr\n      const originalTextExpr = annotation.textExpr;\n\n      const onSaveCallback = (annotation) => {\n        // new text expr\n        const newTextExpr = annotation.textExpr;\n        // create annotation update command\n        const command = new UpdateAnnotationCommand(\n          annotation,\n          {textExpr: originalTextExpr},\n          {textExpr: newTextExpr},\n          drawLayer.getDrawController()\n        );\n        // add command to undo stack\n        this.#app.addToUndoStack(command);\n        // execute command\n        command.execute();\n      };\n\n      // call roi dialog\n      if (typeof custom.openRoiDialog !== 'undefined') {\n        custom.openRoiDialog(annotation, onSaveCallback);\n      } else {\n        defaultOpenRoiDialog(annotation, onSaveCallback);\n      }\n    });\n  }\n\n  /**\n   * Add shape listeners.\n   *\n   * @param {Konva.Group} shapeGroup The shape group to get the shape from.\n   * @param {Annotation} annotation The associated annotation.\n   * @param {DrawLayer} drawLayer The origin draw layer.\n   */\n  #addShapeListeners(shapeGroup, annotation, drawLayer) {\n    const konvaLayer = drawLayer.getKonvaLayer();\n\n    const shape = shapeGroup.getChildren(isNodeNameShape)[0];\n    if (!(shape instanceof Konva.Shape)) {\n      return;\n    }\n    shape.draggable(true);\n\n    // cache vars\n    let dragStartPos;\n    let previousPos;\n    let originalProps;\n    let colour;\n\n    // drag start event handling\n    shape.on('dragstart.draw', (event) => {\n      // store colour\n      colour = shape.stroke();\n      // store pos\n      dragStartPos = {\n        x: shape.x(),\n        y: shape.y()\n      };\n      previousPos = {\n        x: event.target.x(),\n        y: event.target.y()\n      };\n      // store original properties\n      originalProps = {\n        mathShape: annotation.mathShape,\n        referencePoints: annotation.referencePoints\n      };\n\n      // display trash\n      this.#trash.activate(drawLayer);\n      // deactivate anchors to avoid events on null shape\n      this.#shapeEditor.setAnchorsActive(false);\n      // draw\n      konvaLayer.draw();\n    });\n\n    // drag move event handling\n    shape.on('dragmove.draw', (event) => {\n      // if out of range, reset shape position and exit\n      const range = getShapePositionRange(drawLayer.getBaseSize(), shape);\n      if (range && !isShapeInRange(shape, range.min, range.max)) {\n        shape.x(previousPos.x);\n        shape.y(previousPos.y);\n        return;\n      }\n\n      // move associated shapes (but not label)\n      const diff = {\n        x: event.target.x() - previousPos.x,\n        y: event.target.y() - previousPos.y\n      };\n      const children = shapeGroup.getChildren();\n      const labelWithDefaultPosition =\n        typeof annotation.labelPosition === 'undefined';\n      for (const child of children) {\n        // skip shape and label with defined position\n        if (child === event.target ||\n          (child.name() === 'label' && !labelWithDefaultPosition) ||\n          child.name() === 'connector'\n        ) {\n          continue;\n        }\n        // move other nodes\n        child.move(diff);\n      }\n\n      // store pos\n      previousPos = {\n        x: event.target.x(),\n        y: event.target.y()\n      };\n\n      // get appropriate factory\n      const factory = annotation.getFactory();\n      // update annotation\n      factory.updateAnnotationOnTranslation(annotation, diff);\n      // update label\n      factory.updateLabelContent(annotation, shapeGroup, this.#app.getStyle());\n      // update connector\n      factory.updateConnector(shapeGroup);\n      // highlight trash when on it\n      const mousePoint = getMousePoint(event.evt);\n      const offset = {\n        x: mousePoint.getX(),\n        y: mousePoint.getY()\n      };\n      const eventPos = this.#getRealPosition(offset, drawLayer);\n      this.#trash.changeChildrenColourOnTrashHover(eventPos,\n        shapeGroup, colour);\n      // draw\n      konvaLayer.draw();\n    });\n\n    // drag end event handling\n    shape.on('dragend.draw', (event) => {\n      // remove trash\n      this.#trash.remove();\n      // activate(false) will also trigger a dragend.draw\n      if (typeof event === 'undefined' ||\n        typeof event.evt === 'undefined') {\n        return;\n      }\n      const pos = {x: shape.x(), y: shape.y()};\n      // delete case\n      const mousePoint = getMousePoint(event.evt);\n      const offset = {\n        x: mousePoint.getX(),\n        y: mousePoint.getY()\n      };\n      const eventPos = this.#getRealPosition(offset, drawLayer);\n      if (this.#trash.isOverTrash(eventPos)) {\n        // compensate for the drag translation\n        shapeGroup.x(dragStartPos.x);\n        shapeGroup.y(dragStartPos.y);\n        // disable editor\n        this.#shapeEditor.disable();\n        this.#shapeEditor.reset();\n        this.#trash.changeGroupChildrenColour(shapeGroup, colour);\n        // reset math shape (for undo)\n        annotation.mathShape = originalProps.mathShape;\n        annotation.referencePoints = originalProps.referencePoints;\n\n        // create remove annotation command\n        const command = new RemoveAnnotationCommand(\n          annotation,\n          drawLayer.getDrawController()\n        );\n        // add command to undo stack\n        this.#app.addToUndoStack(command);\n        // execute command: triggers draw remove\n        command.execute();\n\n        // reset cursor\n        this.onMouseOutShapeGroup();\n      } else {\n        const translation = {\n          x: pos.x - dragStartPos.x,\n          y: pos.y - dragStartPos.y\n        };\n        if (translation.x !== 0 || translation.y !== 0) {\n          // update annotation command\n          const newProps = {\n            mathShape: annotation.mathShape,\n            referencePoints: annotation.referencePoints\n          };\n          const command = new UpdateAnnotationCommand(\n            annotation,\n            originalProps,\n            newProps,\n            drawLayer.getDrawController()\n          );\n          // add command to undo stack\n          this.#app.addToUndoStack(command);\n          // fire event manually since command is not executed\n          this.#eventCallback({\n            type: 'annotationupdate',\n            data: annotation,\n            dataid: drawLayer.getDataId(),\n            keys: Object.keys(newProps)\n          });\n          // update original shape\n          originalProps = {\n            mathShape: newProps.mathShape,\n            referencePoints: newProps.referencePoints\n          };\n        }\n        // reset anchors\n        this.#shapeEditor.setAnchorsActive(true);\n        this.#shapeEditor.resetAnchors();\n      }\n      // draw\n      konvaLayer.draw();\n      // reset start position\n      dragStartPos = {\n        x: shape.x(),\n        y: shape.y()\n      };\n    });\n  }\n\n  /**\n   * Add label listeners.\n   *\n   * @param {Konva.Group} shapeGroup The shape group to get the label from.\n   * @param {Annotation} annotation The associated annotation.\n   * @param {DrawLayer} drawLayer The origin draw layer.\n   */\n  #addLabelListeners(shapeGroup, annotation, drawLayer) {\n    const label = shapeGroup.getChildren(isNodeNameLabel)[0];\n    if (!(label instanceof Konva.Label)) {\n      return;\n    }\n    label.draggable(true);\n\n    // cache vars\n    let dragStartPos;\n    let originalLabelPosition;\n\n    // drag start event handling\n    label.on('dragstart.draw', (/*event*/) => {\n      // store pos\n      dragStartPos = {\n        x: label.x(),\n        y: label.y()\n      };\n      // store original position\n      originalLabelPosition = annotation.labelPosition;\n    });\n\n    // drag move event handling\n    label.on('dragmove.draw', (/*event*/) => {\n      // get factory\n      const factory = annotation.getFactory();\n      // update label\n      factory.updateConnector(shapeGroup);\n    });\n\n    // drag end event handling\n    label.on('dragend.draw', (/*event*/) => {\n      const translation = {\n        x: label.x() - dragStartPos.x,\n        y: label.y() - dragStartPos.y\n      };\n      if (translation.x !== 0 || translation.y !== 0) {\n        const newLabelPosition = new Point2D(label.x(), label.y());\n        // set label position\n        annotation.labelPosition = newLabelPosition;\n        // update annotation command\n        const command = new UpdateAnnotationCommand(\n          annotation,\n          {labelPosition: originalLabelPosition},\n          {labelPosition: newLabelPosition},\n          drawLayer.getDrawController()\n        );\n        // add command to undo stack\n        this.#app.addToUndoStack(command);\n        // fire event manually since command is not executed\n        this.#eventCallback({\n          type: 'annotationupdate',\n          data: annotation,\n          dataid: drawLayer.getDataId(),\n          keys: ['labelPosition']\n        });\n        // update original position\n        originalLabelPosition = newLabelPosition;\n      }\n      dragStartPos = {x: label.x(), y: label.y()};\n    });\n  }\n\n  /**\n   * Remove shape group listeners.\n   *\n   * @param {Konva.Group} shapeGroup The shape group to set off.\n   */\n  removeShapeListeners(shapeGroup) {\n    // mouse over\n    this.#removeShapeOverListeners(shapeGroup);\n    // double click\n    shapeGroup.off('dblclick');\n    // remove listeners from shape\n    const shape = shapeGroup.getChildren(isNodeNameShape)[0];\n    if (shape instanceof Konva.Shape) {\n      shape.draggable(false);\n      shape.off('dragstart.draw');\n      shape.off('dragmove.draw');\n      shape.off('dragend.draw');\n    }\n    // remove listeners from label\n    const label = shapeGroup.getChildren(isNodeNameLabel)[0];\n    if (label instanceof Konva.Label) {\n      label.draggable(false);\n      label.off('dragstart.draw');\n      label.off('dragend.draw');\n    }\n  }\n} // DrawShapeHandler class","import {Point2D} from '../math/point';\n\n/**\n * Region Of Interest shape.\n * Note: should be a closed path.\n */\nexport class ROI {\n\n  /**\n   * List of points.\n   *\n   * @type {Point2D[]}\n   */\n  #points = [];\n\n  /**\n   * @param {Point2D[]} [points] Optional initial point list.\n   */\n  constructor(points) {\n    if (typeof points !== 'undefined') {\n      this.#points = points;\n    }\n  }\n\n  /**\n   * Get a point of the list at a given index.\n   *\n   * @param {number} index The index of the point to get\n   *   (beware, no size check).\n   * @returns {Point2D|undefined} The Point2D at the given index.\n   */\n  getPoint(index) {\n    return this.#points[index];\n  }\n\n  /**\n   * Get the point list.\n   *\n   * @returns {Point2D[]} The list.\n   */\n  getPoints() {\n    return this.#points;\n  }\n\n  /**\n   * Get the length of the point list.\n   *\n   * @returns {number} The length of the point list.\n   */\n  getLength() {\n    return this.#points.length;\n  }\n\n  /**\n   * Add a point to the ROI.\n   *\n   * @param {Point2D} point The Point2D to add.\n   */\n  addPoint(point) {\n    this.#points.push(point);\n  }\n\n  /**\n   * Add points to the ROI.\n   *\n   * @param {Point2D[]} rhs The array of POints2D to add.\n   */\n  addPoints(rhs) {\n    this.#points = this.#points.concat(rhs);\n  }\n\n  /**\n   * Get the centroid of the roi. Only valid for\n   * a non-self-intersecting closed polygon.\n   * Ref: {@link https://en.wikipedia.org/wiki/Centroid#Of_a_polygon}.\n   *\n   * @returns {Point2D} The centroid point.\n   */\n  getCentroid() {\n    let a = 0;\n    let cx = 0;\n    let cy = 0;\n    for (let i = 0; i < this.#points.length; ++i) {\n      const pi = this.#points[i];\n      let pi1;\n      if (i === this.#points.length - 1) {\n        pi1 = this.#points[0];\n      } else {\n        pi1 = this.#points[i + 1];\n      }\n      const ai = pi.getX() * pi1.getY() - pi1.getX() * pi.getY();\n      a += ai;\n      cx += (pi.getX() + pi1.getX()) * ai;\n      cy += (pi.getY() + pi1.getY()) * ai;\n    }\n    a *= 0.5;\n    const a1 = 1 / (6 * a);\n    cx *= a1;\n    cy *= a1;\n\n    return new Point2D(cx, cy);\n  }\n\n} // ROI class\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D} from '../math/point';\n/* eslint-enable no-unused-vars */\n\n/**\n * Path shape.\n */\nexport class Path {\n\n  /**\n   * @param {Point2D[]} [inputPointArray] The list of Point2D that make\n   *   the path (optional).\n   * @param {number[]} [inputControlPointIndexArray] The list of control\n   *  point of path, as indexes (optional).\n   * Note: first and last point do not need to be equal.\n   */\n  constructor(inputPointArray, inputControlPointIndexArray) {\n    /**\n     * List of points.\n     *\n     * @type {Point2D[]}\n     */\n    this.pointArray = inputPointArray ? inputPointArray.slice() : [];\n    /**\n     * List of control points.\n     *\n     * @type {number[]}\n     */\n    this.controlPointIndexArray = inputControlPointIndexArray\n      ? inputControlPointIndexArray.slice() : [];\n  }\n\n  /**\n   * Get a point of the list.\n   *\n   * @param {number} index The index of the point\n   *   to get (beware, no size check).\n   * @returns {Point2D} The Point2D at the given index.\n   */\n  getPoint(index) {\n    return this.pointArray[index];\n  }\n\n  /**\n   * Is the given point a control point.\n   *\n   * @param {Point2D} point The Point2D to check.\n   * @returns {boolean} True if a control point.\n   */\n  isControlPoint(point) {\n    const index = this.pointArray.indexOf(point);\n    if (index !== -1) {\n      return this.controlPointIndexArray.indexOf(index) !== -1;\n    } else {\n      throw new Error('Error: isControlPoint called with not in list point.');\n    }\n  }\n\n  /**\n   * Get the length of the path.\n   *\n   * @returns {number} The length of the path.\n   */\n  getLength() {\n    return this.pointArray.length;\n  }\n\n  /**\n   * Add a point to the path.\n   *\n   * @param {Point2D} point The Point2D to add.\n   */\n  addPoint(point) {\n    this.pointArray.push(point);\n  }\n\n  /**\n   * Add a control point to the path.\n   *\n   * @param {Point2D} point The Point2D to make a control point.\n   */\n  addControlPoint(point) {\n    const index = this.pointArray.indexOf(point);\n    if (index !== -1) {\n      this.controlPointIndexArray.push(index);\n    } else {\n      throw new Error(\n        'Cannot mark a non registered point as control point.');\n    }\n  }\n\n  /**\n   * Add points to the path.\n   *\n   * @param {Point2D[]} newPointArray The list of Point2D to add.\n   */\n  addPoints(newPointArray) {\n    this.pointArray = this.pointArray.concat(newPointArray);\n  }\n\n  /**\n   * Append a Path to this one.\n   *\n   * @param {Path} other The Path to append.\n   */\n  appenPath(other) {\n    const oldSize = this.pointArray.length;\n    this.pointArray = this.pointArray.concat(other.pointArray);\n    const indexArray = [];\n    for (let i = 0; i < other.controlPointIndexArray.length; ++i) {\n      indexArray[i] = other.controlPointIndexArray[i] + oldSize;\n    }\n    this.controlPointIndexArray =\n      this.controlPointIndexArray.concat(indexArray);\n  }\n\n} // Path class\n","/**\n * Circular Bucket Queue.\n *\n * Returns input'd points in sorted order. All operations run in roughly O(1)\n * time (for input with small cost values), but it has a strict requirement:\n *\n * If the most recent point had a cost of c, any points added should have a cost\n * c' in the range c <= c' <= c + (capacity - 1).\n */\nexport class BucketQueue {\n\n  /**\n   * @param {number} bits Number of bits.\n   * @param {Function} cost_functor The cost functor.\n   */\n  constructor(bits, cost_functor) {\n    this.bucketCount = 1 << bits; // # of buckets = 2^bits\n    this.mask = this.bucketCount - 1; // 2^bits - 1 = index mask\n    this.size = 0;\n\n    this.loc = 0; // Current index in bucket list\n    // Cost defaults to item value\n    this.cost = (typeof (cost_functor) !== 'undefined')\n      ? cost_functor : function (item) {\n        return item;\n      };\n    this.buckets = this.buildArray(this.bucketCount);\n  }\n\n  push(item) {\n    // Prepend item to the list in the appropriate bucket\n    const bucket = this.getBucket(item);\n    item.next = this.buckets[bucket];\n    this.buckets[bucket] = item;\n\n    this.size++;\n  }\n\n  pop() {\n    if (this.size === 0) {\n      throw new Error('Cannot pop, bucketQueue is empty.');\n    }\n\n    // Find first empty bucket\n    while (this.buckets[this.loc] === null) {\n      this.loc = (this.loc + 1) % this.bucketCount;\n    }\n\n    // All items in bucket have same cost, return the first one\n    const ret = this.buckets[this.loc];\n    this.buckets[this.loc] = ret.next;\n    ret.next = null;\n\n    this.size--;\n    return ret;\n  }\n\n  // TODO: needs at least two items...\n  remove(item) {\n    // Tries to remove item from queue. Returns true on success, false otherwise\n    if (!item) {\n      return false;\n    }\n\n    // To find node, go to bucket and search through unsorted list.\n    const bucket = this.getBucket(item);\n    let node = this.buckets[bucket];\n\n    while (node !== null &&\n      !(node.next !== null &&\n      item.x === node.next.x &&\n      item.y === node.next.y)) {\n      node = node.next;\n    }\n\n    if (node === null) {\n      // Item not in list, ergo item not in queue\n      return false;\n    } else {\n      // Found item, do standard list node deletion\n      node.next = node.next.next;\n\n      this.size--;\n      return true;\n    }\n  }\n\n  isEmpty() {\n    return this.size === 0;\n  }\n\n  getBucket(item) {\n    // Bucket index is the masked cost\n    return this.cost(item) & this.mask;\n  }\n\n  buildArray(newSize) {\n    // Create array and initialze pointers to null\n    const buckets = new Array(newSize);\n\n    for (let i = 0; i < buckets.length; i++) {\n      buckets[i] = null;\n    }\n\n    return buckets;\n  }\n\n} // class BucketQueue\n","import {BucketQueue} from './bucketQueue';\n\n// Pre-created to reduce allocation in inner loops\nconst __twothirdpi = (2 / (3 * Math.PI));\n\n/**\n * Compute grey scale.\n *\n * @param {Array} data The input data.\n * @param {number} width The width of the output.\n * @param {number} height The height of the output.\n * @returns {object} A greyscale object.\n */\nfunction computeGreyscale(data, width, height) {\n  // Returns 2D augmented array containing greyscale data\n  // Greyscale values found by averaging colour channels\n  // Input should be in a flat RGBA array, with values between 0 and 255\n  const greyscale = {\n    data: []\n  };\n\n  // Compute actual values\n  for (let y = 0; y < height; y++) {\n    greyscale.data[y] = [];\n\n    for (let x = 0; x < width; x++) {\n      const p = (y * width + x) * 4;\n      greyscale.data[y][x] = (data[p] + data[p + 1] + data[p + 2]) / (3 * 255);\n    }\n  }\n\n  // Augment with convenience functions\n  greyscale.dx = function (x, y) {\n    if (x + 1 === this.data[y].length) {\n      // If we're at the end, back up one\n      x--;\n    }\n    return this.data[y][x + 1] - this.data[y][x];\n  };\n\n  greyscale.dy = function (x, y) {\n    if (y + 1 === this.data.length) {\n      // If we're at the end, back up one\n      y--;\n    }\n    return this.data[y][x] - this.data[y + 1][x];\n  };\n\n  greyscale.gradMagnitude = function (x, y) {\n    const dx = this.dx(x, y);\n    const dy = this.dy(x, y);\n    return Math.sqrt(dx * dx + dy * dy);\n  };\n\n  greyscale.laplace = function (x, y) {\n    // Laplacian of Gaussian\n    let lap = -16 * this.data[y][x];\n    lap += this.data[y - 2][x];\n    lap += this.data[y - 1][x - 1] +\n      2 * this.data[y - 1][x] +\n      this.data[y - 1][x + 1];\n    lap += this.data[y][x - 2] +\n      2 * this.data[y][x - 1] +\n      2 * this.data[y][x + 1] +\n      this.data[y][x + 2];\n    lap += this.data[y + 1][x - 1] +\n      2 * this.data[y + 1][x] +\n      this.data[y + 1][x + 1];\n    lap += this.data[y + 2][x];\n\n    return lap;\n  };\n\n  return greyscale;\n}\n\n/**\n * Compute gradient.\n *\n * @param {object} greyscale The input greyscale.\n * @returns {object} A gradient object.\n */\nfunction computeGradient(greyscale) {\n  // Returns a 2D array of gradient magnitude values for greyscale. The values\n  // are scaled between 0 and 1, and then flipped, so that it works as a cost\n  // function.\n  const gradient = [];\n\n  let max = 0; // Maximum gradient found, for scaling purposes\n\n  let x = 0;\n  let y = 0;\n\n  for (y = 0; y < greyscale.data.length - 1; y++) {\n    gradient[y] = [];\n\n    for (x = 0; x < greyscale.data[y].length - 1; x++) {\n      gradient[y][x] = greyscale.gradMagnitude(x, y);\n      max = Math.max(gradient[y][x], max);\n    }\n\n    gradient[y][greyscale.data[y].length - 1] =\n      gradient[y][greyscale.data.length - 2];\n  }\n\n  gradient[greyscale.data.length - 1] = [];\n  for (let i = 0; i < gradient[0].length; i++) {\n    gradient[greyscale.data.length - 1][i] =\n      gradient[greyscale.data.length - 2][i];\n  }\n\n  // Flip and scale.\n  for (y = 0; y < gradient.length; y++) {\n    for (x = 0; x < gradient[y].length; x++) {\n      // @ts-ignore\n      gradient[y][x] = 1 - (gradient[y][x] / max);\n    }\n  }\n\n  return gradient;\n}\n\n/**\n * @param {object} greyscale The input greyscale.\n * @returns {object} A laplace object.\n */\nfunction computeLaplace(greyscale) {\n  // Returns a 2D array of Laplacian of Gaussian values\n  const laplace = [];\n\n  // Make the edges low cost here.\n\n  laplace[0] = [];\n  laplace[1] = [];\n  for (let i = 1; i < greyscale.data.length; i++) {\n    // Pad top, since we can't compute Laplacian\n    laplace[0][i] = 1;\n    laplace[1][i] = 1;\n  }\n\n  for (let y = 2; y < greyscale.data.length - 2; y++) {\n    laplace[y] = [];\n    // Pad left, ditto\n    laplace[y][0] = 1;\n    laplace[y][1] = 1;\n\n    for (let x = 2; x < greyscale.data[y].length - 2; x++) {\n      // Threshold needed to get rid of clutter.\n      laplace[y][x] = (greyscale.laplace(x, y) > 0.33) ? 0 : 1;\n    }\n\n    // Pad right, ditto\n    laplace[y][greyscale.data[y].length - 2] = 1;\n    laplace[y][greyscale.data[y].length - 1] = 1;\n  }\n\n  laplace[greyscale.data.length - 2] = [];\n  laplace[greyscale.data.length - 1] = [];\n  for (let j = 1; j < greyscale.data.length; j++) {\n    // Pad bottom, ditto\n    laplace[greyscale.data.length - 2][j] = 1;\n    laplace[greyscale.data.length - 1][j] = 1;\n  }\n\n  return laplace;\n}\n\n/**\n * Compute the X gradient.\n *\n * @param {object} greyscale The values.\n * @returns {Array} The gradient.\n */\nfunction computeGradX(greyscale) {\n  // Returns 2D array of x-gradient values for greyscale\n  const gradX = [];\n\n  for (let y = 0; y < greyscale.data.length; y++) {\n    gradX[y] = [];\n\n    for (let x = 0; x < greyscale.data[y].length - 1; x++) {\n      gradX[y][x] = greyscale.dx(x, y);\n    }\n\n    gradX[y][greyscale.data[y].length - 1] =\n      gradX[y][greyscale.data[y].length - 2];\n  }\n\n  return gradX;\n}\n\n/**\n * Compute the Y gradient.\n *\n * @param {object} greyscale The values.\n * @returns {Array} The gradient.\n */\nfunction computeGradY(greyscale) {\n  // Returns 2D array of y-gradient values for greyscale\n  const gradY = [];\n\n  for (let y = 0; y < greyscale.data.length - 1; y++) {\n    gradY[y] = [];\n\n    for (let x = 0; x < greyscale.data[y].length; x++) {\n      gradY[y][x] = greyscale.dy(x, y);\n    }\n  }\n\n  gradY[greyscale.data.length - 1] = [];\n  for (let i = 0; i < greyscale.data[0].length; i++) {\n    gradY[greyscale.data.length - 1][i] = gradY[greyscale.data.length - 2][i];\n  }\n\n  return gradY;\n}\n\n/**\n * Compute the gradient unit vector.\n *\n * @param {Array} gradX The X gradient.\n * @param {Array} gradY The Y gradient.\n * @param {number} px The point X.\n * @param {number} py The point Y.\n * @param {object} out The result.\n */\nfunction gradUnitVector(gradX, gradY, px, py, out) {\n  // Returns the gradient vector at (px,py), scaled to a magnitude of 1\n  const ox = gradX[py][px];\n  const oy = gradY[py][px];\n\n  let gvm = Math.sqrt(ox * ox + oy * oy);\n  gvm = Math.max(gvm, 1e-100); // To avoid possible divide-by-0 errors\n\n  out.x = ox / gvm;\n  out.y = oy / gvm;\n}\n\n/**\n * Compute the gradient direction.\n *\n * @param {Array} gradX The X gradient.\n * @param {Array} gradY The Y gradient.\n * @param {number} px The point X.\n * @param {number} py The point Y.\n * @param {number} qx The q X.\n * @param {number} qy The q Y.\n * @returns {number} The direction.\n */\nfunction gradDirection(gradX, gradY, px, py, qx, qy) {\n  const __dgpuv = {x: -1, y: -1};\n  const __gdquv = {x: -1, y: -1};\n  // Compute the gradiant direction, in radians, between to points\n  gradUnitVector(gradX, gradY, px, py, __dgpuv);\n  gradUnitVector(gradX, gradY, qx, qy, __gdquv);\n\n  let dp = __dgpuv.y * (qx - px) - __dgpuv.x * (qy - py);\n  let dq = __gdquv.y * (qx - px) - __gdquv.x * (qy - py);\n\n  // Make sure dp is positive, to keep things consistant\n  if (dp < 0) {\n    dp = -dp;\n    dq = -dq;\n  }\n\n  if (px !== qx && py !== qy) {\n    // We're going diagonally between pixels\n    dp *= Math.SQRT1_2;\n    dq *= Math.SQRT1_2;\n  }\n\n  return __twothirdpi * (Math.acos(dp) + Math.acos(dq));\n}\n\n/**\n * Compute the sides.\n *\n * @param {number} dist The distance.\n * @param {Array} gradX The X gradient.\n * @param {Array} gradY The Y gradient.\n * @param {object} greyscale The value.\n * @returns {object} The sides.\n */\nfunction computeSides(dist, gradX, gradY, greyscale) {\n  // Returns 2 2D arrays, containing inside and outside greyscale values.\n  // These greyscale values are the intensity just a little bit along the\n  // gradient vector, in either direction, from the supplied point. These\n  // values are used when using active-learning Intelligent Scissors\n\n  const sides = {};\n  sides.inside = [];\n  sides.outside = [];\n\n  const guv = {x: -1, y: -1}; // Current gradient unit vector\n\n  for (let y = 0; y < gradX.length; y++) {\n    sides.inside[y] = [];\n    sides.outside[y] = [];\n\n    for (let x = 0; x < gradX[y].length; x++) {\n      gradUnitVector(gradX, gradY, x, y, guv);\n\n      //(x, y) rotated 90 = (y, -x)\n\n      let ix = Math.round(x + dist * guv.y);\n      let iy = Math.round(y - dist * guv.x);\n      let ox = Math.round(x - dist * guv.y);\n      let oy = Math.round(y + dist * guv.x);\n\n      ix = Math.max(Math.min(ix, gradX[y].length - 1), 0);\n      ox = Math.max(Math.min(ox, gradX[y].length - 1), 0);\n      iy = Math.max(Math.min(iy, gradX.length - 1), 0);\n      oy = Math.max(Math.min(oy, gradX.length - 1), 0);\n\n      sides.inside[y][x] = greyscale.data[iy][ix];\n      sides.outside[y][x] = greyscale.data[oy][ox];\n    }\n  }\n\n  return sides;\n}\n\n/**\n * Gaussian blur an input buffer.\n *\n * @param {Array} buffer The input buffer.\n * @param {Array} out The result.\n */\nfunction gaussianBlur(buffer, out) {\n  // Smooth values over to fill in gaps in the mapping\n  out[0] = 0.4 * buffer[0] + 0.5 * buffer[1] + 0.1 * buffer[1];\n  out[1] = 0.25 * buffer[0] + 0.4 * buffer[1] + 0.25 * buffer[2] +\n    0.1 * buffer[3];\n\n  for (let i = 2; i < buffer.length - 2; i++) {\n    out[i] = 0.05 * buffer[i - 2] + 0.25 * buffer[i - 1] +\n      0.4 * buffer[i] + 0.25 * buffer[i + 1] + 0.05 * buffer[i + 2];\n  }\n\n  const len = buffer.length;\n  out[len - 2] = 0.25 * buffer[len - 1] + 0.4 * buffer[len - 2] +\n    0.25 * buffer[len - 3] + 0.1 * buffer[len - 4];\n  out[len - 1] = 0.4 * buffer[len - 1] + 0.5 * buffer[len - 2] +\n    0.1 * buffer[len - 3];\n}\n\n/**\n * Scissors.\n *\n * Ref: Eric N. Mortensen, William A. Barrett, Interactive Segmentation with\n *   Intelligent Scissors, Graphical Models and Image Processing, Volume 60,\n *   Issue 5, September 1998, Pages 349-384, ISSN 1077-3169,\n *   DOI: 10.1006/gmip.1998.0480.\n *\n * See: {@link http://www.sciencedirect.com/science/article/B6WG4-45JB8WN-9/2/6fe59d8089fd1892c2bfb82283065579}.\n *\n * Highly inspired from: {@link http://code.google.com/p/livewire-javascript/}.\n */\nexport class Scissors {\n\n  constructor() {\n    this.width = -1;\n    this.height = -1;\n\n    this.curPoint = null; // Corrent point we're searching on.\n    this.searchGranBits = 8; // Bits of resolution for BucketQueue.\n    this.searchGran = 1 << this.searchGranBits; //bits.\n    this.pointsPerPost = 500;\n\n    // Precomputed image data. All in ranges 0 >= x >= 1 and\n    //   all inverted (1 - x).\n    this.greyscale = null; // Greyscale of image\n    this.laplace = null; // Laplace zero-crossings (either 0 or 1).\n    this.gradient = null; // Gradient magnitudes.\n    this.gradX = null; // X-differences.\n    this.gradY = null; // Y-differences.\n\n    // Matrix mapping point => parent along shortest-path to root.\n    this.parents = null;\n\n    this.working = false; // Currently computing shortest paths?\n\n    // Begin Training:\n    this.trained = false;\n    this.trainingPoints = null;\n\n    this.edgeWidth = 2;\n    this.trainingLength = 32;\n\n    this.edgeGran = 256;\n    this.edgeTraining = null;\n\n    this.gradPointsNeeded = 32;\n    this.gradGran = 1024;\n    this.gradTraining = null;\n\n    this.insideGran = 256;\n    this.insideTraining = null;\n\n    this.outsideGran = 256;\n    this.outsideTraining = null;\n  }\n  // End Training\n\n\n  // Begin training methods //\n  getTrainingIdx(granularity, value) {\n    return Math.round((granularity - 1) * value);\n  }\n\n  getTrainedEdge(edge) {\n    return this.edgeTraining[this.getTrainingIdx(this.edgeGran, edge)];\n  }\n\n  getTrainedGrad(grad) {\n    return this.gradTraining[this.getTrainingIdx(this.gradGran, grad)];\n  }\n\n  getTrainedInside(inside) {\n    return this.insideTraining[this.getTrainingIdx(this.insideGran, inside)];\n  }\n\n  getTrainedOutside(outside) {\n    return this.outsideTraining[this.getTrainingIdx(this.outsideGran, outside)];\n  }\n  // End training methods //\n\n  setWorking(working) {\n    // Sets working flag\n    this.working = working;\n  }\n\n  setDimensions(width, height) {\n    this.width = width;\n    this.height = height;\n  }\n\n  setData(data) {\n    if (this.width === -1 || this.height === -1) {\n      // The width and height should have already been set\n      throw new Error('Dimensions have not been set.');\n    }\n\n    this.greyscale = computeGreyscale(data, this.width, this.height);\n    this.laplace = computeLaplace(this.greyscale);\n    this.gradient = computeGradient(this.greyscale);\n    this.gradX = computeGradX(this.greyscale);\n    this.gradY = computeGradY(this.greyscale);\n\n    const sides = computeSides(\n      this.edgeWidth, this.gradX, this.gradY, this.greyscale);\n    this.inside = sides.inside;\n    this.outside = sides.outside;\n    this.edgeTraining = [];\n    this.gradTraining = [];\n    this.insideTraining = [];\n    this.outsideTraining = [];\n  }\n\n  findTrainingPoints(p) {\n    // Grab the last handful of points for training\n    const points = [];\n\n    if (this.parents !== null) {\n      for (let i = 0; i < this.trainingLength && p; i++) {\n        points.push(p);\n        p = this.parents[p.y][p.x];\n      }\n    }\n\n    return points;\n  }\n\n  resetTraining() {\n    this.trained = false; // Training is ignored with this flag set\n  }\n\n  doTraining(p) {\n    // Compute training weights and measures\n    this.trainingPoints = this.findTrainingPoints(p);\n\n    if (this.trainingPoints.length < 8) {\n      return; // Not enough points, I think. It might crash if length = 0.\n    }\n\n    const buffer = [];\n    this.calculateTraining(\n      buffer, this.edgeGran, this.greyscale, this.edgeTraining);\n    this.calculateTraining(\n      buffer, this.gradGran, this.gradient, this.gradTraining);\n    this.calculateTraining(\n      buffer, this.insideGran, this.inside, this.insideTraining);\n    this.calculateTraining(\n      buffer, this.outsideGran, this.outside, this.outsideTraining);\n\n    if (this.trainingPoints.length < this.gradPointsNeeded) {\n      // If we have two few training points, the gradient weight map might not\n      // be smooth enough, so average with normal weights.\n      this.addInStaticGrad(this.trainingPoints.length, this.gradPointsNeeded);\n    }\n\n    this.trained = true;\n  }\n\n  calculateTraining(\n    buffer, granularity, input, output) {\n    let i = 0;\n    // Build a map of raw-weights to trained-weights by favoring input values\n    buffer.length = granularity;\n    for (i = 0; i < granularity; i++) {\n      buffer[i] = 0;\n    }\n\n    let maxVal = 1;\n    for (i = 0; i < this.trainingPoints.length; i++) {\n      const p = this.trainingPoints[i];\n      const idx = this.getTrainingIdx(granularity, input[p.y][p.x]);\n      buffer[idx] += 1;\n\n      maxVal = Math.max(maxVal, buffer[idx]);\n    }\n\n    // Invert and scale.\n    for (i = 0; i < granularity; i++) {\n      buffer[i] = 1 - buffer[i] / maxVal;\n    }\n\n    // Blur it, as suggested. Gets rid of static.\n    gaussianBlur(buffer, output);\n  }\n\n  addInStaticGrad(have, need) {\n    // Average gradient raw-weights to trained-weights map with standard weight\n    // map so that we don't end up with something to spiky\n    for (let i = 0; i < this.gradGran; i++) {\n      this.gradTraining[i] = Math.min(\n        this.gradTraining[i],\n        1 - i * (need - have) / (need * this.gradGran)\n      );\n    }\n  }\n\n  gradDirection(px, py, qx, qy) {\n    return gradDirection(this.gradX, this.gradY, px, py, qx, qy);\n  }\n\n  dist(px, py, qx, qy) {\n    // The grand culmunation of most of the code: the weighted distance function\n    let grad = this.gradient[qy][qx];\n\n    if (px === qx || py === qy) {\n      // The distance is Euclidean-ish; non-diagonal edges should be shorter\n      grad *= Math.SQRT1_2;\n    }\n\n    const lap = this.laplace[qy][qx];\n    const dir = this.gradDirection(px, py, qx, qy);\n\n    if (this.trained) {\n      // Apply training magic\n      const gradT = this.getTrainedGrad(grad);\n      const edgeT = this.getTrainedEdge(this.greyscale.data[py][px]);\n      const insideT = this.getTrainedInside(this.inside[py][px]);\n      const outsideT = this.getTrainedOutside(this.outside[py][px]);\n\n      return 0.3 * gradT + 0.3 * lap + 0.1 * (dir + edgeT + insideT + outsideT);\n    } else {\n      // Normal weights\n      return 0.43 * grad + 0.43 * lap + 0.11 * dir;\n    }\n  }\n\n  adj(p) {\n    const list = [];\n\n    const sx = Math.max(p.x - 1, 0);\n    const sy = Math.max(p.y - 1, 0);\n    const ex = Math.min(p.x + 1, this.greyscale.data[0].length - 1);\n    const ey = Math.min(p.y + 1, this.greyscale.data.length - 1);\n\n    let idx = 0;\n    for (let y = sy; y <= ey; y++) {\n      for (let x = sx; x <= ex; x++) {\n        if (x !== p.x || y !== p.y) {\n          list[idx++] = {x: x, y: y};\n        }\n      }\n    }\n\n    return list;\n  }\n\n  #costFunction = (p) => {\n    return Math.round(this.searchGran * this.cost[p.y][p.x]);\n  };\n\n  setPoint(sp) {\n    this.setWorking(true);\n\n    this.curPoint = sp;\n\n    let x = 0;\n    let y = 0;\n\n    this.visited = [];\n    for (y = 0; y < this.height; y++) {\n      this.visited[y] = [];\n      for (x = 0; x < this.width; x++) {\n        this.visited[y][x] = false;\n      }\n    }\n\n    this.parents = [];\n    for (y = 0; y < this.height; y++) {\n      this.parents[y] = [];\n    }\n\n    this.cost = [];\n    for (y = 0; y < this.height; y++) {\n      this.cost[y] = [];\n      for (x = 0; x < this.width; x++) {\n        this.cost[y][x] = Number.MAX_VALUE;\n      }\n    }\n    this.cost[sp.y][sp.x] = 0;\n\n    this.pq = new BucketQueue(this.searchGranBits, this.#costFunction);\n    this.pq.push(sp);\n  }\n\n  doWork() {\n    if (!this.working) {\n      return;\n    }\n\n    this.timeout = null;\n\n    let pointCount = 0;\n    const newPoints = [];\n    while (!this.pq.isEmpty() && pointCount < this.pointsPerPost) {\n      const p = this.pq.pop();\n      newPoints.push(p);\n      newPoints.push(this.parents[p.y][p.x]);\n\n      this.visited[p.y][p.x] = true;\n\n      const adjList = this.adj(p);\n      for (let i = 0; i < adjList.length; i++) {\n        const q = adjList[i];\n\n        const pqCost = this.cost[p.y][p.x] + this.dist(p.x, p.y, q.x, q.y);\n\n        if (pqCost < this.cost[q.y][q.x]) {\n          if (this.cost[q.y][q.x] !== Number.MAX_VALUE) {\n            // Already in PQ, must remove it so we can re-add it.\n            this.pq.remove(q);\n          }\n\n          this.cost[q.y][q.x] = pqCost;\n          this.parents[q.y][q.x] = p;\n          this.pq.push(q);\n        }\n      }\n\n      pointCount++;\n    }\n\n    return newPoints;\n  }\n\n} // Scissors class\n","// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D} from '../math/point';\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Label factory to create and update shape label.\n */\nexport class LabelFactory {\n\n  /**\n   * Default position getter.\n   *\n   * @type {Function}\n   */\n  #defaultPositionGetter;\n\n  /**\n   * @param {Function} positionGetter Default position getter.\n   */\n  constructor(positionGetter) {\n    this.#defaultPositionGetter = positionGetter;\n  }\n\n  /**\n   * Get the annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  getPosition(annotation) {\n    let position = annotation.labelPosition;\n    if (typeof position === 'undefined') {\n      position = this.#defaultPositionGetter(annotation);\n    }\n    return position;\n  }\n\n  /**\n   * Creates the konva label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Label} The Konva label.\n   */\n  create(annotation, style) {\n    // konva text\n    const ktext = new Konva.Text({\n      fontSize: style.getFontSize(),\n      fontFamily: style.getFontFamily(),\n      fill: annotation.colour,\n      padding: style.getTextPadding(),\n      shadowColor: style.getShadowLineColour(),\n      shadowOffset: style.getShadowOffset(),\n      name: 'text'\n    });\n    const labelText = annotation.getText();\n    ktext.setText(labelText);\n\n    // times 2 so that the font size 10 looks like a 10...\n    // (same logic as in the DrawController::updateLabelScale)\n    const zoomScale = style.applyZoomScale(1);\n    const labelScale = {\n      x: 2 * zoomScale.x,\n      y: 2 * zoomScale.y\n    };\n\n    // konva label\n    const labelPosition = this.getPosition(annotation);\n    const klabel = new Konva.Label({\n      x: labelPosition.getX(),\n      y: labelPosition.getY(),\n      scale: labelScale,\n      visible: labelText.length !== 0,\n      name: 'label'\n    });\n    klabel.add(ktext);\n    klabel.add(new Konva.Tag({\n      fill: annotation.colour,\n      opacity: style.getTagOpacity()\n    }));\n\n    return klabel;\n  }\n\n  /**\n   * Update the shape label position.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   */\n  updatePosition(annotation, group) {\n    // associated label\n    const klabel = group.getChildren(function (node) {\n      return node.name() === 'label';\n    })[0];\n    if (!(klabel instanceof Konva.Label)) {\n      return;\n    }\n    // update position\n    const labelPosition = this.getPosition(annotation);\n    klabel.position({\n      x: labelPosition.getX(),\n      y: labelPosition.getY()\n    });\n  }\n\n  /**\n   * Get the anchors positions for the label.\n   *\n   * @param {Konva.Label} label The label.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  getLabelAnchorsPosition(label) {\n    const lx = label.x();\n    const ly = label.y();\n    const dx = label.width() * label.scale().x;\n    const dy = label.height() * label.scale().y;\n    return [\n      new Point2D(lx + dx / 2, ly),\n      new Point2D(lx, ly + dy / 2),\n      new Point2D(lx + dx / 2, ly + dy),\n      new Point2D(lx + dx, ly + dy / 2),\n    ];\n  }\n\n  /**\n   * Get the two closest points of two points lists.\n   *\n   * @param {Point2D[]} points1 The first point list.\n   * @param {Point2D[]} points2 The second point list.\n   * @returns {Point2D[]} The closests points.\n   */\n  getClosestPoints(points1, points2) {\n    let minDist = points1[0].getDistance(points2[0]);\n    let p1 = points1[0];\n    let p2 = points2[0];\n    for (const point1 of points1) {\n      for (const point2 of points2) {\n        const dist = point1.getDistance(point2);\n        if (dist < minDist) {\n          minDist = dist;\n          p1 = point1;\n          p2 = point2;\n        }\n      }\n    }\n    return [p1, p2];\n  }\n\n  /**\n   * Get the connector between this label and its shape.\n   *\n   * @param {Point2D[]} connectorsPos The shape connectors positions.\n   * @param {Konva.Label} label The label.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Line} The connector.\n   */\n  getConnector(connectorsPos, label, style) {\n    const labelAnchorsPos = this.getLabelAnchorsPosition(label);\n    const anchorPoints = this.getClosestPoints(\n      connectorsPos, labelAnchorsPos);\n    return new Konva.Line({\n      points: [\n        anchorPoints[0].getX(),\n        anchorPoints[0].getY(),\n        anchorPoints[1].getX(),\n        anchorPoints[1].getY()\n      ],\n      stroke: label.getText().fill(),\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      visible: label.visible(),\n      dash: [10, 7],\n      name: 'connector'\n    });\n  }\n\n  /**\n   * Update the connector between a label and its shape.\n   *\n   * @param {Konva.Group} group The associated shape group.\n   * @param {Point2D[]} connectorsPos The shape connectors positions.\n   */\n  updateConnector(group, connectorsPos) {\n    // associated label\n    const klabel = group.getChildren(function (node) {\n      return node.name() === 'label';\n    })[0];\n    if (!(klabel instanceof Konva.Label)) {\n      return;\n    }\n\n    const labelAnchorsPos = this.getLabelAnchorsPosition(klabel);\n\n    const anchors = this.getClosestPoints(connectorsPos, labelAnchorsPos);\n\n    const kconnect = group.getChildren(function (node) {\n      return node.name() === 'connector';\n    })[0];\n    if (!(kconnect instanceof Konva.Line)) {\n      return;\n    }\n\n    kconnect.points([\n      anchors[0].getX(),\n      anchors[0].getY(),\n      anchors[1].getX(),\n      anchors[1].getY()\n    ]);\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   */\n  updateContent(annotation, group) {\n    // associated label\n    const klabel = group.getChildren(function (node) {\n      return node.name() === 'label';\n    })[0];\n    if (!(klabel instanceof Konva.Label)) {\n      return;\n    }\n    // update text\n    const text = annotation.getText();\n    const ktext = klabel.getText();\n    ktext.setText(text);\n    // hide if visible and empty\n    if (klabel.visible()) {\n      klabel.visible(text.length !== 0);\n    }\n  }\n\n} // LabelFactory","import {getStats} from './stats';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Index} from './index';\nimport {Point2D} from '../math/point';\nimport {ViewController} from '../app/viewController';\nimport {Scalar2D} from './scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Mulitply the three inputs if the last two are not null.\n *\n * @param {number} a The first input.\n * @param {number} b The second input.\n * @param {number} c The third input.\n * @returns {number} The multiplication of the three inputs or\n *  null if one of the last two is null.\n */\nfunction mulABC(a, b, c) {\n  let res = null;\n  if (b !== null && c !== null) {\n    res = a * b * c;\n  }\n  return res;\n}\n\n/**\n * Circle shape.\n */\nexport class Circle {\n\n  /**\n   * Circle centre.\n   *\n   * @type {Point2D}\n   */\n  #centre;\n\n  /**\n   * Circle radius.\n   *\n   * @type {number}\n   */\n  #radius;\n\n  /**\n   * @param {Point2D} centre A Point2D representing the centre\n   *   of the circle.\n   * @param {number} radius The radius of the circle.\n   */\n  constructor(centre, radius) {\n    this.#centre = centre;\n    this.#radius = radius;\n  }\n\n  /**\n   * Get the centre (point) of the circle.\n   *\n   * @returns {Point2D} The center (point) of the circle.\n   */\n  getCenter() {\n    return this.#centre;\n  }\n\n  /**\n   * Get the centroid of the circle.\n   *\n   * @returns {Point2D} The centroid point.\n   */\n  getCentroid() {\n    return this.#centre;\n  }\n\n  /**\n   * Get the radius of the circle.\n   *\n   * @returns {number} The radius of the circle.\n   */\n  getRadius() {\n    return this.#radius;\n  }\n\n\n  /**\n   * Check for equality.\n   *\n   * @param {Circle} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.getCenter().equals(rhs.getCenter()) &&\n      this.getRadius() === rhs.getRadius();\n  }\n\n  /**\n   * Get the surface of the circle.\n   *\n   * @returns {number} The surface of the circle.\n   */\n  getSurface() {\n    return Math.PI * this.getRadius() * this.getRadius();\n  }\n\n  /**\n   * Get the surface of the circle according to a spacing.\n   *\n   * @param {Scalar2D} spacing2D The 2D spacing.\n   * @returns {number} The surface of the circle multiplied by the given\n   *  spacing or null for null spacings.\n   */\n  getWorldSurface(spacing2D) {\n    return mulABC(this.getSurface(), spacing2D.x, spacing2D.y);\n  }\n\n  /**\n   * Get the rounded limits of the circle.\n   *\n   * See: {@link https://en.wikipedia.org/wiki/Circle#Equations}.\n   *\n   * Circle formula: `x*x + y*y = r*r`.\n   *\n   * Implies: `y = (+-) sqrt(r*r - x*x)`.\n   *\n   * @returns {number[][][]} The rounded limits:\n   *  list of [x, y] pairs (min, max).\n   */\n  getRound() {\n    const centerX = this.getCenter().getX();\n    const centerY = this.getCenter().getY();\n    const radius = this.getRadius();\n    const rSquare = Math.pow(radius, 2);\n    // Y bounds\n    const minY = centerY - radius;\n    const maxY = centerY + radius;\n    const regions = [];\n    // loop through lines and store limits\n    for (let y = minY; y < maxY; ++y) {\n      const diff = rSquare - Math.pow(y - centerY, 2);\n      // remove small values (possibly negative)\n      if (Math.abs(diff) < 1e-7) {\n        continue;\n      }\n      const transX = Math.sqrt(diff);\n      // remove small values\n      if (transX < 0.5) {\n        continue;\n      }\n      regions.push([\n        [Math.round(centerX - transX), Math.round(y)],\n        [Math.round(centerX + transX), Math.round(y)]\n      ]);\n    }\n    return regions;\n  }\n\n  /**\n   * Quantify an circle according to view information.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   * @param {Index} index The index at which to get the\n   *   image values.\n   * @param {string[]} flags A list of stat values to calculate.\n   * @returns {object} A quantification object.\n   */\n  quantify(viewController, index, flags) {\n    const quant = {};\n    // shape quantification\n    const spacing2D = viewController.get2DSpacing();\n    quant.radius = {\n      value: this.getRadius() * spacing2D.x,\n      unit: 'unit.mm'\n    };\n    const surface = this.getWorldSurface(spacing2D);\n    if (surface !== null) {\n      quant.surface = {\n        value: surface / 100,\n        unit: 'unit.cm2'\n      };\n    }\n\n    // pixel values quantification\n    if (viewController.canQuantifyImage()) {\n      const regions = this.getRound();\n      if (regions.length !== 0) {\n        const values = viewController.getImageVariableRegionValues(\n          regions, index);\n        const unit = viewController.getPixelUnit();\n        const quantif = getStats(values, flags);\n        quant.min = {value: quantif.min, unit: unit};\n        quant.max = {value: quantif.max, unit: unit};\n        quant.mean = {value: quantif.mean, unit: unit};\n        quant.stdDev = {value: quantif.stdDev, unit: unit};\n        if (typeof quantif.median !== 'undefined') {\n          quant.median = {value: quantif.median, unit: unit};\n        }\n        if (typeof quantif.p25 !== 'undefined') {\n          quant.p25 = {value: quantif.p25, unit: unit};\n        }\n        if (typeof quantif.p75 !== 'undefined') {\n          quant.p75 = {value: quantif.p75, unit: unit};\n        }\n      }\n    }\n\n    // return\n    return quant;\n  }\n\n} // Circle class\n","import {getStats} from './stats';\nimport {Index} from './index';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D} from '../math/point';\nimport {ViewController} from '../app/viewController';\nimport {Scalar2D} from './scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Mulitply the three inputs if the last two are not null.\n *\n * @param {number} a The first input.\n * @param {number} b The second input.\n * @param {number} c The third input.\n * @returns {number} The multiplication of the three inputs or\n *  null if one of the last two is null.\n */\nfunction mulABC(a, b, c) {\n  let res = null;\n  if (b !== null && c !== null) {\n    res = a * b * c;\n  }\n  return res;\n}\n\n/**\n * Ellipse shape.\n */\nexport class Ellipse {\n\n  /**\n   * Ellipse centre.\n   *\n   * @type {Point2D}\n   */\n  #centre;\n\n  /**\n   * Ellipse horizontal radius.\n   *\n   * @type {number}\n   */\n  #a;\n\n  /**\n   * Ellipse vertical radius.\n   *\n   * @type {number}\n   */\n  #b;\n\n  /**\n   * @param {Point2D} centre A Point2D representing the centre\n   *   of the ellipse.\n   * @param {number} a The radius of the ellipse on the horizontal axe.\n   * @param {number} b The radius of the ellipse on the vertical axe.\n   */\n  constructor(centre, a, b) {\n    this.#centre = centre;\n    this.#a = a;\n    this.#b = b;\n  }\n\n  /**\n   * Get the centre (point) of the ellipse.\n   *\n   * @returns {Point2D} The center (point) of the ellipse.\n   */\n  getCenter() {\n    return this.#centre;\n  }\n\n  /**\n   * Get the centroid of the ellipse.\n   *\n   * @returns {Point2D} The centroid point.\n   */\n  getCentroid() {\n    return this.#centre;\n  }\n\n  /**\n   * Get the radius of the ellipse on the horizontal axe.\n   *\n   * @returns {number} The radius of the ellipse on the horizontal axe.\n   */\n  getA() {\n    return this.#a;\n  }\n\n  /**\n   * Get the radius of the ellipse on the vertical axe.\n   *\n   * @returns {number} The radius of the ellipse on the vertical axe.\n   */\n  getB() {\n    return this.#b;\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Ellipse} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.getCenter().equals(rhs.getCenter()) &&\n      this.getA() === rhs.getA() &&\n      this.getB() === rhs.getB();\n  }\n\n  /**\n   * Get the surface of the ellipse.\n   *\n   * @returns {number} The surface of the ellipse.\n   */\n  getSurface() {\n    return Math.PI * this.getA() * this.getB();\n  }\n\n  /**\n   * Get the surface of the ellipse according to a spacing.\n   *\n   * @param {Scalar2D} spacing2D The 2D spacing.\n   * @returns {number} The surface of the ellipse multiplied by the given\n   *  spacing or null for null spacings.\n   */\n  getWorldSurface(spacing2D) {\n    return mulABC(this.getSurface(), spacing2D.x, spacing2D.y);\n  }\n\n  /**\n   * Get the rounded limits of the ellipse.\n   *\n   * See: {@link https://en.wikipedia.org/wiki/Ellipse#Standard_equation}.\n   *\n   * Ellipse formula: `x*x / a*a + y*y / b*b = 1`.\n   *\n   * Implies: `y = (+-)(b/a) * sqrt(a*a - x*x)`.\n   *\n   * @returns {number[][][]} The rounded limits:\n   *  list of [x, y] pairs (min, max).\n   */\n  getRound() {\n    const centerX = this.getCenter().getX();\n    const centerY = this.getCenter().getY();\n    const radiusX = this.getA();\n    const radiusY = this.getB();\n    const radiusRatio = radiusX / radiusY;\n    const rySquare = Math.pow(radiusY, 2);\n    // Y bounds\n    const minY = centerY - radiusY;\n    const maxY = centerY + radiusY;\n    const regions = [];\n    // loop through lines and store limits\n    for (let y = minY; y < maxY; ++y) {\n      const diff = rySquare - Math.pow(y - centerY, 2);\n      // remove small values (possibly negative)\n      if (Math.abs(diff) < 1e-7) {\n        continue;\n      }\n      const transX = radiusRatio * Math.sqrt(diff);\n      // remove small values\n      if (transX < 0.5) {\n        continue;\n      }\n      regions.push([\n        [Math.round(centerX - transX), Math.round(y)],\n        [Math.round(centerX + transX), Math.round(y)]\n      ]);\n    }\n    return regions;\n  }\n\n  /**\n   * Quantify an ellipse according to view information.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   * @param {Index} index The index at which to get the\n   *   image values.\n   * @param {string[]} flags A list of stat values to calculate.\n   * @returns {object} A quantification object.\n   */\n  quantify(viewController, index, flags) {\n    const quant = {};\n    // shape quantification\n    const spacing2D = viewController.get2DSpacing();\n    quant.a = {\n      value: this.getA() * spacing2D.x,\n      unit: 'unit.mm'\n    };\n    quant.b = {\n      value: this.getB() * spacing2D.y,\n      unit: 'unit.mm'\n    };\n    const surface = this.getWorldSurface(spacing2D);\n    if (surface !== null) {\n      quant.surface = {\n        value: surface / 100,\n        unit: 'unit.cm2'\n      };\n    }\n\n    // pixel values quantification\n    if (viewController.canQuantifyImage()) {\n      const regions = this.getRound();\n      if (regions.length !== 0) {\n        const values = viewController.getImageVariableRegionValues(\n          regions, index);\n        const unit = viewController.getPixelUnit();\n        const quantif = getStats(values, flags);\n        quant.min = {value: quantif.min, unit: unit};\n        quant.max = {value: quantif.max, unit: unit};\n        quant.mean = {value: quantif.mean, unit: unit};\n        quant.stdDev = {value: quantif.stdDev, unit: unit};\n        if (typeof quantif.median !== 'undefined') {\n          quant.median = {value: quantif.median, unit: unit};\n        }\n        if (typeof quantif.p25 !== 'undefined') {\n          quant.p25 = {value: quantif.p25, unit: unit};\n        }\n        if (typeof quantif.p75 !== 'undefined') {\n          quant.p75 = {value: quantif.p75, unit: unit};\n        }\n      }\n    }\n\n    // return\n    return quant;\n  }\n\n} // Ellipse class\n\n/**\n * Get the indices that form a ellpise.\n *\n * @param {Index} center The ellipse center.\n * @param {number[]} radius The 2 ellipse radiuses.\n * @param {number[]} dir The 2 ellipse directions.\n * @returns {Index[]} The indices of the ellipse.\n */\nexport function getEllipseIndices(center, radius, dir) {\n  const centerValues = center.getValues();\n  // keep all values for possible extra dimensions\n  const values = centerValues.slice();\n  const indices = [];\n  const radiusI = radius[0];\n  const radiusJ = radius[1];\n  const radiusRatio = radiusI / radiusJ;\n  const radiusJ2 = Math.pow(radiusJ, 2);\n  const di = dir[0];\n  const dj = dir[1];\n  // deduce 4 positions from top right\n  for (let j = 0; j < radiusJ; ++j) {\n    // right triangle formed by radiuses, j and len\n    // ellipse: i*i / a*a + j*j / b*b = 1\n    // -> i = a/b * sqrt(b*b - j*j)\n    const len = Math.round(\n      radiusRatio * Math.sqrt(radiusJ2 - Math.pow(j, 2)));\n    const jmax = centerValues[dj] + j;\n    const jmin = centerValues[dj] - j;\n    for (let i = 0; i < len; ++i) {\n      const imax = centerValues[di] + i;\n      const imin = centerValues[di] - i;\n\n      // right\n      values[di] = imax;\n      // right - top\n      values[dj] = jmax;\n      indices.push(new Index(values.slice()));\n      // right - bottom\n      if (jmin !== jmax) {\n        values[dj] = jmin;\n        indices.push(new Index(values.slice()));\n      }\n\n      // left\n      if (imin !== imax) {\n        values[di] = imin;\n        // left - top\n        values[dj] = jmax;\n        indices.push(new Index(values.slice()));\n        // left - bottom\n        if (jmin !== jmax) {\n          values[dj] = jmin;\n          indices.push(new Index(values.slice()));\n        }\n      }\n    }\n  }\n  return indices;\n}\n","import {Line, getAngle} from './line';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D} from '../math/point';\nimport {ViewController} from '../app/viewController';\n/* eslint-enable no-unused-vars */\n\n/**\n * Protractor shape: 3 points from which to calculate an angle.\n */\nexport class Protractor {\n\n  /**\n   * List of points.\n   *\n   * @type {Point2D[]}\n   */\n  #points;\n\n  /**\n   * @param {Point2D[]} points The list of Point2D that make\n   *   the protractor.\n   */\n  constructor(points) {\n    if (points.length > 3) {\n      throw new Error('Too many points for a protractor');\n    }\n    this.#points = points.slice(0, 3);\n  }\n\n  /**\n   * Get a point of the list.\n   *\n   * @param {number} index The index of the point\n   *   to get (beware, no size check).\n   * @returns {Point2D|undefined} The Point2D at the given index.\n   */\n  getPoint(index) {\n    return this.#points[index];\n  }\n\n  /**\n   * Get the length of the path (should be 3).\n   *\n   * @returns {number} The length of the path.\n   */\n  getLength() {\n    return this.#points.length;\n  }\n\n  /**\n   * Get the centroid of the protractor.\n   *\n   * @returns {Point2D} THe centroid point.\n   */\n  getCentroid() {\n    return this.#points[1];\n  }\n\n  /**\n   * Quantify a path according to view information.\n   *\n   * @param {ViewController} _viewController The associated view controller.\n   * @param {string[]} _flags A list of stat values to calculate.\n   * @returns {object} A quantification object.\n   */\n  quantify(_viewController, _flags) {\n    const quant = {};\n    if (this.#points.length === 3) {\n      const line0 = new Line(this.#points[0], this.#points[1]);\n      const line1 = new Line(this.#points[1], this.#points[2]);\n      let angle = getAngle(line0, line1);\n      if (angle > 180) {\n        angle = 360 - angle;\n      }\n      quant.angle = {\n        value: angle,\n        unit: 'unit.degree'\n      };\n    }\n    return quant;\n  }\n\n} // Protractor class\n","import {Point2D} from './point';\nimport {getStats} from './stats';\nimport {Index} from './index';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {ViewController} from '../app/viewController';\nimport {Scalar2D} from './scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Mulitply the three inputs if the last two are not null.\n *\n * @param {number} a The first input.\n * @param {number} b The second input.\n * @param {number} c The third input.\n * @returns {number} The multiplication of the three inputs or\n *  null if one of the last two is null.\n */\nfunction mulABC(a, b, c) {\n  let res = null;\n  if (b !== null && c !== null) {\n    res = a * b * c;\n  }\n  return res;\n}\n\n/**\n * Rectangle shape.\n */\nexport class Rectangle {\n\n  /**\n   * Rectangle begin point.\n   *\n   * @type {Point2D}\n   */\n  #begin;\n\n  /**\n   * Rectangle end point.\n   *\n   * @type {Point2D}\n   */\n  #end;\n\n  /**\n   * @param {Point2D} begin A Point2D representing the beginning\n   *   of the rectangle.\n   * @param {Point2D} end A Point2D representing the end\n   *   of the rectangle.\n   */\n  constructor(begin, end) {\n    this.#begin = new Point2D(\n      Math.min(begin.getX(), end.getX()),\n      Math.min(begin.getY(), end.getY())\n    );\n    this.#end = new Point2D(\n      Math.max(begin.getX(), end.getX()),\n      Math.max(begin.getY(), end.getY())\n    );\n  }\n\n  /**\n   * Get the begin point of the rectangle.\n   *\n   * @returns {Point2D} The begin point of the rectangle.\n   */\n  getBegin() {\n    return this.#begin;\n  }\n\n  /**\n   * Get the end point of the rectangle.\n   *\n   * @returns {Point2D} The end point of the rectangle.\n   */\n  getEnd() {\n    return this.#end;\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Rectangle} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.getBegin().equals(rhs.getBegin()) &&\n      this.getEnd().equals(rhs.getEnd());\n  }\n\n  /**\n   * Get the surface of the rectangle.\n   *\n   * @returns {number} The surface of the rectangle.\n   */\n  getSurface() {\n    const begin = this.getBegin();\n    const end = this.getEnd();\n    return Math.abs(end.getX() - begin.getX()) *\n      Math.abs(end.getY() - begin.getY());\n  }\n\n  /**\n   * Get the surface of the rectangle according to a spacing.\n   *\n   * @param {Scalar2D} spacing2D The 2D spacing.\n   * @returns {number} The surface of the rectangle multiplied by the given\n   *  spacing or null for null spacings.\n   */\n  getWorldSurface(spacing2D) {\n    return mulABC(this.getSurface(), spacing2D.x, spacing2D.y);\n  }\n\n  /**\n   * Get the real width of the rectangle.\n   *\n   * @returns {number} The real width of the rectangle.\n   */\n  getRealWidth() {\n    return this.getEnd().getX() - this.getBegin().getX();\n  }\n\n  /**\n   * Get the real height of the rectangle.\n   *\n   * @returns {number} The real height of the rectangle.\n   */\n  getRealHeight() {\n    return this.getEnd().getY() - this.getBegin().getY();\n  }\n\n  /**\n   * Get the width of the rectangle.\n   *\n   * @returns {number} The width of the rectangle.\n   */\n  getWidth() {\n    return Math.abs(this.getRealWidth());\n  }\n\n  /**\n   * Get the height of the rectangle.\n   *\n   * @returns {number} The height of the rectangle.\n   */\n  getHeight() {\n    return Math.abs(this.getRealHeight());\n  }\n\n  /**\n   * Get the rounded limits of the rectangle.\n   *\n   * @returns {object} The rounded limits as {min, max} (Point2D).\n   */\n  getRound() {\n    const roundBegin = new Point2D(\n      Math.round(this.getBegin().getX()),\n      Math.round(this.getBegin().getY())\n    );\n    const roundEnd = new Point2D(\n      Math.round(this.getEnd().getX()),\n      Math.round(this.getEnd().getY())\n    );\n    return {\n      min: roundBegin,\n      max: roundEnd\n    };\n  }\n\n  /**\n   * Get the centroid of the rectangle.\n   *\n   * @returns {Point2D} The centroid point.\n   */\n  getCentroid() {\n    return new Point2D(\n      this.getBegin().getX() + this.getWidth() / 2,\n      this.getBegin().getY() + this.getHeight() / 2\n    );\n  }\n\n  /**\n   * Quantify a rectangle according to view information.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   * @param {Index} index The index at which to get the\n   *   image values.\n   * @param {string[]} flags A list of stat values to calculate.\n   * @returns {object} A quantification object.\n   */\n  quantify(viewController, index, flags) {\n    const quant = {};\n    // shape quantification\n    const spacing2D = viewController.get2DSpacing();\n    quant.width = {\n      value: this.getWidth() * spacing2D.x,\n      unit: 'unit.mm'\n    };\n    quant.height = {\n      value: this.getHeight() * spacing2D.y,\n      unit: 'unit.mm'\n    };\n    const surface = this.getWorldSurface(spacing2D);\n    if (surface !== null) {\n      quant.surface = {\n        value: surface / 100,\n        unit: 'unit.cm2'\n      };\n    }\n\n    // pixel values quantification\n    if (viewController.canQuantifyImage()) {\n      const round = this.getRound();\n      const values = viewController.getImageRegionValues(\n        round.min, round.max, index);\n      const unit = viewController.getPixelUnit();\n      const quantif = getStats(values, flags);\n      quant.min = {value: quantif.min, unit: unit};\n      quant.max = {value: quantif.max, unit: unit};\n      quant.mean = {value: quantif.mean, unit: unit};\n      quant.stdDev = {value: quantif.stdDev, unit: unit};\n      if (typeof quantif.median !== 'undefined') {\n        quant.median = {value: quantif.median, unit: unit};\n      }\n      if (typeof quantif.p25 !== 'undefined') {\n        quant.p25 = {value: quantif.p25, unit: unit};\n      }\n      if (typeof quantif.p75 !== 'undefined') {\n        quant.p75 = {value: quantif.p75, unit: unit};\n      }\n    }\n\n    // return\n    return quant;\n  }\n\n} // Rectangle class\n\n/**\n * Get the indices that form a rectangle.\n *\n * @param {Index} center The rectangle center.\n * @param {number[]} size The 2 rectangle sizes.\n * @param {number[]} dir The 2 rectangle directions.\n * @returns {Index[]} The indices of the rectangle.\n */\nexport function getRectangleIndices(center, size, dir) {\n  const centerValues = center.getValues();\n  // keep all values for possible extra dimensions\n  const values = centerValues.slice();\n  const indices = [];\n  const sizeI = size[0];\n  const halfSizeI = Math.floor(sizeI / 2);\n  const sizeJ = size[1];\n  const halfSizeJ = Math.floor(sizeJ / 2);\n  const di = dir[0];\n  const dj = dir[1];\n  for (let j = 0; j < sizeJ; ++j) {\n    values[dj] = centerValues[dj] - halfSizeJ + j;\n    for (let i = 0; i < sizeI; ++i) {\n      values[di] = centerValues[di] - halfSizeI + i;\n      indices.push(new Index(values.slice()));\n    }\n  }\n  return indices;\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\n/* eslint-enable no-unused-vars */\n\n/**\n * Threshold an image between an input minimum and maximum.\n */\nexport class ThresholdFilter {\n  /**\n   * Threshold minimum.\n   *\n   * @type {number}\n   */\n  #min = 0;\n\n  /**\n   * Threshold maximum.\n   *\n   * @type {number}\n   */\n  #max = 0;\n\n  /**\n   * Get the threshold minimum.\n   *\n   * @returns {number} The threshold minimum.\n   */\n  getMin() {\n    return this.#min;\n  }\n\n  /**\n   * Set the threshold minimum.\n   *\n   * @param {number} val The threshold minimum.\n   */\n  setMin(val) {\n    this.#min = val;\n  }\n\n  /**\n   * Get the threshold maximum.\n   *\n   * @returns {number} The threshold maximum.\n   */\n  getMax() {\n    return this.#max;\n  }\n\n  /**\n   * Set the threshold maximum.\n   *\n   * @param {number} val The threshold maximum.\n   */\n  setMax(val) {\n    this.#max = val;\n  }\n\n  /**\n   * Get the name of the filter.\n   *\n   * @returns {string} The name of the filter.\n   */\n  getName() {\n    return 'Threshold';\n  }\n\n  /**\n   * Original image.\n   *\n   * @type {Image}\n   */\n  #originalImage = null;\n\n  /**\n   * Set the original image.\n   *\n   * @param {Image} image The original image.\n   */\n  setOriginalImage(image) {\n    this.#originalImage = image;\n  }\n\n  /**\n   * Get the original image.\n   *\n   * @returns {Image} The original image.\n   */\n  getOriginalImage() {\n    return this.#originalImage;\n  }\n\n  /**\n   * Transform the main image using this filter.\n   *\n   * @returns {Image} The transformed image.\n   */\n  update() {\n    const image = this.getOriginalImage();\n    const imageMin = image.getDataRange().min;\n    const threshFunction = (value) => {\n      if (value < this.getMin() || value > this.getMax()) {\n        return imageMin;\n      } else {\n        return value;\n      }\n    };\n    return image.transform(threshFunction);\n  }\n\n} // class Threshold\n\n/**\n * Sharpen an image using a sharpen convolution matrix.\n */\nexport class SharpenFilter {\n  /**\n   * Get the name of the filter.\n   *\n   * @returns {string} The name of the filter.\n   */\n  getName() {\n    return 'Sharpen';\n  }\n\n  /**\n   * Original image.\n   *\n   * @type {Image}\n   */\n  #originalImage = null;\n\n  /**\n   * Set the original image.\n   *\n   * @param {Image} image The original image.\n   */\n  setOriginalImage(image) {\n    this.#originalImage = image;\n  }\n\n  /**\n   * Get the original image.\n   *\n   * @returns {Image} The original image.\n   */\n  getOriginalImage() {\n    return this.#originalImage;\n  }\n\n  /**\n   * Transform the main image using this filter.\n   *\n   * @returns {Image} The transformed image.\n   */\n  update() {\n    const image = this.getOriginalImage();\n    /* eslint-disable @stylistic/js/array-element-newline */\n    return image.convolute2D([\n      0, -1, 0,\n      -1, 5, -1,\n      0, -1, 0\n    ]);\n    /* eslint-enable @stylistic/js/array-element-newline */\n  }\n\n} // class Sharpen\n\n/**\n * Apply a Sobel filter to an image.\n */\nexport class SobelFilter {\n  /**\n   * Get the name of the filter.\n   *\n   * @returns {string} The name of the filter.\n   */\n  getName() {\n    return 'Sobel';\n  }\n\n  /**\n   * Original image.\n   *\n   * @type {Image}\n   */\n  #originalImage = null;\n\n  /**\n   * Set the original image.\n   *\n   * @param {Image} image The original image.\n   */\n  setOriginalImage(image) {\n    this.#originalImage = image;\n  }\n\n  /**\n   * Get the original image.\n   *\n   * @returns {Image} The original image.\n   */\n  getOriginalImage() {\n    return this.#originalImage;\n  }\n\n  /**\n   * Transform the main image using this filter.\n   *\n   * @returns {Image} The transformed image.\n   */\n  update() {\n    const image = this.getOriginalImage();\n    /* eslint-disable @stylistic/js/array-element-newline */\n    const gradX = image.convolute2D([\n      1, 0, -1,\n      2, 0, -2,\n      1, 0, -1\n    ]);\n    const gradY = image.convolute2D([\n      1, 2, 1,\n      0, 0, 0,\n      -1, -2, -1\n    ]);\n    /* eslint-enable @stylistic/js/array-element-newline */\n    return gradX.compose(gradY, function (x, y) {\n      return Math.sqrt(x * x + y * y);\n    });\n  }\n\n} // class Sobel\n","import {ListenerHandler} from '../utils/listen';\nimport {\n  ThresholdFilter,\n  SobelFilter,\n  SharpenFilter\n} from '../image/filter';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\n/* eslint-enable no-unused-vars */\n\n/**\n * Filter tool.\n */\nexport class Filter {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Filter list.\n   *\n   * @type {object}\n   */\n  #filterList = null;\n\n  /**\n   * Selected filter.\n   *\n   * @type {object}\n   */\n  #selectedFilter = 0;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} bool Flag to activate or not.\n   */\n  activate(bool) {\n    // setup event listening\n    for (const key in this.#filterList) {\n      if (bool) {\n        this.#filterList[key].addEventListener('filterrun', this.#fireEvent);\n        this.#filterList[key].addEventListener('filter-undo', this.#fireEvent);\n      } else {\n        this.#filterList[key].removeEventListener(\n          'filterrun', this.#fireEvent);\n        this.#filterList[key].removeEventListener(\n          'filter-undo', this.#fireEvent);\n      }\n    }\n  }\n\n  /**\n   * Set the tool options.\n   *\n   * @param {object} options The list of filter names amd classes.\n   */\n  setOptions(options) {\n    this.#filterList = {};\n    // try to instanciate filters from the options\n    for (const key in options) {\n      this.#filterList[key] = new options[key](this.#app);\n    }\n  }\n\n  /**\n   * Get the type of tool options: here 'instance' since the filter\n   * list contains instances of each possible filter.\n   *\n   * @returns {string} The type.\n   */\n  getOptionsType() {\n    return 'instance';\n  }\n\n  /**\n   * Initialise the filter. Called once the image is loaded.\n   */\n  init() {\n    // setup event listening\n    for (const key in this.#filterList) {\n      this.#filterList[key].init();\n    }\n  }\n\n  /**\n   * Handle keydown event.\n   *\n   * @param {object} event The keydown event.\n   */\n  keydown = (event) => {\n    event.context = 'Filter';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Get the list of event names that this tool can fire.\n   *\n   * @returns {string[]} The list of event names.\n   */\n  getEventNames() {\n    return ['filterrun', 'filterundo'];\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  /**\n   * Get the selected filter.\n   *\n   * @returns {object} The selected filter.\n   */\n  getSelectedFilter() {\n    return this.#selectedFilter;\n  }\n\n  /**\n   * Set the tool live features: filter name.\n   *\n   * @param {object} features The list of features.\n   */\n  setFeatures(features) {\n    if (typeof features.filterName !== 'undefined') {\n      // check if we have it\n      if (!this.hasFilter(features.filterName)) {\n        throw new Error('Unknown filter: \\'' + features.filterName + '\\'');\n      }\n      // de-activate last selected\n      if (this.#selectedFilter) {\n        this.#selectedFilter.activate(false);\n      }\n      // enable new one\n      this.#selectedFilter = this.#filterList[features.filterName];\n      // activate the selected filter\n      this.#selectedFilter.activate(true);\n    }\n    if (typeof features.run !== 'undefined' && features.run) {\n      let args = {};\n      if (typeof features.runArgs !== 'undefined') {\n        args = features.runArgs;\n      }\n      this.getSelectedFilter().run(args);\n    }\n  }\n\n  /**\n   * Get the list of filters.\n   *\n   * @returns {Array} The list of filter objects.\n   */\n  getFilterList() {\n    return this.#filterList;\n  }\n\n  /**\n   * Check if a filter is in the filter list.\n   *\n   * @param {string} name The name to check.\n   * @returns {string} The filter list element for the given name.\n   */\n  hasFilter(name) {\n    return this.#filterList[name];\n  }\n\n} // class Filter\n\n/**\n * Threshold filter tool.\n */\nexport class Threshold {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Associated filter.\n   *\n   * @type {object}\n   */\n  #filter = new ThresholdFilter();\n\n  /**\n   * Flag to know wether to reset the image or not.\n   *\n   * @type {boolean}\n   */\n  #resetImage = true;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Activate the filter.\n   *\n   * @param {boolean} bool Flag to activate or not.\n   */\n  activate(bool) {\n    // reset the image when the tool is activated\n    if (bool) {\n      this.#resetImage = true;\n    }\n  }\n\n  /**\n   * Initialise the filter. Called once the image is loaded.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Run the filter.\n   *\n   * @param {*} args The filter arguments.\n   */\n  run(args) {\n    if (typeof args.dataId === 'undefined') {\n      throw new Error('No dataId to run threshod filter on.');\n    }\n    this.#filter.setMin(args.min);\n    this.#filter.setMax(args.max);\n    // reset the image if asked\n    if (this.#resetImage) {\n      const image = this.#app.getData(args.dataId).image;\n      this.#filter.setOriginalImage(image);\n      this.#resetImage = false;\n    }\n    const command = new RunFilterCommand(this.#filter, args.dataId, this.#app);\n    command.onExecute = this.#fireEvent;\n    command.onUndo = this.#fireEvent;\n    command.execute();\n    // save command in undo stack\n    this.#app.addToUndoStack(command);\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *  event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n} // class Threshold\n\n/**\n * Sharpen filter tool.\n */\nexport class Sharpen {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Activate the filter.\n   *\n   * @param {boolean} _bool Flag to activate or not.\n   */\n  activate(_bool) {\n    // does nothing\n  }\n\n  /**\n   * Initialise the filter. Called once the image is loaded.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Run the filter.\n   *\n   * @param {*} args The filter arguments.\n   */\n  run(args) {\n    if (typeof args.dataId === 'undefined') {\n      throw new Error('No dataId to run sharpen filter on.');\n    }\n    const filter = new SharpenFilter();\n    const image = this.#app.getData(args.dataId).image;\n    filter.setOriginalImage(image);\n    const command = new RunFilterCommand(filter, args.dataId, this.#app);\n    command.onExecute = this.#fireEvent;\n    command.onUndo = this.#fireEvent;\n    command.execute();\n    // save command in undo stack\n    this.#app.addToUndoStack(command);\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *    event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n} // filter.Sharpen\n\n/**\n * Sobel filter tool.\n */\nexport class Sobel {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Activate the filter.\n   *\n   * @param {boolean} _bool Flag to activate or not.\n   */\n  activate(_bool) {\n    // does nothing\n  }\n\n  /**\n   * Initialise the filter. Called once the image is loaded.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Run the filter.\n   *\n   * @param {*} args The filter arguments.\n   */\n  run(args) {\n    if (typeof args.dataId === 'undefined') {\n      throw new Error('No dataId to run sobel filter on.');\n    }\n    const filter = new SobelFilter();\n    const image = this.#app.getData(args.dataId).image;\n    filter.setOriginalImage(image);\n    const command = new RunFilterCommand(filter, args.dataId, this.#app);\n    command.onExecute = this.#fireEvent;\n    command.onUndo = this.#fireEvent;\n    command.execute();\n    // save command in undo stack\n    this.#app.addToUndoStack(command);\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *  event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n} // class filter.Sobel\n\n/**\n * Run filter command.\n */\nexport class RunFilterCommand {\n\n  /**\n   * The filter to run.\n   *\n   * @type {object}\n   */\n  #filter;\n\n  /**\n   * Data id.\n   *\n   * @type {string}\n   */\n  #dataId;\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {object} filter The filter to run.\n   * @param {string} dataId The data to filter.\n   * @param {App} app The associated application.\n   */\n  constructor(filter, dataId, app) {\n    this.#filter = filter;\n    this.#dataId = dataId;\n    this.#app = app;\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'Filter-' + this.#filter.getName();\n  }\n\n  /**\n   * Execute the command.\n   *\n   * @fires RunFilterCommand#filterrun\n   */\n  execute() {\n    // run filter and set app image\n    this.#app.setImage(this.#dataId, this.#filter.update());\n    // update display\n    this.#app.render(this.#dataId);\n    /**\n     * Filter run event.\n     *\n     * @event RunFilterCommand#filterrun\n     * @type {object}\n     * @property {string} type The event type: filterrun.\n     * @property {number} id The id of the run command.\n     */\n    const event = {\n      type: 'filterrun',\n      id: this.getName(),\n      dataId: this.#dataId\n    };\n    // callback\n    this.onExecute(event);\n  }\n\n  /**\n   * Undo the command.\n   *\n   * @fires RunFilterCommand#filterundo\n   */\n  undo() {\n    // reset the image\n    this.#app.setImage(this.#dataId, this.#filter.getOriginalImage());\n    // update display\n    this.#app.render(this.#dataId);\n    /**\n     * Filter undo event.\n     *\n     * @event RunFilterCommand#filterundo\n     * @type {object}\n     * @property {string} type The event type: filterundo.\n     * @property {number} id The id of the undone run command.\n     */\n    const event = {\n      type: 'filterundo',\n      id: this.getName(),\n      dataid: this.#dataId\n    }; // callback\n    this.onUndo(event);\n  }\n\n  /**\n   * Handle an execute event.\n   *\n   * @param {object} _event The execute event with type and id.\n   */\n  onExecute(_event) {\n    // default does nothing.\n  }\n\n  /**\n   * Handle an undo event.\n   *\n   * @param {object} _event The undo event with type and id.\n   */\n  onUndo(_event) {\n    // default does nothing.\n  }\n\n} // RunFilterCommand class\n","import {WindowLevel} from './windowLevel';\nimport {Scroll} from './scroll';\nimport {ZoomAndPan} from './zoomPan';\nimport {Opacity} from './opacity';\nimport {Draw} from './draw';\nimport {Floodfill} from './floodfill';\nimport {Livewire} from './livewire';\n\nimport {ArrowFactory} from './arrow';\nimport {CircleFactory} from './circle';\nimport {EllipseFactory} from './ellipse';\nimport {ProtractorFactory} from './protractor';\nimport {RectangleFactory} from './rectangle';\nimport {RoiFactory} from './roi';\nimport {RulerFactory} from './ruler';\n\nimport {Filter, Threshold, Sobel, Sharpen} from './filter';\n\n/**\n * List of client provided tools to be added to\n * the default ones.\n *\n * @example\n * // custom tool\n * class AlertTool {\n *   mousedown() {alert('AlertTool mousedown');}\n *   init() {}\n *   activate() {}\n * }\n * // pass it to dwv tool list\n * dwv.toolList['Alert'] = AlertTool;\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {Alert: {}};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('Alert');\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n *\n * @type {Object<string, any>}\n */\nexport const toolList = {};\n\n/**\n * List of client provided tool options to be added to\n * the default ones.\n *\n * @example\n * // custom factory\n * class LoveFactory {\n *   getName() {return 'love';}\n *   static supports(mathShape) {return mathShape instanceof ROI;}\n *   getNPoints() {return 1;}\n *   getTimeout() {return 0;}\n *   setAnnotationMathShape(annotation, points) {\n *     const px = points[0].getX();\n *     const py = points[0].getY();\n *     annotation.mathShape = new dwv.ROI([\n *       new dwv.Point2D(px+15,py), new dwv.Point2D(px+10,py-10),\n *       new dwv.Point2D(px,py), new dwv.Point2D(px-10,py-10),\n *       new dwv.Point2D(px-15,py), new dwv.Point2D(px,py+20)\n *     ]);\n *     annotation.getFactory = function () {return new LoveFactory();}\n *   }\n *   createShapeGroup(annotation, style) {\n *     const roi = annotation.mathShape;\n *     // konva line\n *     const arr = [];\n *     for (let i = 0; i < roi.getLength(); ++i) {\n *       arr.push(roi.getPoint(i).getX());\n *       arr.push(roi.getPoint(i).getY());\n *     }\n *     const shape = new Konva.Line({\n *       name: 'shape', points: arr,\n *       stroke: 'red', strokeWidth: 2,\n *       closed: true\n *     });\n *     // konva group\n *     const group = new Konva.Group();\n *     group.name('love-group');\n *     group.visible(true);\n *     group.id(annotation.id);\n *     group.add(shape);\n *     return group;\n *   }\n * }\n * // pass it to dwv option list\n * dwv.toolOptions['draw'] = {LoveFactory};\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {Draw: {options: ['Love']}};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('Draw');\n *   app.setToolFeatures({shapeName: 'Love'});\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n *\n * @type {Object<string, Object<string, any>>}\n */\nexport const toolOptions = {};\n\n/**\n * Default tool list.\n *\n * @type {Object<string, any>}\n */\nexport const defaultToolList = {\n  WindowLevel,\n  Scroll,\n  ZoomAndPan,\n  Opacity,\n  Draw,\n  Filter,\n  Floodfill,\n  Livewire\n};\n\n/**\n * Default tool options.\n *\n * @type {Object<string, Object<string, any>>}\n */\nexport const defaultToolOptions = {\n  draw: {\n    ArrowFactory,\n    CircleFactory,\n    EllipseFactory,\n    ProtractorFactory,\n    RectangleFactory,\n    RoiFactory,\n    RulerFactory\n  },\n  filter: {\n    Threshold,\n    Sobel,\n    Sharpen\n  }\n};","import {ScrollWheel} from './scrollWheel';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {\n  validateWindowWidth,\n  WindowLevel as WindowLevelValues\n} from '../image/windowLevel';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {Point2D} from '../math/point';\n/* eslint-enable no-unused-vars */\n\n/**\n * WindowLevel tool: handle window/level related events.\n *\n * @example\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {WindowLevel: new dwv.ToolConfig()};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('WindowLevel');\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n */\nexport class WindowLevel {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Start point.\n   *\n   * @type {Point2D}\n   */\n  #startPoint;\n\n  /**\n   * Scroll wheel handler.\n   *\n   * @type {ScrollWheel}\n   */\n  #scrollWhell;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n    this.#scrollWhell = new ScrollWheel(app);\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   */\n  #start(point, divId) {\n    // check if possible\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer === 'undefined') {\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n    if (!viewController.isMonochrome()) {\n      return;\n    }\n\n    this.#started = true;\n    this.#startPoint = point;\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    // check start flag\n    if (!this.#started) {\n      return;\n    }\n\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer === 'undefined') {\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n\n    // difference to last position\n    const diffX = point.getX() - this.#startPoint.getX();\n    const diffY = this.#startPoint.getY() - point.getY();\n    // data range\n    const range = viewController.getImageRescaledDataRange();\n    // 1/1000 seems to give reasonable results...\n    const pixelToIntensity = (range.max - range.min) * 0.01;\n\n    // calculate new window level\n    const center = viewController.getWindowLevel().center;\n    const width = viewController.getWindowLevel().width;\n    const windowCenter = center + Math.round(diffY * pixelToIntensity);\n    let windowWidth = width + Math.round(diffX * pixelToIntensity);\n    // bound window width\n    windowWidth = validateWindowWidth(windowWidth);\n    // set\n    const wl = new WindowLevelValues(windowCenter, windowWidth);\n    viewController.setWindowLevel(wl);\n\n    // store position\n    this.#startPoint = point;\n  }\n\n  /**\n   * Finish tool interaction.\n   */\n  #finish() {\n    if (this.#started) {\n      this.#started = false;\n    }\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} _event The mouse up event.\n   */\n  mouseup = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} _event The touch end event.\n   */\n  touchend = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle double click event.\n   *\n   * @param {object} event The double click event.\n   */\n  dblclick = (event) => {\n    const layerDetails = getLayerDetailsFromEvent(event);\n    const mousePoint = getMousePoint(event);\n\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    const viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer === 'undefined') {\n      return;\n    }\n    const index = viewLayer.displayToPlaneIndex(mousePoint);\n    const viewController = viewLayer.getViewController();\n    // exit if not possible\n    if (!viewController.isMonochrome()) {\n      return;\n    }\n\n    // update view controller\n    const image = this.#app.getData(viewLayer.getDataId()).image;\n    const wl = new WindowLevelValues(\n      image.getRescaledValueAtIndex(\n        viewController.getCurrentIndex().getWithNew2D(\n          index.get(0),\n          index.get(1)\n        )\n      ),\n      viewController.getWindowLevel().width\n    );\n    viewController.setWindowLevel(wl);\n  };\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {WheelEvent} event The mouse wheel event.\n   */\n  wheel = (event) => {\n    this.#scrollWhell.wheel(event);\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'WindowLevel';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} _bool The flag to activate or not.\n   */\n  activate(_bool) {\n    // does nothing\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Set the tool live features: does nothing.\n   *\n   * @param {object} _features The list of features.\n   */\n  setFeatures(_features) {\n    // does nothing\n  }\n\n} // WindowLevel class\n","import {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {ScrollWheel} from './scrollWheel';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {Point2D} from '../math/point';\nimport {LayerGroup} from '../gui/layerGroup';\nimport {ViewLayer} from '../gui/viewLayer';\n/* eslint-enable no-unused-vars */\n\n/**\n * Scroll class.\n *\n * @example\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {Scroll: new dwv.ToolConfig()};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('Scroll');\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm',\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323707.dcm',\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323563.dcm'\n * ]);\n * @example <caption>Example with slider</caption>\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {Scroll: new dwv.ToolConfig()};\n * app.init(options);\n * // create range\n * const range = document.createElement('input');\n * range.type = 'range';\n * range.min = 0;\n * range.id = 'sliceRange';\n * document.body.appendChild(range);\n * // update app on slider change\n * range.oninput = function () {\n *   const lg = app.getLayerGroupByDivId('layerGroup0');\n *   const vl = lg.getBaseViewLayer();\n *   const vc = vl.getViewController();\n *   const index = vc.getCurrentIndex();\n *   const values = index.getValues();\n *   values[2] = this.value;\n *   vc.setCurrentIndex(new dwv.Index(values));\n * }\n * // activate tool and update range max on load\n * app.addEventListener('load', function () {\n *   app.setTool('Scroll');\n *   const size = app.getData(0).image.getGeometry().getSize();\n *   range.max = size.get(2) - 1;\n * });\n * // update slider on slice change (for ex via mouse wheel)\n * app.addEventListener('positionchange', function () {\n *   const lg = app.getLayerGroupByDivId('layerGroup0');\n *   const vl = lg.getBaseViewLayer();\n *   const vc = vl.getViewController();\n *   range.value = vc.getCurrentIndex().get(2);\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm',\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323707.dcm',\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323563.dcm'\n * ]);\n */\nexport class Scroll {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Start point.\n   *\n   * @type {Point2D}\n   */\n  #startPoint;\n\n  /**\n   * Scroll wheel handler.\n   *\n   * @type {ScrollWheel}\n   */\n  #scrollWhell;\n\n  /**\n   * Touch timer ID (created by setTimeout).\n   *\n   * @type {number}\n   */\n  #touchTimerID;\n\n  /**\n   * Option to show or not a value tooltip on mousemove.\n   *\n   * @type {boolean}\n   */\n  #displayTooltip = false;\n\n  /**\n   * Current layer group div id.\n   *\n   * @type {string}\n   */\n  #currentDivId;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n    this.#scrollWhell = new ScrollWheel(app);\n  }\n\n  /**\n   * Get the associated view layer.\n   *\n   * @param {LayerGroup} layerGroup The layer group to search.\n   * @returns {ViewLayer|undefined} The view layer.\n   */\n  #getViewLayer(layerGroup) {\n    let viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer === 'undefined') {\n      const drawLayer = layerGroup.getActiveDrawLayer();\n      if (typeof drawLayer === 'undefined') {\n        logger.warn('No draw layer to do scroll');\n        return;\n      }\n      viewLayer = layerGroup.getViewLayerById(\n        drawLayer.getReferenceLayerId());\n    }\n    return viewLayer;\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   */\n  #start(point, divId) {\n    // optional tooltip\n    this.#removeTooltipDiv();\n\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to start scroll');\n      return;\n    }\n\n    const viewController = viewLayer.getViewController();\n\n    // stop auto scroll if playing\n    if (viewController.isPlaying()) {\n      viewController.stop();\n    }\n    // update base controller position\n    const planePos = viewLayer.displayToPlanePos(point);\n    const position = viewController.getPositionFromPlanePoint(planePos);\n    viewController.setCurrentPosition(position);\n\n    // start flag\n    this.#started = true;\n    this.#startPoint = point;\n\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    if (!this.#started) {\n      // optional tooltip\n      if (this.#displayTooltip) {\n        this.#showTooltip(point, divId);\n      }\n      return;\n    }\n\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const positionHelper = layerGroup.getPositionHelper();\n\n    // difference to last Y position\n    const diffY = point.getY() - this.#startPoint.getY();\n    const yMove = (Math.abs(diffY) > 15);\n    // difference to last X position\n    const diffX = point.getX() - this.#startPoint.getX();\n    const xMove = (Math.abs(diffX) > 15);\n\n    // do not trigger for small moves\n    if (yMove && layerGroup.canScroll()) {\n      // update view controller\n      if (diffY > 0) {\n        positionHelper.decrementPositionAlongScroll();\n      } else {\n        positionHelper.incrementPositionAlongScroll();\n      }\n    } else if (xMove && layerGroup.moreThanOne(3)) {\n      // update view controller\n      if (diffX > 0) {\n        positionHelper.incrementPosition(3);\n      } else {\n        positionHelper.decrementPosition(3);\n      }\n    }\n\n    // reset origin point\n    if (xMove || yMove) {\n      this.#startPoint = point;\n    }\n  }\n\n  /**\n   * Finish tool interaction.\n   */\n  #finish() {\n    if (this.#started) {\n      this.#started = false;\n    }\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} _event The mouse up event.\n   */\n  mouseup = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    this.#finish();\n    // remove possible tooltip div\n    this.#removeTooltipDiv();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    // long touch triggers the dblclick\n    // @ts-ignore\n    this.#touchTimerID = setTimeout(() => {\n      this.dblclick(event);\n    }, 500);\n    // call start\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    // abort timer if move\n    if (this.#touchTimerID !== null) {\n      clearTimeout(this.#touchTimerID);\n      this.#touchTimerID = null;\n    }\n    // call update\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} _event The touch end event.\n   */\n  touchend = (_event) => {\n    // abort timer\n    if (this.#touchTimerID !== null) {\n      clearTimeout(this.#touchTimerID);\n      this.#touchTimerID = null;\n    }\n    // call mouse equivalent\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {WheelEvent} event The mouse wheel event.\n   */\n  wheel = (event) => {\n    this.#scrollWhell.wheel(event);\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'Scroll';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Handle double click.\n   *\n   * @param {object} event The key down event.\n   */\n  dblclick = (event) => {\n    const layerDetails = getLayerDetailsFromEvent(event);\n\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    const viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer !== 'undefined') {\n      const viewController = viewLayer.getViewController();\n      viewController.play();\n    }\n  };\n\n  /**\n   * Display a tooltip at the given point.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #showTooltip(point, divId) {\n    // get layer group\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    this.#currentDivId = divId;\n    // show new tooltip\n    layerGroup.showTooltip(point);\n  }\n\n  /**\n   * Remove the last tooltip html div.\n   */\n  #removeTooltipDiv() {\n    if (typeof this.#currentDivId !== 'undefined') {\n      const layerGroup = this.#app.getLayerGroupByDivId(this.#currentDivId);\n      layerGroup.removeTooltipDiv();\n      this.#currentDivId = undefined;\n    }\n  }\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} _bool The flag to activate or not.\n   */\n  activate(_bool) {\n    // remove tooltip html when deactivating\n    if (!_bool) {\n      this.#removeTooltipDiv();\n    }\n  }\n\n  /**\n   * Set the tool live features: disaply tooltip.\n   *\n   * @param {object} features The list of features.\n   */\n  setFeatures(features) {\n    if (typeof features.displayTooltip !== 'undefined') {\n      this.#displayTooltip = features.displayTooltip;\n    }\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n} // Scroll class\n","import {Point2D} from '../math/point';\nimport {Line} from '../math/line';\nimport {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {LayerGroup} from '../gui/layerGroup';\nimport {ViewLayer} from '../gui/viewLayer';\n/* eslint-enable no-unused-vars */\n\n/**\n * ZoomAndPan class.\n *\n * @example\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {ZoomAndPan: new dwv.ToolConfig()};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('ZoomAndPan');\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n */\nexport class ZoomAndPan {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Start point.\n   *\n   * @type {Point2D}\n   */\n  #startPoint;\n\n  /**\n   * Move flag: true if mouse or touch move.\n   *\n   * @type {boolean}\n   */\n  #hasMoved;\n\n  /**\n   * Line between input points.\n   *\n   * @type {Line}\n   */\n  #pointsLine;\n\n  /**\n   * PointsLine midpoint.\n   *\n   * @type {Point2D}\n   */\n  #midPoint;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Get the associated view layer.\n   *\n   * @param {LayerGroup} layerGroup The layer group to search.\n   * @returns {ViewLayer|undefined} The view layer.\n   */\n  #getViewLayer(layerGroup) {\n    let viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer === 'undefined') {\n      const drawLayer = layerGroup.getActiveDrawLayer();\n      if (typeof drawLayer === 'undefined') {\n        logger.warn('No draw layer to do zoom/pan');\n        return;\n      }\n      viewLayer = layerGroup.getViewLayerById(\n        drawLayer.getReferenceLayerId());\n    }\n    return viewLayer;\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   */\n  #start(point) {\n    this.#started = true;\n    this.#startPoint = point;\n    this.#hasMoved = false;\n  }\n\n  /**\n   * Two touch start.\n   *\n   * @param {Point2D[]} points The start points.\n   */\n  #twoTouchStart = (points) => {\n    this.#started = true;\n    this.#startPoint = points[0];\n    this.#hasMoved = false;\n    // points line\n    this.#pointsLine = new Line(points[0], points[1]);\n    this.#midPoint = this.#pointsLine.getMidpoint();\n  };\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    if (!this.#started) {\n      return;\n    }\n    this.#hasMoved = true;\n\n    // calculate translation\n    const tx = point.getX() - this.#startPoint.getX();\n    const ty = point.getY() - this.#startPoint.getY();\n    // apply translation\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to update zoom/pan');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n    const planeOffset = viewLayer.displayToPlaneScale(\n      new Point2D(tx, ty)\n    );\n    const offset3D = viewController.getOffset3DFromPlaneOffset({\n      x: planeOffset.getX(),\n      y: planeOffset.getY()\n    });\n    layerGroup.addTranslation({\n      x: offset3D.getX(),\n      y: offset3D.getY(),\n      z: offset3D.getZ()\n    });\n    layerGroup.draw();\n    // reset origin point\n    this.#startPoint = point;\n  }\n\n  /**\n   * Two touch update.\n   *\n   * @param {Point2D[]} points The update points.\n   * @param {string} divId The layer group divId.\n   */\n  #twoTouchUpdate = (points, divId) => {\n    if (!this.#started) {\n      return;\n    }\n    this.#hasMoved = true;\n\n    const newLine = new Line(points[0], points[1]);\n    const lineRatio = newLine.getLength() / this.#pointsLine.getLength();\n\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const positionHelper = layerGroup.getPositionHelper();\n\n    if (lineRatio === 1) {\n      // scroll mode\n      // difference  to last position\n      const diffY = points[0].getY() - this.#startPoint.getY();\n      // do not trigger for small moves\n      if (Math.abs(diffY) < 15) {\n        return;\n      }\n      // update view controller\n      if (layerGroup.canScroll()) {\n        if (diffY > 0) {\n          positionHelper.incrementPositionAlongScroll();\n        } else {\n          positionHelper.decrementPositionAlongScroll();\n        }\n      }\n    } else {\n      // zoom mode\n      const zoom = (lineRatio - 1) / 10;\n      if (Math.abs(zoom) % 0.1 <= 0.05 &&\n        typeof this.#midPoint !== 'undefined') {\n        const viewLayer = this.#getViewLayer(layerGroup);\n        if (typeof viewLayer === 'undefined') {\n          logger.warn('No view layer to do touch zoom/pan');\n          return;\n        }\n        const viewController = viewLayer.getViewController();\n        const planePos = viewLayer.displayToMainPlanePos(this.#midPoint);\n        const center = viewController.getPlanePositionFromPlanePoint(planePos);\n        layerGroup.addScale(zoom, center);\n        layerGroup.draw();\n      }\n    }\n  };\n\n  /**\n   * Set the current position.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #setCurrentPosition(point, divId) {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to set current position');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n    const planePos = viewLayer.displayToPlanePos(point);\n    const position = viewController.getPositionFromPlanePoint(planePos);\n    viewController.setCurrentPosition(position);\n  }\n\n  /**\n   * Finish tool interaction.\n   */\n  #finish() {\n    if (this.#started) {\n      this.#started = false;\n    }\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    this.#start(mousePoint);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} event The mouse up event.\n   */\n  mouseup = (event) => {\n    // update position if no move\n    if (!this.#hasMoved) {\n      const mousePoint = getMousePoint(event);\n      const layerDetails = getLayerDetailsFromEvent(event);\n      this.#setCurrentPosition(mousePoint, layerDetails.groupDivId);\n    }\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    const touchPoints = getTouchPoints(event);\n    if (touchPoints.length === 1) {\n      this.#start(touchPoints[0]);\n    } else if (touchPoints.length === 2) {\n      this.#twoTouchStart(touchPoints);\n    }\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    if (touchPoints.length === 1) {\n      this.#update(touchPoints[0], layerDetails.groupDivId);\n    } else if (touchPoints.length === 2) {\n      this.#twoTouchUpdate(touchPoints, layerDetails.groupDivId);\n    }\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} event The touch end event.\n   */\n  touchend = (event) => {\n    // update position if no move\n    if (!this.#hasMoved) {\n      const mousePoint = getMousePoint(event);\n      const layerDetails = getLayerDetailsFromEvent(event);\n      this.#setCurrentPosition(mousePoint, layerDetails.groupDivId);\n    }\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {object} event The mouse wheel event.\n   */\n  wheel = (event) => {\n    // prevent default page scroll\n    event.preventDefault();\n\n    const step = -event.deltaY / 500;\n\n    const layerDetails = getLayerDetailsFromEvent(event);\n    const mousePoint = getMousePoint(event);\n\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to do wheel zoom/pan');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n    const planePos = viewLayer.displayToMainPlanePos(mousePoint);\n    const center = viewController.getPlanePositionFromPlanePoint(planePos);\n    layerGroup.addScale(step, center);\n    layerGroup.draw();\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'ZoomAndPan';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} _bool The flag to activate or not.\n   */\n  activate(_bool) {\n    // does nothing\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Set the tool live features: does nothing.\n   *\n   * @param {object} _features The list of features.\n   */\n  setFeatures(_features) {\n    // does nothing\n  }\n\n} // ZoomAndPan class\n","import {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {ScrollWheel} from './scrollWheel';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {Point2D} from '../math/point';\n/* eslint-enable no-unused-vars */\n\n/**\n * Opacity class.\n *\n * @example\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {Opacity: new dwv.ToolConfig()};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('Opacity');\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n */\nexport class Opacity {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Start point.\n   *\n   * @type {Point2D}\n   */\n  #startPoint;\n\n  /**\n   * Scroll wheel handler.\n   *\n   * @type {ScrollWheel}\n   */\n  #scrollWhell;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n    this.#scrollWhell = new ScrollWheel(app);\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   */\n  #start(point) {\n    this.#started = true;\n    this.#startPoint = point;\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    if (!this.#started) {\n      return;\n    }\n\n    // difference to last X position\n    const diffX = point.getX() - this.#startPoint.getX();\n    const xMove = (Math.abs(diffX) > 15);\n    // do not trigger for small moves\n    if (xMove) {\n      const layerGroup = this.#app.getLayerGroupByDivId(divId);\n      const layer = layerGroup.getActiveLayer();\n      const op = layer.getOpacity();\n      layer.setOpacity(op + (diffX / 200));\n      layer.draw();\n\n      // reset origin point\n      this.#startPoint = point;\n    }\n  }\n\n  /**\n   * Finish tool interaction.\n   */\n  #finish() {\n    if (this.#started) {\n      this.#started = false;\n    }\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    this.#start(mousePoint);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} _event The mouse up event.\n   */\n  mouseup = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    const touchPoints = getTouchPoints(event);\n    this.#start(touchPoints[0]);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} _event The touch end event.\n   */\n  touchend = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {object} event The mouse wheel event.\n   */\n  wheel = (event) => {\n    this.#scrollWhell.wheel(event);\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'Opacity';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} _bool The flag to activate or not.\n   */\n  activate(_bool) {\n    // does nothing\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Set the tool live features: does nothing.\n   *\n   * @param {object} _features The list of features.\n   */\n  setFeatures(_features) {\n    // does nothing\n  }\n\n} // Opacity class\n","import {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {guid} from '../math/stats';\nimport {logger} from '../utils/logger';\nimport {\n  AddAnnotationCommand,\n  RemoveAnnotationCommand\n} from './drawCommands';\nimport {\n  isNodeNameShape,\n} from './drawBounds';\nimport {Annotation} from '../image/annotation';\nimport {ScrollWheel} from './scrollWheel';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {Style} from '../gui/style';\nimport {LayerGroup} from '../gui/layerGroup';\nimport {Point2D} from '../math/point';\nimport {DrawLayer} from '../gui/drawLayer';\nimport {ViewLayer} from '../gui/viewLayer';\nimport {DrawShapeHandler} from './drawShapeHandler';\n/* eslint-enable no-unused-vars */\n\n/**\n * Drawing tool.\n *\n * This tool is responsible for the draw of layer group structure.\n *\n * ```\n * drawLayer\n * |_ positionGroup: {name=\"position-group\", id=\"#2-0#_#3-1\"}\n *    |_ shapeGroup: {name=\"{shape name}-group\", id=\"#\"}\n *       |_ shape: {name=\"shape\"},\n *       |_ label: {name=\"label\"},\n *       |_ extra: line tick, protractor arc...\n * ```\n *\n * Discussion:\n * - posGroup > shapeGroup:\n *   (pro) slice/frame display: 1 loop -\n *   (cons) multi-slice shape splitted in positionGroups.\n * - shapeGroup > posGroup:\n *   (pros) more logical -\n *   (cons) slice/frame display: 2 loops.\n */\nexport class Draw {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Scroll wheel handler.\n   *\n   * @type {ScrollWheel}\n   */\n  #scrollWhell;\n\n  /**\n   * Drawing style.\n   *\n   * @type {Style}\n   */\n  #style;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #isDrawing = false;\n\n  /**\n   * Shape factory list.\n   *\n   * @type {object}\n   */\n  #shapeFactoryList = null;\n\n  /**\n   * Current shape factory.\n   *\n   * @type {object}\n   */\n  #currentFactory = null;\n\n  /**\n   * Current shape group.\n   *\n   * @type {object}\n   */\n  #tmpShapeGroup = null;\n\n  /**\n   * Shape name.\n   *\n   * @type {string}\n   */\n  #shapeName;\n\n  /**\n   * List of points.\n   *\n   * @type {Point2D[]}\n   */\n  #points = [];\n\n  /**\n   * Last selected point.\n   *\n   * @type {Point2D}\n   */\n  #lastPoint = null;\n\n  /**\n   * With scroll flag.\n   *\n   * @type {boolean}\n   */\n  #withScroll = true;\n\n  /**\n   * Black list: list of dataIds for which draw layer creation\n   *   is forbidden.\n   */\n  #blacklist = [];\n\n  /**\n   * Shape handler: activate listeners on existing shape.\n   *\n   * @type {DrawShapeHandler}\n   */\n  #shapeHandler;\n\n  /**\n   * Auto shape colour: will use defaults colours and\n   * vary them according to the layer.\n   *\n   * @type {boolean}\n   */\n  #autoShapeColour = false;\n\n  /**\n   * Event listeners.\n   */\n  #listeners = {};\n\n  /**\n   * Flag to know if the last added point was made by mouse move.\n   *\n   * @type {boolean}\n   */\n  #lastIsMouseMovePoint = false;\n\n  /**\n   * Callback store to allow attach/detach.\n   *\n   * @type {Array}\n   */\n  #callbackStore = [];\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n    this.#scrollWhell = new ScrollWheel(app);\n    this.#shapeHandler = new DrawShapeHandler(app, this.#fireEvent);\n\n    this.#style = app.getStyle();\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   */\n  #switchEditOrCreateShapeGroup(point, divId) {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    let drawLayer = layerGroup.getActiveDrawLayer();\n\n    if (typeof drawLayer === 'undefined') {\n      const viewLayer = layerGroup.getActiveViewLayer();\n      const refDataId = viewLayer.getDataId();\n      const refData = this.#app.getData(refDataId);\n      const refMeta = refData.image.getMeta();\n      const seriesInstanceUID = refMeta.SeriesInstanceUID;\n      // check black list\n      if (this.#blacklist.includes(seriesInstanceUID)) {\n        /**\n         * Warn event.\n         *\n         * @event Draw#warn\n         * @type {object}\n         * @property {string} type The event type.\n         * @property {string} message The warning message.\n         */\n        this.#fireEvent({\n          type: 'warn',\n          message: 'Cannot create draw layer, data is in black list'\n        });\n        return;\n      }\n      // create new data\n      const data = this.#app.createAnnotationData(refDataId);\n      // render (will create draw layer)\n      this.#app.addAndRenderAnnotationData(data, divId, refDataId);\n      // get draw layer\n      drawLayer = layerGroup.getActiveDrawLayer();\n      // set the layer shape handler\n      drawLayer.setShapeHandler(this.#shapeHandler);\n      // set active to bind to toolboxController\n      layerGroup.setActiveLayerByDataId(drawLayer.getDataId());\n    }\n\n    // data should exist / be created\n    const data = drawLayer.getDrawController().getAnnotationGroup();\n\n    const stage = drawLayer.getKonvaStage();\n\n    // update scale\n    this.#style.setZoomScale(stage.scale());\n\n    if (data.isEditable()) {\n      // determine if the click happened on an existing shape or not\n      const kshape = stage.getIntersection({\n        x: point.getX(),\n        y: point.getY()\n      });\n      if (kshape) {\n        // select shape for edition\n        this.#selectShapeGroup(drawLayer, kshape);\n      } else {\n        // create new shape\n        this.#startShapeGroupCreation(layerGroup, point);\n      }\n    }\n  }\n\n  /**\n   * Get the associated view layer.\n   *\n   * @param {LayerGroup} layerGroup The layer group to search.\n   * @returns {ViewLayer|undefined} The view layer.\n   */\n  #getViewLayer(layerGroup) {\n    const drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      logger.warn('No draw layer to do draw');\n      return;\n    }\n    return layerGroup.getViewLayerById(\n      drawLayer.getReferenceLayerId());\n  }\n\n  /**\n   * Initializes the new shape creation:\n   * - Updates the started variable,\n   * - Gets the factory,\n   * - Initializes the points array.\n   *\n   * @param {LayerGroup} layerGroup The layer group where the user clicks.\n   * @param {Point2D} point The start point where the user clicks.\n   */\n  #startShapeGroupCreation(layerGroup, point) {\n    // disable edition\n    this.#shapeHandler.disableAndResetEditor();\n    this.#setToDrawingState();\n    // store point\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to start shape');\n      return;\n    }\n    this.#lastPoint = viewLayer.displayToPlanePos(point);\n    this.#points.push(this.#lastPoint);\n  }\n\n  /**\n   * Sets the variables to drawing state:\n   * - Updates is drawing variable,\n   * - Initializes the current factory,\n   * - Resets points.\n   */\n  #setToDrawingState() {\n    // start storing points\n    this.#isDrawing = true;\n    // set factory\n    this.#currentFactory = new this.#shapeFactoryList[this.#shapeName]();\n    // clear array\n    this.#points = [];\n  }\n\n  /**\n   * Resets the variables to not drawing state:\n   * - Destroys tmp shape group,\n   * - Updates is drawing variable,\n   * - Resets points.\n   */\n  #setToNotDrawingState() {\n    this.#isDrawing = false;\n    this.#points = [];\n  }\n\n  /**\n   * Selects a shape group.\n   *\n   * @param {DrawLayer} drawLayer The draw layer where to draw.\n   * @param {Konva.Shape} kshape The shape that has been selected.\n   */\n  #selectShapeGroup(drawLayer, kshape) {\n    let group = kshape.getParent();\n    // kshape: Konva.Tag -> parent: Konva.Label -> parent: Konva.Group\n    if (kshape instanceof Konva.Tag) {\n      group = group.getParent();\n    }\n    const selectedShape = group.find('.shape')[0];\n    if (!(selectedShape instanceof Konva.Shape)) {\n      return;\n    }\n    /**\n     * Annotation select event.\n     *\n     * @event Draw#annotationselect\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} annotationid The annotation id.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'annotationselect',\n      annotationid: group.id(),\n      dataid: drawLayer.getDataId()\n    });\n    this.#shapeHandler.setEditorShape(selectedShape, drawLayer);\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #updateShapeGroupCreation(point, divId) {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to update shape');\n      return;\n    }\n    const pos = viewLayer.displayToPlanePos(point);\n\n    // draw line to current pos\n    if (Math.abs(pos.getX() - this.#lastPoint.getX()) > 0 ||\n      Math.abs(pos.getY() - this.#lastPoint.getY()) > 0) {\n      // clear last mouse move point\n      if (this.#lastIsMouseMovePoint) {\n        this.#points.pop();\n      }\n      // current point\n      this.#lastPoint = pos;\n      // mark it as temporary\n      this.#lastIsMouseMovePoint = true;\n      // add it to the list\n      this.#points.push(this.#lastPoint);\n      // update points\n      this.#onNewPoints(this.#points, layerGroup);\n    }\n  }\n\n  /**\n   * Finish tool interaction.\n   *\n   * @param {string} divId The layer group divId.\n   */\n  #finishShapeGroupCreation(divId) {\n    // exit if no points\n    if (this.#points.length === 0) {\n      logger.warn('Draw mouseup but no points...');\n      return;\n    }\n\n    // do we have all the needed points\n    if (this.#points.length === this.#currentFactory.getNPoints()) {\n      // store points\n      const layerGroup =\n        this.#app.getLayerGroupByDivId(divId);\n      this.#onFinalPoints(this.#points, layerGroup);\n      this.#setToNotDrawingState();\n    }\n\n    // reset mouse move point flag\n    this.#lastIsMouseMovePoint = false;\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    // exit if not started draw\n    if (this.#isDrawing) {\n      return;\n    }\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#switchEditOrCreateShapeGroup(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    // exit if not started draw\n    if (!this.#isDrawing) {\n      return;\n    }\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#updateShapeGroupCreation(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} event The mouse up event.\n   */\n  mouseup = (event) => {\n    // exit if not started draw\n    if (!this.#isDrawing) {\n      return;\n    }\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#finishShapeGroupCreation(layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle double click event: some tools use it to finish interaction.\n   *\n   * @param {object} event The double click event.\n   */\n  dblclick = (event) => {\n    // only end by double click undefined NPoints\n    if (this.#currentFactory &&\n      typeof this.#currentFactory.getNPoints() !== 'undefined') {\n      return;\n    }\n    // exit if not started draw\n    if (!this.#isDrawing) {\n      return;\n    }\n    // exit if no points\n    if (this.#points.length === 0) {\n      logger.warn('Draw dblclick but no points...');\n      return;\n    }\n\n    // store points\n    const layerDetails = getLayerDetailsFromEvent(event);\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    this.#onFinalPoints(this.#points, layerGroup);\n    this.#setToNotDrawingState();\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} event The mouse out event.\n   */\n  mouseout = (event) => {\n    // exit if not started draw\n    if (!this.#isDrawing) {\n      return;\n    }\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#finishShapeGroupCreation(layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    // exit if not started draw\n    if (this.#isDrawing) {\n      return;\n    }\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#switchEditOrCreateShapeGroup(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    // exit if not started draw\n    if (!this.#isDrawing) {\n      return;\n    }\n\n    const layerDetails = getLayerDetailsFromEvent(event);\n    const touchPoints = getTouchPoints(event);\n\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to handle touch move');\n      return;\n    }\n    const pos = viewLayer.displayToPlanePos(touchPoints[0]);\n\n    if (Math.abs(pos.getX() - this.#lastPoint.getX()) > 0 ||\n      Math.abs(pos.getY() - this.#lastPoint.getY()) > 0) {\n      // clear last added point from the list (but not the first one)\n      if (this.#points.length !== 1) {\n        this.#points.pop();\n      }\n      // current point\n      this.#lastPoint = pos;\n      // add current one to the list\n      this.#points.push(this.#lastPoint);\n      // allow for anchor points\n      if (this.#points.length < this.#currentFactory.getNPoints()) {\n        clearTimeout(this.timer);\n        this.timer = setTimeout(() => {\n          this.#points.push(this.#lastPoint);\n        }, this.#currentFactory.getTimeout());\n      }\n      // update points\n      this.#onNewPoints(this.#points, layerGroup);\n    }\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} event The touch end event.\n   */\n  touchend = (event) => {\n    this.dblclick(event);\n  };\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {WheelEvent} event The mouse wheel event.\n   */\n  wheel = (event) => {\n    if (this.#withScroll) {\n      this.#scrollWhell.wheel(event);\n    }\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    // call app handler if we are not in the middle of a draw\n    if (!this.#isDrawing) {\n      event.context = 'Draw';\n      this.#app.onKeydown(event);\n    }\n\n    // press delete or backspace key\n    const annotation = this.#shapeHandler.getEditorAnnotation();\n    if ((event.key === 'Delete' ||\n      event.key === 'Backspace') &&\n      typeof annotation !== 'undefined') {\n      const layerGroup = this.#app.getActiveLayerGroup();\n      const drawLayer = layerGroup.getActiveDrawLayer();\n      if (typeof drawLayer === 'undefined') {\n        logger.warn('No draw layer to handle key down');\n        return;\n      }\n      const drawController = drawLayer.getDrawController();\n\n      // create remove annotation command\n      const command = new RemoveAnnotationCommand(annotation, drawController);\n      // add command to undo stack\n      this.#app.addToUndoStack(command);\n      // execute command: triggers draw remove\n      command.execute();\n\n      // reset cursor\n      this.#shapeHandler.onMouseOutShapeGroup();\n    }\n\n    // escape key: exit shape creation\n    if (event.key === 'Escape' && this.#tmpShapeGroup !== null) {\n      const konvaLayer = this.#tmpShapeGroup.getLayer();\n      // reset temporary shape group\n      this.#tmpShapeGroup.destroy();\n      this.#tmpShapeGroup = null;\n      // set state\n      this.#setToNotDrawingState();\n      // redraw\n      konvaLayer.draw();\n    }\n  };\n\n  /**\n   * Update the current draw with new points.\n   *\n   * @param {Point2D[]} tmpPoints The array of new points.\n   * @param {LayerGroup} layerGroup The origin layer group.\n   */\n  #onNewPoints(tmpPoints, layerGroup) {\n    // remove temporary shape draw\n    if (this.#tmpShapeGroup) {\n      this.#tmpShapeGroup.destroy();\n      this.#tmpShapeGroup = null;\n    }\n\n    const drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      logger.warn('No draw layer to handle new points');\n      return;\n    }\n    const drawController = drawLayer.getDrawController();\n    const konvaLayer = drawLayer.getKonvaLayer();\n    const viewLayer = layerGroup.getViewLayerById(\n      drawLayer.getReferenceLayerId());\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to handle new points');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n\n    // auto mode: vary shape colour with layer id\n    if (this.#autoShapeColour) {\n      const colours = [\n        '#ffff80', '#ff80ff', '#80ffff', '#80ff80', '8080ff', 'ff8080'\n      ];\n      // warning: depends on layer id nomenclature\n      const drawLayerId = drawLayer.getId();\n      const layerId = drawLayerId.substring(drawLayerId.length - 1);\n      const layerIndex = parseInt(layerId, 10) - 1;\n      const colour = colours[layerIndex];\n      if (typeof colour !== 'undefined') {\n        this.#style.setLineColour(colour);\n      }\n    }\n\n    // create tmp annotation\n    const annotation = new Annotation();\n    // use group colour if defined\n    const groupColour = drawController.getAnnotationGroup().getColour();\n    if (typeof groupColour !== 'undefined') {\n      annotation.colour = groupColour;\n    } else {\n      annotation.colour = this.#style.getLineColour();\n    }\n    annotation.init(viewController);\n    // set annotation shape\n    this.#currentFactory.setAnnotationMathShape(annotation, tmpPoints);\n    // create shape group\n    this.#tmpShapeGroup =\n      this.#currentFactory.createShapeGroup(annotation, this.#style);\n    // set the label visibility\n    drawLayer.setLabelVisibility(this.#tmpShapeGroup);\n\n    // do not listen during creation\n    const shape = this.#tmpShapeGroup.getChildren(isNodeNameShape)[0];\n    shape.listening(false);\n    konvaLayer.listening(false);\n    // draw shape\n    konvaLayer.add(this.#tmpShapeGroup);\n    konvaLayer.draw();\n  }\n\n  /**\n   * Create the final shape from a point list.\n   *\n   * @param {Point2D[]} finalPoints The array of points.\n   * @param {LayerGroup} layerGroup The origin layer group.\n   */\n  #onFinalPoints(finalPoints, layerGroup) {\n    // remove temporary shape draw\n    // (has to be done before sending add event)\n    if (this.#tmpShapeGroup) {\n      this.#tmpShapeGroup.destroy();\n      this.#tmpShapeGroup = null;\n    }\n\n    const drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      logger.warn('No draw layer to handle final points');\n      return;\n    }\n    const konvaLayer = drawLayer.getKonvaLayer();\n    const drawController = drawLayer.getDrawController();\n    const viewLayer = layerGroup.getViewLayerById(\n      drawLayer.getReferenceLayerId());\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to handle final points');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n\n    // create final annotation\n    const annotation = new Annotation();\n    // use group colour if defined\n    const groupColour = drawController.getAnnotationGroup().getColour();\n    if (typeof groupColour !== 'undefined') {\n      annotation.colour = groupColour;\n    } else {\n      annotation.colour = this.#style.getLineColour();\n    }\n    annotation.id = guid();\n    annotation.init(viewController);\n    // set annotation shape\n    this.#currentFactory.setAnnotationMathShape(annotation, finalPoints);\n\n    // create add annotation command\n    const command = new AddAnnotationCommand(annotation, drawController);\n    // add command to undo stack\n    this.#app.addToUndoStack(command);\n    // execute command: triggers draw creation\n    command.execute();\n\n    // re-activate layer\n    konvaLayer.listening(true);\n  }\n\n  /**\n   * Get a DrawLayer position callback.\n   *\n   * TODO: check need for store item removal.\n   *\n   * @param {DrawLayer} layer The layer to update.\n   * @returns {Function} The callback.\n   */\n  #getPositionCallback(layer) {\n    const layerId = layer.getId();\n    if (typeof this.#callbackStore[layerId] === 'undefined') {\n      this.#callbackStore[layerId] = () => {\n        layer.activateCurrentPositionShapes(true);\n      };\n    }\n    return this.#callbackStore[layerId];\n  }\n\n  /**\n   * Activate a draw layer.\n   *\n   * @param {DrawLayer} drawLayer The layer to update.\n   * @param {boolean} flag The flag to activate or not.\n   */\n  #activateLayer(drawLayer, flag) {\n    drawLayer.setShapeHandler(this.#shapeHandler);\n    drawLayer.activateCurrentPositionShapes(flag);\n    // update on position change\n    if (flag) {\n      this.#app.addEventListener('positionchange',\n        this.#getPositionCallback(drawLayer)\n      );\n    } else {\n      this.#app.removeEventListener('positionchange',\n        this.#getPositionCallback(drawLayer)\n      );\n    }\n  }\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} flag The flag to activate or not.\n   */\n  activate(flag) {\n    // force cursor if deactivate\n    if (!flag) {\n      this.#shapeHandler.onMouseOutShapeGroup();\n    }\n    // update draw layers\n    const drawLayers = this.#app.getDrawLayers();\n    for (const drawLayer of drawLayers) {\n      if (typeof drawLayer !== 'undefined') {\n        this.#activateLayer(drawLayer, flag);\n      }\n    }\n    // activate newly added layers\n    this.#app.addEventListener('drawlayeradd', (event) => {\n      const drawLayers = this.#app.getDrawLayers(function (item) {\n        return item.getId() === event.layerid;\n      });\n      // should be just one\n      if (drawLayers.length === 1) {\n        this.#activateLayer(drawLayers[0], flag);\n      }\n    });\n\n  }\n\n  /**\n   * Set the tool configuration options.\n   *\n   * @param {object} options The list of shape names amd classes.\n   */\n  setOptions(options) {\n    // save the options as the shape factory list\n    this.#shapeFactoryList = options;\n  }\n\n  /**\n   * Get the type of tool options: here 'factory' since the shape\n   * list contains factories to create each possible shape.\n   *\n   * @returns {string} The type.\n   */\n  getOptionsType() {\n    return 'factory';\n  }\n\n  /**\n   * Set the tool live features: shape colour and shape name.\n   *\n   * @param {object} features The list of features.\n   */\n  setFeatures(features) {\n    if (typeof features.autoShapeColour !== 'undefined') {\n      this.#autoShapeColour = features.autoShapeColour;\n    }\n    if (typeof features.shapeColour !== 'undefined') {\n      this.#style.setLineColour(features.shapeColour);\n      this.#autoShapeColour = false;\n    }\n    if (typeof features.shapeName !== 'undefined') {\n      // check if we have it\n      if (!this.hasShape(features.shapeName)) {\n        throw new Error('Unknown shape: \\'' + features.shapeName + '\\'');\n      }\n      this.#shapeName = features.shapeName;\n    }\n    if (typeof features.mouseOverCursor !== 'undefined') {\n      this.#shapeHandler.storeMouseOverCursor(features.mouseOverCursor);\n    }\n    if (typeof features.withScroll !== 'undefined') {\n      this.#withScroll = features.withScroll;\n    }\n    if (typeof features.blacklist !== 'undefined') {\n      this.#blacklist = features.blacklist;\n    }\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Get the list of event names that this tool can fire.\n   *\n   * @returns {string[]} The list of event names.\n   */\n  getEventNames() {\n    return [\n      'annotationupdate', 'annotationselect', 'warn'\n    ];\n  }\n\n  /**\n   * Add an event listener on the app.\n   *\n   * @param {string} type The event type.\n   * @param {Function} listener The function associated with the provided\n   *   event type.\n   */\n  addEventListener(type, listener) {\n    if (typeof this.#listeners[type] === 'undefined') {\n      this.#listeners[type] = [];\n    }\n    this.#listeners[type].push(listener);\n  }\n\n  /**\n   * Remove an event listener from the app.\n   *\n   * @param {string} type The event type.\n   * @param {Function} listener The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, listener) {\n    if (typeof this.#listeners[type] === 'undefined') {\n      return;\n    }\n    for (let i = 0; i < this.#listeners[type].length; ++i) {\n      if (this.#listeners[type][i] === listener) {\n        this.#listeners[type].splice(i, 1);\n      }\n    }\n  }\n\n  // Private Methods -----------------------------------------------------------\n\n  /**\n   * Fire an event: call all associated listeners.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    if (typeof this.#listeners[event.type] === 'undefined') {\n      return;\n    }\n    for (let i = 0; i < this.#listeners[event.type].length; ++i) {\n      this.#listeners[event.type][i](event);\n    }\n  };\n\n  /**\n   * Check if the shape is in the shape list.\n   *\n   * @param {string} name The name of the shape.\n   * @returns {boolean} True if there is a factory for the shape.\n   */\n  hasShape(name) {\n    return typeof this.#shapeFactoryList[name] !== 'undefined';\n  }\n\n} // Draw class\n","import {Annotation} from '../image/annotation';\nimport {\n  AddAnnotationCommand,\n  UpdateAnnotationCommand\n} from '../tools/drawCommands';\n//import {RoiFactory} from '../tools/roi';\nimport {ROI} from '../math/roi';\nimport {guid} from '../math/stats';\nimport {Point2D} from '../math/point';\nimport {Style} from '../gui/style';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {ListenerHandler} from '../utils/listen';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {LayerGroup} from '../gui/layerGroup';\nimport {ViewLayer} from '../gui/viewLayer';\nimport {Scalar2D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * The magic wand namespace.\n *\n * Ref: {@link https://github.com/Tamersoul/magic-wand-js}.\n *\n * @external MagicWand\n */\nimport MagicWand from 'magic-wand-tool';\n\n/**\n * Floodfill painting tool.\n */\nexport class Floodfill {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Original variables from external library. Used as in the lib example.\n   *\n   * @type {number}\n   */\n  #blurRadius = 5;\n  /**\n   * Original variables from external library. Used as in the lib example.\n   *\n   * @type {number}\n   */\n  #simplifyTolerant = 0;\n\n  /**\n   * Original variables from external library. Used as in the lib example.\n   *\n   * @type {number}\n   */\n  #simplifyCount = 2000;\n\n  /**\n   * Canvas info.\n   *\n   * @type {object}\n   */\n  #imageInfo = null;\n\n  /**\n   * Object created by MagicWand lib containing border points.\n   *\n   * @type {object}\n   */\n  #mask = null;\n\n  /**\n   * Threshold default tolerance of the tool border.\n   *\n   * @type {number}\n   */\n  #initialthreshold = 10;\n\n  /**\n   * Threshold tolerance of the tool border.\n   *\n   * @type {number}\n   */\n  #currentthreshold = null;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Current annotation.\n   *\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * Coordinates of the fist mousedown event.\n   *\n   * @type {object}\n   */\n  #initialpoint;\n\n  /**\n   * Floodfill border.\n   *\n   * @type {object}\n   */\n  #border = null;\n\n  /**\n   * List of parent points.\n   *\n   * @type {Point2D[]}\n   */\n  #parentPoints = [];\n\n  /**\n   * Assistant variable to paint border on all slices.\n   *\n   * @type {boolean}\n   */\n  #extender = false;\n\n  /**\n   * Drawing style.\n   *\n   * @type {Style}\n   */\n  #style = new Style();\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Set extend option for painting border on all slices.\n   *\n   * @param {boolean} bool The option to set.\n   */\n  setExtend(bool) {\n    this.#extender = bool;\n  }\n\n  /**\n   * Get extend option for painting border on all slices.\n   *\n   * @returns {boolean} The actual value of of the variable to use Floodfill\n   *   on museup.\n   */\n  getExtend() {\n    return this.#extender;\n  }\n\n  /**\n   * Get the associated view layer.\n   *\n   * @param {LayerGroup} layerGroup The layer group to search.\n   * @returns {ViewLayer|undefined} The view layer.\n   */\n  #getViewLayer(layerGroup) {\n    const drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      logger.warn('No draw layer to do floodfill');\n      return;\n    }\n    return layerGroup.getViewLayerById(\n      drawLayer.getReferenceLayerId());\n  }\n\n  /**\n   * Get (x, y) coordinates referenced to the canvas.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   * @returns {Scalar2D|undefined} The coordinates as a {x,y}.\n   */\n  #getIndex = (point, divId) => {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to get index');\n      return;\n    }\n    const index = viewLayer.displayToPlaneIndex(point);\n    return {\n      x: index.get(0),\n      y: index.get(1)\n    };\n  };\n\n  /**\n   * Calculate border.\n   *\n   * @param {object} points The input points.\n   * @param {number} threshold The threshold of the floodfill.\n   * @param {boolean} simple Return first points or a list.\n   * @returns {Point2D[]} The parent points.\n   */\n  #calcBorder(points, threshold, simple) {\n\n    this.#parentPoints = [];\n    const image = {\n      data: this.#imageInfo.data,\n      width: this.#imageInfo.width,\n      height: this.#imageInfo.height,\n      bytes: 4\n    };\n\n    this.#mask = MagicWand.floodFill(image, points.x, points.y, threshold);\n    this.#mask = MagicWand.gaussBlurOnlyBorder(this.#mask, this.#blurRadius);\n\n    let cs = MagicWand.traceContours(this.#mask);\n    cs = MagicWand.simplifyContours(\n      cs, this.#simplifyTolerant, this.#simplifyCount);\n\n    if (cs.length > 0 && cs[0].points[0].x) {\n      if (simple) {\n        return cs[0].points;\n      }\n      for (let j = 0, icsl = cs[0].points.length; j < icsl; j++) {\n        this.#parentPoints.push(new Point2D(\n          cs[0].points[j].x,\n          cs[0].points[j].y\n        ));\n      }\n      return this.#parentPoints;\n    } else {\n      return [];\n    }\n  }\n\n  /**\n   * Paint Floodfill.\n   *\n   * @param {object} point The start point.\n   * @param {number} threshold The border threshold.\n   * @param {LayerGroup} layerGroup The origin layer group.\n   * @returns {boolean} False if no border.\n   */\n  #paintBorder(point, threshold, layerGroup) {\n    // Calculate the border\n    this.#border = this.#calcBorder(point, threshold, false);\n    // Paint the border\n    if (this.#border.length !== 0) {\n      const drawLayer = layerGroup.getActiveDrawLayer();\n      if (typeof drawLayer === 'undefined') {\n        logger.warn('No draw layer to paint border');\n        return false;\n      }\n      const drawController = drawLayer.getDrawController();\n\n      const newMathShape = new ROI(this.#border);\n\n      let command;\n      if (typeof this.#annotation === 'undefined') {\n        // create annotation\n        this.#annotation = new Annotation();\n        this.#annotation.colour = this.#style.getLineColour();\n        this.#annotation.id = guid();\n\n        const viewLayer =\n          layerGroup.getViewLayerById(drawLayer.getReferenceLayerId());\n        if (typeof viewLayer === 'undefined') {\n          logger.warn('No view layer to paint border');\n          return false;\n        }\n        const viewController = viewLayer.getViewController();\n        this.#annotation.init(viewController);\n\n        this.#annotation.mathShape = newMathShape;\n        command = new AddAnnotationCommand(\n          this.#annotation,\n          drawController\n        );\n      } else {\n        // update annotation\n        const originalMathShape = this.#annotation.mathShape;\n        command = new UpdateAnnotationCommand(\n          this.#annotation,\n          {mathShape: originalMathShape},\n          {mathShape: newMathShape},\n          drawController\n        );\n      }\n\n      // add command to undo stack\n      this.#app.addToUndoStack(command);\n      // execute command: triggers draw creation\n      command.execute();\n    }\n\n    return this.#border.length !== 0;\n  }\n\n  /**\n   * Create Floodfill in all the prev and next slices while border is found.\n   *\n   * @param {number} ini The first slice to extend to.\n   * @param {number} end The last slice to extend to.\n   * @param {object} layerGroup The origin layer group.\n   */\n  extend(ini, end, layerGroup) {\n    //avoid errors\n    if (!this.#initialpoint) {\n      throw '\\'initialpoint\\' not found. User must click before use extend!';\n    }\n\n    const positionHelper = layerGroup.getPositionHelper();\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to extend floodfill');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n\n    const pos = viewController.getCurrentIndex();\n    const imageSize = viewController.getImageSize();\n    const threshold = this.#currentthreshold || this.#initialthreshold;\n\n    // Iterate over the next images and paint border on each slice.\n    for (let i = pos.get(2),\n      len = end\n        ? end : imageSize.get(2);\n      i < len; i++) {\n      if (!this.#paintBorder(this.#initialpoint, threshold, layerGroup)) {\n        break;\n      }\n      positionHelper.incrementPositionAlongScroll();\n    }\n    viewController.setCurrentIndex(pos);\n\n    // Iterate over the prev images and paint border on each slice.\n    for (let j = pos.get(2), jl = ini ? ini : 0; j > jl; j--) {\n      if (!this.#paintBorder(this.#initialpoint, threshold, layerGroup)) {\n        break;\n      }\n      positionHelper.decrementPositionAlongScroll();\n    }\n    viewController.setCurrentIndex(pos);\n  }\n\n  /**\n   * Event fired when threshold change.\n   *\n   * @param {number} _value Current threshold.\n   */\n  onThresholdChange(_value) {\n    // Defaults do nothing\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   */\n  #start(point, divId) {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    let viewLayer;\n    let drawLayer = layerGroup.getActiveDrawLayer();\n\n    if (typeof drawLayer === 'undefined') {\n      viewLayer = layerGroup.getActiveViewLayer();\n      const refDataId = viewLayer.getDataId();\n      // create new data\n      const data = this.#app.createAnnotationData(refDataId);\n      // render (will create draw layer)\n      this.#app.addAndRenderAnnotationData(data, divId, refDataId);\n      // get draw layer\n      drawLayer = layerGroup.getActiveDrawLayer();\n      // set active to bind to toolboxController\n      layerGroup.setActiveLayerByDataId(drawLayer.getDataId());\n    } else {\n      viewLayer = layerGroup.getViewLayerById(\n        drawLayer.getReferenceLayerId());\n      if (typeof viewLayer === 'undefined') {\n        logger.warn('No view layer to start floodfill');\n        return;\n      }\n    }\n\n    this.#imageInfo = viewLayer.getImageData();\n    if (!this.#imageInfo) {\n      logger.error('No image found');\n      return;\n    }\n\n    // update zoom scale\n    this.#style.setZoomScale(\n      drawLayer.getKonvaLayer().getAbsoluteScale());\n\n    this.#started = true;\n    this.#initialpoint = this.#getIndex(point, divId);\n    this.#paintBorder(this.#initialpoint, this.#initialthreshold, layerGroup);\n    this.onThresholdChange(this.#initialthreshold);\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    if (!this.#started) {\n      return;\n    }\n\n    const movedpoint = this.#getIndex(point, divId);\n    this.#currentthreshold = Math.round(Math.sqrt(\n      Math.pow((this.#initialpoint.x - movedpoint.x), 2) +\n      Math.pow((this.#initialpoint.y - movedpoint.y), 2)) / 2);\n    this.#currentthreshold = this.#currentthreshold < this.#initialthreshold\n      ? this.#initialthreshold\n      : this.#currentthreshold - this.#initialthreshold;\n\n    this.#paintBorder(\n      this.#initialpoint,\n      this.#currentthreshold,\n      this.#app.getLayerGroupByDivId(divId)\n    );\n\n    this.onThresholdChange(this.#currentthreshold);\n  }\n\n  /**\n   * Finish tool interaction.\n   */\n  #finish() {\n    if (this.#started) {\n      this.#started = false;\n    }\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} _event The mouse up event.\n   */\n  mouseup = (_event) => {\n    this.#finish();\n    // TODO: re-activate\n    // if (this.#extender) {\n    //   const layerDetails = getLayerDetailsFromEvent(event);\n    //   const layerGroup =\n    //     this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    //   this.extend(layerGroup);\n    // }\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} _event The touch end event.\n   */\n  touchend = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'Floodfill';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} bool The flag to activate or not.\n   */\n  activate(bool) {\n    if (bool) {\n      // init with the app window scale\n      this.#style.setBaseScale(this.#app.getBaseScale());\n      // set the default to the first in the list\n      this.setFeatures({shapeColour: this.#style.getLineColour()});\n    }\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Get the list of event names that this tool can fire.\n   *\n   * @returns {Array} The list of event names.\n   */\n  getEventNames() {\n    return ['drawcreate', 'drawchange', 'drawmove', 'drawdelete'];\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  // #fireEvent = (event) => {\n  //   this.#listenerHandler.fireEvent(event);\n  // };\n\n  /**\n   * Set the tool live features: shape colour.\n   *\n   * @param {object} features The list of features.\n   */\n  setFeatures(features) {\n    if (typeof features.shapeColour !== 'undefined') {\n      this.#style.setLineColour(features.shapeColour);\n    }\n  }\n\n} // Floodfill class\n","import {Style} from '../gui/style';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {Point2D} from '../math/point';\nimport {Path} from '../math/path';\nimport {Scissors} from '../math/scissors';\nimport {guid} from '../math/stats';\nimport {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {ListenerHandler} from '../utils/listen';\nimport {logger} from '../utils/logger';\nimport {ROI} from '../math/roi';\nimport {Annotation} from '../image/annotation';\nimport {\n  AddAnnotationCommand,\n  UpdateAnnotationCommand\n} from '../tools/drawCommands';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\n/* eslint-enable no-unused-vars */\n\n/**\n * Livewire painting tool.\n */\nexport class Livewire {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Start point.\n   *\n   * @type {Point2D}\n   */\n  #startPoint;\n\n  /**\n   * Current annotation.\n   *\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * Drawing style.\n   *\n   * @type {Style}\n   */\n  #style = new Style();\n\n  /**\n   * Path storage. Paths are stored in reverse order.\n   *\n   * @type {Path}\n   */\n  #path = new Path();\n\n  /**\n   * Current path storage. Paths are stored in reverse order.\n   *\n   * @type {Path}\n   */\n  #currentPath = new Path();\n\n  /**\n   * List of parent points.\n   *\n   * @type {Array}\n   */\n  #parentPoints = [];\n\n  /**\n   * Tolerance.\n   *\n   * @type {number}\n   */\n  #tolerance = 5;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Clear the parent points list.\n   *\n   * @param {object} imageSize The image size.\n   */\n  #clearParentPoints(imageSize) {\n    const nrows = imageSize.get(1);\n    for (let i = 0; i < nrows; ++i) {\n      this.#parentPoints[i] = [];\n    }\n  }\n\n  /**\n   * Clear the stored paths.\n   */\n  #clearPaths() {\n    this.#path = new Path();\n    this.#currentPath = new Path();\n  }\n\n  /**\n   * Scissor representation.\n   *\n   * @type {Scissors}\n   */\n  #scissors = new Scissors();\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   */\n  #start(point, divId) {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n\n    let viewLayer;\n    let drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      viewLayer = layerGroup.getActiveViewLayer();\n    } else {\n      viewLayer =\n        layerGroup.getViewLayerById(drawLayer.getReferenceLayerId());\n    }\n\n    const imageSize = viewLayer.getViewController().getImageSize();\n\n    this.#scissors.setDimensions(\n      imageSize.get(0),\n      imageSize.get(1));\n    this.#scissors.setData(viewLayer.getImageData().data);\n\n    const index = viewLayer.displayToPlaneIndex(point);\n\n    // first time\n    if (!this.#started) {\n      this.#started = true;\n      this.#startPoint = new Point2D(index.get(0), index.get(1));\n      // clear vars\n      this.#clearPaths();\n      this.#clearParentPoints(imageSize);\n      // get draw layer\n      if (typeof drawLayer === 'undefined') {\n        const refDataId = viewLayer.getDataId();\n        // create new data\n        const data = this.#app.createAnnotationData(refDataId);\n        // render (will create draw layer)\n        this.#app.addAndRenderAnnotationData(data, divId, refDataId);\n        // get draw layer\n        drawLayer = layerGroup.getActiveDrawLayer();\n        // set active to bind to toolboxController\n        layerGroup.setActiveLayerByDataId(drawLayer.getDataId());\n      }\n      // update zoom scale\n      this.#style.setZoomScale(\n        drawLayer.getKonvaLayer().getAbsoluteScale());\n      // do the training from the first point\n      const p = {x: index.get(0), y: index.get(1)};\n      this.#scissors.doTraining(p);\n      // add the initial point to the path\n      const p0 = new Point2D(index.get(0), index.get(1));\n      this.#path.addPoint(p0);\n      this.#path.addControlPoint(p0);\n    } else {\n      const diffX = Math.abs(index.get(0) - this.#startPoint.getX());\n      const diffY = Math.abs(index.get(1) - this.#startPoint.getY());\n      // final point: at 'tolerance' of the initial point\n      if (diffX < this.#tolerance &&\n        diffY < this.#tolerance) {\n        // finish\n        this.#finishShape();\n      } else {\n        // anchor point\n        this.#path = this.#currentPath;\n        this.#clearParentPoints(imageSize);\n        const pn = {x: index.get(0), y: index.get(1)};\n        this.#scissors.doTraining(pn);\n        this.#path.addControlPoint(this.#currentPath.getPoint(0));\n      }\n    }\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    if (!this.#started) {\n      return;\n    }\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      logger.warn('No draw layer to update livewire');\n      return;\n    }\n    const viewLayer = layerGroup.getViewLayerById(\n      drawLayer.getReferenceLayerId());\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to update livewire');\n      return;\n    }\n    const index = viewLayer.displayToPlaneIndex(point);\n\n    // set the point to find the path to\n    let p = {x: index.get(0), y: index.get(1)};\n    this.#scissors.setPoint(p);\n    // do the work\n    let results = [];\n    let stop = false;\n    while (!this.#parentPoints[p.y][p.x] && !stop) {\n      results = this.#scissors.doWork();\n\n      if (results.length === 0) {\n        stop = true;\n      } else {\n        // fill parents\n        for (let i = 0; i < results.length - 1; i += 2) {\n          const _p = results[i];\n          const _q = results[i + 1];\n          this.#parentPoints[_p.y][_p.x] = _q;\n        }\n      }\n    }\n\n    // get the path\n    this.#currentPath = new Path();\n    stop = false;\n    while (p && !stop) {\n      this.#currentPath.addPoint(new Point2D(p.x, p.y));\n      if (!this.#parentPoints[p.y]) {\n        stop = true;\n      } else {\n        if (!this.#parentPoints[p.y][p.x]) {\n          stop = true;\n        } else {\n          p = this.#parentPoints[p.y][p.x];\n        }\n      }\n    }\n    this.#currentPath.appenPath(this.#path);\n\n    const drawController = drawLayer.getDrawController();\n\n    const newMathShape = new ROI(this.#currentPath.pointArray);\n\n    let command;\n    if (typeof this.#annotation === 'undefined') {\n      // create annotation\n      this.#annotation = new Annotation();\n      this.#annotation.colour = this.#style.getLineColour();\n      this.#annotation.id = guid();\n\n      const viewController = viewLayer.getViewController();\n      this.#annotation.init(viewController);\n\n      this.#annotation.mathShape = newMathShape;\n      command = new AddAnnotationCommand(\n        this.#annotation,\n        drawController\n      );\n    } else {\n      // update annotation\n      const originalMathShape = this.#annotation.mathShape;\n      command = new UpdateAnnotationCommand(\n        this.#annotation,\n        {mathShape: originalMathShape},\n        {mathShape: newMathShape},\n        drawController\n      );\n    }\n\n    // add command to undo stack\n    this.#app.addToUndoStack(command);\n    // execute command: triggers draw creation\n    command.execute();\n  }\n\n  /**\n   * Finish a livewire (roi) shape.\n   */\n  #finishShape() {\n    // set flag\n    this.#started = false;\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} _event The mouse up event.\n   */\n  mouseup(_event) {\n    // nothing to do\n  }\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    // nothing to do\n  };\n\n  /**\n   * Handle double click event.\n   *\n   * @param {object} _event The double click event.\n   */\n  dblclick = (_event) => {\n    this.#finishShape();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} _event The touch end event.\n   */\n  touchend = (_event) => {\n    // nothing to do\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'Livewire';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} bool The flag to activate or not.\n   */\n  activate(bool) {\n    // start scissors if displayed\n    if (bool) {\n      // init with the app window scale\n      this.#style.setBaseScale(this.#app.getBaseScale());\n      // set the default to the first in the list\n      this.setFeatures({shapeColour: this.#style.getLineColour()});\n    }\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Get the list of event names that this tool can fire.\n   *\n   * @returns {Array} The list of event names.\n   */\n  getEventNames() {\n    return ['drawcreate', 'drawchange', 'drawmove', 'drawdelete'];\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *    event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  // #fireEvent = (event) => {\n  //   this.#listenerHandler.fireEvent(event);\n  // };\n\n  /**\n   * Set the tool live features: shape colour.\n   *\n   * @param {object} features The list of features.\n   */\n  setFeatures(features) {\n    if (typeof features.shapeColour !== 'undefined') {\n      this.#style.setLineColour(features.shapeColour);\n    }\n  }\n\n} // Livewire class\n","import {\n  Line,\n  getPerpendicularLine,\n  getPerpendicularLineAtDistance\n} from '../math/line';\nimport {Point2D} from '../math/point';\nimport {custom} from '../app/custom';\nimport {logger} from '../utils/logger';\nimport {\n  defaultLabelTexts,\n  getLineShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Arrow factory.\n */\nexport class ArrowFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'arrow';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Point2D;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 2;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 0;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.referencePoints = [points[1]];\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a line shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(shape);\n    // extras\n    const extras = this.#createShapeExtras(annotation, style);\n    for (const extra of extras) {\n      group.add(extra);\n    }\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(label);\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    const centerX = (points[0] + points[2]) / 2 + sx;\n    const centerY = (points[1] + points[3]) / 2 + sy;\n    return [new Point2D(centerX, centerY)];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    return [\n      new Point2D(points[0] + sx, points[1] + sy),\n      new Point2D(points[2] + sx, points[3] + sy)\n    ];\n  }\n\n  /**\n   * Get anchors to update a line shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} _anchor The active anchor.\n   */\n  constrainAnchorMove(_anchor) {\n    // no constraints\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n    // find anchors\n    const begin = getAnchorShape(group, 0);\n    const end = getAnchorShape(group, 1);\n\n    // math shape\n    // compensate for possible shape drag\n    const pointBegin = new Point2D(\n      begin.x() - kline.x(),\n      begin.y() - kline.y()\n    );\n    const pointEnd = new Point2D(\n      end.x() - kline.x(),\n      end.y() - kline.y()\n    );\n    annotation.mathShape = pointBegin;\n    annotation.referencePoints = [pointEnd];\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const point = annotation.mathShape;\n    const endPoint = annotation.referencePoints[0];\n    const line = new Line(point, endPoint);\n\n    const begin = line.getBegin();\n    const newBegin = new Point2D(\n      begin.getX() + translation.x,\n      begin.getY() + translation.y\n    );\n    const end = line.getEnd();\n    const newEnd = new Point2D(\n      end.getX() + translation.x,\n      end.getY() + translation.y\n    );\n    annotation.mathShape = newBegin;\n    annotation.referencePoints = [newEnd];\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Point2D} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    return points[0];\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Line} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const point = annotation.mathShape;\n    const endPoint = annotation.referencePoints[0];\n    const line = new Line(point, endPoint);\n\n    // konva line\n    const kshape = new Konva.Line({\n      points: [\n        point.getX(),\n        point.getY(),\n        endPoint.getX(),\n        endPoint.getY()\n      ],\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n\n    // larger hitfunc\n    const tickLen = 20;\n    const linePerp0 = getPerpendicularLine(\n      line, point, tickLen, style.getZoomScale());\n    const linePerp1 = getPerpendicularLine(\n      line, endPoint, tickLen, style.getZoomScale());\n    kshape.hitFunc(function (context) {\n      context.beginPath();\n      context.moveTo(linePerp0.getBegin().getX(), linePerp0.getBegin().getY());\n      context.lineTo(linePerp0.getEnd().getX(), linePerp0.getEnd().getY());\n      context.lineTo(linePerp1.getEnd().getX(), linePerp1.getEnd().getY());\n      context.lineTo(linePerp1.getBegin().getX(), linePerp1.getBegin().getY());\n      context.closePath();\n      context.fillStrokeShape(kshape);\n    });\n\n    return kshape;\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Line|undefined} The shape.\n   */\n  #getShape(group) {\n    return getLineShape(group);\n  }\n\n  /**\n   * Creates the konva shape extras.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Array} The konva shape extras.\n   */\n  #createShapeExtras(annotation, style) {\n    const point = annotation.mathShape;\n    const endPoint = annotation.referencePoints[0];\n    const line = new Line(point, endPoint);\n\n    const tickLen = 20;\n    // perpendicular line at 2*tickLen\n    const perpLine = getPerpendicularLineAtDistance(\n      line, 2 * tickLen, tickLen, style.getZoomScale());\n\n    // triangle\n    const ktriangle = new Konva.Line({\n      points: [\n        line.getBegin().getX(),\n        line.getBegin().getY(),\n        perpLine.getBegin().getX(),\n        perpLine.getBegin().getY(),\n        perpLine.getEnd().getX(),\n        perpLine.getEnd().getY(),\n      ],\n      fill: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      closed: true,\n      name: 'shape-triangle'\n    });\n\n    return [ktriangle];\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const point = annotation.mathShape;\n    return point;\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  #updateShape(annotation, anchor, style) {\n    const point = annotation.mathShape;\n    const endPoint = annotation.referencePoints[0];\n    const line = new Line(point, endPoint);\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n\n    // reset position after possible shape drag\n    kline.position({x: 0, y: 0});\n    // update shape\n    kline.points([\n      point.getX(),\n      point.getY(),\n      endPoint.getX(),\n      endPoint.getY(),\n    ]);\n\n    // associated triangle shape\n    const ktriangle = group.getChildren(function (node) {\n      return node.name() === 'shape-triangle';\n    })[0];\n    if (!(ktriangle instanceof Konva.Line)) {\n      return;\n    }\n    // find anchors\n    const begin = getAnchorShape(group, 0);\n    const end = getAnchorShape(group, 1);\n\n    // update 'self' (undo case)\n    switch (anchor.id()) {\n    case 'anchor0':\n      begin.x(anchor.x());\n      begin.y(anchor.y());\n      break;\n    case 'anchor1':\n      end.x(anchor.x());\n      end.y(anchor.y());\n      break;\n    default:\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n\n    const tickLen = 20;\n\n    // triangle\n    const perpLine = getPerpendicularLineAtDistance(\n      line, 2 * tickLen, tickLen, style.getZoomScale());\n    ktriangle.position({x: 0, y: 0});\n    ktriangle.points([\n      line.getBegin().getX(),\n      line.getBegin().getY(),\n      perpLine.getBegin().getX(),\n      perpLine.getBegin().getY(),\n      perpLine.getEnd().getX(),\n      perpLine.getEnd().getY(),\n    ]);\n\n    // larger hitfunc\n    const linePerp0 = getPerpendicularLine(\n      line, point, tickLen, style.getZoomScale());\n    const linePerp1 = getPerpendicularLine(\n      line, endPoint, tickLen, style.getZoomScale());\n    kline.hitFunc(function (context) {\n      context.beginPath();\n      context.moveTo(linePerp0.getBegin().getX(), linePerp0.getBegin().getY());\n      context.lineTo(linePerp0.getEnd().getX(), linePerp0.getEnd().getY());\n      context.lineTo(linePerp1.getEnd().getX(), linePerp1.getEnd().getY());\n      context.lineTo(linePerp1.getBegin().getX(), linePerp1.getBegin().getY());\n      context.closePath();\n      context.fillStrokeShape(kline);\n    });\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} [_group] The associated group.\n   * @returns {Konva.Group|undefined} The shadow konva group.\n   */\n  #getDebugShadow(_annotation, _group) {\n    return;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} _group The associated group.\n   */\n  #updateDebugShadow(_annotation, _group) {\n    // does nothing\n  }\n\n} // class ArrowFactory\n","import {Circle} from '../math/circle';\nimport {Point2D} from '../math/point';\nimport {logger} from '../utils/logger';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  isNodeNameShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Circle factory.\n */\nexport class CircleFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'circle';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Circle;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 2;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 0;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a circle shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(this.#createShape(annotation, style));\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(this.#labelFactory.create(annotation, style));\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Circle} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const centerX = shape.x();\n    const centerY = shape.y();\n    const radius = shape.radius() * Math.sqrt(2) / 2;\n    return [\n      new Point2D(centerX - radius, centerY - radius),\n      new Point2D(centerX + radius, centerY - radius),\n      new Point2D(centerX - radius, centerY + radius),\n      new Point2D(centerX + radius, centerY + radius),\n    ];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Circle} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const centerX = shape.x();\n    const centerY = shape.y();\n    const radius = shape.radius();\n    return [\n      new Point2D(centerX - radius, centerY),\n      new Point2D(centerX + radius, centerY),\n      new Point2D(centerX, centerY + radius),\n      new Point2D(centerX, centerY - radius),\n    ];\n  }\n\n  /**\n   * Get anchors to update a circle shape.\n   *\n   * @param {Konva.Circle} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} anchor The active anchor.\n   */\n  constrainAnchorMove(anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // find special points\n    const left = getAnchorShape(group, 0);\n    const right = getAnchorShape(group, 1);\n    const bottom = getAnchorShape(group, 2);\n    const top = getAnchorShape(group, 3);\n\n    // update 'self' (undo case) and special points\n    switch (anchor.id()) {\n    case 'anchor0':\n      // block y\n      left.y(right.y());\n      break;\n    case 'anchor1':\n      // block y\n      right.y(left.y());\n      break;\n    case 'anchor2':\n      // block x\n      bottom.x(top.x());\n      break;\n    case 'anchor3':\n      // block x\n      top.x(bottom.x());\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // math shape\n    const circle = annotation.mathShape;\n    const center = new Point2D(\n      circle.getCenter().getX(),\n      circle.getCenter().getY()\n    );\n    const anchorPoint = new Point2D(anchor.x(), anchor.y());\n    const newRadius = center.getDistance(anchorPoint);\n    annotation.mathShape = new Circle(center, newRadius);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const circle = annotation.mathShape;\n    const center = circle.getCenter();\n    const newCenter = new Point2D(\n      center.getX() + translation.x,\n      center.getY() + translation.y\n    );\n    annotation.mathShape = new Circle(newCenter, circle.getRadius());\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Circle} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    // calculate radius\n    const a = Math.abs(points[0].getX() - points[1].getX());\n    const b = Math.abs(points[0].getY() - points[1].getY());\n    const radius = Math.round(Math.sqrt(a * a + b * b));\n    // physical shape\n    return new Circle(points[0], radius);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Circle} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const circle = annotation.mathShape;\n    // konva circle\n    return new Konva.Circle({\n      x: circle.getCenter().getX(),\n      y: circle.getCenter().getY(),\n      radius: circle.getRadius(),\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Circle|undefined} The shape.\n   */\n  #getShape(group) {\n    const kshape = group.getChildren(isNodeNameShape)[0];\n    if (!(kshape instanceof Konva.Circle)) {\n      return;\n    }\n    return kshape;\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const circle = annotation.mathShape;\n    const center = circle.getCenter();\n    const radius = circle.getRadius();\n    return new Point2D(\n      center.getX() - radius,\n      center.getY() + radius,\n    );\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} _style The application style.\n   */\n  #updateShape(annotation, anchor, _style) {\n    const circle = annotation.mathShape;\n    const center = circle.getCenter();\n    const radius = circle.getRadius();\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kcircle = this.#getShape(group);\n    // update shape: just update the radius\n    kcircle.radius(radius);\n\n    // find anchors\n    const left = getAnchorShape(group, 0);\n    const right = getAnchorShape(group, 1);\n    const bottom = getAnchorShape(group, 2);\n    const top = getAnchorShape(group, 3);\n\n    const swapX = right.x() < left.x() ? -1 : 1;\n    const swapY = top.y() < bottom.y() ? 1 : -1;\n\n    // update 'self' (undo case) and other anchors\n    switch (anchor.id()) {\n    case 'anchor0':\n      // update self\n      left.x(anchor.x());\n      // update others\n      right.x(center.getX() + swapX * radius);\n      bottom.y(center.getY() + radius);\n      top.y(center.getY() - radius);\n      break;\n    case 'anchor1':\n      // update self\n      right.x(anchor.x());\n      // update others\n      left.x(center.getX() - swapX * radius);\n      bottom.y(center.getY() + radius);\n      top.y(center.getY() - radius);\n      break;\n    case 'anchor2':\n      // update self\n      bottom.y(anchor.y());\n      // update others\n      left.x(center.getX() - radius);\n      right.x(center.getX() + radius);\n      top.y(center.getY() - swapY * radius);\n      break;\n    case 'anchor3':\n      // update self\n      top.y(anchor.y());\n      // update others\n      left.x(center.getX() - radius);\n      right.x(center.getX() + radius);\n      bottom.y(center.getY() + swapY * radius);\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} annotation The annotation to shadow.\n   * @param {Konva.Group} [group] The associated group.\n   * @returns {Konva.Group|undefined} The shadow konva group.\n   */\n  #getDebugShadow(annotation, group) {\n    const circle = annotation.mathShape;\n\n    // possible group offset\n    let offsetX = 0;\n    let offsetY = 0;\n    if (typeof group !== 'undefined') {\n      offsetX = group.x();\n      offsetY = group.y();\n    }\n    const kshadow = new Konva.Group();\n    kshadow.name('shadow');\n    const regions = circle.getRound();\n    for (let i = 0; i < regions.length; ++i) {\n      const region = regions[i];\n      const minX = region[0][0];\n      const minY = region[0][1];\n      const maxX = region[1][0];\n      const pixelLine = new Konva.Rect({\n        x: minX - offsetX,\n        y: minY - offsetY,\n        width: maxX - minX,\n        height: 1,\n        fill: 'grey',\n        strokeWidth: 0,\n        strokeScaleEnabled: false,\n        opacity: 0.3,\n        name: 'shadow-element'\n      });\n      kshadow.add(pixelLine);\n    }\n    return kshadow;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} annotation The annotation to shadow.\n   * @param {Konva.Group} group The associated group.\n   */\n  #updateDebugShadow(annotation, group) {\n    const kshadow = group.getChildren(function (node) {\n      return node.name() === 'shadow';\n    })[0];\n    if (typeof kshadow !== 'undefined') {\n      // remove previous\n      kshadow.destroy();\n      // add new\n      group.add(this.#getDebugShadow(annotation, group));\n    }\n  }\n\n} // class CircleFactory\n","import {Ellipse} from '../math/ellipse';\nimport {Point2D} from '../math/point';\nimport {logger} from '../utils/logger';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  isNodeNameShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Ellipse factory.\n */\nexport class EllipseFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'ellipse';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Ellipse;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 2;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 0;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create an ellipse shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(this.#createShape(annotation, style));\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(this.#labelFactory.create(annotation, style));\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Ellipse} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const centerX = shape.x();\n    const centerY = shape.y();\n    const radiusX = shape.radiusX() * Math.sqrt(2) / 2;\n    const radiusY = shape.radiusY() * Math.sqrt(2) / 2;\n    return [\n      new Point2D(centerX - radiusX, centerY - radiusY),\n      new Point2D(centerX + radiusX, centerY - radiusY),\n      new Point2D(centerX - radiusX, centerY + radiusY),\n      new Point2D(centerX + radiusX, centerY + radiusY),\n    ];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Ellipse} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const centerX = shape.x();\n    const centerY = shape.y();\n    const radius = shape.radius();\n    return [\n      new Point2D(centerX - radius.x, centerY),\n      new Point2D(centerX + radius.x, centerY),\n      new Point2D(centerX, centerY + radius.y),\n      new Point2D(centerX, centerY - radius.y),\n    ];\n  }\n\n  /**\n   * Get anchors to update a ellipse shape.\n   *\n   * @param {Konva.Ellipse} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} anchor The active anchor.\n   */\n  constrainAnchorMove(anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // find special points\n    const left = getAnchorShape(group, 0);\n    const right = getAnchorShape(group, 1);\n    const bottom = getAnchorShape(group, 2);\n    const top = getAnchorShape(group, 3);\n\n    // update 'self' (undo case) and special points\n    switch (anchor.id()) {\n    case 'anchor0':\n      // block y\n      left.y(right.y());\n      break;\n    case 'anchor1':\n      // block y\n      right.y(left.y());\n      break;\n    case 'anchor2':\n      // block x\n      bottom.x(top.x());\n      break;\n    case 'anchor3':\n      // block x\n      top.x(bottom.x());\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // math shape\n    const ellipse = annotation.mathShape;\n    const center = ellipse.getCenter();\n    let radiusX = ellipse.getA();\n    let radiusY = ellipse.getB();\n\n    // update 'self' (undo case) and special points\n    switch (anchor.id()) {\n    case 'anchor0':\n      radiusX = center.getX() - anchor.x();\n      break;\n    case 'anchor1':\n      radiusX = anchor.x() - center.getX();\n      break;\n    case 'anchor2':\n      radiusY = anchor.y() - center.getY();\n      break;\n    case 'anchor3':\n      radiusY = center.getY() - anchor.y();\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n\n    annotation.mathShape = new Ellipse(\n      center, Math.abs(radiusX), Math.abs(radiusY));\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const ellipse = annotation.mathShape;\n    const center = ellipse.getCenter();\n    const newCenter = new Point2D(\n      center.getX() + translation.x,\n      center.getY() + translation.y\n    );\n    annotation.mathShape = new Ellipse(\n      newCenter, ellipse.getA(), ellipse.getB());\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Ellipse} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    // calculate radius\n    const a = Math.abs(points[0].getX() - points[1].getX());\n    const b = Math.abs(points[0].getY() - points[1].getY());\n    // physical shape\n    return new Ellipse(points[0], a, b);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Ellipse} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const ellipse = annotation.mathShape;\n    const center = ellipse.getCenter();\n    const radius = {\n      x: ellipse.getA(),\n      y: ellipse.getB()\n    };\n    // konva circle\n    return new Konva.Ellipse({\n      x: center.getX(),\n      y: center.getY(),\n      radius: radius,\n      radiusX: radius.x,\n      radiusY: radius.y,\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Ellipse|undefined} The shape.\n   */\n  #getShape(group) {\n    const kshape = group.getChildren(isNodeNameShape)[0];\n    if (!(kshape instanceof Konva.Ellipse)) {\n      return;\n    }\n    return kshape;\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const ellipse = annotation.mathShape;\n    const center = ellipse.getCenter();\n    return new Point2D(\n      center.getX() - ellipse.getA(),\n      center.getY() + ellipse.getB()\n    );\n  }\n\n  /**\n   * Update shape on anchor move.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} _style The application style.\n   */\n  #updateShape(annotation, anchor, _style) {\n    const ellipse = annotation.mathShape;\n    const center = ellipse.getCenter();\n    const radiusX = ellipse.getA();\n    const radiusY = ellipse.getB();\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kellipse = this.#getShape(group);\n    // update shape: just update radius\n    kellipse.radius({\n      x: radiusX,\n      y: radiusY\n    });\n\n    // find anchors\n    const left = getAnchorShape(group, 0);\n    const right = getAnchorShape(group, 1);\n    const bottom = getAnchorShape(group, 2);\n    const top = getAnchorShape(group, 3);\n\n    const swapX = right.x() < left.x() ? -1 : 1;\n    const swapY = top.y() < bottom.y() ? 1 : -1;\n\n    // update 'self' (undo case) and other anchors\n    switch (anchor.id()) {\n    case 'anchor0':\n      // update self\n      left.x(anchor.x());\n      // update others\n      right.x(center.getX() + swapX * radiusX);\n      bottom.y(center.getY() + radiusY);\n      top.y(center.getY() - radiusY);\n      break;\n    case 'anchor1':\n      // update self\n      right.x(anchor.x());\n      // update others\n      left.x(center.getX() - swapX * radiusX);\n      bottom.y(center.getY() + radiusY);\n      top.y(center.getY() - radiusY);\n      break;\n    case 'anchor2':\n      // update self\n      bottom.y(anchor.y());\n      // update others\n      left.x(center.getX() - radiusX);\n      right.x(center.getX() + radiusX);\n      top.y(center.getY() - swapY * radiusY);\n      break;\n    case 'anchor3':\n      // update self\n      top.y(anchor.y());\n      // update others\n      left.x(center.getX() - radiusX);\n      right.x(center.getX() + radiusX);\n      bottom.y(center.getY() + swapY * radiusY);\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} annotation The annotation to shadow.\n   * @param {Konva.Group} [group] The associated group.\n   * @returns {Konva.Group|undefined} The shadow konva group.\n   */\n  #getDebugShadow(annotation, group) {\n    const ellipse = annotation.mathShape;\n\n    // possible group offset\n    let offsetX = 0;\n    let offsetY = 0;\n    if (typeof group !== 'undefined') {\n      offsetX = group.x();\n      offsetY = group.y();\n    }\n    const kshadow = new Konva.Group();\n    kshadow.name('shadow');\n    const regions = ellipse.getRound();\n    for (let i = 0; i < regions.length; ++i) {\n      const region = regions[i];\n      const minX = region[0][0];\n      const minY = region[0][1];\n      const maxX = region[1][0];\n      const pixelLine = new Konva.Rect({\n        x: minX - offsetX,\n        y: minY - offsetY,\n        width: maxX - minX,\n        height: 1,\n        fill: 'grey',\n        strokeWidth: 0,\n        strokeScaleEnabled: false,\n        opacity: 0.3,\n        name: 'shadow-element'\n      });\n      kshadow.add(pixelLine);\n    }\n    return kshadow;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} annotation The annotation to shadow.\n   * @param {Konva.Group} group The associated group.\n   */\n  #updateDebugShadow(annotation, group) {\n    const kshadow = group.getChildren(function (node) {\n      return node.name() === 'shadow';\n    })[0];\n    if (typeof kshadow !== 'undefined') {\n      // remove previous\n      kshadow.destroy();\n      // add new\n      group.add(this.#getDebugShadow(annotation, group));\n    }\n  }\n\n} // class EllipseFactory\n","import {Line, getAngle} from '../math/line';\nimport {Protractor} from '../math/protractor';\nimport {Point2D} from '../math/point';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  getLineShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Protractor factory.\n */\nexport class ProtractorFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'protractor';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Protractor;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 3;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 500;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a line shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    const protractor = annotation.mathShape;\n\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(this.#createShape(annotation, style));\n\n    if (protractor.getLength() === this.getNPoints()) {\n      // extras\n      const extras = this.#createShapeExtras(annotation, style);\n      for (const extra of extras) {\n        group.add(extra);\n      }\n      // konva label\n      const label = this.#labelFactory.create(annotation, style);\n      group.add(this.#labelFactory.create(annotation, style));\n      // label-shape connector\n      const connectorsPos = this.#getConnectorsPositions(shape);\n      group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n      // konva shadow (if debug)\n      if (DRAW_DEBUG) {\n        group.add(this.#getDebugShadow(annotation));\n      }\n    }\n    return group;\n  }\n\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    return [\n      new Point2D(points[2] + sx, points[3] + sy)\n    ];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    return [\n      new Point2D(points[0] + sx, points[1] + sy),\n      new Point2D(points[2] + sx, points[3] + sy),\n      new Point2D(points[4] + sx, points[5] + sy)\n    ];\n  }\n\n  /**\n   * Get anchors to update a line shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} _anchor The active anchor.\n   */\n  constrainAnchorMove(_anchor) {\n    // no constraints\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n    // find special points\n    const begin = getAnchorShape(group, 0);\n    const mid = getAnchorShape(group, 1);\n    const end = getAnchorShape(group, 2);\n\n    // math shape\n    // compensate for possible shape drag\n    const pointBegin = new Point2D(\n      begin.x() - kline.x(),\n      begin.y() - kline.y()\n    );\n    const pointMid = new Point2D(\n      mid.x() - kline.x(),\n      mid.y() - kline.y()\n    );\n    const pointEnd = new Point2D(\n      end.x() - kline.x(),\n      end.y() - kline.y()\n    );\n    annotation.mathShape = new Protractor([pointBegin, pointMid, pointEnd]);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const protractor = annotation.mathShape;\n    const newPointList = [];\n    for (let i = 0; i < 3; ++i) {\n      newPointList.push(new Point2D(\n        protractor.getPoint(i).getX() + translation.x,\n        protractor.getPoint(i).getY() + translation.y\n      ));\n    }\n    annotation.mathShape = new Protractor(newPointList);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Protractor} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    return new Protractor(points);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Line} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const protractor = annotation.mathShape;\n    const points = [];\n    for (let i = 0; i < protractor.getLength(); ++i) {\n      points.push(protractor.getPoint(i).getX());\n      points.push(protractor.getPoint(i).getY());\n    }\n\n    // konva line\n    const kshape = new Konva.Line({\n      points: points,\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n\n    if (protractor.getLength() === this.getNPoints()) {\n      // larger hitfunc\n      kshape.hitFunc(function (context) {\n        context.beginPath();\n        context.moveTo(\n          protractor.getPoint(0).getX(), protractor.getPoint(0).getY());\n        context.lineTo(\n          protractor.getPoint(1).getX(), protractor.getPoint(1).getY());\n        context.lineTo(\n          protractor.getPoint(2).getX(), protractor.getPoint(2).getY());\n        context.closePath();\n        context.fillStrokeShape(kshape);\n      });\n    }\n\n    return kshape;\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Line|undefined} The shape.\n   */\n  #getShape(group) {\n    return getLineShape(group);\n  }\n\n  /**\n   * Creates the konva shape extras.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Array} The konva shape extras.\n   */\n  #createShapeExtras(annotation, style) {\n    const protractor = annotation.mathShape;\n    const line0 = new Line(\n      protractor.getPoint(0), protractor.getPoint(1));\n    const line1 = new Line(\n      protractor.getPoint(1), protractor.getPoint(2));\n\n    let angle = getAngle(line0, line1);\n    let inclination = line0.getInclination();\n    if (angle > 180) {\n      angle = 360 - angle;\n      inclination += angle;\n    }\n\n    const radius = Math.min(line0.getLength(), line1.getLength()) * 33 / 100;\n    const karc = new Konva.Arc({\n      innerRadius: radius,\n      outerRadius: radius,\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      angle: angle,\n      rotation: -inclination,\n      x: protractor.getPoint(1).getX(),\n      y: protractor.getPoint(1).getY(),\n      name: 'shape-arc'\n    });\n\n    return [karc];\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const protractor = annotation.mathShape;\n    const line0 = new Line(\n      protractor.getPoint(0), protractor.getPoint(1));\n    const line1 = new Line(\n      protractor.getPoint(1), protractor.getPoint(2));\n\n    const midX =\n      (line0.getMidpoint().getX() + line1.getMidpoint().getX()) / 2;\n    const midY =\n      (line0.getMidpoint().getY() + line1.getMidpoint().getY()) / 2;\n\n    return new Point2D(\n      midX,\n      midY\n    );\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} _style The application style.\n   */\n  #updateShape(annotation, anchor, _style) {\n    const protractor = annotation.mathShape;\n    const line0 = new Line(\n      protractor.getPoint(0), protractor.getPoint(1));\n    const line1 = new Line(\n      protractor.getPoint(1), protractor.getPoint(2));\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n\n    // reset position after possible shape drag\n    kline.position({x: 0, y: 0});\n    // update shape\n    kline.points([\n      protractor.getPoint(0).getX(),\n      protractor.getPoint(0).getY(),\n      protractor.getPoint(1).getX(),\n      protractor.getPoint(1).getY(),\n      protractor.getPoint(2).getX(),\n      protractor.getPoint(2).getY()\n    ]);\n\n    // associated arc\n    const karc = group.getChildren(function (node) {\n      return node.name() === 'shape-arc';\n    })[0];\n    if (!(karc instanceof Konva.Arc)) {\n      return;\n    }\n\n    // find special points\n    const begin = getAnchorShape(group, 0);\n    const mid = getAnchorShape(group, 1);\n    const end = getAnchorShape(group, 2);\n\n    // update special points\n    switch (anchor.id()) {\n    case 'anchor0':\n      begin.x(anchor.x());\n      begin.y(anchor.y());\n      break;\n    case 'anchor1':\n      mid.x(anchor.x());\n      mid.y(anchor.y());\n      break;\n    case 'anchor2':\n      end.x(anchor.x());\n      end.y(anchor.y());\n      break;\n    }\n\n    // angle\n    let angle = getAngle(line0, line1);\n    let inclination = line0.getInclination();\n    if (angle > 180) {\n      angle = 360 - angle;\n      inclination += angle;\n    }\n\n    // arc\n    const radius = Math.min(line0.getLength(), line1.getLength()) * 33 / 100;\n    karc.innerRadius(radius);\n    karc.outerRadius(radius);\n    karc.angle(angle);\n    karc.rotation(-inclination);\n    const arcPos = {x: mid.x(), y: mid.y()};\n    karc.position(arcPos);\n\n    // larger hitfunc\n    kline.hitFunc(function (context) {\n      context.beginPath();\n      context.moveTo(\n        protractor.getPoint(0).getX(), protractor.getPoint(0).getY());\n      context.lineTo(\n        protractor.getPoint(1).getX(), protractor.getPoint(1).getY());\n      context.lineTo(\n        protractor.getPoint(2).getX(), protractor.getPoint(2).getY());\n      context.closePath();\n      context.fillStrokeShape(kline);\n    });\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} [_group] The associated group.\n   * @returns {Konva.Group|undefined} The shadow konva group.\n   */\n  #getDebugShadow(_annotation, _group) {\n    return;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} _group The associated group.\n   */\n  #updateDebugShadow(_annotation, _group) {\n    // does nothing\n  }\n\n} // class ProtractorFactory\n","import {Rectangle} from '../math/rectangle';\nimport {Point2D} from '../math/point';\nimport {logger} from '../utils/logger';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  isNodeNameShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Rectangle factory.\n */\nexport class RectangleFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'rectangle';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Rectangle;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 2;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 0;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a rectangle shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(shape);\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(label);\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Rect} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const sx = shape.x();\n    const sy = shape.y();\n    const width = shape.width();\n    const height = shape.height();\n    return [\n      new Point2D(sx + width / 2, sy),\n      new Point2D(sx, sy + height / 2),\n      new Point2D(sx + width / 2, sy + height),\n      new Point2D(sx + width, sy + height / 2),\n    ];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Rect} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const sx = shape.x();\n    const sy = shape.y();\n    const width = shape.width();\n    const height = shape.height();\n    return [\n      new Point2D(sx, sy),\n      new Point2D(sx + width, sy),\n      new Point2D(sx + width, sy + height),\n      new Point2D(sx, sy + height),\n    ];\n  }\n\n  /**\n   * Get anchors to update a rectangle shape.\n   *\n   * @param {Konva.Rect} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} _anchor The active anchor.\n   */\n  constrainAnchorMove(_anchor) {\n    // no constraints\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // find anchors\n    const topLeft = getAnchorShape(group, 0);\n    const bottomRight = getAnchorShape(group, 2);\n\n    const pointTopLeft = new Point2D(\n      topLeft.x(),\n      topLeft.y()\n    );\n    const pointBottomRight = new Point2D(\n      bottomRight.x(),\n      bottomRight.y()\n    );\n    // new rect\n    annotation.mathShape = new Rectangle(pointTopLeft, pointBottomRight);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const rectangle = annotation.mathShape;\n    const begin = rectangle.getBegin();\n    const newBegin = new Point2D(\n      begin.getX() + translation.x,\n      begin.getY() + translation.y\n    );\n    const end = rectangle.getEnd();\n    const newEnd = new Point2D(\n      end.getX() + translation.x,\n      end.getY() + translation.y\n    );\n    annotation.mathShape = new Rectangle(newBegin, newEnd);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label content.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Rectangle} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    return new Rectangle(points[0], points[1]);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Rect} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const rectangle = annotation.mathShape;\n    // konva rect\n    return new Konva.Rect({\n      x: rectangle.getBegin().getX(),\n      y: rectangle.getBegin().getY(),\n      width: rectangle.getWidth(),\n      height: rectangle.getHeight(),\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Rect|undefined} The shape.\n   */\n  #getShape(group) {\n    const kshape = group.getChildren(isNodeNameShape)[0];\n    if (!(kshape instanceof Konva.Rect)) {\n      return;\n    }\n    return kshape;\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const rectangle = annotation.mathShape;\n    return new Point2D(\n      rectangle.getBegin().getX(),\n      rectangle.getEnd().getY(),\n    );\n  }\n\n  /**\n   * Update shape on anchor move.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} _style The application style.\n   */\n  #updateShape(annotation, anchor, _style) {\n    const rectangle = annotation.mathShape;\n    const begin = rectangle.getBegin();\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const krect = this.#getShape(group);\n    // update shape\n    krect.position({\n      x: begin.getX(),\n      y: begin.getY()\n    });\n    krect.size({\n      width: rectangle.getWidth(),\n      height: rectangle.getHeight()\n    });\n\n    // find anchors\n    const topLeft = getAnchorShape(group, 0);\n    const topRight = getAnchorShape(group, 1);\n    const bottomRight = getAnchorShape(group, 2);\n    const bottomLeft = getAnchorShape(group, 3);\n\n    // update 'self' (undo case) and other anchors\n    switch (anchor.id()) {\n    case 'anchor0':\n      // update self\n      topLeft.x(anchor.x());\n      topLeft.y(anchor.y());\n      // update others\n      topRight.y(anchor.y());\n      bottomLeft.x(anchor.x());\n      break;\n    case 'anchor1':\n      // update self\n      topRight.x(anchor.x());\n      topRight.y(anchor.y());\n      // update others\n      topLeft.y(anchor.y());\n      bottomRight.x(anchor.x());\n      break;\n    case 'anchor2':\n      // update self\n      bottomRight.x(anchor.x());\n      bottomRight.y(anchor.y());\n      // update others\n      bottomLeft.y(anchor.y());\n      topRight.x(anchor.x());\n      break;\n    case 'anchor3':\n      // update self\n      bottomLeft.x(anchor.x());\n      bottomLeft.y(anchor.y());\n      // update others\n      bottomRight.y(anchor.y());\n      topLeft.x(anchor.x());\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} annotation The anootation to shadow.\n   * @param {Konva.Group} [_group] The associated group.\n   * @returns {Konva.Rect} The shadow konva rect.\n   */\n  #getDebugShadow(annotation, _group) {\n    const rectangle = annotation.mathShape;\n    const round = rectangle.getRound();\n    const rWidth = round.max.getX() - round.min.getX();\n    const rHeight = round.max.getY() - round.min.getY();\n    return new Konva.Rect({\n      x: round.min.getX(),\n      y: round.min.getY(),\n      width: rWidth,\n      height: rHeight,\n      fill: 'grey',\n      strokeWidth: 0,\n      strokeScaleEnabled: false,\n      opacity: 0.3,\n      name: 'shadow'\n    });\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} annotation The annotation to shadow.\n   * @param {Konva.Group} group The associated group.\n   */\n  #updateDebugShadow(annotation, group) {\n    const kshadow = group.getChildren(function (node) {\n      return node.name() === 'shadow';\n    })[0];\n    if (typeof kshadow !== 'undefined') {\n      // remove previous\n      kshadow.destroy();\n      // add new\n      group.add(this.#getDebugShadow(annotation, group));\n    }\n  }\n\n} // class RectangleFactory\n","import {ROI} from '../math/roi';\nimport {Point2D} from '../math/point';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  getLineShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorIndex\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * ROI factory.\n */\nexport class RoiFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'roi';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof ROI;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number|undefined} The number of points.\n   */\n  getNPoints() {\n    // undefined to end with double click\n    return undefined;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 100;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a roi shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(this.#createShape(annotation, style));\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(this.#labelFactory.create(annotation, style));\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    const positions = [];\n    for (let i = 0; i < points.length; i = i + 2) {\n      positions.push(new Point2D(\n        points[i] + sx,\n        points[i + 1] + sy\n      ));\n    }\n    return positions;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    const positions = [];\n    for (let i = 0; i < points.length; i += 2) {\n      const nextIndex = (i + 2) % points.length;\n      const midX = (points[i] + points[nextIndex]) / 2 + sx;\n      const midY = (points[i + 1] + points[nextIndex + 1]) / 2 + sy;\n      positions.push(new Point2D(midX, midY));\n    }\n    return positions;\n  }\n\n  /**\n   * Get anchors to update a roi shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} _anchor The active anchor.\n   */\n  constrainAnchorMove(_anchor) {\n    // no constraints\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kroi = this.#getShape(group);\n\n    // update the roi point and compensate for possible drag\n    // (the anchor id is the index of the point in the main list)\n    const roi = annotation.mathShape;\n    const points = roi.getPoints().slice();\n    const newPoint = new Point2D(\n      anchor.x() - kroi.x(),\n      anchor.y() - kroi.y()\n    );\n    const index = getAnchorIndex(anchor.id());\n    points[index] = newPoint;\n\n    // new math shape\n    annotation.mathShape = new ROI(points);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const roi = annotation.mathShape;\n    const newPoints = [];\n    for (let i = 0; i < roi.getLength(); ++i) {\n      newPoints.push(new Point2D(\n        roi.getPoint(i).getX() + translation.x,\n        roi.getPoint(i).getY() + translation.y\n      ));\n    }\n    annotation.mathShape = new ROI(newPoints);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {ROI} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    return new ROI(points);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Line} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const roi = annotation.mathShape;\n    // konva line\n    const arr = [];\n    for (let i = 0; i < roi.getLength(); ++i) {\n      arr.push(roi.getPoint(i).getX());\n      arr.push(roi.getPoint(i).getY());\n    }\n    return new Konva.Line({\n      points: arr,\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape',\n      closed: true\n    });\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Line|undefined} The shape.\n   */\n  #getShape(group) {\n    return getLineShape(group);\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const roi = annotation.mathShape;\n    return new Point2D(\n      roi.getPoint(0).getX(),\n      roi.getPoint(0).getY()\n    );\n  }\n\n  /**\n   * Update shape on anchor move.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} _style The application style.\n   */\n  #updateShape(annotation, anchor, _style) {\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kroi = this.#getShape(group);\n    // update the roi point and compensate for possible drag\n    // (the anchor id is the index of the point in the main list)\n    const points = kroi.points();\n    const index = getAnchorIndex(anchor.id()) * 2;\n    points[index] = anchor.x() - kroi.x();\n    points[index + 1] = anchor.y() - kroi.y();\n    kroi.points(points);\n\n    // update self\n    const point = group.getChildren(function (node) {\n      return node.id() === anchor.id();\n    })[0];\n\n    point.x(anchor.x());\n    point.y(anchor.y());\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} _annotation The anootation to shadow.\n   * @param {Konva.Group} [_group] The associated group.\n   * @returns {Konva.Line} The shadow konva line.\n   */\n  #getDebugShadow(_annotation, _group) {\n    // does nothing\n    return undefined;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} _group The associated group.\n   */\n  #updateDebugShadow(_annotation, _group) {\n    // does nothing\n  }\n\n} // class RoiFactory\n","import {Line, getPerpendicularLine} from '../math/line';\nimport {Point2D} from '../math/point';\nimport {logger} from '../utils/logger';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  getLineShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Ruler factory.\n */\nexport class RulerFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'ruler';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Line;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 2;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 0;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a line shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(this.#createShape(annotation, style));\n    // extras\n    const extras = this.#createShapeExtras(annotation, style);\n    for (const extra of extras) {\n      group.add(extra);\n    }\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(this.#labelFactory.create(annotation, style));\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    const centerX = (points[0] + points[2]) / 2 + sx;\n    const centerY = (points[1] + points[3]) / 2 + sy;\n    return [new Point2D(centerX, centerY)];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    return [\n      new Point2D(points[0] + sx, points[1] + sy),\n      new Point2D(points[2] + sx, points[3] + sy)\n    ];\n  }\n\n  /**\n   * Get anchors to update a line shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} _anchor The active anchor.\n   */\n  constrainAnchorMove(_anchor) {\n    // no constraints\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n    // find anchors\n    const begin = getAnchorShape(group, 0);\n    const end = getAnchorShape(group, 1);\n\n    // math shape\n    // compensate for possible shape drag\n    const pointBegin = new Point2D(\n      begin.x() - kline.x(),\n      begin.y() - kline.y()\n    );\n    const pointEnd = new Point2D(\n      end.x() - kline.x(),\n      end.y() - kline.y()\n    );\n    annotation.mathShape = new Line(pointBegin, pointEnd);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const line = annotation.mathShape;\n    const begin = line.getBegin();\n    const newBegin = new Point2D(\n      begin.getX() + translation.x,\n      begin.getY() + translation.y\n    );\n    const end = line.getEnd();\n    const newEnd = new Point2D(\n      end.getX() + translation.x,\n      end.getY() + translation.y\n    );\n    annotation.mathShape = new Line(newBegin, newEnd);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Line} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    return new Line(points[0], points[1]);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Line} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const line = annotation.mathShape;\n\n    // konva line\n    const kshape = new Konva.Line({\n      points: [\n        line.getBegin().getX(),\n        line.getBegin().getY(),\n        line.getEnd().getX(),\n        line.getEnd().getY()\n      ],\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n\n    // larger hitfunc\n    const tickLen = 20;\n    const linePerp0 = getPerpendicularLine(\n      line, line.getBegin(), tickLen, style.getZoomScale());\n    const linePerp1 = getPerpendicularLine(\n      line, line.getEnd(), tickLen, style.getZoomScale());\n    kshape.hitFunc(function (context) {\n      context.beginPath();\n      context.moveTo(linePerp0.getBegin().getX(), linePerp0.getBegin().getY());\n      context.lineTo(linePerp0.getEnd().getX(), linePerp0.getEnd().getY());\n      context.lineTo(linePerp1.getEnd().getX(), linePerp1.getEnd().getY());\n      context.lineTo(linePerp1.getBegin().getX(), linePerp1.getBegin().getY());\n      context.closePath();\n      context.fillStrokeShape(kshape);\n    });\n\n    return kshape;\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Line|undefined} The shape.\n   */\n  #getShape(group) {\n    return getLineShape(group);\n  }\n\n  /**\n   * Creates the konva shape extras.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Array} The konva shape extras.\n   */\n  #createShapeExtras(annotation, style) {\n    const line = annotation.mathShape;\n\n    const tickLen = 20;\n\n    // tick begin\n    const linePerp0 = getPerpendicularLine(\n      line, line.getBegin(), tickLen, style.getZoomScale());\n    const ktick0 = new Konva.Line({\n      points: [\n        linePerp0.getBegin().getX(),\n        linePerp0.getBegin().getY(),\n        linePerp0.getEnd().getX(),\n        linePerp0.getEnd().getY()\n      ],\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape-tick0'\n    });\n\n    // tick end\n    const linePerp1 = getPerpendicularLine(\n      line, line.getEnd(), tickLen, style.getZoomScale());\n    const ktick1 = new Konva.Line({\n      points: [\n        linePerp1.getBegin().getX(),\n        linePerp1.getBegin().getY(),\n        linePerp1.getEnd().getX(),\n        linePerp1.getEnd().getY()\n      ],\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape-tick1'\n    });\n\n    return [ktick0, ktick1];\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const line = annotation.mathShape;\n    const begin = line.getBegin();\n    const end = line.getEnd();\n    // lowest point\n    let res = begin;\n    if (begin.getY() < end.getY()) {\n      res = end;\n    }\n    return res;\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  #updateShape(annotation, anchor, style) {\n    const line = annotation.mathShape;\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n\n    // reset position after possible shape drag\n    kline.position({x: 0, y: 0});\n    // update shape\n    kline.points([\n      line.getBegin().getX(),\n      line.getBegin().getY(),\n      line.getEnd().getX(),\n      line.getEnd().getY(),\n    ]);\n\n    // associated tick0\n    const ktick0 = group.getChildren(function (node) {\n      return node.name() === 'shape-tick0';\n    })[0];\n    if (!(ktick0 instanceof Konva.Line)) {\n      return;\n    }\n    // associated tick1\n    const ktick1 = group.getChildren(function (node) {\n      return node.name() === 'shape-tick1';\n    })[0];\n    if (!(ktick1 instanceof Konva.Line)) {\n      return;\n    }\n    // find anchors\n    const begin = getAnchorShape(group, 0);\n    const end = getAnchorShape(group, 1);\n\n    // update 'self' (undo case)\n    switch (anchor.id()) {\n    case 'anchor0':\n      begin.x(anchor.x());\n      begin.y(anchor.y());\n      break;\n    case 'anchor1':\n      end.x(anchor.x());\n      end.y(anchor.y());\n      break;\n    default:\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n\n    // tick\n    const tickLen = 20;\n    const linePerp0 = getPerpendicularLine(\n      line, line.getBegin(), tickLen, style.getZoomScale());\n    ktick0.position({x: 0, y: 0});\n    ktick0.points([linePerp0.getBegin().getX(),\n      linePerp0.getBegin().getY(),\n      linePerp0.getEnd().getX(),\n      linePerp0.getEnd().getY()]);\n    const linePerp1 = getPerpendicularLine(\n      line, line.getEnd(), tickLen, style.getZoomScale());\n    ktick1.position({x: 0, y: 0});\n    ktick1.points([linePerp1.getBegin().getX(),\n      linePerp1.getBegin().getY(),\n      linePerp1.getEnd().getX(),\n      linePerp1.getEnd().getY()]);\n\n    // larger hitfunc\n    kline.hitFunc(function (context) {\n      context.beginPath();\n      context.moveTo(linePerp0.getBegin().getX(), linePerp0.getBegin().getY());\n      context.lineTo(linePerp0.getEnd().getX(), linePerp0.getEnd().getY());\n      context.lineTo(linePerp1.getEnd().getX(), linePerp1.getEnd().getY());\n      context.lineTo(linePerp1.getBegin().getX(), linePerp1.getBegin().getY());\n      context.closePath();\n      context.fillStrokeShape(kline);\n    });\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} [_group] The associated group.\n   * @returns {Konva.Group|undefined} The shadow konva group.\n   */\n  #getDebugShadow(_annotation, _group) {\n    return;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} _group The associated group.\n   */\n  #updateDebugShadow(_annotation, _group) {\n    // does nothing\n  }\n\n} // class RulerFactory\n","import {logger} from '../utils/logger';\nimport {getFlags, replaceFlags} from '../utils/string';\nimport {Point} from '../math/point';\nimport {getOrientationName} from '../math/orientation';\nimport {defaultToolOptions, toolOptions} from '../tools/index';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D, Point3D} from '../math/point';\nimport {Index} from '../math/index';\nimport {ViewController} from '../app/viewController';\nimport {PlaneHelper} from './planeHelper';\n/* eslint-enable no-unused-vars */\n\n/**\n * Image annotation.\n */\nexport class Annotation {\n  /**\n   * The ID.\n   *\n   * @type {string}\n   */\n  id;\n\n  /**\n   * The reference image SOP UID.\n   *\n   * @type {string}\n   */\n  referenceSopUID;\n\n  /**\n   * The mathematical shape.\n   *\n   * @type {object}\n   */\n  mathShape;\n\n  /**\n   * Additional points used to define the annotation.\n   *\n   * @type {Point2D[]|undefined}\n   */\n  referencePoints;\n\n  /**\n   * The color: for example 'green', '#00ff00' or 'rgb(0,255,0)'.\n   *\n   * @type {string|undefined}\n   */\n  colour;\n\n  /**\n   * Annotation quantification.\n   *\n   * @type {object|undefined}\n   */\n  quantification;\n\n  /**\n   * Text expression. Can contain variables surrounded with '{}' that will\n   * be extracted from the quantification object.\n   *\n   * @type {string|undefined}\n   */\n  textExpr;\n\n  /**\n   * Label position. If undefined, the default shape\n   *   label position will be used.\n   *\n   * @type {Point2D|undefined}\n   */\n  labelPosition;\n\n  /**\n   * The plane origin, the 3D position of index [0, 0, k].\n   *\n   * @type {Point3D|undefined}\n   */\n  planeOrigin;\n\n  /**\n   * A couple of points that help define the annotation plane.\n   *\n   * @type {Point3D[]|undefined}\n   */\n  planePoints;\n\n  /**\n   * Associated view controller: needed for quantification and label.\n   *\n   * @type {ViewController|undefined}\n   */\n  #viewController;\n\n  /**\n   * Get the orientation name for this annotation.\n   *\n   * @returns {string|undefined} The orientation name,\n   *   undefined if same as reference data.\n   */\n  getOrientationName() {\n    let res;\n    if (typeof this.planePoints !== 'undefined') {\n      const cosines = this.planePoints[1].getValues().concat(\n        this.planePoints[2].getValues()\n      );\n      res = getOrientationName(cosines);\n    }\n    return res;\n  }\n\n  /**\n   * Initialise the annotation.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   */\n  init(viewController) {\n    if (typeof this.referenceSopUID !== 'undefined') {\n      logger.debug('Cannot initialise annotation twice');\n      return;\n    }\n\n    this.#viewController = viewController;\n    // set UID\n    this.referenceSopUID = viewController.getCurrentImageUid();\n    // set plane origin (not saved with file)\n    this.planeOrigin =\n      viewController.getOriginForImageUid(this.referenceSopUID);\n    // set plane points if not aquisition orientation\n    // (planePoints are saved with file if present)\n    if (!viewController.isAquisitionOrientation()) {\n      this.planePoints = viewController.getPlanePoints(\n        viewController.getCurrentPosition()\n      );\n    }\n  }\n\n  /**\n   * Check if an input view is compatible with the annotation.\n   *\n   * @param {PlaneHelper} planeHelper The input view to check.\n   * @returns {boolean} True if compatible view.\n   */\n  isCompatibleView(planeHelper) {\n    let res = false;\n\n    // TODO: add check for referenceSopUID\n\n    if (typeof this.planePoints === 'undefined') {\n      // non oriented view\n      if (planeHelper.isAquisitionOrientation()) {\n        res = true;\n      }\n    } else {\n      // oriented view: compare cosines (independent of slice index)\n      const cosines = planeHelper.getCosines();\n      const cosine1 = new Point3D(cosines[0], cosines[1], cosines[2]);\n      const cosine2 = new Point3D(cosines[3], cosines[4], cosines[5]);\n\n      if (cosine1.equals(this.planePoints[1]) &&\n        cosine2.equals(this.planePoints[2])) {\n        res = true;\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Set the associated view controller if it is compatible.\n   *\n   * @param {ViewController} viewController The view controller.\n   */\n  setViewController(viewController) {\n    // check uid\n    if (!viewController.includesImageUid(this.referenceSopUID)) {\n      return;\n    }\n    // check if same view\n    if (!this.isCompatibleView(viewController.getPlaneHelper())) {\n      return;\n    }\n    this.#viewController = viewController;\n\n    // set plane origin (not saved with file)\n    this.planeOrigin =\n      viewController.getOriginForImageUid(this.referenceSopUID);\n  }\n\n  /**\n   * Get the index of the plane origin.\n   *\n   * @returns {Index|undefined} The index.\n   */\n  #getOriginIndex() {\n    let res;\n    if (typeof this.#viewController !== 'undefined') {\n      let origin = this.planeOrigin;\n      if (typeof this.planePoints !== 'undefined') {\n        origin = this.planePoints[0];\n      }\n      const originPoint =\n        new Point([origin.getX(), origin.getY(), origin.getZ()]);\n      res = this.#viewController.getIndexFromPosition(originPoint);\n    }\n    return res;\n  }\n\n  /**\n   * Get the centroid of the math shape.\n   *\n   * @returns {Point|undefined} The 3D centroid point.\n   */\n  getCentroid() {\n    let res;\n    if (typeof this.#viewController !== 'undefined' &&\n      typeof this.mathShape.getCentroid !== 'undefined') {\n      // find the slice index of the annotation origin\n      const originIndex = this.#getOriginIndex();\n      const scrollDimIndex = this.#viewController.getScrollDimIndex();\n      const k = originIndex.getValues()[scrollDimIndex];\n      // shape center converted to 3D\n      const planePoint = this.mathShape.getCentroid();\n      res = this.#viewController.getPositionFromPlanePoint(planePoint, k);\n    }\n    return res;\n  }\n\n  /**\n   * Set the annotation text expression.\n   *\n   * @param {Object.<string, string>} labelText The list of label\n   *   texts indexed by modality.\n   */\n  setTextExpr(labelText) {\n    if (typeof this.#viewController !== 'undefined') {\n      const modality = this.#viewController.getModality();\n\n      if (typeof labelText[modality] !== 'undefined') {\n        this.textExpr = labelText[modality];\n      } else {\n        this.textExpr = labelText['*'];\n      }\n    } else {\n      logger.warn('Cannot set text expr without a view controller');\n    }\n  }\n\n  /**\n   * Get the annotation label text by applying the\n   *   text expression on the current quantification.\n   *\n   * @returns {string} The resulting text.\n   */\n  getText() {\n    return replaceFlags(this.textExpr, this.quantification);\n  }\n\n  /**\n   * Update the annotation quantification.\n   */\n  updateQuantification() {\n    if (typeof this.#viewController !== 'undefined' &&\n      typeof this.mathShape.quantify !== 'undefined') {\n      this.quantification = this.mathShape.quantify(\n        this.#viewController,\n        this.#getOriginIndex(),\n        getFlags(this.textExpr)\n      );\n    }\n  }\n\n  /**\n   * Get the math shape associated draw factory.\n   *\n   * @returns {object} The factory.\n   */\n  getFactory() {\n    let fac;\n    // check in user provided factories\n    if (typeof toolOptions.draw !== 'undefined') {\n      for (const factoryName in toolOptions.draw) {\n        const factory = toolOptions.draw[factoryName];\n        if (factory.supports(this.mathShape)) {\n          fac = new factory();\n          break;\n        }\n      }\n    }\n    // check in default factories\n    if (typeof fac === 'undefined') {\n      for (const factoryName in defaultToolOptions.draw) {\n        const factory = defaultToolOptions.draw[factoryName];\n        if (factory.supports(this.mathShape)) {\n          fac = new factory();\n          break;\n        }\n      }\n    }\n    if (typeof fac === 'undefined') {\n      logger.warn('No shape factory found for math shape');\n    }\n    return fac;\n  }\n}\n","import {logger} from '../utils/logger';\nimport {ListenerHandler} from '../utils/listen';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Annotation} from './annotation';\nimport {ViewController} from '../app/viewController';\n/* eslint-enable no-unused-vars */\n\n/**\n * Annotation group.\n */\nexport class AnnotationGroup {\n  /**\n   * @type {Annotation[]}\n   */\n  #list;\n\n  /**\n   * Annotation meta data.\n   *\n   * @type {Object<string, any>}\n   */\n  #meta = {};\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Editable flag.\n   *\n   * @type {boolean}\n   */\n  #editable;\n\n  /**\n   * Group colour as hex string. If defined, it will be used as\n   *   default colour for new annotations in draw tool.\n   *\n   * @type {string|undefined}\n   */\n  #colour;\n\n  /**\n   * @param {Annotation[]} [list] Optional list, will\n   *   create new if not provided.\n   */\n  constructor(list) {\n    if (typeof list !== 'undefined') {\n      this.#list = list;\n    } else {\n      this.#list = [];\n    }\n    this.#editable = true;\n  }\n\n  /**\n   * Get the annotation group as an array.\n   *\n   * @returns {Annotation[]} The array.\n   */\n  getList() {\n    return this.#list;\n  }\n\n  /**\n   * Get the number of annotations of this list.\n   *\n   * @returns {number} The number of annotations.\n   */\n  getLength() {\n    return this.#list.length;\n  }\n\n  /**\n   * Check if the annotation group is editable.\n   *\n   * @returns {boolean} True if editable.\n   */\n  isEditable() {\n    return this.#editable;\n  }\n\n  /**\n   * Set the annotation group editability.\n   *\n   * @param {boolean} flag True to make the annotation group editable.\n   */\n  setEditable(flag) {\n    this.#editable = flag;\n    /**\n     * Annotation group editable flag change event.\n     *\n     * @event AnnotationGroup#annotationgroupeditablechange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {boolean} data The value of the editable flag.\n     */\n    this.#fireEvent({\n      type: 'annotationgroupeditablechange',\n      data: flag\n    });\n  }\n\n  /**\n   * Get the group colour.\n   *\n   * @returns {string} The colour as hex string.\n   */\n  getColour() {\n    return this.#colour;\n  }\n\n  /**\n   * Set the group colour.\n   *\n   * @param {string} colour The colour as hex string.\n   */\n  setColour(colour) {\n    this.#colour = colour;\n  }\n\n  /**\n   * Add a new annotation.\n   *\n   * @param {Annotation} annotation The annotation to add.\n   */\n  add(annotation) {\n    this.#list.push(annotation);\n    /**\n     * Annotation add event.\n     *\n     * @event AnnotationGroup#annotationadd\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Annotation} data The added annnotation.\n     */\n    this.#fireEvent({\n      type: 'annotationadd',\n      data: annotation\n    });\n  }\n\n  /**\n   * Update an existing annotation.\n   *\n   * @param {Annotation} annotation The annotation to update.\n   * @param {string[]} [propKeys] Optional properties that got updated.\n   */\n  update(annotation, propKeys) {\n    const index = this.#list.findIndex((item) => item.id === annotation.id);\n    if (index !== -1) {\n      // update quantification if needed\n      if (propKeys.includes('mathShape') ||\n        propKeys.includes('textExpr')) {\n        annotation.updateQuantification();\n      }\n      // update list\n      this.#list[index] = annotation;\n      /**\n       * Annotation update event.\n       *\n       * @event AnnotationGroup#annotationupdate\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {Annotation} data The added annnotation.\n       * @property {string[]} keys The properties that were updated.\n       */\n      this.#fireEvent({\n        type: 'annotationupdate',\n        data: annotation,\n        keys: propKeys\n      });\n    } else {\n      logger.warn('Cannot find annotation to update');\n    }\n  }\n\n  /**\n   * Remove an annotation.\n   *\n   * @param {string} id The id of the annotation to remove.\n   */\n  remove(id) {\n    const index = this.#list.findIndex((item) => item.id === id);\n    if (index !== -1) {\n      const annotation = this.#list.splice(index, 1)[0];\n      /**\n       * Annotation update event.\n       *\n       * @event AnnotationGroup#annotationremove\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {Annotation} data The added annnotation.\n       * @property {string[]} keys The properties that were updated.\n       */\n      this.#fireEvent({\n        type: 'annotationremove',\n        data: annotation\n      });\n    } else {\n      logger.warn('Cannot find annotation to remove');\n    }\n  }\n\n  /**\n   * Set the associated view controller.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   */\n  setViewController(viewController) {\n    for (const item of this.#list) {\n      item.setViewController(viewController);\n      item.updateQuantification();\n    }\n  }\n\n  /**\n   * Find an annotation.\n   *\n   * @param {string} id The id of the annotation to find.\n   * @returns {Annotation|undefined} The found annotation.\n   */\n  find(id) {\n    return this.#list.find((item) => item.id === id);\n  }\n\n  /**\n   * Get the meta data.\n   *\n   * @returns {Object<string, any>} The meta data.\n   */\n  getMeta() {\n    return this.#meta;\n  }\n\n  /**\n   * Check if this list contains a meta data value.\n   *\n   * @param {string} key The key to check.\n   * @returns {boolean} True if the meta data is present.\n   */\n  hasMeta(key) {\n    return typeof this.#meta[key] !== 'undefined';\n  }\n\n  /**\n   * Get a meta data value.\n   *\n   * @param {string} key The meta data key.\n   * @returns {string|object} The meta data value.\n   */\n  getMetaValue(key) {\n    return this.#meta[key];\n  }\n\n  /**\n   * Set a meta data.\n   *\n   * @param {string} key The meta data key.\n   * @param {string|object} value The value of the meta data.\n   */\n  setMetaValue(key, value) {\n    this.#meta[key] = value;\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n}\n","import {AnnotationGroup} from '../image/annotationGroup';\nimport {\n  RemoveAnnotationCommand,\n  UpdateAnnotationCommand\n} from '../tools/drawCommands';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Draw controller.\n */\nexport class DrawController {\n\n  /**\n   * The annotation group.\n   *\n   * @type {AnnotationGroup}\n   */\n  #annotationGroup;\n\n  /**\n   * Get an annotation.\n   *\n   * @param {string} id The annotation id.\n   * @returns {Annotation|undefined} The annotation.\n   */\n  getAnnotation(id) {\n    return this.#annotationGroup.find(id);\n  }\n\n  /**\n   * Get the annotation group.\n   *\n   * @returns {AnnotationGroup} The list.\n   */\n  getAnnotationGroup() {\n    return this.#annotationGroup;\n  }\n\n  /**\n   * Check if the annotation group is editable.\n   *\n   * @returns {boolean} True if editable.\n   */\n  isAnnotationGroupEditable() {\n    return this.#annotationGroup.isEditable();\n  }\n\n  /**\n   * Set the annotation group editability.\n   *\n   * @param {boolean} flag True to make the annotation group editable.\n   */\n  setAnnotationGroupEditable(flag) {\n    this.#annotationGroup.setEditable(flag);\n  }\n\n  /**\n   * Add an annotation.\n   *\n   * @param {Annotation} annotation The annotation to add.\n   */\n  addAnnotation(annotation) {\n    this.#annotationGroup.add(annotation);\n  }\n\n  /**\n   * Update an anotation from the list.\n   *\n   * @param {Annotation} annotation The annotation to update.\n   * @param {string[]} [propKeys] Optional properties that got updated.\n   */\n  updateAnnotation(annotation, propKeys) {\n    this.#annotationGroup.update(annotation, propKeys);\n  }\n\n  /**\n   * Remove an anotation for the list.\n   *\n   * @param {string} id The id of the annotation to remove.\n   */\n  removeAnnotation(id) {\n    this.#annotationGroup.remove(id);\n  }\n\n  /**\n   * Remove an annotation via a remove command (triggers draw actions).\n   *\n   * @param {string} id The annotation id.\n   * @param {Function} exeCallback The undo stack callback.\n   */\n  removeAnnotationWithCommand(id, exeCallback) {\n    const annotation = this.getAnnotation(id);\n    if (typeof annotation === 'undefined') {\n      logger.warn(\n        'Cannot create remove command for undefined annotation: ' + id);\n      return;\n    }\n    // create remove annotation command\n    const command = new RemoveAnnotationCommand(annotation, this);\n    // add command to undo stack\n    exeCallback(command);\n    // execute command: triggers draw remove\n    command.execute();\n  }\n\n  /**\n   * Update an annotation via an update command (triggers draw actions).\n   *\n   * @param {string} id The annotation id.\n   * @param {object} originalProps The original annotation properties\n   *   that will be updated.\n   * @param {object} newProps The new annotation properties\n   *   that will replace the original ones.\n   * @param {Function} exeCallback The undo stack callback.\n   */\n  updateAnnotationWithCommand(id, originalProps, newProps, exeCallback) {\n    const annotation = this.getAnnotation(id);\n    if (typeof annotation === 'undefined') {\n      logger.warn(\n        'Cannot create update command for undefined annotation: ' + id);\n      return;\n    }\n    // create remove annotation command\n    const command = new UpdateAnnotationCommand(\n      annotation, originalProps, newProps, this);\n    // add command to undo stack\n    exeCallback(command);\n    // execute command: triggers draw remove\n    command.execute();\n  }\n\n  /**\n   * Remove all annotations via remove commands (triggers draw actions).\n   *\n   * @param {Function} exeCallback The undo stack callback.\n   */\n  removeAllAnnotationsWithCommand(exeCallback) {\n    for (const annotation of this.#annotationGroup.getList()) {\n      this.removeAnnotationWithCommand(annotation.id, exeCallback);\n    }\n  }\n\n  /**\n   * @param {AnnotationGroup} [group] Optional annotation group.\n   */\n  constructor(group) {\n    if (typeof group !== 'undefined') {\n      this.#annotationGroup = group;\n    } else {\n      this.#annotationGroup = new AnnotationGroup();\n    }\n  }\n\n  /**\n   * Check if the annotation group contains a meta data value.\n   *\n   * @param {string} key The key to check.\n   * @returns {boolean} True if the meta data is present.\n   */\n  hasAnnotationMeta(key) {\n    return this.#annotationGroup.hasMeta(key);\n  }\n\n  /**\n   * Set an annotation meta data.\n   *\n   * @param {string} key The meta data to set.\n   * @param {string} value The value of the meta data.\n   */\n  setAnnotationMeta(key, value) {\n    this.#annotationGroup.setMetaValue(key, value);\n  }\n\n} // class DrawController\n","import {ListenerHandler} from '../utils/listen';\nimport {DrawController} from '../app/drawController';\nimport {getScaledOffset} from './layerGroup';\nimport {InteractionEventNames} from './generic';\nimport {logger} from '../utils/logger';\nimport {toStringId} from '../utils/array';\nimport {precisionRound} from '../utils/string';\nimport {AddAnnotationCommand} from '../tools/drawCommands';\nimport {\n  isNodeWithId,\n  isPositionNode,\n  isNodeNameShape,\n  isNodeNameLabel\n} from '../tools/drawBounds';\nimport {Style} from '../gui/style';\nimport {Line} from '../math/line';\nimport {Rectangle} from '../math/rectangle';\nimport {ROI} from '../math/roi';\nimport {Protractor} from '../math/protractor';\nimport {Ellipse} from '../math/ellipse';\nimport {Circle} from '../math/circle';\nimport {Point2D} from '../math/point';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point, Point3D} from '../math/point';\nimport {Index} from '../math/index';\nimport {Vector3D} from '../math/vector';\nimport {Scalar2D, Scalar3D} from '../math/scalar';\nimport {PlaneHelper} from '../image/planeHelper';\nimport {Annotation} from '../image/annotation';\nimport {AnnotationGroup} from '../image/annotationGroup';\nimport {DrawShapeHandler} from '../tools/drawShapeHandler';\n/* eslint-enable no-unused-vars */\n\n/**\n * Debug function to output the layer hierarchy as text.\n *\n * @param {object} layer The Konva layer.\n * @param {string} prefix A display prefix (used in recursion).\n * @returns {string} A text representation of the hierarchy.\n */\n// function getHierarchyLog(layer, prefix) {\n//   if (typeof prefix === 'undefined') {\n//     prefix = '';\n//   }\n//   const kids = layer.getChildren();\n//   let log = prefix + '|__ ' + layer.name() + ': ' + layer.id() + '\\n';\n//   for (let i = 0; i < kids.length; ++i) {\n//     log += getHierarchyLog(kids[i], prefix + '    ');\n//   }\n//   return log;\n// }\n\n/**\n * Draw layer.\n */\nexport class DrawLayer {\n\n  /**\n   * The container div.\n   *\n   * @type {HTMLDivElement}\n   */\n  #containerDiv;\n\n  /**\n   * Konva stage.\n   *\n   * @type {Konva.Stage}\n   */\n  #konvaStage = null;\n\n  /**\n   * The layer base size as {x,y}.\n   *\n   * @type {Scalar2D}\n   */\n  #baseSize;\n\n  /**\n   * The layer base spacing as {x,y}.\n   *\n   * @type {Scalar2D}\n   */\n  #baseSpacing;\n\n  /**\n   * The layer fit scale.\n   *\n   * @type {Scalar2D}\n   */\n  #fitScale = {x: 1, y: 1};\n\n  /**\n   * The layer flip scale.\n   *\n   * @type {Scalar3D}\n   */\n  #flipScale = {x: 1, y: 1, z: 1};\n\n  /**\n   * The base layer offset.\n   *\n   * @type {Scalar2D}\n   */\n  #baseOffset = {x: 0, y: 0};\n\n  /**\n   * The view offset.\n   *\n   * @type {Scalar2D}\n   */\n  #viewOffset = {x: 0, y: 0};\n\n  /**\n   * The zoom offset.\n   *\n   * @type {Scalar2D}\n   */\n  #zoomOffset = {x: 0, y: 0};\n\n  /**\n   * The flip offset.\n   *\n   * @type {Scalar2D}\n   */\n  #flipOffset = {x: 0, y: 0};\n\n  /**\n   * The draw controller.\n   *\n   * @type {DrawController}\n   */\n  #drawController;\n\n  /**\n   * The plane helper.\n   *\n   * @type {PlaneHelper}\n   */\n  #planeHelper;\n\n  /**\n   * The associated data id.\n   *\n   * @type {string}\n   */\n  #dataId;\n\n  /**\n   * The reference layer id.\n   *\n   * @type {string}\n   */\n  #referenceLayerId;\n\n  /**\n   * Current position group id.\n   *\n   * @type {string|undefined}\n   */\n  #currentPosGroupId;\n\n  /**\n   * Draw shape handler.\n   *\n   * @type {DrawShapeHandler|undefined}\n   */\n  #shapeHandler;\n\n  /**\n   * Visible labels flag.\n   *\n   * @type {boolean}\n   */\n  #visibleLabels = true;\n\n  /**\n   * @param {HTMLDivElement} containerDiv The layer div, its id will be used\n   *   as this layer id.\n   */\n  constructor(containerDiv) {\n    this.#containerDiv = containerDiv;\n    // specific css class name\n    this.#containerDiv.className += ' drawLayer';\n  }\n\n  /**\n   * Set the draw shape handler.\n   *\n   * @param {DrawShapeHandler|undefined} handler The shape handler.\n   */\n  setShapeHandler(handler) {\n    this.#shapeHandler = handler;\n  }\n\n  /**\n   * Get the associated data id.\n   *\n   * @returns {string} The id.\n   */\n  getDataId() {\n    return this.#dataId;\n  }\n\n  /**\n   * Get the reference layer id.\n   *\n   * @returns {string} The id.\n   */\n  getReferenceLayerId() {\n    return this.#referenceLayerId;\n  }\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Get the Konva stage.\n   *\n   * @returns {Konva.Stage} The stage.\n   */\n  getKonvaStage() {\n    return this.#konvaStage;\n  }\n\n  /**\n   * Get the Konva layer.\n   *\n   * @returns {Konva.Layer} The layer.\n   */\n  getKonvaLayer() {\n    // there should only be one layer\n    return this.#konvaStage.getLayers()[0];\n  }\n\n  /**\n   * Get the draw controller.\n   *\n   * @returns {DrawController} The controller.\n   */\n  getDrawController() {\n    return this.#drawController;\n  }\n\n  /**\n   * Set the plane helper.\n   *\n   * @param {PlaneHelper} helper The helper.\n   */\n  setPlaneHelper(helper) {\n    this.#planeHelper = helper;\n  }\n\n  // common layer methods [start] ---------------\n\n  /**\n   * Get the id of the layer.\n   *\n   * @returns {string} The string id.\n   */\n  getId() {\n    return this.#containerDiv.id;\n  }\n\n  /**\n   * Remove the HTML element from the DOM.\n   */\n  removeFromDOM() {\n    this.#containerDiv.remove();\n  }\n\n  /**\n   * Get the layer base size (without scale).\n   *\n   * @returns {Scalar2D} The size as {x,y}.\n   */\n  getBaseSize() {\n    return this.#baseSize;\n  }\n\n  /**\n   * Get the layer opacity.\n   *\n   * @returns {number} The opacity ([0:1] range).\n   */\n  getOpacity() {\n    return this.#konvaStage.opacity();\n  }\n\n  /**\n   * Set the layer opacity.\n   *\n   * @param {number} alpha The opacity ([0:1] range).\n   */\n  setOpacity(alpha) {\n    this.#konvaStage.opacity(Math.min(Math.max(alpha, 0), 1));\n  }\n\n  /**\n   * Add a flip offset along the layer X axis.\n   */\n  addFlipOffsetX() {\n    // flip offset\n    const scale = this.#konvaStage.scale();\n    const size = this.#konvaStage.size();\n    this.#flipOffset.x += size.width / scale.x;\n    // apply\n    const offset = this.#konvaStage.offset();\n    offset.x += this.#flipOffset.x;\n    this.#konvaStage.offset(offset);\n  }\n\n  /**\n   * Add a flip offset along the layer Y axis.\n   */\n  addFlipOffsetY() {\n    // flip offset\n    const scale = this.#konvaStage.scale();\n    const size = this.#konvaStage.size();\n    this.#flipOffset.y += size.height / scale.y;\n    // apply\n    const offset = this.#konvaStage.offset();\n    offset.y += this.#flipOffset.y;\n    this.#konvaStage.offset(offset);\n  }\n\n  /**\n   * Flip the scale along the layer X axis.\n   */\n  flipScaleX() {\n    this.#flipScale.x *= -1;\n  }\n\n  /**\n   * Flip the scale along the layer Y axis.\n   */\n  flipScaleY() {\n    this.#flipScale.y *= -1;\n  }\n\n  /**\n   * Flip the scale along the layer Z axis.\n   */\n  flipScaleZ() {\n    this.#flipScale.z *= -1;\n  }\n\n  /**\n   * Set the layer scale.\n   *\n   * @param {Scalar3D} newScale The scale as {x,y,z}.\n   * @param {Point3D} [center] The scale center.\n   */\n  setScale(newScale, center) {\n    const orientedNewScale =\n      this.#planeHelper.getTargetOrientedPositiveXYZ({\n        x: newScale.x * this.#flipScale.x,\n        y: newScale.y * this.#flipScale.y,\n        z: newScale.z * this.#flipScale.z,\n      });\n    const finalNewScale = {\n      x: this.#fitScale.x * orientedNewScale.x,\n      y: this.#fitScale.y * orientedNewScale.y\n    };\n\n    const offset = this.#konvaStage.offset();\n\n    if (Math.abs(newScale.x) === 1 &&\n      Math.abs(newScale.y) === 1 &&\n      Math.abs(newScale.z) === 1) {\n      // reset zoom offset for scale=1\n      const resetOffset = {\n        x: offset.x - this.#zoomOffset.x,\n        y: offset.y - this.#zoomOffset.y\n      };\n      // store new offset\n      this.#zoomOffset = {x: 0, y: 0};\n      this.#konvaStage.offset(resetOffset);\n    } else {\n      if (typeof center !== 'undefined') {\n        let worldCenter = this.#planeHelper.getPlaneOffsetFromOffset3D({\n          x: center.getX(),\n          y: center.getY(),\n          z: center.getZ()\n        });\n        // center was obtained with viewLayer.displayToMainPlanePos\n        // compensated for baseOffset\n        // TODO: justify...\n        worldCenter = {\n          x: worldCenter.x + this.#baseOffset.x,\n          y: worldCenter.y + this.#baseOffset.y\n        };\n\n        const newOffset = getScaledOffset(\n          offset, this.#konvaStage.scale(), finalNewScale, worldCenter);\n\n        const newZoomOffset = {\n          x: this.#zoomOffset.x + newOffset.x - offset.x,\n          y: this.#zoomOffset.y + newOffset.y - offset.y\n        };\n        // store new offset\n        this.#zoomOffset = newZoomOffset;\n        this.#konvaStage.offset(newOffset);\n      }\n    }\n\n    this.#konvaStage.scale(finalNewScale);\n    // update labels\n    this.#updateLabelScale(finalNewScale);\n  }\n\n  /**\n   * Initialise the layer scale.\n   *\n   * @param {Scalar3D} newScale The scale as {x,y,z}.\n   * @param {Scalar2D} absoluteZoomOffset The zoom offset as {x,y}\n   *   without the fit scale (as provided by getAbsoluteZoomOffset).\n   */\n  initScale(newScale, absoluteZoomOffset) {\n    const orientedNewScale = this.#planeHelper.getTargetOrientedPositiveXYZ({\n      x: newScale.x * this.#flipScale.x,\n      y: newScale.y * this.#flipScale.y,\n      z: newScale.z * this.#flipScale.z,\n    });\n    const finalNewScale = {\n      x: this.#fitScale.x * orientedNewScale.x,\n      y: this.#fitScale.y * orientedNewScale.y\n    };\n    this.#konvaStage.scale(finalNewScale);\n\n    this.#zoomOffset = {\n      x: absoluteZoomOffset.x / this.#fitScale.x,\n      y: absoluteZoomOffset.y / this.#fitScale.y\n    };\n    const offset = this.#konvaStage.offset();\n    this.#konvaStage.offset({\n      x: offset.x + this.#zoomOffset.x,\n      y: offset.y + this.#zoomOffset.y\n    });\n  }\n\n  /**\n   * Set the layer offset.\n   *\n   * @param {Scalar3D} newOffset The offset as {x,y,z}.\n   */\n  setOffset(newOffset) {\n    const planeNewOffset =\n      this.#planeHelper.getPlaneOffsetFromOffset3D(newOffset);\n    this.#konvaStage.offset({\n      x: planeNewOffset.x +\n        this.#viewOffset.x +\n        this.#baseOffset.x +\n        this.#zoomOffset.x +\n        this.#flipOffset.x,\n      y: planeNewOffset.y +\n        this.#viewOffset.y +\n        this.#baseOffset.y +\n        this.#zoomOffset.y +\n        this.#flipOffset.y\n    });\n  }\n\n  /**\n   * Set the base layer offset. Updates the layer offset.\n   *\n   * @param {Vector3D} scrollOffset The scroll offset vector.\n   * @param {Vector3D} planeOffset The plane offset vector.\n   * @returns {boolean} True if the offset was updated.\n   */\n  setBaseOffset(scrollOffset, planeOffset) {\n    const scrollDimIndex = this.#planeHelper.getNativeScrollDimIndex();\n    const newOffset = this.#planeHelper.getPlaneOffsetFromOffset3D({\n      x: scrollDimIndex === 0 ? scrollOffset.getX() : planeOffset.getX(),\n      y: scrollDimIndex === 1 ? scrollOffset.getY() : planeOffset.getY(),\n      z: scrollDimIndex === 2 ? scrollOffset.getZ() : planeOffset.getZ(),\n    });\n    const needsUpdate = this.#baseOffset.x !== newOffset.x ||\n      this.#baseOffset.y !== newOffset.y;\n    // reset offset if needed\n    if (needsUpdate) {\n      const offset = this.#konvaStage.offset();\n      this.#konvaStage.offset({\n        x: offset.x - this.#baseOffset.x + newOffset.x,\n        y: offset.y - this.#baseOffset.y + newOffset.y\n      });\n      this.#baseOffset = newOffset;\n    }\n    return needsUpdate;\n  }\n\n  /**\n   * Display the layer.\n   *\n   * @param {boolean} flag Whether to display the layer or not.\n   */\n  display(flag) {\n    this.#containerDiv.style.display = flag ? '' : 'none';\n  }\n\n  /**\n   * Check if the layer is visible.\n   *\n   * @returns {boolean} True if the layer is visible.\n   */\n  isVisible() {\n    return this.#containerDiv.style.display === '';\n  }\n\n  /**\n   * Draw the content (imageData) of the layer.\n   * The imageData variable needs to be set.\n   */\n  draw() {\n    this.#konvaStage.draw();\n  }\n\n  /**\n   * Initialise the layer: set the canvas and context.\n   *\n   * @param {Scalar2D} size The image size as {x,y}.\n   * @param {Scalar2D} spacing The image spacing as {x,y}.\n   * @param {string} refLayerId The reference image dataId.\n   */\n  initialise(size, spacing, refLayerId) {\n    // set locals\n    this.#baseSize = size;\n    this.#baseSpacing = spacing;\n    this.#referenceLayerId = refLayerId;\n\n    // create stage\n    this.#konvaStage = new Konva.Stage({\n      container: this.#containerDiv,\n      width: this.#baseSize.x,\n      height: this.#baseSize.y,\n      listening: false\n    });\n    // reset style\n    // (avoids a not needed vertical scrollbar)\n    this.#konvaStage.getContent().setAttribute('style', '');\n\n    // create layer\n    const konvaLayer = new Konva.Layer({\n      listening: false,\n      visible: true\n    });\n    this.#konvaStage.add(konvaLayer);\n  }\n\n  /**\n   * Set the annotation group.\n   *\n   * @param {AnnotationGroup} annotationGroup The annotation group.\n   * @param {string} dataId The associated data id.\n   * @param {object} exeCallback The undo stack callback.\n   */\n  setAnnotationGroup(annotationGroup, dataId, exeCallback) {\n    this.#dataId = dataId;\n    // local listeners\n    annotationGroup.addEventListener('annotationadd', (event) => {\n      // draw annotation\n      this.#addAnnotationDraw(event.data, true);\n      this.getKonvaLayer().draw();\n    });\n    annotationGroup.addEventListener('annotationupdate', (event) => {\n      // update annotation draw\n      this.#updateAnnotationDraw(event.data);\n      this.getKonvaLayer().draw();\n    });\n    annotationGroup.addEventListener('annotationremove', (event) => {\n      // remove annotation draw\n      this.#removeAnnotationDraw(event.data);\n      this.getKonvaLayer().draw();\n    });\n    annotationGroup.addEventListener(\n      'annotationgroupeditablechange',\n      (event) => {\n        this.activateCurrentPositionShapes(event.data);\n      }\n    );\n\n    // create draw controller\n    this.#drawController = new DrawController(annotationGroup);\n\n    // annotations are allready in the annotation list,\n    // -> no need to add them, just draw and save command\n    if (annotationGroup.getLength() !== 0) {\n      for (const annotation of annotationGroup.getList()) {\n        // draw annotation\n        this.#addAnnotationDraw(annotation, false);\n        // create the draw command\n        const command = new AddAnnotationCommand(\n          annotation, this.getDrawController());\n        // add command to undo stack\n        exeCallback(command);\n      }\n    }\n  }\n\n  /**\n   * Activate shapes at current position.\n   *\n   * @param {boolean} flag The flag to activate or not.\n   */\n  activateCurrentPositionShapes(flag) {\n    const konvaLayer = this.getKonvaLayer();\n\n    // stop stage listening\n    this.#konvaStage.listening(false);\n\n    if (typeof this.#shapeHandler !== 'undefined') {\n      // reset shape editor (remove anchors)\n      this.#shapeHandler.disableAndResetEditor();\n      // remove listeners for all position groups\n      const allPosGroups = konvaLayer.getChildren();\n      for (const posGroup of allPosGroups) {\n        if (posGroup instanceof Konva.Group) {\n          posGroup.getChildren().forEach((group) => {\n            if (group instanceof Konva.Group) {\n              this.#shapeHandler.removeShapeListeners(group);\n            }\n          });\n        }\n      }\n    }\n\n    // activate shape listeners if possible\n    const drawController = this.getDrawController();\n    if (flag &&\n      drawController.getAnnotationGroup().isEditable()) {\n      // start stage listening\n      this.#konvaStage.listening(true);\n      // shape groups at the current position\n      const shapeGroups =\n        this.#getCurrentPosGroup().getChildren();\n      // listen if we have shapes\n      if (shapeGroups.length !== 0) {\n        konvaLayer.listening(true);\n      }\n      // add listeners for position group\n      if (typeof this.#shapeHandler !== 'undefined') {\n        shapeGroups.forEach((group) => {\n          if (group instanceof Konva.Group) {\n            const annotation = drawController.getAnnotation(group.id());\n            this.#shapeHandler.addShapeGroupListeners(group, annotation, this);\n          }\n        });\n      }\n    }\n\n    konvaLayer.draw();\n  }\n\n  /**\n   * Get the position group id for an annotation.\n   *\n   * @param {Annotation} annotation The target annotation.\n   * @returns {string|undefined} The group id.\n   */\n  #getAnnotationPosGroupId(annotation) {\n    let points;\n    // annotation planePoints are only present\n    // for non aquisition plane\n    if (typeof annotation.planePoints !== 'undefined') {\n      // use plane points\n      points = annotation.planePoints;\n    } else {\n      // just use plane origin\n      points = [annotation.planeOrigin];\n    }\n    return this.#getPositionId(points);\n  }\n\n  /**\n   * Get a string id from input plane points.\n   *\n   * @param {Point3D[]} points A list of points that defined a plane.\n   * @returns {string} The string id.\n   */\n  #getPositionId(points) {\n    let res = '';\n    for (const point of points) {\n      if (res.length !== 0) {\n        res += '-';\n      }\n      const posValues = [\n        precisionRound(point.getX(), 2),\n        precisionRound(point.getY(), 2),\n        precisionRound(point.getZ(), 2),\n      ];\n      res += toStringId(posValues);\n    }\n    return res;\n  }\n\n  /**\n   * Find the shape group associated to an annotation.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Konva.Group|undefined} The shape group.\n   */\n  #findShapeGroup(annotation) {\n    let res;\n\n    const posGroupId = this.#getAnnotationPosGroupId(annotation);\n    const layerChildren = this.getKonvaLayer().getChildren(\n      isNodeWithId(posGroupId));\n    if (layerChildren.length !== 0) {\n      const posGroup = layerChildren[0];\n      if (!(posGroup instanceof Konva.Group)) {\n        return;\n      }\n      const posChildren = posGroup.getChildren(\n        isNodeWithId(annotation.id));\n      if (posChildren.length !== 0 &&\n        posChildren[0] instanceof Konva.Group) {\n        res = posChildren[0];\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Draw an annotation: create the shape group and add it to\n   *   the Konva layer.\n   *\n   * @param {Annotation} annotation The annotation to draw.\n   * @param {boolean} visible The position group visibility.\n   */\n  #addAnnotationDraw(annotation, visible) {\n    // check for compatible view\n    if (!annotation.isCompatibleView(this.#planeHelper)) {\n      return;\n    }\n    const posGroupId = this.#getAnnotationPosGroupId(annotation);\n    // Get or create position-group if it does not exist and\n    // append it to konvaLayer\n    let posGroup = this.getKonvaLayer().getChildren(\n      isNodeWithId(posGroupId))[0];\n    if (typeof posGroup === 'undefined') {\n      posGroup = new Konva.Group({\n        id: posGroupId,\n        name: 'position-group',\n        visible: visible\n      });\n      this.getKonvaLayer().add(posGroup);\n    }\n    if (!(posGroup instanceof Konva.Group)) {\n      return;\n    };\n\n    const style = new Style();\n    const stage = this.getKonvaStage();\n    style.setZoomScale(stage.scale());\n\n    // shape group (use first one since it will be removed from\n    // the group when we change it)\n    const factory = annotation.getFactory();\n    const shapeGroup = factory.createShapeGroup(annotation, style);\n    // add group to posGroup (switches its parent)\n    posGroup.add(shapeGroup);\n\n    // activate shape if possible\n    if (visible &&\n      typeof this.#shapeHandler !== 'undefined'\n    ) {\n      this.#shapeHandler.addShapeGroupListeners(shapeGroup, annotation, this);\n    }\n    // set label visibility\n    this.setLabelVisibility(shapeGroup);\n  }\n\n  /**\n   * Remove an annotation draw.\n   *\n   * @param {Annotation} annotation The annotation to remove.\n   * @returns {boolean} True if the shape group has been found and removed.\n   */\n  #removeAnnotationDraw(annotation) {\n    const shapeGroup = this.#findShapeGroup(annotation);\n    if (!(shapeGroup instanceof Konva.Group)) {\n      logger.debug('No shape group to remove');\n      return false;\n    };\n    shapeGroup.remove();\n    return true;\n  }\n\n  /**\n   * Update an annotation draw.\n   *\n   * @param {Annotation} annotation The annotation to update.\n   */\n  #updateAnnotationDraw(annotation) {\n    if (this.#removeAnnotationDraw(annotation)) {\n      this.#addAnnotationDraw(annotation, true);\n    }\n  }\n\n  /**\n   * Fit the layer to its parent container.\n   *\n   * @param {Scalar2D} containerSize The container size as {x,y}.\n   * @param {number} divToWorldSizeRatio The div to world size ratio.\n   * @param {Scalar2D} fitOffset The fit offset as {x,y}.\n   */\n  fitToContainer(containerSize, divToWorldSizeRatio, fitOffset) {\n    // update konva\n    this.#konvaStage.width(containerSize.x);\n    this.#konvaStage.height(containerSize.y);\n\n    // fit scale\n    const divToImageSizeRatio = {\n      x: divToWorldSizeRatio * this.#baseSpacing.x,\n      y: divToWorldSizeRatio * this.#baseSpacing.y\n    };\n    // #scale = inputScale * fitScale * flipScale\n    // flipScale does not change here, we can omit it\n    // newScale = (#scale / fitScale) * newFitScale\n    const newScale = {\n      x: this.#konvaStage.scale().x * divToImageSizeRatio.x / this.#fitScale.x,\n      y: this.#konvaStage.scale().y * divToImageSizeRatio.y / this.#fitScale.y\n    };\n\n    // set scales if different from previous\n    if (this.#konvaStage.scale().x !== newScale.x ||\n      this.#konvaStage.scale().y !== newScale.y) {\n      this.#fitScale = divToImageSizeRatio;\n      this.#konvaStage.scale(newScale);\n    }\n\n    // view offset\n    const newViewOffset = {\n      x: fitOffset.x / divToImageSizeRatio.x,\n      y: fitOffset.y / divToImageSizeRatio.y\n    };\n    // flip offset\n    const scaledImageSize = {\n      x: containerSize.x / divToImageSizeRatio.x,\n      y: containerSize.y / divToImageSizeRatio.y\n    };\n    const newFlipOffset = {\n      x: this.#flipOffset.x !== 0 ? scaledImageSize.x : 0,\n      y: this.#flipOffset.y !== 0 ? scaledImageSize.y : 0,\n    };\n\n    // set offsets if different from previous\n    if (this.#viewOffset.x !== newViewOffset.x ||\n      this.#viewOffset.y !== newViewOffset.y ||\n      this.#flipOffset.x !== newFlipOffset.x ||\n      this.#flipOffset.y !== newFlipOffset.y) {\n      // update global offset\n      this.#konvaStage.offset({\n        x: this.#konvaStage.offset().x +\n          newViewOffset.x - this.#viewOffset.x +\n          newFlipOffset.x - this.#flipOffset.x,\n        y: this.#konvaStage.offset().y +\n          newViewOffset.y - this.#viewOffset.y +\n          newFlipOffset.y - this.#flipOffset.y,\n      });\n      // update private local offsets\n      this.#flipOffset = newFlipOffset;\n      this.#viewOffset = newViewOffset;\n    }\n  }\n\n  /**\n   * Check the visibility of an annotation.\n   *\n   * @param {string} id The id of the annotation.\n   * @returns {boolean} True if the annotation is visible.\n   */\n  isAnnotationVisible(id) {\n    // get the group (annotation and group have same id)\n    const group = this.#getGroup(id);\n    if (typeof group === 'undefined') {\n      return false;\n    }\n    // get visibility\n    return group.isVisible();\n  }\n\n  /**\n   * Set the visibility of an annotation.\n   *\n   * @param {string} id The id of the annotation.\n   * @param {boolean} [visible] True to set to visible,\n   *   will toggle visibility if not defined.\n   * @returns {boolean} False if the annotation shape cannot be found.\n   */\n  setAnnotationVisibility(id, visible) {\n    // get the group (annotation and group have same id)\n    const group = this.#getGroup(id);\n    if (typeof group === 'undefined') {\n      return false;\n    }\n    // if not set, toggle visibility\n    if (typeof visible === 'undefined') {\n      visible = !group.isVisible();\n    }\n    group.visible(visible);\n\n    // udpate\n    this.draw();\n\n    return true;\n  }\n\n  /**\n   * Set the visibility of all labels.\n   *\n   * @param {boolean} [visible] True to set to visible,\n   *   will toggle visibility if not defined.\n   */\n  setLabelsVisibility(visible) {\n    this.#visibleLabels = visible;\n\n    const posGroups = this.getKonvaLayer().getChildren();\n    for (const posGroup of posGroups) {\n      if (posGroup instanceof Konva.Group) {\n        const shapeGroups = posGroup.getChildren();\n        for (const shapeGroup of shapeGroups) {\n          if (shapeGroup instanceof Konva.Group) {\n            this.#setLabelVisibility(shapeGroup, visible);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Set a shape group label visibility.\n   *\n   * @param {Konva.Group} shapeGroup The shape group.\n   * @param {boolean} [visible] True to set to visible,\n   *   will toggle visibility if not defined.\n   */\n  #setLabelVisibility(shapeGroup, visible) {\n    const label = shapeGroup.getChildren(isNodeNameLabel)[0];\n    if (!(label instanceof Konva.Label)) {\n      return;\n    }\n    // if not set, toggle visibility\n    if (typeof visible === 'undefined') {\n      visible = !label.isVisible();\n    }\n    // set visible only for non empty text\n    if (typeof label.getText() !== 'undefined' &&\n      label.getText().text().length !== 0) {\n      label.visible(visible);\n      const connector = shapeGroup.getChildren(node =>\n        (node.className === 'Line') && node.name() === 'connector')[0];\n      if (connector) {\n        connector.visible(visible);\n      }\n    }\n  }\n\n  /**\n   * Set a shape group label visibility according to\n   *  this layer setting.\n   *\n   * @param {Konva.Group} shapeGroup The shape group.\n   */\n  setLabelVisibility(shapeGroup) {\n    this.#setLabelVisibility(shapeGroup, this.#visibleLabels);\n  }\n\n  /**\n   * Delete a Draw from the stage.\n   *\n   * @deprecated Since v0.34, please switch to `annotationGroup.remove`.\n   * @param {string} _id The id of the group to delete.\n   * @param {Function} _exeCallback The callback to call once the\n   *  DeleteCommand has been executed.\n   */\n  deleteDraw(_id, _exeCallback) {\n    // does nothing\n  }\n\n  /**\n   * Delete all Draws from the stage.\n   *\n   * @deprecated Since v0.34, please switch to `annotationGroup.remove`.\n   * @param {Function} _exeCallback The callback to call once the\n   *  DeleteCommand has been executed.\n   */\n  deleteDraws(_exeCallback) {\n    // does nothing\n  }\n\n  /**\n   * Get the total number of draws of this layer\n   * (at all positions).\n   *\n   * @returns {number|undefined} The total number of draws.\n   */\n  getNumberOfDraws() {\n    const posGroups = this.getKonvaLayer().getChildren();\n    let count = 0;\n    for (const posGroup of posGroups) {\n      if (posGroup instanceof Konva.Group) {\n        count += posGroup.getChildren().length;\n      }\n    }\n    return count;\n  }\n\n  /**\n   * Enable and listen to container interaction events.\n   */\n  bindInteraction() {\n    this.#konvaStage.listening(true);\n    // allow pointer events\n    this.#containerDiv.style.pointerEvents = 'auto';\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      this.#containerDiv.addEventListener(names[i], this.#fireEvent);\n    }\n  }\n\n  /**\n   * Disable and stop listening to container interaction events.\n   */\n  unbindInteraction() {\n    this.#konvaStage.listening(false);\n    // disable pointer events\n    this.#containerDiv.style.pointerEvents = 'none';\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      this.#containerDiv.removeEventListener(names[i], this.#fireEvent);\n    }\n  }\n\n  /**\n   * Set the current position.\n   *\n   * @param {Point} position The new position.\n   * @param {Index} [index] Optional coresponding index.\n   * @returns {boolean} True if the position was updated.\n   */\n  setCurrentPosition(position, index) {\n    if (typeof index === 'undefined') {\n      index = this.#planeHelper.worldToIndex(position);\n    }\n    const planePoints = this.#planeHelper.getPlanePoints(position);\n    let points;\n    if (this.#planeHelper.isAquisitionOrientation()) {\n      // just use plane origin\n      points = [planePoints[0]];\n    } else {\n      // use plane points\n      points = planePoints;\n    }\n    const posGroupId = this.#getPositionId(points);\n\n    this.#activateDrawLayer(posGroupId);\n    // TODO: add check\n    this.#fireEvent({\n      type: 'positionchange',\n      value: [\n        index.getValues(),\n        position.getValues(),\n      ],\n      valid: true\n    });\n\n    return true;\n  }\n\n  /**\n   * Activate the current draw layer.\n   *\n   * @param {string} posGroupId The position group ID.\n   */\n  #activateDrawLayer(posGroupId) {\n    this.#currentPosGroupId = posGroupId;\n\n    // get all position groups\n    const posGroups = this.getKonvaLayer().getChildren(isPositionNode);\n    // reset or set the visible property\n    let visible;\n    for (let i = 0, leni = posGroups.length; i < leni; ++i) {\n      visible = false;\n      if (typeof posGroupId !== 'undefined' &&\n        posGroups[i].id() === posGroupId) {\n        visible = true;\n      }\n      // group members inherit the visible property\n      posGroups[i].visible(visible);\n    }\n\n    // show current draw layer\n    this.getKonvaLayer().draw();\n  }\n\n  /**\n   * Get the current position group.\n   *\n   * @returns {Konva.Group|undefined} The Konva group.\n   */\n  #getCurrentPosGroup() {\n    if (typeof this.#currentPosGroupId === 'undefined') {\n      return;\n    }\n    // get position groups\n    const posGroups = this.getKonvaLayer().getChildren((node) => {\n      return node.id() === this.#currentPosGroupId;\n    });\n    // if one group, use it\n    // if no group, create one\n    let posGroup;\n    if (posGroups.length === 1) {\n      if (posGroups[0] instanceof Konva.Group) {\n        posGroup = posGroups[0];\n      }\n    } else if (posGroups.length === 0) {\n      posGroup = new Konva.Group();\n      posGroup.name('position-group');\n      posGroup.id(this.#currentPosGroupId);\n      posGroup.visible(true); // dont inherit\n      // add new group to layer\n      this.getKonvaLayer().add(posGroup);\n    } else {\n      logger.warn('Unexpected number of draw position groups');\n    }\n    // return\n    return posGroup;\n  }\n\n  /**\n   * Get a Konva group using its id.\n   *\n   * @param {string} id The group id.\n   * @returns {Konva.Group|undefined} The Konva group.\n   */\n  #getGroup(id) {\n    return this.getKonvaLayer().findOne('#' + id);\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    event.srclayerid = this.getId();\n    event.dataid = this.#dataId;\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  // common layer methods [end] ---------------\n\n  /**\n   * Update label scale: compensate for it so\n   *   that label size stays visually the same.\n   *\n   * @param {Scalar2D} scale The scale to compensate for as {x,y}.\n   */\n  #updateLabelScale(scale) {\n    // same formula as in labelFactory::create\n    // compensate for scale and times 2 so that font 10 looks like a 10\n    const ratioX = 2 / scale.x;\n    const ratioY = 2 / scale.y;\n    // compensate scale for labels\n    const labels = this.#konvaStage.find('Label');\n    for (let i = 0; i < labels.length; ++i) {\n      labels[i].scale({x: ratioX, y: ratioY});\n    }\n  }\n\n} // DrawLayer class\n\n// *************************\n// legacy code to allow to convert old state into annotation\n// *************************\n\n/**\n * Draw meta data.\n */\nexport class DrawMeta {\n  /**\n   * Draw quantification.\n   *\n   * @type {object}\n   */\n  quantification;\n\n  /**\n   * Draw text expression. Can contain variables surrounded with '{}' that will\n   * be extracted from the quantification object.\n   *\n   * @type {string}\n   */\n  textExpr;\n}\n\n/**\n * Draw details.\n */\nexport class DrawDetails {\n  /**\n   * The draw ID.\n   *\n   * @type {number}\n   */\n  id;\n\n  /**\n   * The draw position: an Index converted to string.\n   *\n   * @type {string}\n   */\n  position;\n\n  /**\n   * The draw type.\n   *\n   * @type {string}\n   */\n  type;\n\n  /**\n   * The draw color: for example 'green', '#00ff00' or 'rgb(0,255,0)'.\n   *\n   * @type {string}\n   */\n  color;\n\n  /**\n   * The draw meta.\n   *\n   * @type {DrawMeta}\n   */\n  meta;\n}\n\n/**\n * Convert a KonvaLayer object to a list of annotations.\n *\n * @param {Array} drawings An array of drawings stored\n *   with 'KonvaLayer().toObject()'.\n * @param {DrawDetails[]} drawingsDetails An array of drawings details.\n * @returns {Annotation[]} The associated list of annotations.\n */\nexport function konvaToAnnotation(drawings, drawingsDetails) {\n  const annotations = [];\n\n  // regular Konva deserialize\n  const stateLayer = Konva.Node.create(drawings);\n\n  // get all position groups\n  const statePosGroups = stateLayer.getChildren(isPositionNode);\n\n  for (let i = 0, leni = statePosGroups.length; i < leni; ++i) {\n    const statePosGroup = statePosGroups[i];\n    const statePosKids = statePosGroup.getChildren();\n    for (let j = 0, lenj = statePosKids.length; j < lenj; ++j) {\n      const annotation = new Annotation();\n\n      // shape group (use first one since it will be removed from\n      // the group when we change it)\n      const stateGroup = statePosKids[0];\n      // annotation id\n      annotation.id = stateGroup.id();\n\n      // shape\n      const shape = stateGroup.getChildren(isNodeNameShape)[0];\n      // annotation colour\n      annotation.colour = shape.stroke();\n\n      if (stateGroup.name() === 'line-group') {\n        const points = shape.points();\n        annotation.mathShape = new Point2D(points[0], points[1]);\n        annotation.referencePoints = [\n          new Point2D(points[2], points[3])\n        ];\n      } else if (stateGroup.name() === 'ruler-group') {\n        const points = shape.points();\n        annotation.mathShape = new Line(\n          new Point2D(points[0], points[1]),\n          new Point2D(points[2], points[3])\n        );\n      } else if (stateGroup.name() === 'rectangle-group') {\n        annotation.mathShape = new Rectangle(\n          new Point2D(shape.x(), shape.y()),\n          new Point2D(shape.x() + shape.width(), shape.y() + shape.height())\n        );\n      } else if (stateGroup.name() === 'roi-group') {\n        const points = shape.points();\n        const pointsArray = [];\n        for (let i = 0; i < points.length; i = i + 2) {\n          pointsArray.push(new Point2D(points[i], points[i + 1]));\n        }\n        annotation.mathShape = new ROI(pointsArray);\n      } else if (stateGroup.name() === 'freeHand-group') {\n        logger.warn('Converting freehand into ROI shape');\n        const points = shape.points();\n        const pointsArray = [];\n        for (let i = 0; i < points.length; i = i + 2) {\n          pointsArray.push(new Point2D(points[i], points[i + 1]));\n        }\n        annotation.mathShape = new ROI(pointsArray);\n      } else if (stateGroup.name() === 'protractor-group') {\n        const points = shape.points();\n        annotation.mathShape = new Protractor([\n          new Point2D(points[0], points[1]),\n          new Point2D(points[2], points[3]),\n          new Point2D(points[4], points[5])\n        ]);\n      } else if (stateGroup.name() === 'ellipse-group') {\n        const absPosition = shape.absolutePosition();\n        annotation.mathShape = new Ellipse(\n          new Point2D(absPosition.x, absPosition.y),\n          shape.radiusX(),\n          shape.radiusY()\n        );\n      } else if (stateGroup.name() === 'circle-group') {\n        const absPosition = shape.absolutePosition();\n        annotation.mathShape = new Circle(\n          new Point2D(absPosition.x, absPosition.y),\n          shape.radius()\n        );\n      }\n\n      // details\n      if (drawingsDetails) {\n        const details = drawingsDetails[stateGroup.id()];\n        annotation.textExpr = details.meta.textExpr;\n        annotation.quantification = details.meta.quantification;\n      }\n\n      annotations.push(annotation);\n    }\n  }\n\n  return annotations;\n}\n","import {Index} from '../math/index';\nimport {Point} from '../math/point';\nimport {Vector3D} from '../math/vector';\nimport {viewEventNames} from '../image/view';\nimport {ListenerHandler} from '../utils/listen';\nimport {logger} from '../utils/logger';\nimport {precisionRound} from '../utils/string';\nimport {ViewLayer} from './viewLayer';\nimport {DrawLayer} from './drawLayer';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D, Point3D} from '../math/point';\nimport {Scalar2D, Scalar3D} from '../math/scalar';\nimport {PositionHelper} from '../image/positionHelper';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get the layer div id.\n *\n * @param {string} groupDivId The layer group div id.\n * @param {number} layerIndex The layer index.\n * @returns {string} A string id.\n */\nexport function getLayerDivId(groupDivId, layerIndex) {\n  return groupDivId + '-layer-' + layerIndex;\n}\n\n/**\n * Get the layer details from a div id.\n *\n * @param {string} idString The layer div id.\n * @returns {object} The layer details as {groupDivId, layerIndex, layerId}.\n */\nexport function getLayerDetailsFromLayerDivId(idString) {\n  const split = idString.split('-layer-');\n  if (split.length !== 2) {\n    logger.warn('Not the expected layer div id format...');\n  }\n  return {\n    groupDivId: split[0],\n    layerIndex: split[1],\n    layerId: idString,\n  };\n}\n\n/**\n * Get the layer details from a mouse event.\n *\n * @param {object} event The event to get the layer div id from. Expecting\n * an event origininating from a canvas inside a layer HTML div\n * with the 'layer' class and id generated with `getLayerDivId`.\n * @returns {object} The layer details as {groupDivId, layerIndex, layerId}.\n */\nexport function getLayerDetailsFromEvent(event) {\n  let res = null;\n  // get the closest element from the event target and with the 'layer' class\n  const layerDiv = event.target.closest('.layer');\n  if (layerDiv && typeof layerDiv.id !== 'undefined') {\n    res = getLayerDetailsFromLayerDivId(layerDiv.id);\n  }\n  return res;\n}\n\n/**\n * Get a scaled offset to adapt to new scale and such as the input center\n * stays at the same position.\n *\n * @param {Scalar2D} offset The previous offset as {x,y}.\n * @param {Scalar2D} scale The previous scale as {x,y}.\n * @param {Scalar2D} newScale The new scale as {x,y}.\n * @param {Scalar2D} center The scale center as {x,y}.\n * @returns {Scalar2D} The scaled offset as {x,y}.\n */\nexport function getScaledOffset(offset, scale, newScale, center) {\n  // worldPoint = indexPoint / scale + offset\n  //=> indexPoint = (worldPoint - offset ) * scale\n\n  // plane center should stay the same:\n  // indexCenter / newScale + newOffset =\n  //   indexCenter / oldScale + oldOffset\n  //=> newOffset = indexCenter / oldScale + oldOffset -\n  //     indexCenter / newScale\n  //=> newOffset = worldCenter - indexCenter / newScale\n  const indexCenter = {\n    x: (center.x - offset.x) * scale.x,\n    y: (center.y - offset.y) * scale.y\n  };\n  return {\n    x: center.x - (indexCenter.x / newScale.x),\n    y: center.y - (indexCenter.y / newScale.y)\n  };\n}\n\n/**\n * Layer group.\n *\n * - Display position: {x,y},\n * - Plane position: Index (access: get(i)),\n * - (world) Position: Point3D (access: getX, getY, getZ).\n *\n * Display -> World:\n * - planePos = viewLayer.displayToPlanePos(displayPos)\n *   -> compensate for layer scale and offset,\n * - pos = viewController.getPositionFromPlanePoint(planePos).\n *\n * World -> Display:\n * - planePos = viewController.getOffset3DFromPlaneOffset(pos)\n *   no need yet for a planePos to displayPos...\n */\nexport class LayerGroup {\n\n  /**\n   * The container div.\n   *\n   * @type {HTMLElement}\n   */\n  #containerDiv;\n\n  // jsdoc does not like\n  // @type {(ViewLayer|DrawLayer)[]}\n\n  /**\n   * List of layers.\n   *\n   * @type {Array<ViewLayer|DrawLayer>}\n   */\n  #layers = [];\n\n  /**\n   * The layer scale as {x,y,z}.\n   *\n   * @type {Scalar3D}\n   */\n  #scale = {x: 1, y: 1, z: 1};\n\n  /**\n   * The base scale as {x,y,z}: all posterior scale will be on top of this one.\n   *\n   * @type {Scalar3D}\n   */\n  #baseScale = {x: 1, y: 1, z: 1};\n\n  /**\n   * The layer offset as {x,y,z}.\n   *\n   * @type {Scalar3D}\n   */\n  #offset = {x: 0, y: 0, z: 0};\n\n  /**\n   * Active layer index.\n   *\n   * @type {number}\n   */\n  #activeLayerIndex = undefined;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Flag to activate crosshair or not.\n   *\n   * @type {boolean}\n   */\n  #showCrosshair = false;\n\n  /**\n   * Crosshair HTML elements.\n   *\n   * @type {HTMLElement[]}\n   */\n  #crosshairHtmlElements = [];\n\n  /**\n   * Tooltip HTML element.\n   *\n   * @type {HTMLElement}\n   */\n  #tooltipHtmlElement;\n\n  /**\n   * The current position used for the crosshair.\n   *\n   * @type {Point}\n   */\n  #currentPosition;\n\n  /**\n   * Image smoothing flag.\n   *\n   * @type {boolean}\n   */\n  #imageSmoothing = false;\n\n  /**\n   * Position helper.\n   *\n   * @type {PositionHelper}\n   */\n  #positionHelper;\n\n  /**\n   * Flag to update the position helper or not.\n   *\n   * @type {boolean}\n   */\n  #positionHelperNeedsUpdate = false;\n\n  /**\n   * Get the position helper.\n   *\n   * @returns {PositionHelper} The position helper.\n   */\n  getPositionHelper() {\n    if (this.#positionHelperNeedsUpdate) {\n      this.#positionHelper = undefined;\n    }\n    if (typeof this.#positionHelper === 'undefined') {\n      for (const layer of this.#layers) {\n        if (layer instanceof ViewLayer) {\n          const controller = layer.getViewController();\n          const helper = controller.getPositionHelper();\n          if (typeof this.#positionHelper === 'undefined') {\n            this.#positionHelper = helper;\n          } else {\n            this.#positionHelper.merge(helper);\n          }\n        }\n      }\n      this.#positionHelperNeedsUpdate = false;\n    }\n    return this.#positionHelper;\n  }\n\n  /**\n   * @param {HTMLElement} containerDiv The associated HTML div.\n   */\n  constructor(containerDiv) {\n    this.#containerDiv = containerDiv;\n  }\n\n  /**\n   * Get the showCrosshair flag.\n   *\n   * @returns {boolean} True to display the crosshair.\n   */\n  getShowCrosshair() {\n    return this.#showCrosshair;\n  }\n\n  /**\n   * Set the showCrosshair flag.\n   *\n   * @param {boolean} flag True to display the crosshair.\n   */\n  setShowCrosshair(flag) {\n    this.#showCrosshair = flag;\n    if (flag) {\n      // listen to offset and zoom change\n      this.addEventListener('offsetchange', this.#updateCrosshairOnChange);\n      this.addEventListener('zoomchange', this.#updateCrosshairOnChange);\n      // show crosshair div\n      this.#showCrosshairDiv();\n    } else {\n      // listen to offset and zoom change\n      this.removeEventListener('offsetchange', this.#updateCrosshairOnChange);\n      this.removeEventListener('zoomchange', this.#updateCrosshairOnChange);\n      // remove crosshair div\n      this.#removeCrosshairDiv();\n    }\n  }\n\n  /**\n   * Set the imageSmoothing flag value.\n   *\n   * @param {boolean} flag True to enable smoothing.\n   */\n  setImageSmoothing(flag) {\n    this.#imageSmoothing = flag;\n    // set for existing layers\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        layer.setImageSmoothing(flag);\n      }\n    }\n  }\n\n  /**\n   * Update crosshair on offset or zoom change.\n   *\n   * @param {object} _event The change event.\n   */\n  #updateCrosshairOnChange = (_event) => {\n    this.#showCrosshairDiv();\n  };\n\n  /**\n   * Get the Id of the container div.\n   *\n   * @returns {string|undefined} The id of the div.\n   */\n  getDivId() {\n    let divId;\n    // could be null if html changed\n    if (this.#containerDiv !== null) {\n      divId = this.#containerDiv.id;\n    }\n    return divId;\n  }\n\n  /**\n   * Get the layer scale.\n   *\n   * @returns {Scalar3D} The scale as {x,y,z}.\n   */\n  getScale() {\n    return this.#scale;\n  }\n\n  /**\n   * Get the base scale.\n   *\n   * @returns {Scalar3D} The scale as {x,y,z}.\n   */\n  getBaseScale() {\n    return this.#baseScale;\n  }\n\n\n  /**\n   * Get the added scale: the scale added to the base scale.\n   *\n   * @returns {Scalar3D} The scale as {x,y,z}.\n   */\n  getAddedScale() {\n    return {\n      x: this.#scale.x / this.#baseScale.x,\n      y: this.#scale.y / this.#baseScale.y,\n      z: this.#scale.z / this.#baseScale.z\n    };\n  }\n\n  /**\n   * Get the layer offset.\n   *\n   * @returns {Scalar3D} The offset as {x,y,z}.\n   */\n  getOffset() {\n    return this.#offset;\n  }\n\n  /**\n   * Get the number of layers handled by this class.\n   *\n   * @returns {number} The number of layers.\n   */\n  getNumberOfLayers() {\n    let count = 0;\n    this.#layers.forEach(item => {\n      if (typeof item !== 'undefined') {\n        count++;\n      }\n    });\n    return count;\n  }\n\n  /**\n   * Check if this layerGroup contains a layer with the input id.\n   *\n   * @param {string} id The layer id to look for.\n   * @returns {boolean} True if this group contains\n   *   a layer with the input id.\n   */\n  includes(id) {\n    if (typeof id === 'undefined') {\n      return false;\n    }\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined' &&\n        layer.getId() === id) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Get a list of view layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a ViewLayer as input and returns a boolean. If undefined,\n   *   returns all view layers.\n   * @returns {ViewLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getViewLayers(callbackFn) {\n    if (typeof callbackFn === 'undefined') {\n      callbackFn = function () {\n        return true;\n      };\n    }\n    const res = [];\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer &&\n        callbackFn(layer)) {\n        res.push(layer);\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Test if one of the view layers satisfies an input callbackFn.\n   *\n   * @param {Function} callbackFn A function that takes\n   *   a ViewLayer as input and returns a boolean.\n   * @returns {boolean} True if one of the ViewLayers\n   *   satisfies the callbackFn.\n   */\n  someViewLayer(callbackFn) {\n    let hasOne = false;\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer &&\n        callbackFn(layer)) {\n        hasOne = true;\n        break;\n      }\n    }\n    return hasOne;\n  }\n\n  /**\n   * Get a list of draw layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a DrawLayer as input and returns a boolean. If undefined,\n   *   returns all draw layers.\n   * @returns {DrawLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getDrawLayers(callbackFn) {\n    if (typeof callbackFn === 'undefined') {\n      callbackFn = function () {\n        return true;\n      };\n    }\n    const res = [];\n    for (const layer of this.#layers) {\n      if (layer instanceof DrawLayer &&\n        callbackFn(layer)) {\n        res.push(layer);\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Get the number of view layers handled by this class.\n   *\n   * @returns {number} The number of layers.\n   */\n  getNumberOfViewLayers() {\n    let count = 0;\n    this.#layers.forEach(item => {\n      if (typeof item !== 'undefined' &&\n        item instanceof ViewLayer) {\n        count++;\n      }\n    });\n    return count;\n  }\n\n  /**\n   * Get the active image layer.\n   *\n   * @returns {ViewLayer|DrawLayer|undefined} The layer.\n   */\n  getActiveLayer() {\n    let layer;\n    if (typeof this.#activeLayerIndex !== 'undefined') {\n      layer = this.#layers[this.#activeLayerIndex];\n    }\n    return layer;\n  }\n\n  /**\n   * Get the active image layer.\n   *\n   * @returns {ViewLayer|undefined} The layer.\n   */\n  getActiveViewLayer() {\n    let layer;\n    const activeLayer = this.getActiveLayer();\n    if (typeof activeLayer !== 'undefined' &&\n      activeLayer instanceof ViewLayer) {\n      layer = activeLayer;\n    }\n    return layer;\n  }\n\n  /**\n   * Get the base view layer.\n   *\n   * @returns {ViewLayer|undefined} The layer.\n   */\n  getBaseViewLayer() {\n    // use first layer as base for calculating position and\n    // line sizes\n    let baseLayer;\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        baseLayer = layer;\n        break;\n      }\n    }\n    if (typeof baseLayer === 'undefined') {\n      logger.warn('No layer found');\n      return;\n    }\n    return baseLayer;\n  }\n\n  /**\n   * Get a view layer associated to a data id.\n   *\n   * @param {string} id The layer id.\n   * @returns {ViewLayer|undefined} The layer.\n   */\n  getViewLayerById(id) {\n    const callbackFn = function (layer) {\n      return layer.getId() === id;\n    };\n    const layers = this.getViewLayers(callbackFn);\n    let layer;\n    if (layers.length === 1) {\n      layer = layers[0];\n    }\n    return layer;\n  }\n\n  /**\n   * Get the view layers associated to a data id.\n   *\n   * @param {string} dataId The data id.\n   * @returns {ViewLayer[]} The layers.\n   */\n  getViewLayersByDataId(dataId) {\n    const callbackFn = function (layer) {\n      return layer.getDataId() === dataId;\n    };\n    return this.getViewLayers(callbackFn);\n  }\n\n  /**\n   * Search view layers for equal imae meta data.\n   *\n   * @param {object} meta The meta data to find.\n   * @returns {ViewLayer[]} The list of view layers that contain matched data.\n   */\n  searchViewLayers(meta) {\n    const res = [];\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        if (layer.getViewController().equalImageMeta(meta)) {\n          res.push(layer);\n        }\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Get the view layers data indices.\n   *\n   * @returns {string[]} The list of indices.\n   */\n  getViewDataIndices() {\n    const res = [];\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        res.push(layer.getDataId());\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Get the active draw layer.\n   *\n   * @returns {DrawLayer|undefined} The layer.\n   */\n  getActiveDrawLayer() {\n    let layer;\n    const activeLayer = this.getActiveLayer();\n    if (typeof activeLayer !== 'undefined' &&\n      activeLayer instanceof DrawLayer) {\n      layer = activeLayer;\n    }\n    return layer;\n  }\n\n  /**\n   * Get a draw layer associated to a data id.\n   *\n   * @param {string} id The layer id.\n   * @returns {DrawLayer|undefined} The layer.\n   */\n  getDrawLayerById(id) {\n    const callbackFn = function (layer) {\n      return layer.getId() === id;\n    };\n    const layers = this.getDrawLayers(callbackFn);\n    let layer;\n    if (layers.length === 1) {\n      layer = layers[0];\n    }\n    return layer;\n  }\n\n  /**\n   * Get the draw layers associated to a data id.\n   *\n   * @param {string} dataId The data id.\n   * @returns {DrawLayer[]} The layers.\n   */\n  getDrawLayersByDataId(dataId) {\n    const callbackFn = function (layer) {\n      return layer.getDataId() === dataId;\n    };\n    return this.getDrawLayers(callbackFn);\n  }\n\n  /**\n   * Set the active layer.\n   *\n   * @param {number} index The index of the layer to set as active.\n   */\n  setActiveLayer(index) {\n    this.#activeLayerIndex = index;\n    /**\n     * Active layer change event.\n     *\n     * @event LayerGroup#activelayerchange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} value The changed value.\n     */\n    this.#fireEvent({\n      type: 'activelayerchange',\n      value: [this.#layers[index]]\n    });\n  }\n\n  /**\n   * Set the active layer with a data id.\n   *\n   * @param {string} dataId The data id.\n   */\n  setActiveLayerByDataId(dataId) {\n    let index;\n    for (let i = 0; i < this.#layers.length; ++i) {\n      if (typeof this.#layers[i] !== 'undefined' &&\n        this.#layers[i].getDataId() === dataId) {\n        // stop at first one\n        index = i;\n        break;\n      }\n    }\n    if (typeof index !== 'undefined') {\n      this.setActiveLayer(index);\n    } else {\n      logger.warn('No layer to set as active with dataId: ' +\n        dataId);\n    }\n  }\n\n  /**\n   * Add a view layer.\n   *\n   * The new layer will be marked as the active view layer.\n   *\n   * @returns {ViewLayer} The created layer.\n   */\n  addViewLayer() {\n    // layer index\n    const viewLayerIndex = this.#layers.length;\n    // create div\n    const div = this.#getNextLayerDiv();\n    // prepend to container\n    this.#containerDiv.append(div);\n    // view layer\n    const layer = new ViewLayer(div);\n    layer.setImageSmoothing(this.#imageSmoothing);\n    // add layer\n    this.#layers.push(layer);\n    // mark it as active\n    this.setActiveLayer(viewLayerIndex);\n    // bind view layer events\n    this.#bindViewLayer(layer);\n\n    // update flag\n    this.#positionHelperNeedsUpdate = true;\n\n    // return\n    return layer;\n  }\n\n  /**\n   * Add a draw layer.\n   *\n   * The new layer will be marked as the active draw layer.\n   *\n   * @returns {DrawLayer} The created layer.\n   */\n  addDrawLayer() {\n    // store active index\n    this.#activeLayerIndex = this.#layers.length;\n    // create div\n    const div = this.#getNextLayerDiv();\n    // prepend to container\n    this.#containerDiv.append(div);\n    // draw layer\n    const layer = new DrawLayer(div);\n    // add layer\n    this.#layers.push(layer);\n    // bind draw layer events\n    this.#bindDrawLayer(layer);\n    // return\n    return layer;\n  }\n\n  /**\n   * Bind view layer events to this.\n   *\n   * @param {ViewLayer} viewLayer The view layer to bind.\n   */\n  #bindViewLayer(viewLayer) {\n    // listen to position change to update other group layers\n    viewLayer.addEventListener(\n      'positionchange', this.updateLayersToPositionChange);\n    // propagate view viewLayer-layer events\n    for (const eventName of viewEventNames) {\n      viewLayer.addEventListener(eventName, this.#fireEvent);\n    }\n    // propagate viewLayer events\n    viewLayer.addEventListener('renderstart', this.#fireEvent);\n    viewLayer.addEventListener('renderend', this.#fireEvent);\n  }\n\n  /**\n   * Un-bind a view layer events to this.\n   *\n   * @param {ViewLayer} viewLayer The view layer to unbind.\n   */\n  #unbindViewLayer(viewLayer) {\n    // stop listening to position change to update other group layers\n    viewLayer.removeEventListener(\n      'positionchange', this.updateLayersToPositionChange);\n    // stop propagating view viewLayer-layer events\n    for (const eventName of viewEventNames) {\n      viewLayer.removeEventListener(eventName, this.#fireEvent);\n    }\n    // stop propagating viewLayer events\n    viewLayer.removeEventListener('renderstart', this.#fireEvent);\n    viewLayer.removeEventListener('renderend', this.#fireEvent);\n\n    // stop view layer - image binding\n    // (binding is done in layer.setView)\n    viewLayer.unbindImage();\n  }\n\n  /**\n   * Bind draw layer events to this.\n   *\n   * @param {DrawLayer} drawLayer The draw layer to bind.\n   */\n  #bindDrawLayer(drawLayer) {\n    // listen to position change to update other group layers\n    drawLayer.addEventListener(\n      'positionchange', this.updateLayersToPositionChange);\n    drawLayer.addEventListener(\n      'positionchange', this.#fireEvent);\n    // propagate drawLayer events\n    drawLayer.addEventListener('drawcreate', this.#fireEvent);\n    drawLayer.addEventListener('drawdelete', this.#fireEvent);\n  }\n\n  /**\n   * Un-bind a draw layer events to this.\n   *\n   * @param {DrawLayer} drawLayer The draw layer to unbind.\n   */\n  #unbindDrawLayer(drawLayer) {\n    // stop listening to position change to update other group layers\n    drawLayer.removeEventListener(\n      'positionchange', this.updateLayersToPositionChange);\n    drawLayer.removeEventListener(\n      'positionchange', this.#fireEvent);\n    // propagate drawLayer events\n    drawLayer.removeEventListener('drawcreate', this.#fireEvent);\n    drawLayer.removeEventListener('drawdelete', this.#fireEvent);\n  }\n\n  /**\n   * Get the next layer DOM div.\n   *\n   * @returns {HTMLDivElement} A DOM div.\n   */\n  #getNextLayerDiv() {\n    const div = document.createElement('div');\n    div.id = getLayerDivId(this.getDivId(), this.#layers.length);\n    div.className = 'layer';\n    div.style.pointerEvents = 'none';\n    return div;\n  }\n\n  /**\n   * Empty the layer list.\n   */\n  empty() {\n    this.#layers = [];\n    // reset active indices\n    this.#activeLayerIndex = undefined;\n    // remove possible crosshair\n    this.#removeCrosshairDiv();\n    // clean container div\n    const previous = this.#containerDiv.getElementsByClassName('layer');\n    if (previous) {\n      while (previous.length > 0) {\n        previous[0].remove();\n      }\n    }\n  }\n\n  /**\n   * Remove all layers for a specific data.\n   *\n   * @param {string} dataId The data to remove its layers.\n   */\n  removeLayersByDataId(dataId) {\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined' &&\n        layer.getDataId() === dataId) {\n        this.removeLayer(layer);\n      }\n    }\n  }\n\n  /**\n   * Remove a layer from this layer group.\n   * Warning: if current active layer, the index will\n   *   be set to `undefined`. Call one of the setActive\n   *   methods to define the active index.\n   *\n   * @param {ViewLayer | DrawLayer} layer The layer to remove.\n   */\n  removeLayer(layer) {\n    // find layer\n    const index = this.#layers.findIndex((item) => item === layer);\n    if (index === -1) {\n      throw new Error('Cannot find layer to remove');\n    }\n    // update active index\n    if (this.#activeLayerIndex === index) {\n      this.#activeLayerIndex = undefined;\n    }\n    // unbind and update active index\n    if (layer instanceof ViewLayer) {\n      this.#unbindViewLayer(layer);\n    } else {\n      this.#unbindDrawLayer(layer);\n    }\n    // reset in storage\n    this.#layers[index] = undefined;\n    // update html\n    layer.removeFromDOM();\n  }\n\n  /**\n   * Show a crosshair at a given position.\n   *\n   * @param {Point} [position] The position where to show the crosshair,\n   *   defaults to current position.\n   */\n  #showCrosshairDiv(position) {\n    if (typeof position === 'undefined') {\n      position = this.#currentPosition;\n    }\n\n    // remove previous\n    this.#removeCrosshairDiv();\n\n    // use first layer as base for calculating position and\n    // line sizes\n    let baseLayer;\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        baseLayer = layer;\n        break;\n      }\n    }\n    if (typeof baseLayer === 'undefined') {\n      logger.warn('No layer to show crosshair');\n      return;\n    }\n\n    const vc = baseLayer.getViewController();\n    const planePos = vc.getPlanePositionFromPosition(position);\n    const displayPos = baseLayer.planePosToDisplay(planePos);\n\n    // horizontal line\n    if (typeof displayPos.getY() !== 'undefined') {\n      const lineH = document.createElement('hr');\n      lineH.id = this.getDivId() + '-scroll-crosshair-horizontal';\n      lineH.className = 'horizontal';\n      lineH.style.width = this.#containerDiv.offsetWidth + 'px';\n      lineH.style.left = '0px';\n      lineH.style.top = displayPos.getY() + 'px';\n      // add to local array\n      this.#crosshairHtmlElements.push(lineH);\n      // add to html\n      this.#containerDiv.appendChild(lineH);\n    }\n\n    // vertical line\n    if (typeof displayPos.getX() !== 'undefined') {\n      const lineV = document.createElement('hr');\n      lineV.id = this.getDivId() + '-scroll-crosshair-vertical';\n      lineV.className = 'vertical';\n      lineV.style.width = this.#containerDiv.offsetHeight + 'px';\n      lineV.style.left = (displayPos.getX()) + 'px';\n      lineV.style.top = '0px';\n      // add to local array\n      this.#crosshairHtmlElements.push(lineV);\n      // add to html\n      this.#containerDiv.appendChild(lineV);\n    }\n  }\n\n  /**\n   * Remove crosshair divs.\n   */\n  #removeCrosshairDiv() {\n    for (const element of this.#crosshairHtmlElements) {\n      element.remove();\n    }\n    this.#crosshairHtmlElements = [];\n  }\n\n  /**\n   * Displays a tooltip in a temporary `span`.\n   * Works with css to hide/show the span only on mouse hover.\n   *\n   * @param {Point2D} point The update point.\n   */\n  showTooltip(point) {\n    // remove previous div\n    this.removeTooltipDiv();\n\n    const viewLayer = this.getBaseViewLayer();\n    const viewController = viewLayer.getViewController();\n    const planePos = viewLayer.displayToPlanePos(point);\n    const position = viewController.getPositionFromPlanePoint(planePos);\n    const value = viewController.getRescaledImageValue(position);\n\n    // create\n    if (typeof value !== 'undefined') {\n      const span = document.createElement('span');\n      span.id = 'scroll-tooltip';\n      // tooltip position\n      span.style.left = (point.getX() + 10) + 'px';\n      span.style.top = (point.getY() + 10) + 'px';\n      let text = precisionRound(value, 3).toString();\n      if (typeof viewController.getPixelUnit() !== 'undefined') {\n        text += ' ' + viewController.getPixelUnit();\n      }\n      span.appendChild(document.createTextNode(text));\n      // add to local var\n      this.#tooltipHtmlElement = span;\n      // add to html\n      this.#containerDiv.appendChild(span);\n    }\n  }\n\n  /**\n   * Remove the tooltip html div.\n   */\n  removeTooltipDiv() {\n    if (typeof this.#tooltipHtmlElement !== 'undefined') {\n      this.#tooltipHtmlElement.remove();\n      this.#tooltipHtmlElement = undefined;\n    }\n  }\n\n  /**\n   * Can the input position be set on one of the view layers.\n   *\n   * @param {Point} position The input position.\n   * @returns {boolean} True if one view layer accepts the input position.\n   */\n  isPositionInBounds(position) {\n    return this.someViewLayer(function (layer) {\n      return layer.getViewController().isPositionInBounds(position);\n    });\n  }\n\n  /**\n   * Can one of the view layers be scrolled.\n   *\n   * @returns {boolean} True if one view layer can be scrolled.\n   */\n  canScroll() {\n    return this.someViewLayer(function (layer) {\n      return layer.getViewController().canScroll();\n    });\n  }\n\n  /**\n   * Does one of the view layer have more than one slice in the\n   *   given dimension.\n   *\n   * @param {number} dim The input dimension.\n   * @returns {boolean} True if one view layer has more than one slice.\n   */\n  moreThanOne(dim) {\n    return this.someViewLayer(function (layer) {\n      return layer.getViewController().moreThanOne(dim);\n    });\n  }\n\n  /**\n   * Update layers (but not the event source layer) to a position change.\n   *\n   * @param {object} event The position change event.\n   * @function\n   */\n  updateLayersToPositionChange = (event) => {\n    // pause positionchange listeners\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.removeEventListener(\n          'positionchange', this.updateLayersToPositionChange);\n        layer.removeEventListener('positionchange', this.#fireEvent);\n      }\n    }\n\n    const index = new Index(event.value[0]);\n    const position = new Point(event.value[1]);\n\n    // store current position\n    this.#currentPosition = position;\n\n    if (this.#showCrosshair) {\n      this.#showCrosshairDiv(position);\n    }\n\n    // origin of the first view layer\n    const viewLayerOffsets = {};\n    let baseViewLayerOrigin0;\n    let baseViewLayerOrigin;\n    // update position for all layers except the source one\n    for (const layer of this.#layers) {\n      if (typeof layer === 'undefined') {\n        continue;\n      }\n      let hasSetOffset = false;\n\n      // view layer case: define and set offsets\n      if (layer instanceof ViewLayer) {\n        const vc = layer.getViewController();\n        // origin0 should always be there\n        const origin0 = vc.getOrigin();\n        // depending on position, origin could be undefined\n        const origin = vc.getOrigin(position);\n\n        let scrollOffset;\n        let planeOffset;\n\n        if (typeof baseViewLayerOrigin === 'undefined') {\n          // first view layer, store origins\n          baseViewLayerOrigin0 = origin0;\n          baseViewLayerOrigin = origin;\n          // no offset\n          scrollOffset = new Vector3D(0, 0, 0);\n          planeOffset = new Vector3D(0, 0, 0);\n        } else {\n          if (vc.isPositionInBounds(position) &&\n            typeof origin !== 'undefined') {\n            // TODO: compensate for possible different orientation between views\n            const scrollDiff = baseViewLayerOrigin0.minus(origin0);\n            scrollOffset = new Vector3D(\n              scrollDiff.getX(), scrollDiff.getY(), scrollDiff.getZ());\n            const planeDiff = baseViewLayerOrigin.minus(origin);\n            planeOffset = new Vector3D(\n              planeDiff.getX(), planeDiff.getY(), planeDiff.getZ());\n          }\n        }\n\n        // set and store offsets\n        if (typeof scrollOffset !== 'undefined' &&\n          typeof planeOffset !== 'undefined') {\n          hasSetOffset =\n            layer.setBaseOffset(\n              scrollOffset, planeOffset,\n              baseViewLayerOrigin, baseViewLayerOrigin0\n            );\n          // store\n          viewLayerOffsets[layer.getId()] = {\n            scroll: scrollOffset,\n            plane: planeOffset\n          };\n        }\n      }\n\n      // draw layer case: use associated view layer offsets\n      if (layer instanceof DrawLayer) {\n        const refOffsets = viewLayerOffsets[layer.getReferenceLayerId()];\n        if (typeof refOffsets !== 'undefined') {\n          hasSetOffset =\n            layer.setBaseOffset(refOffsets.scroll, refOffsets.plane);\n        }\n      }\n\n      // update position (triggers redraw)\n      let hasSetPos = false;\n      if (layer.getId() !== event.srclayerid) {\n        hasSetPos = layer.setCurrentPosition(position, index);\n      }\n\n      // force redraw if needed\n      if (!hasSetPos && hasSetOffset) {\n        layer.draw();\n      }\n    }\n\n    // re-start positionchange listeners\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.addEventListener(\n          'positionchange', this.updateLayersToPositionChange);\n        layer.addEventListener('positionchange', this.#fireEvent);\n      }\n    }\n  };\n\n  /**\n   * Calculate the div to world size ratio needed to fit\n   *   the largest data.\n   *\n   * @returns {number|undefined} The ratio.\n   */\n  getDivToWorldSizeRatio() {\n    // check container\n    if (this.#containerDiv.offsetWidth === 0 &&\n      this.#containerDiv.offsetHeight === 0) {\n      throw new Error('Cannot fit to zero sized container.');\n    }\n    // get max world size\n    const maxWorldSize = this.getMaxWorldSize();\n    if (typeof maxWorldSize === 'undefined') {\n      return undefined;\n    }\n    // if the container has a width but no height,\n    // resize it to follow the same ratio to completely\n    // fill the div with the image\n    if (this.#containerDiv.offsetHeight === 0) {\n      const ratioX = this.#containerDiv.offsetWidth / maxWorldSize.x;\n      const height = maxWorldSize.y * ratioX;\n      this.#containerDiv.style.height = height + 'px';\n    }\n    // return best fit\n    return Math.min(\n      this.#containerDiv.offsetWidth / maxWorldSize.x,\n      this.#containerDiv.offsetHeight / maxWorldSize.y\n    );\n  }\n\n  /**\n   * Fit to container: set the layers div to world size ratio.\n   *\n   * @param {number} divToWorldSizeRatio The ratio.\n   */\n  fitToContainer(divToWorldSizeRatio) {\n    // get maximum world size\n    const maxWorldSize = this.getMaxWorldSize();\n    // exit if none\n    if (typeof maxWorldSize === 'undefined') {\n      return;\n    }\n\n    const containerSize = {\n      x: this.#containerDiv.offsetWidth,\n      y: this.#containerDiv.offsetHeight\n    };\n    // offset to keep data centered\n    const fitOffset = {\n      x: -0.5 *\n        (containerSize.x - Math.floor(maxWorldSize.x * divToWorldSizeRatio)),\n      y: -0.5 *\n        (containerSize.y - Math.floor(maxWorldSize.y * divToWorldSizeRatio))\n    };\n\n    // apply to layers\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.fitToContainer(containerSize, divToWorldSizeRatio, fitOffset);\n      }\n    }\n\n    // update crosshair\n    if (this.#showCrosshair) {\n      this.#showCrosshairDiv();\n    }\n  }\n\n  /**\n   * Get the largest data world (mm) size.\n   *\n   * @returns {Scalar2D|undefined} The largest size as {x,y}.\n   */\n  getMaxWorldSize() {\n    let maxSize = {x: 0, y: 0};\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        const size = layer.getImageWorldSize();\n        if (size.x > maxSize.x) {\n          maxSize.x = size.x;\n        }\n        if (size.y > maxSize.y) {\n          maxSize.y = size.y;\n        }\n      }\n    }\n    if (maxSize.x === 0 && maxSize.y === 0) {\n      maxSize = undefined;\n    }\n    return maxSize;\n  }\n\n  /**\n   * Flip all layers along the Z axis without offset compensation.\n   */\n  flipScaleZ() {\n    this.#baseScale.z *= -1;\n    this.setScale(this.#baseScale);\n  }\n\n  /**\n   * Add scale to the layers. Scale cannot go lower than 0.1.\n   *\n   * @param {number} scaleStep The scale to add.\n   * @param {Point3D} center The scale center Point3D.\n   */\n  addScale(scaleStep, center) {\n    const newScale = {\n      x: this.#scale.x * (1 + scaleStep),\n      y: this.#scale.y * (1 + scaleStep),\n      z: this.#scale.z * (1 + scaleStep)\n    };\n    this.setScale(newScale, center);\n  }\n\n  /**\n   * Set the layers' scale.\n   *\n   * @param {Scalar3D} newScale The scale to apply as {x,y,z}.\n   * @param {Point3D} [center] The scale center Point3D.\n   * @fires LayerGroup#zoomchange\n   */\n  setScale(newScale, center) {\n    this.#scale = newScale;\n    // apply to layers\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.setScale(this.#scale, center);\n      }\n    }\n\n    // event value\n    const value = [\n      newScale.x,\n      newScale.y,\n      newScale.z\n    ];\n    if (typeof center !== 'undefined') {\n      value.push(center.getX());\n      value.push(center.getY());\n      value.push(center.getZ());\n    }\n\n    /**\n     * Zoom change event.\n     *\n     * @event LayerGroup#zoomchange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} value The changed value.\n     */\n    this.#fireEvent({\n      type: 'zoomchange',\n      value: value\n    });\n  }\n\n  /**\n   * Add translation to the layers.\n   *\n   * @param {Scalar3D} translation The translation as {x,y,z}.\n   */\n  addTranslation(translation) {\n    this.setOffset({\n      x: this.#offset.x - translation.x,\n      y: this.#offset.y - translation.y,\n      z: this.#offset.z - translation.z\n    });\n  }\n\n  /**\n   * Set the layers' offset.\n   *\n   * @param {Scalar3D} newOffset The offset as {x,y,z}.\n   * @fires LayerGroup#offsetchange\n   */\n  setOffset(newOffset) {\n    // store\n    this.#offset = newOffset;\n    // apply to layers\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.setOffset(this.#offset);\n      }\n    }\n\n    /**\n     * Offset change event.\n     *\n     * @event LayerGroup#offsetchange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} value The changed value.\n     */\n    this.#fireEvent({\n      type: 'offsetchange',\n      value: [\n        this.#offset.x,\n        this.#offset.y,\n        this.#offset.z\n      ]\n    });\n  }\n\n  /**\n   * Reset the stage to its initial scale and no offset.\n   */\n  reset() {\n    this.setScale(this.#baseScale);\n    this.setOffset({x: 0, y: 0, z: 0});\n  }\n\n  /**\n   * Draw the layer.\n   */\n  draw() {\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.draw();\n      }\n    }\n  }\n\n  /**\n   * Display the layer.\n   *\n   * @param {boolean} flag Whether to display the layer or not.\n   */\n  display(flag) {\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.display(flag);\n      }\n    }\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n} // LayerGroup class\n","import {Point, Point3D} from '../math/point';\nimport {WindowLevel} from '../image/windowLevel';\nimport {LayerGroup} from './layerGroup';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {ViewLayer} from '../gui/viewLayer';\nimport {DrawLayer} from '../gui/drawLayer';\n/* eslint-enable no-unused-vars */\n\n/**\n * Window/level binder.\n */\nexport class WindowLevelBinder {\n  getEventType = function () {\n    return 'wlchange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      const viewLayers = layerGroup.getViewLayersByDataId(event.dataid);\n      if (viewLayers.length !== 0) {\n        const vc = viewLayers[0].getViewController();\n        if (event.value.length === 2) {\n          const wl = new WindowLevel(event.value[0], event.value[1]);\n          vc.setWindowLevel(wl);\n        }\n        if (event.value.length === 3) {\n          vc.setWindowLevelPreset(event.value[2]);\n        }\n      }\n    };\n  };\n}\n\n/**\n * Colour map binder.\n */\nexport class ColourMapBinder {\n  getEventType = function () {\n    return 'colourmapchange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      const viewLayers = layerGroup.getViewLayersByDataId(event.dataid);\n      if (viewLayers.length !== 0) {\n        const vc = viewLayers[0].getViewController();\n        vc.setColourMap(event.value[0]);\n      }\n    };\n  };\n}\n\n/**\n * Position binder.\n */\nexport class PositionBinder {\n  getEventType = function () {\n    return 'positionchange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      const pointValues = event.value[1];\n      const vl = layerGroup.getBaseViewLayer();\n      const vc = vl.getViewController();\n      // handle different number of dimensions\n      const currentPos = vc.getCurrentPosition();\n      const currentDims = currentPos.length();\n      const inputDims = pointValues.length;\n      if (inputDims !== currentDims) {\n        if (inputDims === currentDims - 1) {\n          // add missing dim, for ex: input 3D -> current 4D\n          pointValues.push(currentPos.get(currentDims - 1));\n        } else if (inputDims === currentDims + 1) {\n          // remove extra dim, for ex: input 4D -> current 3D\n          pointValues.pop();\n        }\n      }\n      vc.setCurrentPosition(new Point(pointValues));\n    };\n  };\n}\n\n/**\n * Zoom binder.\n */\nexport class ZoomBinder {\n  getEventType = function () {\n    return 'zoomchange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      const scale = {\n        x: event.value[0],\n        y: event.value[1],\n        z: event.value[2]\n      };\n      let center;\n      if (event.value.length === 6) {\n        center = new Point3D(\n          event.value[3],\n          event.value[4],\n          event.value[5]\n        );\n      }\n      layerGroup.setScale(scale, center);\n      layerGroup.draw();\n    };\n  };\n}\n\n/**\n * Offset binder.\n */\nexport class OffsetBinder {\n  getEventType = function () {\n    return 'offsetchange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      layerGroup.setOffset({\n        x: event.value[0],\n        y: event.value[1],\n        z: event.value[2]\n      });\n      layerGroup.draw();\n    };\n  };\n}\n\n/**\n * Opacity binder. Only propagates to view layers of the same data.\n */\nexport class OpacityBinder {\n  getEventType = function () {\n    return 'opacitychange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      // exit if no data id\n      if (typeof event.dataid === 'undefined') {\n        return;\n      }\n      // propagate to first view layer if it is not base layer\n      const viewLayers = layerGroup.getViewLayersByDataId(event.dataid);\n      const baseLayer = layerGroup.getBaseViewLayer();\n      if (viewLayers.length !== 0 && baseLayer !== viewLayers[0]) {\n        viewLayers[0].setOpacity(event.value);\n        viewLayers[0].draw();\n      }\n    };\n  };\n}\n\n/**\n * List of binders.\n */\nexport const binderList = {\n  WindowLevelBinder,\n  PositionBinder,\n  ZoomBinder,\n  OffsetBinder,\n  OpacityBinder,\n  ColourMapBinder\n};\n\n/**\n * Stage: controls a list of layer groups and their\n * synchronisation.\n */\nexport class Stage {\n\n  /**\n   * Associated layer groups.\n   *\n   * @type {LayerGroup[]}\n   */\n  #layerGroups = [];\n\n  /**\n   * Active layer group index.\n   *\n   * @type {number|undefined}\n   */\n  #activeLayerGroupIndex;\n\n  /**\n   * Image smoothing flag.\n   *\n   * @type {boolean}\n   */\n  #imageSmoothing = false;\n\n  // layer group binders\n  #binders = [];\n  // binder callbacks\n  #callbackStore = null;\n\n  /**\n   * Get the layer group at the given index.\n   *\n   * @param {number} index The index.\n   * @returns {LayerGroup|undefined} The layer group.\n   */\n  getLayerGroup(index) {\n    return this.#layerGroups[index];\n  }\n\n  /**\n   * Get the number of layer groups that form the stage.\n   *\n   * @returns {number} The number of layer groups.\n   */\n  getNumberOfLayerGroups() {\n    return this.#layerGroups.length;\n  }\n\n  /**\n   * Get the active layer group.\n   *\n   * @returns {LayerGroup|undefined} The layer group.\n   */\n  getActiveLayerGroup() {\n    return this.getLayerGroup(this.#activeLayerGroupIndex);\n  }\n\n  /**\n   * Set the active layer group.\n   *\n   * @param {number} index The layer group index.\n   */\n  setActiveLayerGroup(index) {\n    if (typeof this.getLayerGroup(index) !== 'undefined') {\n      this.#activeLayerGroupIndex = index;\n    } else {\n      logger.warn('No layer group to set as active with index: ' +\n        index);\n    }\n  }\n\n  /**\n   * Get the view layers associated to a data id.\n   *\n   * @param {string} dataId The data id.\n   * @returns {ViewLayer[]} The layers.\n   */\n  getViewLayersByDataId(dataId) {\n    let res = [];\n    for (const layerGroup of this.#layerGroups) {\n      res = res.concat(layerGroup.getViewLayersByDataId(dataId));\n    }\n    return res;\n  }\n\n  /**\n   * Get a list of view layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a ViewLayer as input and returns a boolean. If undefined,\n   *   returns all view layers.\n   * @returns {ViewLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getViewLayers(callbackFn) {\n    let res = [];\n    for (const layerGroup of this.#layerGroups) {\n      res = res.concat(layerGroup.getViewLayers(callbackFn));\n    }\n    return res;\n  }\n\n  /**\n   * Get the draw layers associated to a data id.\n   *\n   * @param {string} dataId The data id.\n   * @returns {DrawLayer[]} The layers.\n   */\n  getDrawLayersByDataId(dataId) {\n    let res = [];\n    for (const layerGroup of this.#layerGroups) {\n      res = res.concat(layerGroup.getDrawLayersByDataId(dataId));\n    }\n    return res;\n  }\n\n  /**\n   * Get a list of draw layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a DrawLayer as input and returns a boolean. If undefined,\n   *   returns all draw layers.\n   * @returns {DrawLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getDrawLayers(callbackFn) {\n    let res = [];\n    for (const layerGroup of this.#layerGroups) {\n      res = res.concat(layerGroup.getDrawLayers(callbackFn));\n    }\n    return res;\n  }\n\n  /**\n   * Add a layer group to the list.\n   *\n   * The new layer group will be marked as the active layer group.\n   *\n   * @param {object} htmlElement The HTML element of the layer group.\n   * @returns {LayerGroup} The newly created layer group.\n   */\n  addLayerGroup(htmlElement) {\n    this.#activeLayerGroupIndex = this.#layerGroups.length;\n    const layerGroup = new LayerGroup(htmlElement);\n    layerGroup.setImageSmoothing(this.#imageSmoothing);\n    // add to storage\n    const isBound = this.#callbackStore && this.#callbackStore.length !== 0;\n    if (isBound) {\n      this.unbindLayerGroups();\n    }\n    this.#layerGroups.push(layerGroup);\n    if (isBound) {\n      this.bindLayerGroups();\n    }\n    // return created group\n    return layerGroup;\n  }\n\n  /**\n   * Get a layer group from an HTML element id.\n   *\n   * @param {string} id The element id to find.\n   * @returns {LayerGroup|undefined} The layer group.\n   */\n  getLayerGroupByDivId(id) {\n    return this.#layerGroups.find(function (item) {\n      return item.getDivId() === id;\n    });\n  }\n\n  /**\n   * Set the layer groups binders.\n   *\n   * @param {Array} list The list of binder objects.\n   */\n  setBinders(list) {\n    if (typeof list === 'undefined' || list === null) {\n      throw new Error('Cannot set null or undefined binders');\n    }\n    if (this.#binders.length !== 0) {\n      this.unbindLayerGroups();\n    }\n    this.#binders = list.slice();\n    this.bindLayerGroups();\n  }\n\n  /**\n   * Empty the layer group list.\n   */\n  empty() {\n    this.unbindLayerGroups();\n    for (const layerGroup of this.#layerGroups) {\n      layerGroup.empty();\n    }\n    this.#layerGroups = [];\n    this.#activeLayerGroupIndex = undefined;\n  }\n\n  /**\n   * Remove all layers for a specific data.\n   *\n   * @param {string} dataId The data to remove its layers.\n   */\n  removeLayersByDataId(dataId) {\n    for (const layerGroup of this.#layerGroups) {\n      layerGroup.removeLayersByDataId(dataId);\n    }\n  }\n\n  /**\n   * Remove a layer group from this stage.\n   *\n   * @param {LayerGroup} layerGroup The layer group to remove.\n   */\n  removeLayerGroup(layerGroup) {\n    // find layer\n    const index = this.#layerGroups.findIndex((item) => item === layerGroup);\n    if (index === -1) {\n      throw new Error('Cannot find layerGroup to remove');\n    }\n    // unbind\n    this.unbindLayerGroups();\n    // empty layer group\n    layerGroup.empty();\n    // remove from storage\n    this.#layerGroups.splice(index, 1);\n    // update active index\n    if (this.#activeLayerGroupIndex === index) {\n      this.#activeLayerGroupIndex = undefined;\n    }\n    // bind\n    this.bindLayerGroups();\n  }\n\n  /**\n   * Reset the stage: calls reset on all layer groups.\n   */\n  reset() {\n    for (const layerGroup of this.#layerGroups) {\n      layerGroup.reset();\n    }\n  }\n\n  /**\n   * Draw the stage: calls draw on all layer groups.\n   */\n  draw() {\n    for (const layerGroup of this.#layerGroups) {\n      layerGroup.draw();\n    }\n  }\n\n  /**\n   * Fit to container: synchronise the div to world size ratio\n   *   of the group layers.\n   */\n  fitToContainer() {\n    // find the minimum ratio\n    let minRatio;\n    const hasRatio = [];\n    for (let i = 0; i < this.#layerGroups.length; ++i) {\n      const ratio = this.#layerGroups[i].getDivToWorldSizeRatio();\n      if (typeof ratio !== 'undefined') {\n        hasRatio.push(i);\n        if (typeof minRatio === 'undefined' || ratio < minRatio) {\n          minRatio = ratio;\n        }\n      }\n    }\n    // exit if no ratio\n    if (typeof minRatio === 'undefined') {\n      return;\n    }\n    // apply min ratio to layers\n    for (let j = 0; j < this.#layerGroups.length; ++j) {\n      if (hasRatio.includes(j)) {\n        this.#layerGroups[j].fitToContainer(minRatio);\n      }\n    }\n  }\n\n  /**\n   * Bind the layer groups of the stage.\n   */\n  bindLayerGroups() {\n    if (this.#layerGroups.length === 0 ||\n      this.#layerGroups.length === 1 ||\n      this.#binders.length === 0) {\n      return;\n    }\n    // create callback store\n    this.#callbackStore = new Array(this.#layerGroups.length);\n    // add listeners\n    for (let i = 0; i < this.#layerGroups.length; ++i) {\n      for (let j = 0; j < this.#binders.length; ++j) {\n        this.#addEventListeners(i, this.#binders[j]);\n      }\n    }\n  }\n\n  /**\n   * Unbind the layer groups of the stage.\n   */\n  unbindLayerGroups() {\n    if (this.#layerGroups.length === 0 ||\n      this.#layerGroups.length === 1 ||\n      this.#binders.length === 0 ||\n      !this.#callbackStore) {\n      return;\n    }\n    // remove listeners\n    for (let i = 0; i < this.#layerGroups.length; ++i) {\n      for (let j = 0; j < this.#binders.length; ++j) {\n        this.#removeEventListeners(i, this.#binders[j]);\n      }\n    }\n    // clear callback store\n    this.#callbackStore = null;\n  }\n\n  /**\n   * Set the imageSmoothing flag value.\n   *\n   * @param {boolean} flag True to enable smoothing.\n   */\n  setImageSmoothing(flag) {\n    this.#imageSmoothing = flag;\n    // set for existing layer groups\n    for (const layerGroup of this.#layerGroups) {\n      layerGroup.setImageSmoothing(flag);\n    }\n  }\n\n  /**\n   * Get the binder callback function for a given layer group index.\n   * The function is created if not yet stored.\n   *\n   * @param {object} binder The layer binder.\n   * @param {number} index The index of the associated layer group.\n   * @returns {Function} The binder function.\n   */\n  #getBinderCallback(binder, index) {\n    if (typeof this.#callbackStore[index] === 'undefined') {\n      this.#callbackStore[index] = [];\n    }\n    const store = this.#callbackStore[index];\n    let binderObj = store.find(function (elem) {\n      return elem.binder === binder;\n    });\n    if (typeof binderObj === 'undefined') {\n      // create new callback object\n      binderObj = {\n        binder: binder,\n        callback: (event) => {\n          // stop listeners\n          this.#removeEventListeners(index, binder);\n          // apply binder\n          binder.getCallback(this.#layerGroups[index])(event);\n          // re-start listeners\n          this.#addEventListeners(index, binder);\n        }\n      };\n      this.#callbackStore[index].push(binderObj);\n    }\n    return binderObj.callback;\n  }\n\n  /**\n   * Add event listeners for a given layer group index and binder.\n   *\n   * @param {number} index The index of the associated layer group.\n   * @param {object} binder The layer binder.\n   */\n  #addEventListeners(index, binder) {\n    for (let i = 0; i < this.#layerGroups.length; ++i) {\n      if (i !== index) {\n        this.#layerGroups[index].addEventListener(\n          binder.getEventType(),\n          this.#getBinderCallback(binder, i)\n        );\n      }\n    }\n  }\n\n  /**\n   * Remove event listeners for a given layer group index and binder.\n   *\n   * @param {number} index The index of the associated layer group.\n   * @param {object} binder The layer binder.\n   */\n  #removeEventListeners(index, binder) {\n    for (let i = 0; i < this.#layerGroups.length; ++i) {\n      if (i !== index) {\n        this.#layerGroups[index].removeEventListener(\n          binder.getEventType(),\n          this.#getBinderCallback(binder, i)\n        );\n      }\n    }\n  }\n\n} // class Stage\n","import {Index} from '../math/index';\nimport {colourNameToHex} from '../utils/colour';\nimport {WindowLevel} from '../image/windowLevel';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\n/* eslint-enable no-unused-vars */\n\n/**\n * State class.\n * Saves: data url/path, display info.\n *\n * History:\n * - v0.5 (dwv 0.30.0, 12/2021):\n *   - store position as array,\n *   - new draw position group key.\n * - v0.4 (dwv 0.29.0, 06/2021):\n *   - move drawing details into meta property,\n *   - remove scale center and translation, add offset.\n * - v0.3 (dwv v0.23.0, 03/2018):\n *   - new drawing structure, drawings are now the full layer object and\n *     using toObject to avoid saving a string representation,\n *   - new details structure: simple array of objects referenced by draw ids.\n * - v0.2 (dwv v0.17.0, 12/2016):\n *   - adds draw details: array [nslices][nframes] of detail objects.\n * - v0.1 (dwv v0.15.0, 07/2016):\n *   - adds version,\n *   - drawings: array [nslices][nframes] with all groups.\n * - initial release (dwv v0.10.0, 05/2015), no version number:\n *   - content: window-center, window-width, position, scale,\n *       scaleCenter, translation, drawings,\n *   - drawings: array [nslices] with all groups.\n */\nexport class State {\n  /**\n   * The state data id.\n   *\n   * @type {string}\n   */\n  #dataId;\n\n  /**\n   * @param {string} dataId The associated data id.\n   */\n  constructor(dataId) {\n    this.#dataId = dataId;\n  }\n\n  /**\n   * Load an application state from JSON.\n   *\n   * @param {string} json The state as a JSON string.\n   * @returns {object} The state object.\n   */\n  fromJSON(json) {\n    const data = JSON.parse(json);\n    let res = null;\n    if (data.version === '0.1') {\n      res = this.#readV01(data);\n    } else if (data.version === '0.2') {\n      res = this.#readV02(data);\n    } else if (data.version === '0.3') {\n      res = this.#readV03(data);\n    } else if (data.version === '0.4') {\n      res = this.#readV04(data);\n    } else if (data.version === '0.5') {\n      res = this.#readV05(data);\n    } else {\n      throw new Error('Unknown state file format version: \\'' +\n        data.version + '\\'.');\n    }\n    return res;\n  }\n\n  /**\n   * Load an application state from JSON.\n   *\n   * @param {App} app The app to apply the state to.\n   * @param {object} data The state data.\n   */\n  apply(app, data) {\n    const layerGroup = app.getActiveLayerGroup();\n    const viewLayer = layerGroup.getBaseViewLayer();\n    const viewController = viewLayer.getViewController();\n    // display\n    const wl = new WindowLevel(data['window-center'], data['window-width']);\n    viewController.setWindowLevel(wl);\n    // position is index...\n    viewController.setCurrentIndex(new Index(data.position));\n    // apply saved scale on top of current base one\n    const baseScale = app.getActiveLayerGroup().getBaseScale();\n    let scale = null;\n    let offset = null;\n    if (typeof data.scaleCenter !== 'undefined') {\n      scale = {\n        x: data.scale * baseScale.x,\n        y: data.scale * baseScale.y,\n        z: 1\n      };\n      // ---- transform translation (now) ----\n      // Tx = -offset.x * scale.x\n      // => offset.x = -Tx / scale.x\n      // ---- transform translation (before) ----\n      // origin.x = centerX - (centerX - origin.x) * (newZoomX / zoom.x);\n      // (zoom.x -> initial zoom = base scale, origin.x = 0)\n      // Tx = origin.x + (trans.x * zoom.x)\n      const originX = data.scaleCenter.x - data.scaleCenter.x * data.scale;\n      const originY = data.scaleCenter.y - data.scaleCenter.y * data.scale;\n      const oldTx = originX + data.translation.x * scale.x;\n      const oldTy = originY + data.translation.y * scale.y;\n      offset = {\n        x: -oldTx / scale.x,\n        y: -oldTy / scale.y,\n        z: 0\n      };\n    } else {\n      scale = {\n        x: data.scale.x * baseScale.x,\n        y: data.scale.y * baseScale.y,\n        z: baseScale.z\n      };\n      offset = {\n        x: data.offset.x,\n        y: data.offset.y,\n        z: 0\n      };\n    }\n    app.getActiveLayerGroup().setScale(scale);\n    app.getActiveLayerGroup().setOffset(offset);\n    // drawings (will draw the draw layer)\n    app.setDrawings(data.drawings, data.drawingsDetails, this.#dataId);\n  }\n\n  /**\n   * Read an application state from an Object in v0.1 format.\n   *\n   * @param {object} data The Object representation of the state.\n   * @returns {object} The state object.\n   */\n  #readV01(data) {\n    // v0.1 -> v0.2\n    const v02DAndD = v01Tov02DrawingsAndDetails(data.drawings);\n    // v0.2 -> v0.3, v0.4\n    data.drawings = v02Tov03Drawings(v02DAndD.drawings).toObject();\n    data.drawingsDetails = v03Tov04DrawingsDetails(\n      v02DAndD.drawingsDetails);\n    // v0.4 -> v0.5\n    data = v04Tov05Data(data);\n    data.drawings = v04Tov05Drawings(data.drawings);\n    return data;\n  }\n\n  /**\n   * Read an application state from an Object in v0.2 format.\n   *\n   * @param {object} data The Object representation of the state.\n   * @returns {object} The state object.\n   */\n  #readV02(data) {\n    // v0.2 -> v0.3, v0.4\n    data.drawings = v02Tov03Drawings(data.drawings).toObject();\n    data.drawingsDetails = v03Tov04DrawingsDetails(\n      v02Tov03DrawingsDetails(data.drawingsDetails));\n    // v0.4 -> v0.5\n    data = v04Tov05Data(data);\n    data.drawings = v04Tov05Drawings(data.drawings);\n    return data;\n  }\n\n  /**\n   * Read an application state from an Object in v0.3 format.\n   *\n   * @param {object} data The Object representation of the state.\n   * @returns {object} The state object.\n   */\n  #readV03(data) {\n    // v0.3 -> v0.4\n    data.drawingsDetails = v03Tov04DrawingsDetails(data.drawingsDetails);\n    // v0.4 -> v0.5\n    data = v04Tov05Data(data);\n    data.drawings = v04Tov05Drawings(data.drawings);\n    return data;\n  }\n\n  /**\n   * Read an application state from an Object in v0.4 format.\n   *\n   * @param {object} data The Object representation of the state.\n   * @returns {object} The state object.\n   */\n  #readV04(data) {\n    // v0.4 -> v0.5\n    data = v04Tov05Data(data);\n    data.drawings = v04Tov05Drawings(data.drawings);\n    return data;\n  }\n  /**\n   * Read an application state from an Object in v0.5 format.\n   *\n   * @param {object} data The Object representation of the state.\n   * @returns {object} The state object.\n   */\n  #readV05(data) {\n    return data;\n  }\n\n} // State class\n\n/**\n * Convert drawings from v0.2 to v0.3:\n * - v0.2: one layer per slice/frame,\n * - v0.3: one layer, one group per slice. `setDrawing` expects the full stage.\n *\n * @param {Array} drawings An array of drawings.\n * @returns {object} The layer with the converted drawings.\n */\nfunction v02Tov03Drawings(drawings) {\n  // Auxiliar variables\n  let group, groupShapes, parentGroup;\n  // Avoid errors when dropping multiple states\n  //drawLayer.getChildren().each(function(node){\n  //    node.visible(false);\n  //});\n\n  /**\n   * Get the draw group id for a given position.\n   *\n   * @param {Index} currentPosition The current position.\n   * @returns {string} The group id.\n   */\n  function getDrawPositionGroupId(currentPosition) {\n    const sliceNumber = currentPosition.get(2);\n    const frameNumber = currentPosition.length() === 4\n      ? currentPosition.get(3) : 0;\n    return 'slice-' + sliceNumber + '_frame-' + frameNumber;\n  }\n\n  const drawLayer = new Konva.Layer({\n    listening: false,\n    visible: true\n  });\n\n  // Get the positions-groups data\n  const groupDrawings = typeof drawings === 'string'\n    ? JSON.parse(drawings) : drawings;\n  // Iterate over each position-groups\n  for (let k = 0, lenk = groupDrawings.length; k < lenk; ++k) {\n    // Iterate over each frame\n    for (let f = 0, lenf = groupDrawings[k].length; f < lenf; ++f) {\n      groupShapes = groupDrawings[k][f];\n      if (groupShapes.length !== 0) {\n        // Create position-group set as visible and append it to drawLayer\n        parentGroup = new Konva.Group({\n          id: getDrawPositionGroupId(new Index([1, 1, k, f])),\n          name: 'position-group',\n          visible: false\n        });\n\n        // Iterate over shapes-group\n        for (let g = 0, leng = groupShapes.length; g < leng; ++g) {\n          // create the konva group\n          group = Konva.Node.create(groupShapes[g]);\n          // enforce draggable: only the shape was draggable in v0.2,\n          // now the whole group is.\n          group.draggable(true);\n          group.getChildren().forEach(function (gnode) {\n            gnode.draggable(false);\n          });\n          // add to position group\n          parentGroup.add(group);\n        }\n        // add to layer\n        drawLayer.add(parentGroup);\n      }\n    }\n  }\n\n  return drawLayer;\n}\n\n/**\n * Convert drawings from v0.1 to v0.2:\n * - v0.1: text on its own,\n * - v0.2: text as part of label.\n *\n * @param {Array} inputDrawings An array of drawings.\n * @returns {object} The converted drawings.\n */\nfunction v01Tov02DrawingsAndDetails(inputDrawings) {\n  const newDrawings = [];\n  const drawingsDetails = {};\n\n  let drawGroups;\n  let drawGroup;\n  // loop over each slice\n  for (let k = 0, lenk = inputDrawings.length; k < lenk; ++k) {\n    // loop over each frame\n    newDrawings[k] = [];\n    for (let f = 0, lenf = inputDrawings[k].length; f < lenf; ++f) {\n      // draw group\n      drawGroups = inputDrawings[k][f];\n      const newFrameDrawings = [];\n      // Iterate over shapes-group\n      for (let g = 0, leng = drawGroups.length; g < leng; ++g) {\n        // create konva group from input\n        drawGroup = Konva.Node.create(drawGroups[g]);\n        // force visible (not set in state)\n        drawGroup.visible(true);\n        // label position\n        let pos = {x: 0, y: 0};\n        // update shape colour\n        const kshape = drawGroup.getChildren(function (node) {\n          return node.name() === 'shape';\n        })[0];\n        kshape.stroke(colourNameToHex(kshape.stroke()));\n        // special line case\n        if (drawGroup.name() === 'line-group') {\n          // update name\n          drawGroup.name('ruler-group');\n          // add ticks\n          const ktick0 = new Konva.Line({\n            points: [kshape.points()[0],\n              kshape.points()[1],\n              kshape.points()[0],\n              kshape.points()[1]],\n            name: 'shape-tick0'\n          });\n          drawGroup.add(ktick0);\n          const ktick1 = new Konva.Line({\n            points: [kshape.points()[2],\n              kshape.points()[3],\n              kshape.points()[2],\n              kshape.points()[3]],\n            name: 'shape-tick1'\n          });\n          drawGroup.add(ktick1);\n        }\n        // special protractor case: update arc name\n        const karcs = drawGroup.getChildren(function (node) {\n          return node.name() === 'arc';\n        });\n        if (karcs.length === 1) {\n          karcs[0].name('shape-arc');\n        }\n        // get its text\n        const ktexts = drawGroup.getChildren(function (node) {\n          return node.name() === 'text';\n        });\n        // update text: move it into a label\n        let ktext = new Konva.Text({\n          name: 'text',\n          text: ''\n        });\n        if (ktexts.length === 1) {\n          pos.x = ktexts[0].x();\n          pos.y = ktexts[0].y();\n          // remove it from the group\n          ktexts[0].remove();\n          // use it\n          ktext = ktexts[0];\n        } else {\n          // use shape position if no text\n          if (kshape.points().length !== 0) {\n            pos = {x: kshape.points()[0],\n              y: kshape.points()[1]};\n          }\n        }\n        // create new label with text and tag\n        const klabel = new Konva.Label({\n          x: pos.x,\n          y: pos.y,\n          name: 'label'\n        });\n        klabel.add(ktext);\n        klabel.add(new Konva.Tag());\n        // add label to group\n        drawGroup.add(klabel);\n        // add group to list\n        newFrameDrawings.push(JSON.stringify(drawGroup.toObject()));\n\n        // create details (v0.3 format)\n        let textExpr = ktext.text();\n        const txtLen = textExpr.length;\n        let quant = null;\n        // adapt to text with flag\n        if (drawGroup.name() === 'ruler-group') {\n          quant = {\n            length: {\n              value: parseFloat(textExpr.substring(0, txtLen - 2)),\n              unit: textExpr.substring(-2)\n            }\n          };\n          textExpr = '{length}';\n        } else if (drawGroup.name() === 'ellipse-group' ||\n                    drawGroup.name() === 'rectangle-group') {\n          quant = {\n            surface: {\n              value: parseFloat(textExpr.substring(0, txtLen - 3)),\n              unit: textExpr.substring(-3)\n            }\n          };\n          textExpr = '{surface}';\n        } else if (drawGroup.name() === 'protractor-group' ||\n                    drawGroup.name() === 'rectangle-group') {\n          quant = {\n            angle: {\n              value: parseFloat(textExpr.substring(0, txtLen - 1)),\n              unit: textExpr.substring(-1)\n            }\n          };\n          textExpr = '{angle}';\n        }\n        // set details\n        drawingsDetails[drawGroup.id()] = {\n          textExpr: textExpr,\n          longText: '',\n          quant: quant\n        };\n\n      }\n      newDrawings[k].push(newFrameDrawings);\n    }\n  }\n\n  return {drawings: newDrawings, drawingsDetails: drawingsDetails};\n}\n\n/**\n * Convert drawing details from v0.2 to v0.3:\n * - v0.2: array [nslices][nframes] with all,\n * - v0.3: simple array of objects referenced by draw ids.\n *\n * @param {Array} details An array of drawing details.\n * @returns {object} The converted drawings.\n */\nfunction v02Tov03DrawingsDetails(details) {\n  const res = {};\n  // Get the positions-groups data\n  const groupDetails = typeof details === 'string'\n    ? JSON.parse(details) : details;\n  // Iterate over each position-groups\n  for (let k = 0, lenk = groupDetails.length; k < lenk; ++k) {\n    // Iterate over each frame\n    for (let f = 0, lenf = groupDetails[k].length; f < lenf; ++f) {\n      // Iterate over shapes-group\n      for (let g = 0, leng = groupDetails[k][f].length; g < leng; ++g) {\n        const group = groupDetails[k][f][g];\n        res[group.id] = {\n          textExpr: group.textExpr,\n          longText: group.longText,\n          quant: group.quant\n        };\n      }\n    }\n  }\n  return res;\n}\n\n/**\n * Convert drawing details from v0.3 to v0.4:\n * - v0.3: properties at group root,\n * - v0.4: properties in group meta object.\n *\n * @param {Array} details An array of drawing details.\n * @returns {object} The converted drawings.\n */\nfunction v03Tov04DrawingsDetails(details) {\n  const res = {};\n  const keys = Object.keys(details);\n  // Iterate over each position-groups\n  for (let k = 0, lenk = keys.length; k < lenk; ++k) {\n    const detail = details[keys[k]];\n    res[keys[k]] = {\n      meta: {\n        textExpr: detail.textExpr,\n        longText: detail.longText,\n        quantification: detail.quant\n      }\n    };\n  }\n  return res;\n}\n\n/**\n * Convert drawing from v0.4 to v0.5:\n * - v0.4: position as object,\n * - v0.5: position as array.\n *\n * @param {object} data An array of drawing.\n * @returns {object} The converted drawings.\n */\nfunction v04Tov05Data(data) {\n  const pos = data.position;\n  data.position = [pos.i, pos.j, pos.k];\n  return data;\n}\n\n/**\n * Convert drawing from v0.4 to v0.5:\n * - v0.4: draw id as 'slice-0_frame-1',\n * - v0.5: draw id as '#2-0_#3-1'.\n *\n * @param {object} inputDrawings An array of drawing.\n * @returns {object} The converted drawings.\n */\nfunction v04Tov05Drawings(inputDrawings) {\n  // Iterate over each position-groups\n  const posGroups = inputDrawings.children;\n  for (let k = 0, lenk = posGroups.length; k < lenk; ++k) {\n    const posGroup = posGroups[k];\n    const id = posGroup.attrs.id;\n    const ids = id.split('_');\n    const sliceNumber = parseInt(ids[0].substring(6), 10); // 'slice-0'\n    const frameNumber = parseInt(ids[1].substring(6), 10); // 'frame-0'\n    let newId = '#2-';\n    if (sliceNumber === 0 && frameNumber !== 0) {\n      newId += frameNumber;\n    } else {\n      newId += sliceNumber;\n    }\n    posGroup.attrs.id = newId;\n  }\n  return inputDrawings;\n}\n","import {logger} from './logger';\nimport {splitKeyValueString} from './string';\n\n/**\n * Get an full object URL from a string uri.\n *\n * @param {string} uri A string representing the url.\n * @returns {URL} A URL object.\n */\nexport function getUrlFromUri(uri) {\n  // add base to allow for relative urls\n  // (base is not used for absolute urls)\n  let base;\n  if (window.location.origin !== 'null') {\n    base = window.location.origin;\n  }\n  return new URL(uri, base);\n}\n\n/**\n * Split an input URI:\n * 'root?key0=val00&key0=val01&key1=val10' returns\n * { base : root, query : [ key0 : [val00, val01], key1 : val1 ] }\n * Returns an empty object if the input string is not correct (null, empty...)\n * or if it is not a query string (no question mark).\n *\n * @param {string} uri The string to split.\n * @returns {object} The split string.\n */\nexport function splitUri(uri) {\n  // result\n  const result = {};\n  // check if query string\n  let sepIndex = null;\n  if (uri && (sepIndex = uri.indexOf('?')) !== -1) {\n    // base: before the '?'\n    result.base = uri.substring(0, sepIndex);\n    // query : after the '?' and until possible '#'\n    let hashIndex = uri.indexOf('#');\n    if (hashIndex === -1) {\n      hashIndex = uri.length;\n    }\n    const query = uri.substring(sepIndex + 1, hashIndex);\n    // split key/value pairs of the query\n    result.query = splitKeyValueString(query);\n  }\n  // return\n  return result;\n}\n\n/**\n * Get the query part, split into an array, of an input URI.\n * The URI scheme is: `base?query#fragment`.\n *\n * @param {string} uri The input URI.\n * @returns {object} The query part, split into an array, of the input URI.\n */\nexport function getUriQuery(uri) {\n  // split\n  const parts = splitUri(uri);\n  // check not empty\n  if (Object.keys(parts).length === 0) {\n    return null;\n  }\n  // return query\n  return parts.query;\n}\n\n/**\n * Generic URI query decoder.\n * Supports manifest:\n *   `[dwv root]?input=encodeURIComponent('[manifest file]')&type=manifest`.\n * Or encoded URI with base and key value/pairs:\n *   `[dwv root]?input=encodeURIComponent([root]?key0=value0&key1=value1)`.\n *\n * @param {object} query The query part to the input URI.\n * @param {Function} callback The function to call with the decoded file urls.\n * @param {object} options Optional url request options.\n */\nexport function decodeQuery(query, callback, options) {\n  // manifest\n  if (query.type && query.type === 'manifest') {\n    decodeManifestQuery(query, callback);\n  } else {\n    // default case: encoded URI with base and key/value pairs\n    callback(\n      decodeKeyValueUri(query.input, query.dwvReplaceMode),\n      options);\n  }\n}\n\n/**\n * Decode a Key/Value pair URI. If a key is repeated, the result\n *   be an array of base + each key.\n *\n * @param {string} uri The URI to decode.\n * @param {string} replaceMode The key replace mode. Can be:\n * - key (default): keep the key\n * - other than key: do not use the key\n *   'file' is a special case where the '?' of the query is not kept.\n * @returns {string[]} The list of input file urls.\n */\nexport function decodeKeyValueUri(uri, replaceMode) {\n  const result = [];\n\n  // repeat key replace mode (default to keep key)\n  let repeatKeyReplaceMode = 'key';\n  if (replaceMode) {\n    repeatKeyReplaceMode = replaceMode;\n  }\n\n  // decode input URI\n  const queryUri = decodeURIComponent(uri);\n  // get key/value pairs from input URI\n  const inputQueryPairs = splitUri(queryUri);\n  if (Object.keys(inputQueryPairs).length === 0) {\n    result.push(queryUri);\n  } else {\n    const keys = Object.keys(inputQueryPairs.query);\n    // find repeat key\n    let repeatKey = null;\n    for (let i = 0; i < keys.length; ++i) {\n      if (inputQueryPairs.query[keys[i]] instanceof Array) {\n        repeatKey = keys[i];\n        break;\n      }\n    }\n\n    if (!repeatKey) {\n      result.push(queryUri);\n    } else {\n      const repeatList = inputQueryPairs.query[repeatKey];\n      // build base uri\n      let baseUrl = inputQueryPairs.base;\n      // add '?' when:\n      // - base is not empty\n      // - the repeatKey is not 'file'\n      // root/path/to/?file=0.jpg&file=1.jpg\n      if (baseUrl !== '' && repeatKey !== 'file') {\n        baseUrl += '?';\n      }\n      let gotOneArg = false;\n      for (let j = 0; j < keys.length; ++j) {\n        if (keys[j] !== repeatKey) {\n          if (gotOneArg) {\n            baseUrl += '&';\n          }\n          baseUrl += keys[j] + '=' + inputQueryPairs.query[keys[j]];\n          gotOneArg = true;\n        }\n      }\n      // append built urls to result\n      let url;\n      for (let k = 0; k < repeatList.length; ++k) {\n        url = baseUrl;\n        if (gotOneArg) {\n          url += '&';\n        }\n        if (repeatKeyReplaceMode === 'key') {\n          url += repeatKey + '=';\n        }\n        // other than 'key' mode: do nothing\n        url += repeatList[k];\n        result.push(url);\n      }\n    }\n  }\n  // return\n  return result;\n}\n\n/**\n * Decode a manifest query.\n *\n * @external XMLHttpRequest\n * @param {object} query The manifest query: {input, nslices},\n * with input the input URI and nslices the number of slices.\n * @param {Function} callback The function to call with the decoded urls.\n */\nfunction decodeManifestQuery(query, callback) {\n  let uri = '';\n  if (query.input[0] === '/') {\n    uri = window.location.protocol + '//' + window.location.host;\n  }\n  // TODO: needs to be decoded (decodeURIComponent?\n  uri += query.input;\n\n  /**\n   * Handle error.\n   *\n   * @param {object} event The error event.\n   */\n  function onError(event) {\n    logger.warn('RequestError while receiving manifest: ' +\n      event.target.status);\n  }\n\n  /**\n   * Handle load.\n   *\n   * @param {object} event The load event.\n   */\n  function onLoad(event) {\n    callback(decodeManifest(event.target.responseXML, query.nslices));\n  }\n\n  const request = new XMLHttpRequest();\n  request.open('GET', decodeURIComponent(uri), true);\n  request.responseType = 'document';\n  request.onload = onLoad;\n  request.onerror = onError;\n  request.send(null);\n}\n\n/**\n * Decode an XML manifest.\n *\n * @param {object} manifest The manifest to decode.\n * @param {number} nslices The number of slices to load.\n * @returns {string[]} The decoded manifest.\n */\nexport function decodeManifest(manifest, nslices) {\n  const result = [];\n  // wado url\n  const wadoElement = manifest.getElementsByTagName('wado_query');\n  const wadoURL = wadoElement[0].getAttribute('wadoURL');\n  const rootURL = wadoURL + '?requestType=WADO&contentType=application/dicom&';\n  // patient list\n  const patientList = manifest.getElementsByTagName('Patient');\n  if (patientList.length > 1) {\n    logger.warn('More than one patient, loading first one.');\n  }\n  // study list\n  const studyList = patientList[0].getElementsByTagName('Study');\n  if (studyList.length > 1) {\n    logger.warn('More than one study, loading first one.');\n  }\n  const studyUID = studyList[0].getAttribute('StudyInstanceUID');\n  // series list\n  const seriesList = studyList[0].getElementsByTagName('Series');\n  if (seriesList.length > 1) {\n    logger.warn('More than one series, loading first one.');\n  }\n  const seriesUID = seriesList[0].getAttribute('SeriesInstanceUID');\n  // instance list\n  const instanceList = seriesList[0].getElementsByTagName('Instance');\n  // loop on instances and push links\n  let max = instanceList.length;\n  if (nslices < max) {\n    max = nslices;\n  }\n  for (let i = 0; i < max; ++i) {\n    const sopInstanceUID = instanceList[i].getAttribute('SOPInstanceUID');\n    const link = rootURL +\n        '&studyUID=' + studyUID +\n        '&seriesUID=' + seriesUID +\n        '&objectUID=' + sopInstanceUID;\n    result.push(link);\n  }\n  // return\n  return result;\n}\n","import {ListenerHandler} from './listen';\n\n/**\n * UndoStack class.\n */\nexport class UndoStack {\n  /**\n   * Array of commands.\n   *\n   * @type {Array}\n   */\n  #stack = [];\n\n  /**\n   * Current command index.\n   *\n   * @type {number}\n   */\n  #curCmdIndex = 0;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Get the stack size.\n   *\n   * @returns {number} The size of the stack.\n   */\n  getStackSize() {\n    return this.#stack.length;\n  }\n\n  /**\n   * Get the current stack index.\n   *\n   * @returns {number} The stack index.\n   */\n  getCurrentStackIndex() {\n    return this.#curCmdIndex;\n  }\n\n  /**\n   * Add a command to the stack.\n   *\n   * @param {object} cmd The command to add.\n   * @fires UndoStack#undoadd\n   */\n  add(cmd) {\n    // clear commands after current index\n    this.#stack = this.#stack.slice(0, this.#curCmdIndex);\n    // store command\n    this.#stack.push(cmd);\n    // increment index\n    ++this.#curCmdIndex;\n    /**\n     * Command add to undo stack event.\n     *\n     * @event UndoStack#undoadd\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} command The name of the command added to the\n     *   undo stack.\n     */\n    this.#fireEvent({\n      type: 'undoadd',\n      command: cmd.getName()\n    });\n  }\n\n  /**\n   * Remove a command to the stack.\n   *\n   * @param {string} name The name of the command to remove.\n   * @returns {boolean} True if the command was found and removed.\n   * @fires UndoStack#undoremove\n   */\n  remove(name) {\n    let res = false;\n    const hasInputName = function (element) {\n      return element.getName() === name;\n    };\n    const index = this.#stack.findIndex(hasInputName);\n    if (index !== -1) {\n      // remove command\n      this.#stack.splice(index, 1);\n      // decrement index\n      --this.#curCmdIndex;\n      // result\n      res = true;\n      /**\n       * Command remove from undo stack event.\n       *\n       * @event UndoStack#undoremove\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {string} command The name of the command added to the\n       *   undo stack.\n       */\n      this.#fireEvent({\n        type: 'undoremove',\n        command: name\n      });\n    }\n    return res;\n  }\n\n  /**\n   * Undo the last command.\n   *\n   * @fires UndoStack#undo\n   */\n  undo() {\n    // a bit inefficient...\n    if (this.#curCmdIndex > 0) {\n      // decrement command index\n      --this.#curCmdIndex;\n      // undo last command\n      this.#stack[this.#curCmdIndex].undo();\n      /**\n       * Command undo event.\n       *\n       * @event UndoStack#undo\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {string} command The name of the undone command.\n       */\n      this.#fireEvent({\n        type: 'undo',\n        command: this.#stack[this.#curCmdIndex].getName()\n      });\n    }\n  }\n\n  /**\n   * Redo the last command.\n   *\n   * @fires UndoStack#redo\n   */\n  redo() {\n    if (this.#curCmdIndex < this.#stack.length) {\n      // run last command\n      this.#stack[this.#curCmdIndex].execute();\n      /**\n       * Command redo event.\n       *\n       * @event UndoStack#redo\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {string} command The name of the redone command.\n       */\n      this.#fireEvent({\n        type: 'redo',\n        command: this.#stack[this.#curCmdIndex].getName()\n      });\n      // increment command index\n      ++this.#curCmdIndex;\n    }\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *    event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n} // UndoStack class\n","import {InteractionEventNames} from '../gui/generic';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {LayerGroup} from '../gui/layerGroup';\nimport {ViewLayer} from '../gui/viewLayer';\nimport {DrawLayer} from '../gui/drawLayer';\n/* eslint-enable no-unused-vars */\n\n/**\n * Toolbox controller.\n */\nexport class ToolboxController {\n\n  /**\n   * List of tools to control.\n   *\n   * @type {object}\n   */\n  #toolList;\n\n  /**\n   * Selected tool.\n   *\n   * @type {object}\n   */\n  #selectedTool = null;\n\n  /**\n   * Callback store to allow attach/detach.\n   *\n   * @type {Array}\n   */\n  #callbackStore = [];\n\n  /**\n   * Current layers bound to tool.\n   *\n   * @type {object}\n   */\n  #boundLayers = {};\n\n  /**\n   * @param {object} toolList The list of tool objects.\n   */\n  constructor(toolList) {\n    this.#toolList = toolList;\n  }\n\n  /**\n   * Initialise.\n   */\n  init() {\n    for (const key in this.#toolList) {\n      this.#toolList[key].init();\n    }\n    // enable shortcuts\n    this.enableShortcuts(true);\n  }\n\n  /**\n   * Enable or disable shortcuts. The 'init' methods enables shortcuts\n   *  by default. Call this method after init to disable shortcuts.\n   *\n   * @param {boolean} flag True to enable shortcuts.\n   */\n  enableShortcuts(flag) {\n    if (flag) {\n      window.addEventListener('keydown',\n        this.#getCallback('window', 'keydown'), true);\n    } else {\n      window.removeEventListener('keydown',\n        this.#getCallback('window', 'keydown'), true);\n    }\n  }\n\n  /**\n   * Get the tool list.\n   *\n   * @returns {Array} The list of tool objects.\n   */\n  getToolList() {\n    return this.#toolList;\n  }\n\n  /**\n   * Check if a tool is in the tool list.\n   *\n   * @param {string} name The name to check.\n   * @returns {boolean} The tool list element for the given name.\n   */\n  hasTool(name) {\n    return typeof this.getToolList()[name] !== 'undefined';\n  }\n\n  /**\n   * Get the selected tool.\n   *\n   * @returns {object} The selected tool.\n   */\n  getSelectedTool() {\n    return this.#selectedTool;\n  }\n\n  /**\n   * Get the selected tool event handler.\n   *\n   * @param {string} eventType The event type, for example\n   *   mousedown, touchstart...\n   * @returns {Function} The event handler.\n   */\n  getSelectedToolEventHandler(eventType) {\n    return this.getSelectedTool()[eventType];\n  }\n\n  /**\n   * Set the selected tool.\n   *\n   * @param {string} name The name of the tool.\n   */\n  setSelectedTool(name) {\n    // check if we have it\n    if (!this.hasTool(name)) {\n      throw new Error('Unknown tool: \\'' + name + '\\'');\n    }\n    // de-activate previous\n    if (this.#selectedTool) {\n      this.#selectedTool.activate(false);\n    }\n    // set internal var\n    this.#selectedTool = this.#toolList[name];\n    // activate new tool\n    this.#selectedTool.activate(true);\n  }\n\n  /**\n   * Set the selected tool live features.\n   *\n   * @param {object} list The list of features.\n   */\n  setToolFeatures(list) {\n    if (this.getSelectedTool()) {\n      this.getSelectedTool().setFeatures(list);\n    }\n  }\n\n  /**\n   * Listen to layer interaction events.\n   *\n   * @param {LayerGroup} layerGroup The associated layer group.\n   * @param {ViewLayer|DrawLayer} layer The layer to listen to.\n   */\n  bindLayerGroup(layerGroup, layer) {\n    const divId = layerGroup.getDivId();\n    // listen to active layer changes\n    layerGroup.addEventListener(\n      'activelayerchange', this.#getActiveLayerChangeHandler(divId));\n    // bind the layer\n    this.#internalBindLayerGroup(divId, layer);\n  }\n\n  /**\n   * Bind a layer group to this controller.\n   *\n   * @param {string} layerGroupDivId The layer group div id.\n   * @param {ViewLayer|DrawLayer} layer The layer.\n   */\n  #internalBindLayerGroup(layerGroupDivId, layer) {\n    // remove from local list if preset\n    if (typeof this.#boundLayers[layerGroupDivId] !== 'undefined') {\n      this.#unbindLayer(this.#boundLayers[layerGroupDivId]);\n    }\n    // replace layer in local list\n    this.#boundLayers[layerGroupDivId] = layer;\n    // bind layer\n    this.#bindLayer(layer);\n  }\n\n  /**\n   * Get an active layer change handler.\n   *\n   * @param {string} divId The associated layer group div id.\n   * @returns {Function} The event handler.\n   */\n  #getActiveLayerChangeHandler(divId) {\n    return (event) => {\n      const layer = event.value[0];\n      if (typeof layer !== 'undefined') {\n        this.#internalBindLayerGroup(divId, layer);\n      }\n    };\n  }\n\n  /**\n   * Add canvas mouse and touch listeners to a layer.\n   *\n   * @param {ViewLayer|DrawLayer} layer The layer to start listening to.\n   */\n  #bindLayer(layer) {\n    layer.bindInteraction();\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      layer.addEventListener(names[i],\n        this.#getCallback(layer.getId(), names[i]));\n    }\n  }\n\n  /**\n   * Remove canvas mouse and touch listeners to a layer.\n   *\n   * @param {ViewLayer|DrawLayer} layer The layer to stop listening to.\n   */\n  #unbindLayer(layer) {\n    layer.unbindInteraction();\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      layer.removeEventListener(names[i],\n        this.#getCallback(layer.getId(), names[i]));\n    }\n  }\n\n  /**\n   * Mou(se) and (T)ouch event handler. This function just determines\n   * the mouse/touch position relative to the canvas element.\n   * It then passes it to the current tool.\n   *\n   * @param {string} layerId The layer id.\n   * @param {string} eventType The event type.\n   * @returns {object} A callback for the provided layer and event.\n   */\n  #getCallback(layerId, eventType) {\n    if (typeof this.#callbackStore[layerId] === 'undefined') {\n      this.#callbackStore[layerId] = [];\n    }\n\n    if (typeof this.#callbackStore[layerId][eventType] === 'undefined') {\n      const applySelectedTool = (event) => {\n        // make sure we have a tool\n        if (this.#selectedTool) {\n          const func = this.#selectedTool[event.type];\n          if (func) {\n            func(event);\n          }\n        }\n      };\n      // store callback\n      this.#callbackStore[layerId][eventType] = applySelectedTool;\n    }\n\n    return this.#callbackStore[layerId][eventType];\n  }\n\n} // class ToolboxController\n","/**\n * Multiple progresses handler.\n * Stores a multi dimensional list of progresses to allow to\n * calculate a global progress.\n *\n */\nexport class MultiProgressHandler {\n\n  /**\n   * List of progresses.\n   * First dimension is a list of item for which the progress is recorded,\n   *   for example file names.\n   * Second dimension is a list of possible progresses, for example\n   *   the progress of the download and the progress of the decoding.\n   *\n   * @type {Array}\n   */\n  #progresses = [];\n\n  /**\n   * Number of dimensions.\n   *\n   * @type {number}\n   */\n  #numberOfDimensions = 2;\n\n  /**\n   * Progress callback.\n   *\n   * @type {Function}\n   */\n  #callback;\n\n  /**\n   * @param {Function} callback The function to pass the global progress to.\n   */\n  constructor(callback) {\n    this.#callback = callback;\n  }\n\n  /**\n   * Set the number of dimensions.\n   *\n   * @param {number} num The number.\n   */\n  setNumberOfDimensions(num) {\n    this.#numberOfDimensions = num;\n  }\n\n  /**\n   * Set the number of data to load.\n   *\n   * @param {number} n The number of data to load.\n   */\n  setNToLoad(n) {\n    for (let i = 0; i < n; ++i) {\n      this.#progresses[i] = [];\n      for (let j = 0; j < this.#numberOfDimensions; ++j) {\n        this.#progresses[i][j] = 0;\n      }\n    }\n  }\n\n  /**\n   * Handle a load progress.\n   * Call the member callback with a global event.\n   *\n   * @param {object} event The progress event.\n   */\n  onprogress = (event) => {\n    // check event\n    if (!event.lengthComputable) {\n      return;\n    }\n    if (typeof event.subindex === 'undefined') {\n      return;\n    }\n    if (typeof event.index === 'undefined') {\n      return;\n    }\n    // calculate percent\n    const percent = (event.loaded * 100) / event.total;\n    // set percent for index\n    this.#progresses[event.index][event.subindex] = percent;\n\n    // item progress\n    let item = null;\n    if (typeof event.item !== 'undefined') {\n      item = event.item;\n    } else {\n      item = {\n        loaded: this.#getItemProgress(event.index),\n        total: 100,\n        source: event.source\n      };\n    }\n\n    // call callback with a global event\n    this.#callback({\n      lengthComputable: true,\n      loaded: this.#getGlobalPercent(),\n      total: 100,\n      item: item\n    });\n  };\n\n  /**\n   * Get the item load percent.\n   *\n   * @param {number} index The index of the item.\n   * @returns {number} The load percentage.\n   */\n  #getItemProgress(index) {\n    let sum = 0;\n    for (let j = 0; j < this.#numberOfDimensions; ++j) {\n      sum += this.#progresses[index][j];\n    }\n    return sum / this.#numberOfDimensions;\n  }\n\n  /**\n   * Get the global load percent including the provided one.\n   *\n   * @returns {number} The accumulated percentage.\n   */\n  #getGlobalPercent() {\n    let sum = 0;\n    const lenprog = this.#progresses.length;\n    for (let i = 0; i < lenprog; ++i) {\n      sum += this.#getItemProgress(i);\n    }\n    return Math.round(sum / lenprog);\n  }\n\n\n  /**\n   * @callback eventFn\n   * @param {object} event The event.\n   */\n\n  /**\n   * Create a mono progress event handler.\n   *\n   * @param {number} index The index of the data.\n   * @param {number} subindex The sub-index of the data.\n   * @returns {eventFn} A progress handler function.\n   */\n  getMonoProgressHandler(index, subindex) {\n    return (event) => {\n      event.index = index;\n      event.subindex = subindex;\n      this.onprogress(event);\n    };\n  }\n\n  /**\n   * Create a mono progress event handler with an undefined index.\n   * Warning: The caller handles the progress index.\n   *\n   * @param {number} subindex The sub-index of the data.\n   * @returns {eventFn} A progress handler function.\n   */\n  getUndefinedMonoProgressHandler(subindex) {\n    return (event) => {\n      event.subindex = subindex;\n      this.onprogress(event);\n    };\n  }\n}\n","import {endsWith, getRootPath} from '../utils/string';\nimport {MultiProgressHandler} from '../utils/progress';\nimport {getFileListFromDicomDir} from '../dicom/dicomElementsWrapper';\nimport {loaderList} from './loaderList';\n\n// url content types\nexport const urlContentTypes = {\n  Text: 0,\n  ArrayBuffer: 1\n};\n\n/**\n * Urls loader.\n */\nexport class UrlsLoader {\n\n  /**\n   * Input data.\n   *\n   * @type {string[]}\n   */\n  #inputData = null;\n\n  /**\n   * Array of launched requests.\n   *\n   * @type {XMLHttpRequest[]}\n   */\n  #requests = [];\n\n  /**\n   * Data loader.\n   *\n   * @type {object}\n   */\n  #runningLoader = null;\n\n  /**\n   * Number of loaded data.\n   *\n   * @type {number}\n   */\n  #nLoad = 0;\n\n  /**\n   * Number of load end events.\n   *\n   * @type {number}\n   */\n  #nLoadend = 0;\n\n  /**\n   * Flag to know if the load is aborting.\n   *\n   * @type {boolean}\n   */\n  #aborting;\n\n  /**\n   * The default character set (optional).\n   *\n   * @type {string}\n   */\n  #defaultCharacterSet;\n\n  /**\n   * Get the default character set.\n   *\n   * @returns {string} The default character set.\n   */\n  getDefaultCharacterSet() {\n    return this.#defaultCharacterSet;\n  }\n\n  /**\n   * Set the default character set.\n   *\n   * @param {string} characterSet The character set.\n   */\n  setDefaultCharacterSet(characterSet) {\n    this.#defaultCharacterSet = characterSet;\n  }\n\n  /**\n   * Store the current input.\n   *\n   * @param {string[]} data The input data.\n   */\n  #storeInputData(data) {\n    this.#inputData = data;\n    // reset counters\n    this.#nLoad = 0;\n    this.#nLoadend = 0;\n    // reset flag\n    this.#aborting = false;\n    // clear storage\n    this.#clearStoredRequests();\n    this.#clearStoredLoader();\n  }\n\n  /**\n   * Store a launched request.\n   *\n   * @param {XMLHttpRequest} request The launched request.\n   */\n  #storeRequest(request) {\n    this.#requests.push(request);\n  }\n\n  /**\n   * Clear the stored requests.\n   *\n   */\n  #clearStoredRequests() {\n    this.#requests = [];\n  }\n\n  /**\n   * Store the launched loader.\n   *\n   * @param {object} loader The launched loader.\n   */\n  #storeLoader(loader) {\n    this.#runningLoader = loader;\n  }\n\n  /**\n   * Clear the stored loader.\n   *\n   */\n  #clearStoredLoader() {\n    this.#runningLoader = null;\n  }\n\n  /**\n   * Increment the number of loaded data\n   *   and call onload if loaded all data.\n   *\n   * @param {object} _event The load data event.\n   */\n  #addLoad = (_event) => {\n    this.#nLoad++;\n    // call onload when all is loaded\n    // (not using the input event since it is\n    //   an individual load)\n    if (this.#nLoad === this.#inputData.length) {\n      this.onload({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * Increment the counter of load end events\n   *   and run callbacks when all done, erroneus or not.\n   *\n   * @param {object} _event The load end event.\n   */\n  #addLoadend = (_event) => {\n    this.#nLoadend++;\n    // call onloadend when all is run\n    // (not using the input event since it is\n    //   an individual load end)\n    if (this.#nLoadend === this.#inputData.length) {\n      this.onloadend({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * @callback eventFn\n   * @param {object} event The event.\n   */\n\n  /**\n   * Augment a callback event with a srouce.\n   *\n   * @param {object} callback The callback to augment its event.\n   * @param {object} source The source to add to the event.\n   * @returns {eventFn} The augmented callback.\n   */\n  #augmentCallbackEvent(callback, source) {\n    return (event) => {\n      event.source = source;\n      callback(event);\n    };\n  }\n\n  /**\n   * Load a list of URLs or a DICOMDIR.\n   *\n   * @param {string[]} data The list of urls to load.\n   * @param {object} [options] Load options.\n   */\n  load(data, options) {\n    // send start event\n    this.onloadstart({\n      source: data\n    });\n\n    // check if DICOMDIR case\n    if (data.length === 1 &&\n      (endsWith(data[0], 'DICOMDIR') ||\n      endsWith(data[0], '.dcmdir'))) {\n      this.#loadDicomDir(data[0], options);\n    } else {\n      this.#loadUrls(data, options);\n    }\n  }\n\n  /**\n   * Get a load handler for a data element.\n   *\n   * @param {object} loader The associated loader.\n   * @param {string} dataElement The data element.\n   * @param {number} i The index of the element.\n   * @returns {eventFn} A load handler.\n   */\n  #getLoadHandler(loader, dataElement, i) {\n    return (event) => {\n      // check response status\n      // https://developer.mozilla.org/en-US/docs/Web/HTTP/Response_codes\n      // status 200: \"OK\"; status 0: \"debug\"\n      const status = event.target.status;\n      if (status !== 200 && status !== 0) {\n        this.onerror({\n          source: dataElement,\n          error: 'GET ' + event.target.responseURL +\n            ' ' + event.target.status +\n            ' (' + event.target.statusText + ')',\n          target: event.target\n        });\n        this.#addLoadend();\n      } else {\n        loader.load(event.target.response, dataElement, i);\n      }\n    };\n  }\n\n  /**\n   * Load a list of urls.\n   *\n   * @param {string[]} data The list of urls to load.\n   * @param {object} [options] The options object, can contain:\n   * - requestHeaders: an array of {name, value} to use as request headers,\n   * - withCredentials: boolean xhr.withCredentials flag to pass\n   *   to the request,\n   * - batchSize: the size of the request url batch.\n   */\n  #loadUrls(data, options) {\n    // check input\n    if (typeof data === 'undefined' || data.length === 0) {\n      return;\n    }\n    this.#storeInputData(data);\n\n    // create prgress handler\n    const mproghandler = new MultiProgressHandler(this.onprogress);\n    mproghandler.setNToLoad(data.length);\n\n    // create loaders\n    const loaders = [];\n    for (let m = 0; m < loaderList.length; ++m) {\n      loaders.push(new loaderList[m]());\n    }\n\n    // find an appropriate loader\n    let dataElement = data[0];\n    let loader = null;\n    let foundLoader = false;\n    for (let l = 0; l < loaders.length; ++l) {\n      loader = loaders[l];\n      if (loader.canLoadUrl(dataElement, options)) {\n        foundLoader = true;\n        // load options\n        loader.setOptions({\n          numberOfFiles: data.length,\n          defaultCharacterSet: this.getDefaultCharacterSet()\n        });\n        // set loader callbacks\n        // loader.onloadstart: nothing to do\n        loader.onprogress = mproghandler.getUndefinedMonoProgressHandler(1);\n        loader.onloaditem = this.onloaditem;\n        loader.onload = this.#addLoad;\n        loader.onloadend = this.#addLoadend;\n        loader.onerror = this.onerror;\n        loader.onabort = this.onabort;\n\n        // store loader\n        this.#storeLoader(loader);\n        // exit\n        break;\n      }\n    }\n    if (!foundLoader) {\n      throw new Error('No loader found for url: ' + dataElement);\n    }\n\n    // store last run request index\n    let lastRunRequestIndex = 0;\n    const requestOnLoadEnd = () => {\n      // launch next in queue\n      if (lastRunRequestIndex < this.#requests.length - 1 && !this.#aborting) {\n        ++lastRunRequestIndex;\n        this.#requests[lastRunRequestIndex].send(null);\n      }\n    };\n\n    // loop on I/O elements\n    for (let i = 0; i < data.length; ++i) {\n      dataElement = data[i];\n\n      // check loader\n      if (!loader.canLoadUrl(dataElement, options)) {\n        throw new Error('Input url of different type: ' + dataElement);\n      }\n      /**\n       * The http request.\n       *\n       * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest}.\n       *\n       * @external XMLHttpRequest\n       */\n      const request = new XMLHttpRequest();\n      request.open('GET', dataElement, true);\n\n      // request options\n      if (typeof options !== 'undefined') {\n        // optional request headers\n        if (typeof options.requestHeaders !== 'undefined') {\n          const requestHeaders = options.requestHeaders;\n          for (let j = 0; j < requestHeaders.length; ++j) {\n            if (typeof requestHeaders[j].name !== 'undefined' &&\n              typeof requestHeaders[j].value !== 'undefined') {\n              request.setRequestHeader(\n                requestHeaders[j].name, requestHeaders[j].value);\n            }\n          }\n        }\n        // optional withCredentials\n        // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials\n        if (typeof options.withCredentials !== 'undefined') {\n          request.withCredentials = options.withCredentials;\n        }\n      }\n\n      // set request callbacks\n      // request.onloadstart: nothing to do\n      request.onprogress = this.#augmentCallbackEvent(\n        mproghandler.getMonoProgressHandler(i, 0), dataElement);\n      request.onload = this.#getLoadHandler(loader, dataElement, i);\n      request.onloadend = requestOnLoadEnd;\n      const errorCallback =\n        this.#augmentCallbackEvent(this.onerror, dataElement);\n      request.onerror = (event) => {\n        this.#addLoadend();\n        errorCallback(event);\n      };\n      const timeoutCallback =\n        this.#augmentCallbackEvent(this.ontimeout, dataElement);\n      request.ontimeout = (event) => {\n        this.#addLoadend();\n        timeoutCallback(event);\n      };\n      const abortCallback =\n        this.#augmentCallbackEvent(this.onabort, dataElement);\n      request.onabort = (event) => {\n        this.#addLoadend();\n        abortCallback(event);\n      };\n      // response type (default is 'text')\n      if (loader.loadUrlAs() === urlContentTypes.ArrayBuffer) {\n        request.responseType = 'arraybuffer';\n      }\n\n      // store request\n      this.#storeRequest(request);\n    }\n\n    // launch requests in batch\n    let batchSize = this.#requests.length;\n    if (typeof options !== 'undefined') {\n      // optional request batch size\n      if (typeof options.batchSize !== 'undefined' && batchSize !== 0) {\n        batchSize = Math.min(options.batchSize, this.#requests.length);\n      }\n    }\n    for (let r = 0; r < batchSize; ++r) {\n      if (!this.#aborting) {\n        lastRunRequestIndex = r;\n        this.#requests[lastRunRequestIndex].send(null);\n      }\n    }\n  }\n\n  /**\n   * Load a DICOMDIR.\n   *\n   * @param {string} dicomDirUrl The DICOMDIR url.\n   * @param {object} [options] Load options.\n   */\n  #loadDicomDir(dicomDirUrl, options) {\n    // read DICOMDIR\n    const request = new XMLHttpRequest();\n    request.open('GET', dicomDirUrl, true);\n    request.responseType = 'arraybuffer';\n    // request.onloadstart: nothing to do\n    /**\n     * @param {object} event The load event.\n     */\n    request.onload = (event) => {\n      // check status\n      const status = event.target.status;\n      if (status !== 200 && status !== 0) {\n        this.onerror({\n          source: dicomDirUrl,\n          error: 'GET ' + event.target.responseURL +\n            ' ' + event.target.status +\n            ' (' + event.target.statusText + ')',\n          target: event.target\n        });\n        this.onloadend({});\n      } else {\n        // get the file list\n        const list = getFileListFromDicomDir(event.target.response);\n        // use the first list\n        const urls = list[0][0];\n        // append root url\n        const rootUrl = getRootPath(dicomDirUrl);\n        const fullUrls = [];\n        for (let i = 0; i < urls.length; ++i) {\n          fullUrls.push(rootUrl + '/' + urls[i]);\n        }\n        // load urls\n        this.#loadUrls(fullUrls, options);\n      }\n    };\n    request.onerror = (event) => {\n      this.#augmentCallbackEvent(this.onerror, dicomDirUrl)(event);\n      this.onloadend({});\n    };\n    request.onabort = (event) => {\n      this.#augmentCallbackEvent(this.onabort, dicomDirUrl)(event);\n      this.onloadend({});\n    };\n    // request.onloadend: nothing to do\n    // send request\n    request.send(null);\n  }\n\n  /**\n   * Abort a load.\n   */\n  abort() {\n    this.#aborting = true;\n    // abort non finished requests\n    for (let i = 0; i < this.#requests.length; ++i) {\n      // 0: UNSENT, 1: OPENED, 2: HEADERS_RECEIVED (send()), 3: LOADING, 4: DONE\n      if (this.#requests[i].readyState !== 4) {\n        this.#requests[i].abort();\n      }\n    }\n    // abort loader\n    if (this.#runningLoader && this.#runningLoader.isLoading()) {\n      this.#runningLoader.abort();\n    }\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle a load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle a timeout event.\n   * Default does nothing.\n   *\n   * @param {object} _event The timeout event.\n   */\n  ontimeout(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class UrlsLoader\n","/**\n * Thread Pool.\n *\n * Highly inspired from {@link http://www.smartjava.org/content/html5-easily-parallelize-jobs-using-web-workers-and-threadpool}.\n */\nexport class ThreadPool {\n\n  /**\n   * @param {number} poolSize The size of the pool.\n   */\n  constructor(poolSize) {\n    this.poolSize = poolSize;\n    // task queue\n    this.taskQueue = [];\n    // lsit of available threads\n    this.freeThreads = [];\n    // create 'poolSize' number of worker threads\n    for (let i = 0; i < poolSize; ++i) {\n      this.freeThreads.push(new WorkerThread(this));\n    }\n    // list of running threads (unsed in abort)\n    this.runningThreads = [];\n  }\n\n  /**\n   * Add a worker task to the queue.\n   * Will be run when a thread is made available.\n   *\n   * @param {object} workerTask The task to add to the queue.\n   */\n  addWorkerTask(workerTask) {\n    // send work start if first task\n    if (this.freeThreads.length === this.poolSize) {\n      this.onworkstart({type: 'work-start'});\n    }\n    // launch task or queue\n    if (this.freeThreads.length > 0) {\n      // get the first free worker thread\n      const workerThread = this.freeThreads.shift();\n      // add the thread to the runnning list\n      this.runningThreads.push(workerThread);\n      // run the input task\n      workerThread.run(workerTask);\n    } else {\n      // no free thread, add task to queue\n      this.taskQueue.push(workerTask);\n    }\n  }\n\n  /**\n   * Abort all threads.\n   */\n  abort() {\n    // stop all threads\n    this.#stop();\n    // callback\n    this.onabort({type: 'work-abort'});\n    this.onworkend({type: 'work-end'});\n  }\n\n  /**\n   * Handle a task end.\n   *\n   * @param {object} workerThread The thread to free.\n   */\n  onTaskEnd(workerThread) {\n    // launch next task in queue or finish\n    if (this.taskQueue.length > 0) {\n      // get waiting task\n      const workerTask = this.taskQueue.shift();\n      // use input thread to run the waiting task\n      workerThread.run(workerTask);\n    } else {\n      // stop the worker\n      workerThread.stop();\n      // no task to run, add to free list\n      this.freeThreads.push(workerThread);\n      // remove from running list\n      for (let i = 0; i < this.runningThreads.length; ++i) {\n        if (this.runningThreads[i].getId() === workerThread.getId()) {\n          this.runningThreads.splice(i, 1);\n        }\n      }\n      // the work is done when the queue is back to its initial size\n      if (this.freeThreads.length === this.poolSize) {\n        this.onwork({type: 'work'});\n        this.onworkend({type: 'work-end'});\n      }\n    }\n  }\n\n  /**\n   * Handle an error message from a worker.\n   *\n   * @param {object} event The error event.\n   */\n  handleWorkerError = (event) => {\n    // stop all threads\n    this.#stop();\n    // callback\n    this.onerror({error: event});\n    this.onworkend({type: 'work-end'});\n  };\n\n  // private ----------------------------------------------------------------\n\n  /**\n   * Stop the pool: stop all running threads.\n   *\n   */\n  #stop() {\n    // clear tasks\n    this.taskQueue = [];\n    // cancel running workers\n    for (let i = 0; i < this.runningThreads.length; ++i) {\n      this.runningThreads[i].stop();\n    }\n    this.runningThreads = [];\n  }\n\n\n  /**\n   * Handle a work start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The work start event.\n   */\n  onworkstart(_event) {}\n\n  /**\n   * Handle a work item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The work item event fired\n   *   when a work item ended successfully.\n   */\n  onworkitem(_event) {}\n\n  /**\n   * Handle a work event.\n   * Default does nothing.\n   *\n   * @param {object} _event The work event fired\n   *   when a work ended successfully.\n   */\n  onwork(_event) {}\n\n  /**\n   * Handle a work end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The work end event fired\n   *  when a work has completed, successfully or not.\n   */\n  onworkend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // ThreadPool\n\n/**\n * Worker background task.\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/Worker}.\n *\n * @external Worker\n */\n\n/**\n * Worker thread.\n */\nclass WorkerThread {\n\n  /**\n   * @param {object} parentPool The parent pool.\n   */\n  constructor(parentPool) {\n    this.parentPool = parentPool;\n    // thread ID\n    this.id = Math.random().toString(36).substring(2, 15);\n    // running task\n    this.runningTask = null;\n    // worker used to run task\n    this.worker;\n  }\n\n  /**\n   * Get the thread ID.\n   *\n   * @returns {string} The thread ID (alphanumeric).\n   */\n  getId() {\n    return this.id;\n  }\n\n  /**\n   * Run a worker task.\n   *\n   * @param {object} workerTask The task to run.\n   */\n  run(workerTask) {\n    // store task\n    this.runningTask = workerTask;\n    // create a new web worker if not done yet\n    if (typeof this.worker === 'undefined') {\n      this.worker = new Worker(this.runningTask.script);\n      // set callbacks\n      this.worker.onmessage = this.onmessage;\n      this.worker.onerror = this.onerror;\n    }\n    // launch the worker\n    this.worker.postMessage(this.runningTask.startMessage);\n  }\n\n  /**\n   * Finish a task and tell the parent.\n   */\n  stop() {\n    // stop the worker\n    if (typeof this.worker !== 'undefined') {\n      this.worker.terminate();\n      // force create at next run\n      this.worker = undefined;\n    }\n  }\n\n  /**\n   * Message event handler.\n   * For now assume we only get a single callback from a worker\n   * which also indicates the end of this worker.\n   *\n   * @param {object} event The message event.\n   */\n  onmessage = (event) => {\n    // augment event\n    event.itemNumber = this.runningTask.info.itemNumber;\n    event.numberOfItems = this.runningTask.info.numberOfItems;\n    event.index = this.runningTask.info.index;\n    // send event\n    this.parentPool.onworkitem(event);\n    // tell the parent pool the task is done\n    this.parentPool.onTaskEnd(this);\n  };\n\n  /**\n   * Error event handler.\n   *\n   * @param {object} event The error event.\n   */\n  onerror = (event) => {\n    // augment event\n    event.itemNumber = this.runningTask.info.itemNumber;\n    event.numberOfItems = this.runningTask.info.numberOfItems;\n    event.index = this.runningTask.info.index;\n    // pass to parent\n    this.parentPool.handleWorkerError(event);\n    // stop the worker and free the thread\n    this.stop();\n  };\n} // class WorkerThread\n\n/**\n * Worker task.\n */\nexport class WorkerTask {\n  /**\n   * @param {string} script The worker script.\n   * @param {object} message The data to pass to the worker.\n   * @param {object} info Information object about the input data.\n   */\n  constructor(script, message, info) {\n    // worker script\n    this.script = script;\n    // worker start message\n    this.startMessage = message;\n    // information about the work data\n    this.info = info;\n  }\n}\n","import {ThreadPool, WorkerTask} from '../utils/thread';\n\n/**\n * The JPEG baseline decoder.\n *\n * Ref: {@link https://github.com/mozilla/pdf.js/blob/master/src/core/jpg.js}.\n *\n * @external JpegImage\n */\n/* global JpegImage */\n// @ts-ignore\nconst hasJpegBaselineDecoder = (typeof JpegImage !== 'undefined');\n\n/**\n * The JPEG decoder namespace.\n *\n * Ref: {@link https://github.com/rii-mango/JPEGLosslessDecoderJS}.\n *\n * @external jpeg\n */\n/* global jpeg */\nconst hasJpegLosslessDecoder =\n  // @ts-ignore\n  (typeof jpeg !== 'undefined') && (typeof jpeg.lossless !== 'undefined');\n\n/**\n * The JPEG 2000 decoder.\n *\n * Ref: {@link https://github.com/jpambrun/jpx-medical/blob/master/jpx.js}.\n *\n * @external JpxImage\n */\n/* global JpxImage */\n// @ts-ignore\nconst hasJpeg2000Decoder = (typeof JpxImage !== 'undefined');\n\n/* global dwvdecoder */\n\n/**\n * Decoder scripts to be passed to web workers for image decoding.\n */\nexport const decoderScripts = {\n  jpeg2000: '',\n  'jpeg-lossless': '',\n  'jpeg-baseline': '',\n  rle: ''\n};\n\n/**\n * Asynchronous pixel buffer decoder.\n */\nclass AsynchPixelBufferDecoder {\n\n  /**\n   * The associated worker script.\n   *\n   * @type {string}\n   */\n  #script;\n\n  /**\n   * Associated thread pool.\n   *\n   * @type {ThreadPool}\n   */\n  #pool = new ThreadPool(10);\n\n  /**\n   * Flag to know if callbacks are set.\n   *\n   * @type {boolean}\n   */\n  #areCallbacksSet = false;\n\n  /**\n   * @param {string} script The path to the decoder script to be used\n   *   by the web worker.\n   * @param {number} _numberOfData The anticipated number of data to decode.\n   */\n  constructor(script, _numberOfData) {\n    this.#script = script;\n  }\n\n  /**\n   * Decode a pixel buffer.\n   *\n   * @param {Array} pixelBuffer The pixel buffer.\n   * @param {object} pixelMeta The input meta data.\n   * @param {object} info Information object about the input data.\n   */\n  decode(pixelBuffer, pixelMeta, info) {\n    if (!this.#areCallbacksSet) {\n      this.#areCallbacksSet = true;\n      // set event handlers\n      this.#pool.onworkstart = this.ondecodestart;\n      this.#pool.onworkitem = this.ondecodeditem;\n      this.#pool.onwork = this.ondecoded;\n      this.#pool.onworkend = this.ondecodeend;\n      this.#pool.onerror = this.onerror;\n      this.#pool.onabort = this.onabort;\n    }\n    // create worker task\n    const workerTask = new WorkerTask(\n      this.#script,\n      {\n        buffer: pixelBuffer,\n        meta: pixelMeta\n      },\n      info\n    );\n    // add it the queue and run it\n    this.#pool.addWorkerTask(workerTask);\n  }\n\n  /**\n   * Abort decoding.\n   */\n  abort() {\n    // abort the thread pool, will trigger pool.onabort\n    this.#pool.abort();\n  }\n\n  /**\n   * Handle a decode start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode start event.\n   */\n  ondecodestart(_event) {}\n\n  /**\n   * Handle a decode item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode item event fired\n   *   when a decode item ended successfully.\n   */\n  ondecodeditem(_event) {}\n\n  /**\n   * Handle a decode event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode event fired\n   *   when a file has been decoded successfully.\n   */\n  ondecoded(_event) {}\n\n  /**\n   * Handle a decode end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode end event fired\n   *  when a file decoding has completed, successfully or not.\n   */\n  ondecodeend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class AsynchPixelBufferDecoder\n\n/**\n * Synchronous pixel buffer decoder.\n */\nclass SynchPixelBufferDecoder {\n\n  /**\n   * Name of the compression algorithm.\n   *\n   * @type {string}\n   */\n  #algoName;\n\n  /**\n   * Number of data.\n   *\n   * @type {number}\n   */\n  #numberOfData;\n\n  /**\n   * @param {string} algoName The decompression algorithm name.\n   * @param {number} numberOfData The anticipated number of data to decode.\n   */\n  constructor(algoName, numberOfData) {\n    this.#algoName = algoName;\n    this.#numberOfData = numberOfData;\n  }\n\n  // decode count\n  #decodeCount = 0;\n\n  /**\n   * Decode a pixel buffer.\n   *\n   * @param {Array} pixelBuffer The pixel buffer.\n   * @param {object} pixelMeta The input meta data.\n   * @param {object} info Information object about the input data.\n   * @external jpeg\n   * @external JpegImage\n   * @external JpxImage\n   */\n  decode(pixelBuffer, pixelMeta, info) {\n    ++this.#decodeCount;\n\n    let decoder = null;\n    let decodedBuffer = null;\n    if (this.#algoName === 'jpeg-lossless') {\n      if (!hasJpegLosslessDecoder) {\n        throw new Error('No JPEG Lossless decoder provided');\n      }\n      // bytes per element\n      const bpe = pixelMeta.bitsAllocated / 8;\n      const buf = new Uint8Array(pixelBuffer);\n      // @ts-ignore\n      decoder = new jpeg.lossless.Decoder();\n      const decoded = decoder.decode(buf.buffer, 0, buf.buffer.byteLength, bpe);\n      if (pixelMeta.bitsAllocated === 8) {\n        if (pixelMeta.isSigned) {\n          decodedBuffer = new Int8Array(decoded.buffer);\n        } else {\n          decodedBuffer = new Uint8Array(decoded.buffer);\n        }\n      } else if (pixelMeta.bitsAllocated === 16) {\n        if (pixelMeta.isSigned) {\n          decodedBuffer = new Int16Array(decoded.buffer);\n        } else {\n          decodedBuffer = new Uint16Array(decoded.buffer);\n        }\n      }\n    } else if (this.#algoName === 'jpeg-baseline') {\n      if (!hasJpegBaselineDecoder) {\n        throw new Error('No JPEG Baseline decoder provided');\n      }\n      // @ts-ignore\n      decoder = new JpegImage();\n      decoder.parse(pixelBuffer);\n      decodedBuffer = decoder.getData(decoder.width, decoder.height);\n    } else if (this.#algoName === 'jpeg2000') {\n      if (!hasJpeg2000Decoder) {\n        throw new Error('No JPEG 2000 decoder provided');\n      }\n      // decompress pixel buffer into Int16 image\n      // @ts-ignore\n      decoder = new JpxImage();\n      decoder.parse(pixelBuffer);\n      // set the pixel buffer\n      decodedBuffer = decoder.tiles[0].items;\n    } else if (this.#algoName === 'rle') {\n      // decode DICOM buffer\n      // @ts-ignore\n      decoder = new dwvdecoder.RleDecoder();\n      // set the pixel buffer\n      decodedBuffer = decoder.decode(\n        pixelBuffer,\n        pixelMeta.bitsAllocated,\n        pixelMeta.isSigned,\n        pixelMeta.sliceSize,\n        pixelMeta.samplesPerPixel,\n        pixelMeta.planarConfiguration);\n    }\n    // send decode events\n    this.ondecodeditem({\n      data: [decodedBuffer],\n      index: info.index,\n      numberOfItems: info.numberOfItems,\n      itemNumber: info.itemNumber\n    });\n    // decode end?\n    if (this.#decodeCount === this.#numberOfData) {\n      this.ondecoded({});\n      this.ondecodeend({});\n    }\n  }\n\n  /**\n   * Abort decoding.\n   */\n  abort() {\n    // nothing to do in the synchronous case.\n    // callback\n    this.onabort({});\n    this.ondecodeend({});\n  }\n\n  /**\n   * Handle a decode start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode start event.\n   */\n  ondecodestart(_event) {}\n\n  /**\n   * Handle a decode item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode item event fired\n   *   when a decode item ended successfully.\n   */\n  ondecodeditem(_event) {}\n\n  /**\n   * Handle a decode event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode event fired\n   *   when a file has been decoded successfully.\n   */\n  ondecoded(_event) {}\n\n  /**\n   * Handle a decode end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode end event fired\n   *  when a file decoding has completed, successfully or not.\n   */\n  ondecodeend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class SynchPixelBufferDecoder\n\n/**\n * Decode a pixel buffer.\n *\n * If the 'decoderScripts' variable does not contain the desired,\n * algorythm the decoder will switch to the synchronous mode.\n */\nexport class PixelBufferDecoder {\n\n  /**\n   * Flag to know if callbacks are set.\n   *\n   * @type {boolean}\n   */\n  #areCallbacksSet = false;\n\n  /**\n   * Pixel decoder.\n   * Defined only once.\n   *\n   * @type {object}\n   */\n  #pixelDecoder = null;\n\n  /**\n   * @param {string} algoName The decompression algorithm name.\n   * @param {number} numberOfData The anticipated number of data to decode.\n   */\n  constructor(algoName, numberOfData) {\n    // initialise the asynch decoder (if possible)\n    if (typeof decoderScripts !== 'undefined' &&\n      typeof decoderScripts[algoName] !== 'undefined') {\n      this.#pixelDecoder = new AsynchPixelBufferDecoder(\n        decoderScripts[algoName], numberOfData);\n    } else {\n      this.#pixelDecoder = new SynchPixelBufferDecoder(\n        algoName, numberOfData);\n    }\n  }\n\n  /**\n   * Get data from an input buffer using a DICOM parser.\n   *\n   * @param {Array} pixelBuffer The input data buffer.\n   * @param {object} pixelMeta The input meta data.\n   * @param {object} info Information object about the input data.\n   */\n  decode(pixelBuffer, pixelMeta, info) {\n    if (!this.#areCallbacksSet) {\n      this.#areCallbacksSet = true;\n      // set callbacks\n      this.#pixelDecoder.ondecodestart = this.ondecodestart;\n      this.#pixelDecoder.ondecodeditem = this.ondecodeditem;\n      this.#pixelDecoder.ondecoded = this.ondecoded;\n      this.#pixelDecoder.ondecodeend = this.ondecodeend;\n      this.#pixelDecoder.onerror = this.onerror;\n      this.#pixelDecoder.onabort = this.onabort;\n    }\n    // decode and call the callback\n    this.#pixelDecoder.decode(pixelBuffer, pixelMeta, info);\n  }\n\n  /**\n   * Abort decoding.\n   */\n  abort() {\n    // decoder classes should define an abort\n    this.#pixelDecoder.abort();\n  }\n\n  /**\n   * Handle a decode start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode start event.\n   */\n  ondecodestart(_event) {}\n\n  /**\n   * Handle a decode item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode item event fired\n   *   when a decode item ended successfully.\n   */\n  ondecodeditem(_event) {}\n\n  /**\n   * Handle a decode event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode event fired\n   *   when a file has been decoded successfully.\n   */\n  ondecoded(_event) {}\n\n  /**\n   * Handle a decode end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode end event fired\n   *  when a file decoding has completed, successfully or not.\n   */\n  ondecodeend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class PixelBufferDecoder\n","import {\n  getCode,\n  getDicomCodeItem\n} from './dicomCode';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\nimport {DicomCode} from './dicomCode';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  NumericValue: '0040A30A',\n  FloatingPointValue: '0040A161',\n  RationalNumeratorValue: '0040A162',\n  RationalDenominatorValue: '0040A163',\n  MeasurementUnitsCodeSequence: '004008EA'\n};\n\n/**\n * DICOM measured value: property of a numeric measurement.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.18.html#table_C.18.1-1}.\n */\nexport class MeasuredValue {\n  /**\n   * @type {number}\n   */\n  numericValue;\n\n  /**\n   * @type {number}\n   */\n  floatingPointValue;\n\n  /**\n   * @type {number}\n   */\n  rationalNumeratorValue;\n\n  /**\n   * @type {number}\n   */\n  rationalDenominatorValue;\n\n  /**\n   * @type {DicomCode}\n   */\n  measurementUnitsCode;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    return this.numericValue + ' ' +\n      this.measurementUnitsCode.toString();\n  };\n\n};\n\n/**\n * Get a measured value object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {MeasuredValue} A measured value object.\n */\nexport function getMeasuredValue(dataElements) {\n  const value = new MeasuredValue();\n\n  if (typeof dataElements[TagKeys.NumericValue] !== 'undefined') {\n    value.numericValue = dataElements[TagKeys.NumericValue].value[0];\n  }\n  if (typeof dataElements[TagKeys.FloatingPointValue] !== 'undefined') {\n    value.floatingPointValue =\n      dataElements[TagKeys.FloatingPointValue].value[0];\n  }\n  if (typeof dataElements[TagKeys.RationalNumeratorValue] !== 'undefined') {\n    value.rationalNumeratorValue =\n      dataElements[TagKeys.RationalNumeratorValue].value[0];\n  }\n  if (typeof dataElements[TagKeys.RationalDenominatorValue] !== 'undefined') {\n    value.rationalDenominatorValue =\n      dataElements[TagKeys.RationalDenominatorValue].value[0];\n  }\n  if (typeof dataElements[TagKeys.MeasurementUnitsCodeSequence] !==\n    'undefined') {\n    value.measurementUnitsCode = getCode(\n      dataElements[TagKeys.MeasurementUnitsCodeSequence].value[0]);\n  }\n\n  return value;\n};\n\n/**\n * Get a simple dicom element item from a measured value object.\n *\n * @param {MeasuredValue} value The measured value object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomMeasuredValueItem(value) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof value.measurementUnitsCode !== 'undefined') {\n    item.MeasurementUnitsCodeSequence = {\n      value: [getDicomCodeItem(value.measurementUnitsCode)]\n    };\n  }\n  if (typeof value.floatingPointValue !== 'undefined') {\n    item.FloatingPointValue = value.floatingPointValue;\n  }\n  if (typeof value.rationalNumeratorValue !== 'undefined') {\n    item.RationalNumeratorValue = value.rationalNumeratorValue;\n  }\n  if (typeof value.rationalDenominatorValue !== 'undefined') {\n    item.RationalDenominatorValue = value.rationalDenominatorValue;\n  }\n  if (typeof value.numericValue !== 'undefined') {\n    item.NumericValue = value.numericValue;\n  }\n\n  // return\n  return item;\n}\n","import {\n  getCode,\n  getDicomCodeItem\n} from './dicomCode';\nimport {\n  getMeasuredValue,\n  getDicomMeasuredValueItem\n} from './dicomMeasuredValue';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\nimport {MeasuredValue} from './dicomMeasuredValue';\nimport {DicomCode} from './dicomCode';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  MeasuredValueSequence: '0040A300',\n  NumericValueQualifierCodeSequence: '0040A301'\n};\n\n/**\n * DICOM numeric measurement: item of a SR content sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.18.html#table_C.18.1-1}.\n */\nexport class NumericMeasurement {\n  /**\n   * @type {MeasuredValue}\n   */\n  measuredValue;\n\n  /**\n   * @type {DicomCode}\n   */\n  numericValueQualifierCode;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    let res = this.measuredValue.toString();\n    if (typeof this.numericValueQualifierCode !== 'undefined') {\n      res += ' ' + this.numericValueQualifierCode.toString();\n    }\n    return res;\n  }\n};\n\n/**\n * Get a measurement object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {NumericMeasurement} A measurement object.\n */\nexport function getNumericMeasurement(dataElements) {\n  const measurement = new NumericMeasurement();\n\n  if (typeof dataElements[TagKeys.MeasuredValueSequence] !== 'undefined') {\n    measurement.measuredValue = getMeasuredValue(\n      dataElements[TagKeys.MeasuredValueSequence].value[0]);\n  }\n  if (typeof dataElements[TagKeys.NumericValueQualifierCodeSequence] !==\n    'undefined') {\n    measurement.numericValueQualifierCode = getCode(\n      dataElements[TagKeys.NumericValueQualifierCodeSequence].value[0]);\n  }\n\n  return measurement;\n};\n\n/**\n * Get a simple dicom element item from a measurement object.\n *\n * @param {NumericMeasurement} measurement The measurement object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomNumericMeasurementItem(measurement) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof measurement.measuredValue !== 'undefined') {\n    item.MeasuredValueSequence = {\n      value: [getDicomMeasuredValueItem(measurement.measuredValue)]\n    };\n  }\n  if (typeof measurement.numericValueQualifierCode !== 'undefined') {\n    item.NumericValueQualifierCodeSequence = {\n      value: [getDicomCodeItem(measurement.numericValueQualifierCode)]\n    };\n  }\n\n  // return\n  return item;\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  ReferencedSOPClassUID: '00081150',\n  ReferencedSOPInstanceUID: '00081155'\n};\n\n/**\n * DICOM sop instance reference.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_10.8.html#table_10-11}.\n */\nexport class SopInstanceReference {\n  /**\n   * @type {string}\n   */\n  referencedSOPClassUID;\n\n  /**\n   * @type {string}\n   */\n  referencedSOPInstanceUID;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    return this.referencedSOPInstanceUID + ' (class: ' +\n      this.referencedSOPClassUID + ')';\n  };\n};\n\n/**\n * Get a SOP reference object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {SopInstanceReference} A SOP reference object.\n */\nexport function getSopInstanceReference(dataElements) {\n  const ref = new SopInstanceReference();\n\n  if (typeof dataElements[TagKeys.ReferencedSOPClassUID] !== 'undefined') {\n    ref.referencedSOPClassUID =\n      dataElements[TagKeys.ReferencedSOPClassUID].value[0];\n  }\n  if (typeof dataElements[TagKeys.ReferencedSOPInstanceUID] !== 'undefined') {\n    ref.referencedSOPInstanceUID =\n      dataElements[TagKeys.ReferencedSOPInstanceUID].value[0];\n  }\n\n  return ref;\n};\n\n/**\n * Get a simple dicom element item from a SOP reference object.\n *\n * @param {SopInstanceReference} ref The SOP reference object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSopInstanceReferenceItem(ref) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof ref.referencedSOPClassUID !== 'undefined') {\n    item.ReferencedSOPClassUID = ref.referencedSOPClassUID;\n  }\n  if (typeof ref.referencedSOPInstanceUID !== 'undefined') {\n    item.ReferencedSOPInstanceUID = ref.referencedSOPInstanceUID;\n  }\n\n  // return\n  return item;\n}\n","import {\n  getSopInstanceReference,\n  getDicomSopInstanceReferenceItem\n} from './dicomSopInstanceReference';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  ReferencedFrameNumber: '00081160',\n  ReferencedSOPSequence: '00081199',\n  ReferencedSegmentNumber: '0062000B'\n};\n\n/**\n * DICOM image reference: item of a SR content sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.18.4.html#table_C.18.4-1}.\n */\nexport class ImageReference {\n  /**\n   * @type {object}\n   */\n  referencedSOPSequence;\n\n  /**\n   * @type {object}\n   */\n  referencedFrameNumber;\n\n  /**\n   * @type {string}\n   */\n  referencedSegmentNumber;\n\n  /**\n   * @type {string}\n   */\n  fiducialUID;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    return this.referencedSOPSequence.toString();\n  };\n};\n\n/**\n * Get a reference object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {ImageReference} A reference object.\n */\nexport function getImageReference(dataElements) {\n  const ref = new ImageReference();\n\n  if (typeof dataElements[TagKeys.ReferencedFrameNumber] !== 'undefined') {\n    ref.referencedFrameNumber =\n      dataElements[TagKeys.ReferencedFrameNumber].value[0];\n  }\n  if (typeof dataElements[TagKeys.ReferencedSOPSequence] !== 'undefined') {\n    ref.referencedSOPSequence = getSopInstanceReference(\n      dataElements[TagKeys.ReferencedSOPSequence].value[0]);\n  }\n  if (typeof dataElements[TagKeys.ReferencedSegmentNumber] !== 'undefined') {\n    ref.referencedSegmentNumber =\n      dataElements[TagKeys.ReferencedSegmentNumber].value[0];\n  }\n\n  return ref;\n};\n\n/**\n * Get a simple dicom element item from a reference object.\n *\n * @param {ImageReference} ref The reference object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomImageReferenceItem(ref) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof ref.referencedFrameNumber !== 'undefined') {\n    item.ReferencedFrameNumber = ref.referencedFrameNumber;\n  }\n  if (typeof ref.referencedSOPSequence !== 'undefined') {\n    item.ReferencedSOPSequence = {\n      value: [getDicomSopInstanceReferenceItem(ref.referencedSOPSequence)]\n    };\n  }\n  if (typeof ref.referencedSegmentNumber !== 'undefined') {\n    item.ReferencedSegmentNumber =\n      ref.referencedSegmentNumber;\n  }\n\n  // return\n  return item;\n}\n","import {Point2D} from '../math/point';\nimport {Line, areOrthogonal} from '../math/line';\nimport {Protractor} from '../math/protractor';\nimport {ROI} from '../math/roi';\nimport {Circle} from '../math/circle';\nimport {Ellipse} from '../math/ellipse';\nimport {Rectangle} from '../math/rectangle';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  PixelOriginInterpretation: '00480301',\n  GraphicData: '00700022',\n  GraphicType: '00700023',\n  FiducialUID: '0070031A'\n};\n\n/**\n * DICOM graphic types.\n */\nexport const GraphicTypes = {\n  point: 'POINT',\n  multipoint: 'MULTIPOINT',\n  polyline: 'POLYLINE',\n  circle: 'CIRCLE',\n  ellipse: 'ELLIPSE'\n};\n\n/**\n * DICOM spatial coordinate (SCOORD): item of a SR content sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.18.6.html#table_C.18.6-1}.\n */\nexport class SpatialCoordinate {\n  /**\n   * @type {string[]}\n   */\n  graphicData;\n\n  /**\n   * @type {string}\n   */\n  graphicType;\n\n  /**\n   * @type {string}\n   */\n  pixelOriginInterpretation;\n\n  /**\n   * @type {string}\n   */\n  fiducialUID;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    return this.graphicType +\n      ' {' + this.graphicData + '}';\n  };\n};\n\n/**\n * Get a scoord object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {SpatialCoordinate} A scoord object.\n */\nexport function getSpatialCoordinate(dataElements) {\n  const scoord = new SpatialCoordinate();\n\n  if (typeof dataElements[TagKeys.GraphicData] !== 'undefined') {\n    scoord.graphicData = dataElements[TagKeys.GraphicData].value;\n  }\n  if (typeof dataElements[TagKeys.GraphicType] !== 'undefined') {\n    scoord.graphicType = dataElements[TagKeys.GraphicType].value[0];\n  }\n  if (typeof dataElements[TagKeys.PixelOriginInterpretation] !== 'undefined') {\n    scoord.pixelOriginInterpretation =\n      dataElements[TagKeys.PixelOriginInterpretation].value[0];\n  }\n  if (typeof dataElements[TagKeys.FiducialUID] !== 'undefined') {\n    scoord.fiducialUID = dataElements[TagKeys.FiducialUID].value[0];\n  }\n  return scoord;\n};\n\n/**\n * Get a simple dicom element item from a scoord object.\n *\n * @param {SpatialCoordinate} scoord The scoord object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSpatialCoordinateItem(scoord) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof scoord.pixelOriginInterpretation !== 'undefined') {\n    item.PixelOriginInterpretation = scoord.pixelOriginInterpretation;\n  }\n  if (typeof scoord.graphicData !== 'undefined') {\n    item.GraphicData = scoord.graphicData;\n  }\n  if (typeof scoord.graphicType !== 'undefined') {\n    item.GraphicType = scoord.graphicType;\n  }\n  if (typeof scoord.fiducialUID !== 'undefined') {\n    item.FiducialUID = scoord.fiducialUID;\n  }\n\n  // return\n  return item;\n}\n\n/**\n * Get a DICOM spatial coordinate (SCOORD) from a mathematical shape.\n *\n * @param {Point2D|Line|Protractor|ROI|Circle|Ellipse|Rectangle} shape\n *   The math shape.\n * @returns {SpatialCoordinate} The DICOM scoord.\n */\nexport function getScoordFromShape(shape) {\n  const scoord = new SpatialCoordinate();\n\n  if (shape instanceof Point2D) {\n    scoord.graphicData = [\n      shape.getX().toString(),\n      shape.getY().toString(),\n    ];\n    scoord.graphicType = GraphicTypes.point;\n  } else if (shape instanceof Line) {\n    scoord.graphicData = [\n      shape.getBegin().getX().toString(),\n      shape.getBegin().getY().toString(),\n      shape.getEnd().getX().toString(),\n      shape.getEnd().getY().toString(),\n    ];\n    scoord.graphicType = GraphicTypes.polyline;\n  } else if (shape instanceof Protractor) {\n    scoord.graphicData = [];\n    for (let i = 0; i < 3; ++i) {\n      scoord.graphicData.push(shape.getPoint(i).getX().toString());\n      scoord.graphicData.push(shape.getPoint(i).getY().toString());\n    }\n    scoord.graphicType = GraphicTypes.polyline;\n  } else if (shape instanceof ROI) {\n    scoord.graphicData = [];\n    for (let i = 0; i < shape.getLength(); ++i) {\n      scoord.graphicData.push(shape.getPoint(i).getX().toString());\n      scoord.graphicData.push(shape.getPoint(i).getY().toString());\n    }\n    // repeat first point to close shape\n    const firstPoint = shape.getPoint(0);\n    scoord.graphicData.push(firstPoint.getX().toString());\n    scoord.graphicData.push(firstPoint.getY().toString());\n\n    scoord.graphicType = GraphicTypes.polyline;\n  } else if (shape instanceof Circle) {\n    const center = shape.getCenter();\n    const pointPerimeter = new Point2D(\n      center.getX() + shape.getRadius(), center.getY()\n    );\n    scoord.graphicData = [\n      center.getX().toString(),\n      center.getY().toString(),\n      pointPerimeter.getX().toString(),\n      pointPerimeter.getY().toString(),\n    ];\n    scoord.graphicType = GraphicTypes.circle;\n  } else if (shape instanceof Ellipse) {\n    const center = shape.getCenter();\n    const radiusX = shape.getA();\n    const radiusY = shape.getB();\n    scoord.graphicData = [\n      (center.getX() - radiusX).toString(),\n      center.getY().toString(),\n      (center.getX() + radiusX).toString(),\n      center.getY().toString(),\n      center.getX().toString(),\n      (center.getY() - radiusY).toString(),\n      center.getX().toString(),\n      (center.getY() + radiusY).toString()\n    ];\n    scoord.graphicType = GraphicTypes.ellipse;\n  } else if (shape instanceof Rectangle) {\n    const begin = shape.getBegin();\n    const end = shape.getEnd();\n    // begin as first and last point to close shape\n    scoord.graphicData = [\n      begin.getX().toString(),\n      begin.getY().toString(),\n      begin.getX().toString(),\n      end.getY().toString(),\n      end.getX().toString(),\n      end.getY().toString(),\n      end.getX().toString(),\n      begin.getY().toString(),\n      begin.getX().toString(),\n      begin.getY().toString()\n    ];\n    scoord.graphicType = GraphicTypes.polyline;\n  }\n\n  return scoord;\n};\n\n/**\n * Get a mathematical shape from a DICOM spatial coordinate (SCOORD).\n *\n * @param {SpatialCoordinate} scoord The DICOM scoord.\n * @returns {Point2D|Line|Protractor|ROI|Circle|Ellipse|Rectangle}\n *   The math shape.\n */\nexport function getShapeFromScoord(scoord) {\n  // extract points\n  const dataLength = scoord.graphicData.length;\n  if (dataLength % 2 !== 0) {\n    throw new Error('Expecting even number of coordinates in scroord data');\n  }\n  const points = [];\n  for (let i = 0; i < dataLength; i += 2) {\n    points.push(new Point2D(\n      parseFloat(scoord.graphicData[i]),\n      parseFloat(scoord.graphicData[i + 1])\n    ));\n  }\n  let isClosed = false;\n  const numberOfPoints = points.length;\n  if (numberOfPoints > 2) {\n    const firstPoint = points[0];\n    const lastPoint = points[numberOfPoints - 1];\n    isClosed = firstPoint.equals(lastPoint);\n  }\n\n  // create math shape\n  let shape;\n  if (scoord.graphicType === GraphicTypes.point) {\n    if (points.length !== 1) {\n      throw new Error('Expecting 1 point for point');\n    }\n    shape = points[0];\n  } else if (scoord.graphicType === GraphicTypes.circle) {\n    if (points.length !== 2) {\n      throw new Error('Expecting 2 points for circles');\n    }\n    const center = points[0];\n    const pointPerimeter = points[1];\n    const radius = pointPerimeter.getDistance(center);\n    shape = new Circle(center, radius);\n  } else if (scoord.graphicType === GraphicTypes.ellipse) {\n    if (points.length !== 4) {\n      throw new Error('Expecting 4 points for ellipses');\n    }\n    // TODO: make more generic\n    const radiusX = points[0].getDistance(points[1]) / 2;\n    const radiusY = points[2].getDistance(points[3]) / 2;\n    const center = new Point2D(\n      points[0].getX() + radiusX,\n      points[0].getY()\n    );\n    shape = new Ellipse(center, radiusX, radiusY);\n  } else if (scoord.graphicType === GraphicTypes.polyline) {\n    if (!isClosed) {\n      if (points.length === 2) {\n        shape = new Line(points[0], points[1]);\n      } else if (points.length === 3) {\n        shape = new Protractor([points[0], points[1], points[2]]);\n      }\n    } else {\n      if (points.length === 5) {\n        const line0 = new Line(points[0], points[1]);\n        const line1 = new Line(points[1], points[2]);\n        const line2 = new Line(points[2], points[3]);\n        const line3 = new Line(points[3], points[4]);\n        if (areOrthogonal(line0, line1) &&\n          areOrthogonal(line1, line2) &&\n          areOrthogonal(line2, line3)) {\n          shape = new Rectangle(points[0], points[2]);\n        } else {\n          // remove last=first point for closed shape\n          shape = new ROI(points.slice(0, -1));\n        }\n      } else {\n        // remove last=first point for closed shape\n        shape = new ROI(points.slice(0, -1));\n      }\n    }\n  }\n\n  return shape;\n};","// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  GraphicData: '00700022',\n  GraphicType: '00700023',\n  ReferencedFrameofReferenceUID: '30060024',\n  FiducialUID: '0070031A'\n};\n\n/**\n * DICOM spatial coordinate 3D (SCOORD3D): item of a SR content sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.18.9.html#table_C.18.9-1}.\n */\nexport class SpatialCoordinate3D {\n  /**\n   * @type {string[]}\n   */\n  graphicData;\n\n  /**\n   * @type {string}\n   */\n  graphicType;\n\n  /**\n   * @type {string}\n   */\n  referencedFrameofReferenceUID;\n\n  /**\n   * @type {string}\n   */\n  fiducialUID;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    return this.graphicType +\n      '{' + this.graphicData + '}';\n  };\n};\n\n/**\n * Get a scoord3d object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {SpatialCoordinate3D} A scoord3d object.\n */\nexport function getSpatialCoordinate3D(dataElements) {\n  const scoord = new SpatialCoordinate3D();\n\n  if (typeof dataElements[TagKeys.GraphicData] !== 'undefined') {\n    scoord.graphicData = dataElements[TagKeys.GraphicData].value;\n  }\n  if (typeof dataElements[TagKeys.GraphicType] !== 'undefined') {\n    scoord.graphicType = dataElements[TagKeys.GraphicType].value[0];\n  }\n  if (typeof dataElements[TagKeys.ReferencedFrameofReferenceUID] !==\n    'undefined') {\n    scoord.referencedFrameofReferenceUID =\n      dataElements[TagKeys.ReferencedFrameofReferenceUID].value[0];\n  }\n  if (typeof dataElements[TagKeys.FiducialUID] !== 'undefined') {\n    scoord.fiducialUID = dataElements[TagKeys.FiducialUID].value[0];\n  }\n  return scoord;\n};\n\n/**\n * Get a simple dicom element item from a scoord3d object.\n *\n * @param {SpatialCoordinate3D} scoord The scoord3d object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSpatialCoordinate3DItem(scoord) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof scoord.graphicData !== 'undefined') {\n    item.GraphicData = scoord.graphicData;\n  }\n  if (typeof scoord.graphicType !== 'undefined') {\n    item.GraphicType = scoord.graphicType;\n  }\n  if (typeof scoord.referencedFrameofReferenceUID !== 'undefined') {\n    item.ReferencedFrameofReferenceUID =\n      scoord.referencedFrameofReferenceUID;\n  }\n  if (typeof scoord.fiducialUID !== 'undefined') {\n    item.FiducialUID = scoord.fiducialUID;\n  }\n\n  // return\n  return item;\n}","import {\n  NumericMeasurement,\n  getNumericMeasurement,\n  getDicomNumericMeasurementItem\n} from './dicomNumericMeasurement';\nimport {\n  getCode,\n  getDicomCodeItem,\n  getConceptNameCode,\n  getMeasurementUnitsCode\n} from './dicomCode';\nimport {\n  getImageReference,\n  getDicomImageReferenceItem\n} from './dicomImageReference';\nimport {\n  getSopInstanceReference,\n  getDicomSopInstanceReferenceItem\n} from './dicomSopInstanceReference';\nimport {\n  getSpatialCoordinate,\n  getDicomSpatialCoordinateItem\n} from './dicomSpatialCoordinate';\nimport {\n  getSpatialCoordinate3D,\n  getDicomSpatialCoordinate3DItem\n} from './dicomSpatialCoordinate3D';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\nimport {DicomCode} from './dicomCode';\nimport {MeasuredValue} from './dicomMeasuredValue';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  ReferencedSOPSequence: '00081199',\n  RelationshipType: '0040A010',\n  ValueType: '0040A040',\n  ConceptNameCodeSequence: '0040A043',\n  ConceptCodeSequence: '0040A168',\n  ContentSequence: '0040A730',\n  DateTime: '0040A120',\n  Date: '0040A121',\n  Time: '0040A122',\n  UID: '0040A124',\n  PersonName: '0040A123',\n  TextValue: '0040A160',\n  ContinuityOfContent: '0040A050'\n};\n\n/**\n * DICOM relationship types.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.17.3.2.4.html#sect_C.17.3.2.4}.\n */\nexport const RelationshipTypes = {\n  contains: 'CONTAINS',\n  hasProperties: 'HAS PROPERTIES',\n  hasObsContext: 'HAS OBS CONTEXT',\n  hasAcqContext: 'HAS ACQ CONTEXT',\n  inferredFrom: 'INFERRED FROM',\n  selectedFrom: 'SELECTED FROM',\n  hasConceptMod: 'HAS CONCEPT MOD'\n};\n\n/**\n * DICOM value types.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.17.3.2.html#sect_C.17.3.2.1}.\n */\nexport const ValueTypes = {\n  text: 'TEXT',\n  num: 'NUM',\n  code: 'CODE',\n  date: 'DATE',\n  time: 'TIME',\n  datetime: 'DATETIME',\n  uidref: 'UIDREF',\n  pname: 'PNAME',\n  composite: 'COMPOSITE',\n  image: 'IMAGE',\n  waveform: 'WAVEFORM',\n  scoord: 'SCOORD',\n  scoord3d: 'SCOORD3D',\n  tcoord: 'TCOORD',\n  container: 'CONTAINER',\n  table: 'TABLE',\n};\n\n/**\n * DICOM value type to associated tag name.\n */\nexport const ValueTypeValueTagName = {\n  TEXT: 'TextValue',\n  DATE: 'Date',\n  TIME: 'Time',\n  DATETIME: 'DateTime',\n  UIDREF: 'UID',\n  PNAME: 'PersonName',\n  CONTAINER: 'ContinuityOfContent',\n};\n\n/**\n * DICOM SR content: item of a SR content sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.17.3.html}.\n */\nexport class DicomSRContent {\n  /**\n   * Value type.\n   *\n   * @type {string}\n   */\n  valueType;\n  /**\n   * Concept name code.\n   *\n   * @type {DicomCode|undefined}\n   */\n  conceptNameCode;\n  /**\n   * Relationship Type.\n   *\n   * @type {string}\n   */\n  relationshipType;\n\n  /**\n   * Content sequence (0040,A730).\n   *\n   * @type {DicomSRContent[]|undefined}\n   */\n  contentSequence;\n\n  /**\n   * Value.\n   *\n   * @type {object}\n   */\n  value;\n\n  /**\n   * @param {string} valueType The content item value type.\n   */\n  constructor(valueType) {\n    this.valueType = valueType;\n  }\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @param {string} [prefix] An optional prefix for recursive content.\n   * @returns {string} The object as string.\n   */\n  toString(prefix) {\n    if (typeof prefix === 'undefined') {\n      prefix = '';\n    }\n\n    let res = '';\n\n    if (typeof this.relationshipType !== 'undefined') {\n      res += '(' + this.relationshipType + ') ';\n    }\n\n    res += this.valueType + ': ';\n\n    if (typeof this.conceptNameCode !== 'undefined') {\n      res += this.conceptNameCode.toString();\n    }\n\n    res += ' = ' + this.value.toString();\n\n    if (typeof this.contentSequence !== 'undefined') {\n      for (const item of this.contentSequence) {\n        res += '\\n' + prefix + '- ' + item.toString(prefix + '  ');\n      }\n    }\n\n    return res;\n  }\n}\n\n/**\n * Check if two content item objects are equal.\n *\n * @param {DicomCode} item1 The first content item.\n * @param {DicomCode} item2 The second content item.\n * @returns {boolean} True if both content items are equal.\n */\nexport function isEqualContentItem(item1, item2) {\n  return Object.keys(item1).length === Object.keys(item2).length &&\n  Object.keys(item1).every(key =>\n    Object.prototype.hasOwnProperty.call(item2, key) &&\n    item1[key] === item2[key]\n  );\n}\n\n/**\n * Get a content item object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {DicomSRContent} A content item object.\n */\nexport function getSRContent(dataElements) {\n  // valueType -> ValueType (type1)\n  let valueType = '';\n  if (typeof dataElements[TagKeys.ValueType] !== 'undefined') {\n    valueType = dataElements[TagKeys.ValueType].value[0];\n  }\n\n  const content = new DicomSRContent(valueType);\n\n  // relationshipType -> RelationType (type1)\n  if (typeof dataElements[TagKeys.RelationshipType] !== 'undefined') {\n    content.relationshipType =\n      dataElements[TagKeys.RelationshipType].value[0];\n  }\n\n  if (typeof dataElements[TagKeys.ConceptNameCodeSequence] !== 'undefined') {\n    content.conceptNameCode =\n      getCode(dataElements[TagKeys.ConceptNameCodeSequence].value[0]);\n  }\n\n  // set value acording to valueType\n  // (date and time are stored as string)\n  if (valueType === ValueTypes.code) {\n    content.value = getCode(\n      dataElements[TagKeys.ConceptCodeSequence].value[0]);\n  } else if (valueType === ValueTypes.num) {\n    content.value = getNumericMeasurement(dataElements);\n  } else if (valueType === ValueTypes.image) {\n    content.value = getImageReference(dataElements);\n  } else if (valueType === ValueTypes.composite) {\n    content.value = getSopInstanceReference(\n      dataElements[TagKeys.ReferencedSOPSequence].value[0]\n    );\n  } else if (valueType === ValueTypes.scoord) {\n    content.value = getSpatialCoordinate(dataElements);\n  } else if (valueType === ValueTypes.scoord3d) {\n    content.value = getSpatialCoordinate3D(dataElements);\n  } else {\n    const valueTagName = ValueTypeValueTagName[valueType];\n    if (typeof valueTagName !== 'undefined') {\n      content.value = dataElements[TagKeys[valueTagName]].value[0];\n    } else {\n      console.warn('Unsupported input ValueType: ' + valueType);\n    }\n  }\n\n  const contentSqEl = dataElements[TagKeys.ContentSequence];\n  if (typeof contentSqEl !== 'undefined') {\n    content.contentSequence = [];\n    for (const item of dataElements[TagKeys.ContentSequence].value) {\n      content.contentSequence.push(getSRContent(item));\n    }\n  }\n\n  return content;\n}\n\n/**\n * Get a simple dicom element item from a content item object.\n *\n * @param {DicomSRContent} content The content item object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSRContentItem(content) {\n  // dicom item (tags are in ~group/element order)\n  let contentItem = {};\n\n  if (typeof content.relationshipType !== 'undefined') {\n    contentItem.RelationshipType = content.relationshipType;\n  }\n  if (typeof content.valueType !== 'undefined') {\n    contentItem.ValueType = content.valueType;\n  }\n  if (typeof content.conceptNameCode !== 'undefined') {\n    contentItem.ConceptNameCodeSequence = {\n      value: [getDicomCodeItem(content.conceptNameCode)]\n    };\n  }\n\n  // set appropriate value tag (data and time are stored as string)\n  if (content.valueType === 'CODE') {\n    contentItem.ConceptCodeSequence = {\n      value: [getDicomCodeItem(content.value)]\n    };\n  } else if (content.valueType === ValueTypes.num) {\n    contentItem = {\n      ...contentItem,\n      ...getDicomNumericMeasurementItem(content.value)\n    };\n  } else if (content.valueType === ValueTypes.image) {\n    contentItem = {\n      ...contentItem,\n      ...getDicomImageReferenceItem(content.value)\n    };\n  } else if (content.valueType === ValueTypes.composite) {\n    contentItem = {\n      ...contentItem,\n      ...getDicomSopInstanceReferenceItem(content.value)\n    };\n  } else if (content.valueType === ValueTypes.scoord) {\n    contentItem = {\n      ...contentItem,\n      ...getDicomSpatialCoordinateItem(content.value)\n    };\n  } else if (content.valueType === ValueTypes.scoord3d) {\n    contentItem = {\n      ...contentItem,\n      ...getDicomSpatialCoordinate3DItem(content.value)\n    };\n  } else {\n    const valueTagName = ValueTypeValueTagName[content.valueType];\n    if (typeof valueTagName !== 'undefined') {\n      contentItem[valueTagName] = content.value;\n    } else {\n      console.warn('Unsupported output ValueType: ' + content.valueType);\n    }\n  }\n\n  if (typeof content.contentSequence !== 'undefined') {\n    contentItem.ContentSequence = {\n      value: []\n    };\n    for (const item of content.contentSequence) {\n      contentItem.ContentSequence.value.push(getDicomSRContentItem(item));\n    }\n  }\n\n  return contentItem;\n}\n\n/**\n * Get a DicomSRContent from a value.\n *\n * @param {string} name The value name.\n * @param {object} value The value.\n * @param {string} unit The values' unit.\n * @returns {DicomSRContent|undefined} The SR content.\n */\nexport function getSRContentFromValue(name, value, unit) {\n  const conceptNameCode = getConceptNameCode(name);\n\n  if (typeof conceptNameCode === 'undefined') {\n    return undefined;\n  }\n\n  const content = new DicomSRContent(ValueTypes.num);\n  content.relationshipType = RelationshipTypes.contains;\n  content.conceptNameCode = conceptNameCode;\n\n  const measure = new MeasuredValue();\n  measure.numericValue = value;\n  measure.measurementUnitsCode = getMeasurementUnitsCode(unit);\n  const numMeasure = new NumericMeasurement();\n  numMeasure.measuredValue = measure;\n\n  content.value = numMeasure;\n\n  return content;\n}","import {\n  dateToDateObj,\n  getDicomDate,\n  dateToTimeObj,\n  getDicomTime,\n} from '../dicom/dicomDate';\nimport {safeGet} from '../dicom/dataElement';\nimport {\n  ValueTypes,\n  RelationshipTypes,\n  getSRContent,\n  getDicomSRContentItem,\n  DicomSRContent,\n  getSRContentFromValue\n} from '../dicom/dicomSRContent';\nimport {\n  isEqualCode,\n  getPathCode,\n  getMeasurementGroupCode,\n  getImageRegionCode,\n  getReferenceGeometryCode,\n  getSourceImageCode,\n  getTrackingIdentifierCode,\n  getShortLabelCode,\n  getReferencePointsCode,\n  getColourCode,\n  getQuantificationName,\n  getQuantificationUnit\n} from '../dicom/dicomCode';\nimport {getElementsFromJSONTags} from '../dicom/dicomWriter';\nimport {ImageReference} from '../dicom/dicomImageReference';\nimport {SopInstanceReference} from '../dicom/dicomSopInstanceReference';\nimport {\n  GraphicTypes,\n  getScoordFromShape,\n  getShapeFromScoord,\n  SpatialCoordinate\n} from '../dicom/dicomSpatialCoordinate';\nimport {SpatialCoordinate3D} from '../dicom/dicomSpatialCoordinate3D';\nimport {guid} from '../math/stats';\nimport {logger} from '../utils/logger';\nimport {Annotation} from './annotation';\nimport {AnnotationGroup} from './annotationGroup';\nimport {Line} from '../math/line';\nimport {Point2D, Point3D} from '../math/point';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from '../dicom/dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * Merge two tag lists.\n *\n * @param {object} tags1 Base list, will be modified.\n * @param {object} tags2 List to merge.\n */\nfunction mergeTags(tags1, tags2) {\n  const keys2 = Object.keys(tags2);\n  for (const tagName2 of keys2) {\n    if (tags1[tagName2] !== undefined) {\n      logger.trace('Overwritting tag: ' + tagName2);\n    }\n    tags1[tagName2] = tags2[tagName2];\n  }\n}\n\n/**\n * {@link AnnotationGroup} factory.\n */\nexport class AnnotationGroupFactory {\n\n  /**\n   * Possible warning created by checkElements.\n   *\n   * @type {string|undefined}\n   */\n  #warning;\n\n  /**\n   * Get a warning string if elements are not as expected.\n   * Created by checkElements.\n   *\n   * @returns {string|undefined} The warning.\n   */\n  getWarning() {\n    return this.#warning;\n  }\n\n  /**\n   * Check dicom elements.\n   *\n   * @param {Object<string, DataElement>} dataElements The DICOM data elements.\n   * @returns {string|undefined} A possible warning.\n   * @throws Error for missing or wrong data.\n   */\n  checkElements(dataElements) {\n    // reset\n    this.#warning = undefined;\n\n    const srContent = getSRContent(dataElements);\n    if (typeof srContent.conceptNameCode !== 'undefined') {\n      if (srContent.conceptNameCode.value !== getMeasurementGroupCode().value) {\n        this.#warning = 'Not a measurement group';\n      }\n    } else {\n      this.#warning = 'No root concept name code';\n    }\n\n    return this.#warning;\n  }\n\n  /**\n   * Convert a DICOM SR content of type SCOORD into an annotation.\n   *\n   * @param {DicomSRContent} item The input SCOORD.\n   * @returns {Annotation} The annotation.\n   */\n  #scoordToAnnotation(item) {\n    const annotation = new Annotation();\n    annotation.mathShape = getShapeFromScoord(item.value);\n    // default\n    annotation.id = guid();\n    annotation.textExpr = '';\n\n    for (const subItem of item.contentSequence) {\n      // reference image UID\n      if (subItem.valueType === ValueTypes.image &&\n        subItem.relationshipType === RelationshipTypes.selectedFrom &&\n        isEqualCode(subItem.conceptNameCode, getSourceImageCode())) {\n        annotation.referenceSopUID =\n          subItem.value.referencedSOPSequence.referencedSOPInstanceUID;\n      }\n      // annotation id\n      if (subItem.valueType === ValueTypes.uidref &&\n        subItem.relationshipType === RelationshipTypes.hasProperties &&\n        isEqualCode(subItem.conceptNameCode, getTrackingIdentifierCode())) {\n        annotation.id = subItem.value;\n      }\n      // text expr\n      if (subItem.valueType === ValueTypes.text &&\n        subItem.relationshipType === RelationshipTypes.hasProperties &&\n        isEqualCode(subItem.conceptNameCode, getShortLabelCode())) {\n        annotation.textExpr = subItem.value;\n        if (typeof subItem.contentSequence !== 'undefined') {\n          for (const subsubItem of subItem.contentSequence) {\n            if (subsubItem.valueType === ValueTypes.scoord &&\n              subsubItem.relationshipType === RelationshipTypes.hasProperties &&\n              isEqualCode(\n                subsubItem.conceptNameCode, getReferencePointsCode())) {\n              annotation.labelPosition = new Point2D(\n                subsubItem.value.graphicData[0],\n                subsubItem.value.graphicData[1]\n              );\n            }\n          }\n        }\n      }\n      // color\n      if (subItem.valueType === ValueTypes.text &&\n        subItem.relationshipType === RelationshipTypes.hasProperties &&\n        isEqualCode(subItem.conceptNameCode, getColourCode())) {\n        annotation.colour = subItem.value;\n      }\n      // reference points\n      if (subItem.valueType === ValueTypes.scoord &&\n        subItem.relationshipType === RelationshipTypes.hasProperties &&\n        isEqualCode(subItem.conceptNameCode, getReferencePointsCode()) &&\n        subItem.value.graphicType === GraphicTypes.multipoint) {\n        const points = [];\n        for (let i = 0; i < subItem.value.graphicData.length; i += 2) {\n          points.push(new Point2D(\n            subItem.value.graphicData[i],\n            subItem.value.graphicData[i + 1]\n          ));\n        }\n        annotation.referencePoints = points;\n      }\n      // plane points\n      if (subItem.valueType === ValueTypes.scoord3d &&\n        subItem.relationshipType === RelationshipTypes.hasProperties &&\n        isEqualCode(\n          subItem.conceptNameCode, getReferenceGeometryCode()) &&\n        subItem.value.graphicType === GraphicTypes.multipoint) {\n        const data = subItem.value.graphicData;\n        const points = [];\n        const nPoints = Math.floor(data.length / 3);\n        for (let i = 0; i < nPoints; ++i) {\n          const j = i * 3;\n          points.push(new Point3D(data[j], data[j + 1], data[j + 2]));\n        }\n        annotation.planePoints = points;\n      }\n      // quantification\n      if (subItem.valueType === ValueTypes.num &&\n        subItem.relationshipType === RelationshipTypes.contains) {\n        const quantifName =\n          getQuantificationName(subItem.conceptNameCode);\n        if (typeof quantifName === 'undefined') {\n          continue;\n        }\n        const measuredValue = subItem.value.measuredValue;\n        const quantifUnit = getQuantificationUnit(\n          measuredValue.measurementUnitsCode);\n        if (typeof annotation.quantification === 'undefined') {\n          annotation.quantification = {};\n        }\n        annotation.quantification[quantifName] = {\n          value: measuredValue.numericValue,\n          unit: quantifUnit\n        };\n      }\n    }\n    return annotation;\n  }\n\n  /**\n   * Get an {@link Annotation} object from the read DICOM file.\n   *\n   * @param {Object<string, DataElement>} dataElements The DICOM tags.\n   * @returns {AnnotationGroup} A new annotation group.\n   * @throws Error for missing or wrong data.\n   */\n  create(dataElements) {\n    const annotations = [];\n    const srContent = getSRContent(dataElements);\n    for (const item of srContent.contentSequence) {\n      if (item.valueType === ValueTypes.scoord) {\n        annotations.push(this.#scoordToAnnotation(item));\n      }\n    }\n    const annotationGroup = new AnnotationGroup(annotations);\n\n    const safeGetLocal = function (key) {\n      return safeGet(dataElements, key);\n    };\n\n    // StudyInstanceUID\n    annotationGroup.setMetaValue('StudyInstanceUID', safeGetLocal('0020000D'));\n    // Modality\n    annotationGroup.setMetaValue('Modality', safeGetLocal('00080060'));\n    // patient info\n    annotationGroup.setMetaValue('PatientName', safeGetLocal('00100010'));\n    annotationGroup.setMetaValue('PatientID', safeGetLocal('00100020'));\n    annotationGroup.setMetaValue('PatientBirthDate', safeGetLocal('00100030'));\n    annotationGroup.setMetaValue('PatientSex', safeGetLocal('00100040'));\n\n    // ReferencedSeriesSequence\n    const element = dataElements['00081115'];\n    if (typeof element !== 'undefined') {\n      const seriesElement = element.value[0]['0020000E'];\n      if (typeof seriesElement !== 'undefined') {\n        annotationGroup.setMetaValue(\n          'ReferencedSeriesSequence', {\n            value: [{\n              SeriesInstanceUID: seriesElement.value[0]\n            }]\n          }\n        );\n      }\n    }\n\n    return annotationGroup;\n  }\n\n  /**\n   * Convert an annotation into a DICOM SCOORD.\n   *\n   * @param {Annotation} annotation The input annotation.\n   * @returns {DicomSRContent} An SR content of type SCOORD.\n   */\n  #annotationToScoord(annotation) {\n    const srScoord = new DicomSRContent(ValueTypes.scoord);\n    srScoord.relationshipType = RelationshipTypes.contains;\n    if (annotation.mathShape instanceof Line) {\n      srScoord.conceptNameCode = getPathCode();\n    } else {\n      srScoord.conceptNameCode = getImageRegionCode();\n    }\n    srScoord.value = getScoordFromShape(annotation.mathShape);\n\n    const itemContentSequence = [];\n\n    // reference image UID\n    const srImage = new DicomSRContent(ValueTypes.image);\n    srImage.relationshipType = RelationshipTypes.selectedFrom;\n    srImage.conceptNameCode = getSourceImageCode();\n    const sopRef = new SopInstanceReference();\n    sopRef.referencedSOPClassUID = '';\n    sopRef.referencedSOPInstanceUID = annotation.referenceSopUID;\n    const imageRef = new ImageReference();\n    imageRef.referencedSOPSequence = sopRef;\n    srImage.value = imageRef;\n    itemContentSequence.push(srImage);\n\n    // annotation id\n    const srUid = new DicomSRContent(ValueTypes.uidref);\n    srUid.relationshipType = RelationshipTypes.hasProperties;\n    srUid.conceptNameCode = getTrackingIdentifierCode();\n    srUid.value = annotation.id;\n    itemContentSequence.push(srUid);\n\n    // text expr\n    const shortLabel = new DicomSRContent(ValueTypes.text);\n    shortLabel.relationshipType = RelationshipTypes.hasProperties;\n    shortLabel.conceptNameCode = getShortLabelCode();\n    shortLabel.value = annotation.textExpr;\n    // label position\n    if (typeof annotation.labelPosition !== 'undefined') {\n      const labelPosition = new DicomSRContent(ValueTypes.scoord);\n      labelPosition.relationshipType = RelationshipTypes.hasProperties;\n      labelPosition.conceptNameCode = getReferencePointsCode();\n      const labelPosScoord = new SpatialCoordinate();\n      labelPosScoord.graphicType = GraphicTypes.point;\n      const graphicData = [\n        annotation.labelPosition.getX().toString(),\n        annotation.labelPosition.getY().toString()\n      ];\n      labelPosScoord.graphicData = graphicData;\n      labelPosition.value = labelPosScoord;\n\n      // add position to label sequence\n      shortLabel.contentSequence = [labelPosition];\n    }\n    itemContentSequence.push(shortLabel);\n\n    // colour\n    const colour = new DicomSRContent(ValueTypes.text);\n    colour.relationshipType = RelationshipTypes.hasProperties;\n    colour.conceptNameCode = getColourCode();\n    colour.value = annotation.colour;\n    itemContentSequence.push(colour);\n\n    // reference points\n    if (typeof annotation.referencePoints !== 'undefined') {\n      const referencePoints = new DicomSRContent(ValueTypes.scoord);\n      referencePoints.relationshipType = RelationshipTypes.hasProperties;\n      referencePoints.conceptNameCode = getReferencePointsCode();\n      const refPointsScoord = new SpatialCoordinate();\n      refPointsScoord.graphicType = GraphicTypes.multipoint;\n      const graphicData = [];\n      for (const point of annotation.referencePoints) {\n        graphicData.push(point.getX().toString());\n        graphicData.push(point.getY().toString());\n      }\n      refPointsScoord.graphicData = graphicData;\n\n      referencePoints.value = refPointsScoord;\n      itemContentSequence.push(referencePoints);\n    }\n\n    // plane points\n    if (typeof annotation.planePoints !== 'undefined') {\n      const planePoints = new DicomSRContent(ValueTypes.scoord3d);\n      planePoints.relationshipType = RelationshipTypes.hasProperties;\n      planePoints.conceptNameCode = getReferenceGeometryCode();\n      const pointsScoord = new SpatialCoordinate3D();\n      pointsScoord.graphicType = GraphicTypes.multipoint;\n      const graphicData = [];\n      for (const planePoint of annotation.planePoints) {\n        graphicData.push(planePoint.getX().toString());\n        graphicData.push(planePoint.getY().toString());\n        graphicData.push(planePoint.getZ().toString());\n      }\n      pointsScoord.graphicData = graphicData;\n\n      planePoints.value = pointsScoord;\n      itemContentSequence.push(planePoints);\n    }\n\n    // quantification\n    if (typeof annotation.quantification !== 'undefined') {\n      for (const key in annotation.quantification) {\n        const quatifContent = getSRContentFromValue(\n          key,\n          annotation.quantification[key].value,\n          annotation.quantification[key].unit\n        );\n        if (typeof quatifContent !== 'undefined') {\n          itemContentSequence.push(quatifContent);\n        }\n      }\n    }\n\n    srScoord.contentSequence = itemContentSequence;\n    return srScoord;\n  }\n\n  /**\n   * Convert an annotation group into a DICOM SR object.\n   *\n   * @param {AnnotationGroup} annotationGroup The annotation group.\n   * @param {Object<string, any>} [extraTags] Optional list of extra tags.\n   * @returns {Object<string, DataElement>} A list of dicom elements.\n   */\n  toDicom(annotationGroup, extraTags) {\n    let tags = annotationGroup.getMeta();\n\n    // transfer syntax: ExplicitVRLittleEndian\n    tags.TransferSyntaxUID = '1.2.840.10008.1.2.1';\n    // class: Basic Text SR Storage\n    tags.SOPClassUID = '1.2.840.10008.5.1.4.1.1.88.11';\n    tags.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.88.11';\n    tags.CompletionFlag = 'PARTIAL';\n    tags.VerificationFlag = 'UNVERIFIED';\n\n    const now = new Date();\n    tags.ContentDate = getDicomDate(dateToDateObj(now));\n    tags.ContentTime = getDicomTime(dateToTimeObj(now));\n\n    const contentSequence = [];\n    for (const annotation of annotationGroup.getList()) {\n      contentSequence.push(this.#annotationToScoord(annotation));\n    }\n\n    // main\n    if (contentSequence.length !== 0) {\n      const srContent = new DicomSRContent(ValueTypes.container);\n      srContent.conceptNameCode = getMeasurementGroupCode();\n      srContent.contentSequence = contentSequence;\n\n      tags = {\n        ...tags,\n        ...getDicomSRContentItem(srContent)\n      };\n    }\n\n    // merge extra tags if provided\n    if (typeof extraTags !== 'undefined') {\n      mergeTags(tags, extraTags);\n    }\n\n    return getElementsFromJSONTags(tags);\n  }\n\n}","import {ListenerHandler} from '../utils/listen';\nimport {mergeObjects} from '../utils/operator';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from '../image/image';\nimport {AnnotationGroup} from '../image/annotationGroup';\n/* eslint-enable no-unused-vars */\n\n/**\n * DICOM data: meta and possible image.\n */\nexport class DicomData {\n  /**\n   * DICOM meta data.\n   *\n   * @type {object}\n   */\n  meta;\n\n  /**\n   * Image extracted from meta data.\n   *\n   * @type {Image|undefined}\n   */\n  image;\n  /**\n   * Annotattion group extracted from meta data.\n   *\n   * @type {AnnotationGroup|undefined}\n   */\n  annotationGroup;\n\n  /**\n   * @param {object} meta The DICOM meta data.\n   */\n  constructor(meta) {\n    this.meta = meta;\n  }\n}\n\n/*\n * DicomData controller.\n */\nexport class DataController {\n\n  /**\n   * List of DICOM data.\n   *\n   * @type {Object<string, DicomData>}\n   */\n  #dataList = {};\n\n  /**\n   * Distinct data loaded counter.\n   *\n   * @type {number}\n   */\n  #dataIdCounter = -1;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Get the next data id.\n   *\n   * @returns {string} The data id.\n   */\n  getNextDataId() {\n    ++this.#dataIdCounter;\n    return this.#dataIdCounter.toString();\n  }\n\n  /**\n   * Get the list of ids in the data storage.\n   *\n   * @returns {string[]} The list of data ids.\n   */\n  getDataIds() {\n    return Object.keys(this.#dataList);\n  }\n\n  /**\n   * Reset the class: empty the data storage.\n   */\n  reset() {\n    this.#dataList = {};\n  }\n\n  /**\n   * Get a data at a given index.\n   *\n   * @param {string} dataId The data id.\n   * @returns {DicomData|undefined} The DICOM data.\n   */\n  get(dataId) {\n    return this.#dataList[dataId];\n  }\n\n  /**\n   * Get the list of dataIds that contain the input UIDs.\n   *\n   * @param {string[]} uids A list of UIDs.\n   * @returns {string[]} The list of dataIds that contain the UIDs.\n   */\n  getDataIdsFromSopUids(uids) {\n    const res = [];\n    // check input\n    if (typeof uids === 'undefined' ||\n      uids.length === 0) {\n      return res;\n    }\n    const keys = Object.keys(this.#dataList);\n    for (const key of keys) {\n      if (typeof this.#dataList[key].image !== 'undefined' &&\n        this.#dataList[key].image.containsImageUids(uids)) {\n        res.push(key);\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Set the image at a given index.\n   *\n   * @param {string} dataId The data id.\n   * @param {Image} image The image to set.\n   */\n  setImage(dataId, image) {\n    this.#dataList[dataId].image = image;\n    /**\n     * Data image set event.\n     *\n     * @event DataController#dataimageset\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} value The event value, first element is the image.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'dataimageset',\n      value: [image],\n      dataid: dataId\n    });\n    // listen to image change\n    image.addEventListener('imagecontentchange', this.#getFireEvent(dataId));\n    image.addEventListener('imagegeometrychange', this.#getFireEvent(dataId));\n  }\n\n  /**\n   * Add a new data.\n   *\n   * @param {string} dataId The data id.\n   * @param {DicomData} data The data.\n   */\n  add(dataId, data) {\n    if (typeof this.#dataList[dataId] !== 'undefined') {\n      throw new Error('Data id already used in storage: ' + dataId);\n    }\n    // store the new image\n    this.#dataList[dataId] = data;\n    /**\n     * Data add event.\n     *\n     * @event DataController#dataadd\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'dataadd',\n      dataid: dataId\n    });\n    // listen to image change\n    if (typeof data.image !== 'undefined') {\n      data.image.addEventListener(\n        'imagecontentchange', this.#getFireEvent(dataId));\n      data.image.addEventListener(\n        'imagegeometrychange', this.#getFireEvent(dataId));\n    }\n    if (typeof data.annotationGroup !== 'undefined') {\n      data.annotationGroup.addEventListener(\n        'annotationadd', this.#getFireEvent(dataId));\n      data.annotationGroup.addEventListener(\n        'annotationupdate', this.#getFireEvent(dataId));\n      data.annotationGroup.addEventListener(\n        'annotationremove', this.#getFireEvent(dataId));\n    }\n  }\n\n  /**\n   * Remove a data from the list.\n   *\n   * @param {string} dataId The data id.\n   */\n  remove(dataId) {\n    if (typeof this.#dataList[dataId] !== 'undefined') {\n      // stop listeners\n      const image = this.#dataList[dataId].image;\n      if (typeof image !== 'undefined') {\n        image.removeEventListener(\n          'imagecontentchange', this.#getFireEvent(dataId));\n        image.removeEventListener(\n          'imagegeometrychange', this.#getFireEvent(dataId));\n      }\n      const annotationGroup = this.#dataList[dataId].annotationGroup;\n      if (typeof annotationGroup !== 'undefined') {\n        annotationGroup.removeEventListener(\n          'annotationadd', this.#getFireEvent(dataId));\n        annotationGroup.removeEventListener(\n          'annotationupdate', this.#getFireEvent(dataId));\n        annotationGroup.removeEventListener(\n          'annotationremove', this.#getFireEvent(dataId));\n      }\n      // remove data from list\n      delete this.#dataList[dataId];\n      /**\n       * Data remove event.\n       *\n       * @event DataController#dataremove\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {string} dataid The data id.\n       */\n      this.#fireEvent({\n        type: 'dataremove',\n        dataid: dataId\n      });\n    }\n  }\n\n  /**\n   * Update the current data.\n   *\n   * @param {string} dataId The data id.\n   * @param {DicomData} data The data.\n   */\n  update(dataId, data) {\n    if (typeof this.#dataList[dataId] === 'undefined') {\n      throw new Error('Cannot find data to update: ' + dataId);\n    }\n    const dataToUpdate = this.#dataList[dataId];\n\n    // add slice to current image\n    if (typeof dataToUpdate.image !== 'undefined' &&\n      typeof data.image !== 'undefined'\n    ) {\n      dataToUpdate.image.appendSlice(data.image);\n    }\n\n    // update meta data\n    // TODO add time support\n    let idKey = '';\n    if (typeof data.meta['00020010'] !== 'undefined') {\n      // dicom case, use 'InstanceNumber'\n      idKey = '00200013';\n    } else {\n      idKey = 'imageUid';\n    }\n    dataToUpdate.meta = mergeObjects(\n      dataToUpdate.meta,\n      data.meta,\n      idKey,\n      'value');\n\n    /**\n     * Data udpate event.\n     *\n     * @event DataController#dataupdate\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'dataupdate',\n      dataid: dataId\n    });\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  /**\n   * Get a fireEvent function that adds the input data id\n   * to the event value.\n   *\n   * @param {string} dataId The data id.\n   * @returns {Function} A fireEvent function.\n   */\n  #getFireEvent(dataId) {\n    return (event) => {\n      event.dataid = dataId;\n      this.#fireEvent(event);\n    };\n  }\n\n} // DataController class\n","import {arrayEquals} from './array';\n\n/**\n * Merge two similar objects.\n *\n * Objects need to be in the form of:\n * <code>\n * {\n *   idKey: {valueKey: [0]},\n *   key0: {valueKey: [\"abc\"]},\n *   key1: {valueKey: [33]}\n * }\n * </code>.\n *\n * Merged objects will be in the form of:\n * <code>\n * {\n *   idKey: {valueKey: [0,1,2], merged: true},\n *   key0: {valueKey: {\n *     0: [\"abc\"],\n *     1: [\"def\"],\n *     2: [\"ghi\"]\n *   }},\n *   key1: {valueKey: {\n *     0: [33],\n *     1: [44],\n *     2: [55]\n *   }}\n * }\n * </code>.\n *\n * @param {object} obj1 The first object, can be the result of a previous merge.\n * @param {object} obj2 The second object.\n * @param {string} idKey The key to use as index for duplicate values.\n * @param {string} valueKey The key to use to access object values.\n * @returns {object} The merged object.\n */\nexport function mergeObjects(obj1, obj2, idKey, valueKey) {\n  const res = {};\n  // check id key\n  if (!idKey) {\n    throw new Error('Cannot merge object with an undefined id key: ' + idKey);\n  } else {\n    if (!Object.prototype.hasOwnProperty.call(obj1, idKey)) {\n      throw new Error('Id key not found in first object while merging: ' +\n        idKey + ', obj: ' + obj1);\n    }\n    if (!Object.prototype.hasOwnProperty.call(obj2, idKey)) {\n      throw new Error('Id key not found in second object while merging: ' +\n        idKey + ', obj: ' + obj2);\n    }\n  }\n  // check value key\n  if (!valueKey) {\n    throw new Error('Cannot merge object with an undefined value key: ' +\n      valueKey);\n  }\n\n  // check if merged object\n  let mergedObj1 = false;\n  if (Object.prototype.hasOwnProperty.call(obj1[idKey], 'merged') &&\n    obj1[idKey].merged) {\n    mergedObj1 = true;\n  }\n  // handle the id part\n  if (!Object.prototype.hasOwnProperty.call(obj1[idKey], valueKey)) {\n    throw new Error('Id value not found in first object while merging: ' +\n      idKey + ', valueKey: ' + valueKey + ', ojb: ' + obj1);\n  }\n  if (!Object.prototype.hasOwnProperty.call(obj2[idKey], valueKey)) {\n    throw new Error('Id value not found in second object while merging: ' +\n      idKey + ', valueKey: ' + valueKey + ', ojb: ' + obj2);\n  }\n  let id1 = obj1[idKey][valueKey];\n  const id2 = obj2[idKey][valueKey][0];\n  // update id key\n  res[idKey] = obj1[idKey];\n  if (mergedObj1) {\n    // check if array does not include id2\n    for (let k = 0; k < id1.length; ++k) {\n      if (id1[k] === id2) {\n        throw new Error('The first object already contains id2: ' +\n          id2 + ', id1: ' + id1);\n      }\n    }\n    res[idKey][valueKey].push(id2);\n  } else {\n    id1 = id1[0];\n    if (id1 === id2) {\n      throw new Error('Cannot merge object with same ids: ' +\n        id1 + ', id2: ' + id2);\n    }\n    // update merge object\n    res[idKey][valueKey].push(id2);\n    res[idKey].merged = true;\n  }\n\n  // get keys\n  const keys1 = Object.keys(obj1);\n  // keys2 without duplicates of keys1\n  const keys2 = Object.keys(obj2).filter(function (item) {\n    return keys1.indexOf(item) < 0;\n  });\n  const keys = keys1.concat(keys2);\n\n  // loop through keys\n  for (let i = 0; i < keys.length; ++i) {\n    const key = keys[i];\n    if (key !== idKey) {\n      // first\n      let value1;\n      let subValue1;\n      if (Object.prototype.hasOwnProperty.call(obj1, key)) {\n        value1 = obj1[key];\n        if (Object.prototype.hasOwnProperty.call(value1, valueKey)) {\n          subValue1 = value1[valueKey];\n        }\n      }\n      // second\n      let value2;\n      let subValue2;\n      if (Object.prototype.hasOwnProperty.call(obj2, key)) {\n        value2 = obj2[key];\n        if (Object.prototype.hasOwnProperty.call(value2, valueKey)) {\n          subValue2 = value2[valueKey];\n        }\n      }\n      // result value\n      let value;\n      // use existing to copy properties\n      if (typeof value1 !== 'undefined') {\n        value = value1;\n      } else if (typeof value2 !== 'undefined') {\n        value = value2;\n      }\n      // create merge object if different values\n      if (!arrayEquals(subValue1, subValue2)) {\n        // add to merged object or create new\n        if (mergedObj1) {\n          if (Array.isArray(subValue1)) {\n            // merged object with repeated value\n            // copy it with the index list\n            value[valueKey] = {};\n            for (let j = 0; j < id1.length; ++j) {\n              value[valueKey][id1[j]] = subValue1;\n            }\n          } else {\n            value[valueKey] = subValue1;\n          }\n          // undefined subValue1\n          if (typeof value[valueKey] === 'undefined') {\n            value[valueKey] = {};\n          }\n          // add obj2 value\n          value[valueKey][id2] = subValue2;\n        } else {\n          // create merge object\n          const newValue = {};\n          newValue[id1] = subValue1;\n          newValue[id2] = subValue2;\n          value[valueKey] = newValue;\n        }\n      }\n      // store value in result object\n      res[key] = value;\n    }\n  }\n  return res;\n}\n","import {logger} from '../utils/logger';\nimport {\n  DicomParser,\n  getSyntaxDecompressionName\n} from '../dicom/dicomParser';\nimport {ImageFactory} from './imageFactory';\nimport {MaskFactory} from './maskFactory';\nimport {PixelBufferDecoder} from './decoder';\nimport {AnnotationGroupFactory} from './annotationGroupFactory';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from '../dicom/dataElement';\nimport {DicomData} from '../app/dataController';\n/* eslint-enable no-unused-vars */\n\n/**\n * Create a View from a DICOM buffer.\n */\nexport class DicomBufferToView {\n\n  /**\n   * Converter options.\n   *\n   * @type {object}\n   */\n  #options;\n\n  /**\n   * Set the converter options.\n   *\n   * @param {object} opt The input options.\n   */\n  setOptions(opt) {\n    this.#options = opt;\n  }\n\n  /**\n   * Pixel buffer decoder.\n   * Define only once to allow optional asynchronous mode.\n   *\n   * @type {object}\n   */\n  #pixelDecoder = null;\n\n  // local tmp storage\n  #dicomParserStore = [];\n  #finalBufferStore = [];\n  #decompressedSizes = [];\n  #factories = [];\n\n  /**\n   * Get the factory associated to input DICOM elements.\n   *\n   * @param {Object<string, DataElement>} elements The DICOM elements.\n   * @returns {ImageFactory|MaskFactory|AnnotationGroupFactory|undefined}\n   *   The associated factory.\n   */\n  #getFactory(elements) {\n    let factory;\n    const modalityElement = elements['00080060'];\n    if (typeof modalityElement !== 'undefined') {\n      const modality = modalityElement.value[0];\n      if (modality === 'SEG') {\n        // mask factory for DICOM SEG\n        factory = new MaskFactory();\n      } else if (modality === 'SR') {\n        // annotation factory for DICOM SR\n        factory = new AnnotationGroupFactory();\n      }\n    }\n    // image factory for pixel data\n    if (typeof factory === 'undefined') {\n      const pixelElement = elements['7FE00010'];\n      if (typeof pixelElement !== 'undefined') {\n        factory = new ImageFactory();\n      }\n    }\n    return factory;\n  }\n\n  /**\n   * Generate the data object.\n   *\n   * @param {number} index The data index.\n   * @param {string} origin The data origin.\n   * @returns {boolean} True if the generation went ok.\n   */\n  #generateData(index, origin) {\n    const dataElements = this.#dicomParserStore[index].getDicomElements();\n    const factory = this.#factories[index];\n    // exit if no factory\n    if (typeof factory === 'undefined') {\n      return false;\n    }\n    // create data\n    try {\n      const data = new DicomData(dataElements);\n      if (factory instanceof AnnotationGroupFactory) {\n        data.annotationGroup = factory.create(dataElements);\n      } else {\n        data.image = factory.create(\n          dataElements,\n          this.#finalBufferStore[index],\n          this.#options.numberOfFiles);\n      }\n      // call onloaditem\n      this.onloaditem({\n        data: data,\n        source: origin,\n        warn: factory.getWarning()\n      });\n    } catch (error) {\n      this.onerror({\n        error: error,\n        source: origin\n      });\n      this.onloadend({\n        source: origin\n      });\n      // false for error\n      return false;\n    }\n\n    // all good\n    return true;\n  }\n\n  /**\n   * Generate a single data object.\n   *\n   * @param {number} index The data index.\n   * @param {string} origin The data origin.\n   */\n  #generateSingleData(index, origin) {\n    // generate image\n    if (this.#generateData(index, origin)) {\n      // send load event\n      this.onload({\n        source: origin\n      });\n    }\n    // allways send loadend\n    this.onloadend({\n      source: origin\n    });\n  }\n\n  /**\n   * Generate the image object from an uncompressed buffer.\n   *\n   * @param {number} index The data index.\n   * @param {string} origin The data origin.\n   */\n  #generateImageUncompressed(index, origin) {\n    // send 100% progress\n    this.onprogress({\n      lengthComputable: true,\n      loaded: 100,\n      total: 100,\n      index: index,\n      source: origin\n    });\n    // generate single data\n    this.#generateSingleData(index, origin);\n  }\n\n  /**\n   * Generate the image object from an compressed buffer.\n   *\n   * @param {number} index The data index.\n   * @param {Array} pixelBuffer The dicom parser.\n   * @param {string} algoName The compression algorithm name.\n   */\n  #generateImageCompressed(index, pixelBuffer, algoName) {\n    const dicomParser = this.#dicomParserStore[index];\n\n    // gather pixel buffer meta data\n    const bitsAllocated =\n      dicomParser.getDicomElements()['00280100'].value[0];\n    const pixelRepresentation =\n      dicomParser.getDicomElements()['00280103'].value[0];\n    const pixelMeta = {\n      bitsAllocated: bitsAllocated,\n      isSigned: (pixelRepresentation === 1)\n    };\n    const columnsElement = dicomParser.getDicomElements()['00280011'];\n    const rowsElement = dicomParser.getDicomElements()['00280010'];\n    if (typeof columnsElement !== 'undefined' &&\n      typeof rowsElement !== 'undefined') {\n      pixelMeta.sliceSize = columnsElement.value[0] * rowsElement.value[0];\n    }\n    const samplesPerPixelElement =\n      dicomParser.getDicomElements()['00280002'];\n    if (typeof samplesPerPixelElement !== 'undefined') {\n      pixelMeta.samplesPerPixel = samplesPerPixelElement.value[0];\n    }\n    const planarConfigurationElement =\n      dicomParser.getDicomElements()['00280006'];\n    if (typeof planarConfigurationElement !== 'undefined') {\n      pixelMeta.planarConfiguration = planarConfigurationElement.value[0];\n    }\n\n    const numberOfItems = pixelBuffer.length;\n\n    // setup the decoder (one decoder per all converts)\n    if (this.#pixelDecoder === null) {\n      this.#pixelDecoder = new PixelBufferDecoder(\n        algoName, numberOfItems);\n      // callbacks\n      // pixelDecoder.ondecodestart: nothing to do\n      this.#pixelDecoder.ondecodeditem = (event) => {\n        this.#onDecodedItem(event);\n        // send onload and onloadend when all items have been decoded\n        if (event.itemNumber + 1 === event.numberOfItems) {\n          this.onload(event);\n          this.onloadend(event);\n        }\n      };\n      // pixelDecoder.ondecoded: nothing to do\n      // pixelDecoder.ondecodeend: nothing to do\n      this.#pixelDecoder.onerror = this.onerror;\n      this.#pixelDecoder.onabort = this.onabort;\n    }\n\n    // launch decode\n    for (let i = 0; i < numberOfItems; ++i) {\n      this.#pixelDecoder.decode(pixelBuffer[i], pixelMeta,\n        {\n          itemNumber: i,\n          numberOfItems: numberOfItems,\n          index: index\n        }\n      );\n    }\n  }\n\n  /**\n   * Handle a decoded item event.\n   *\n   * @param {object} event The decoded item event.\n   */\n  #onDecodedItem(event) {\n    // send progress\n    this.onprogress({\n      lengthComputable: true,\n      loaded: event.itemNumber + 1,\n      total: event.numberOfItems,\n      index: event.index,\n      source: origin\n    });\n\n    const dataIndex = event.index;\n\n    // store decoded data\n    const decodedData = event.data[0];\n    if (event.numberOfItems !== 1) {\n      // allocate buffer if not done yet\n      if (typeof this.#decompressedSizes[dataIndex] === 'undefined') {\n        this.#decompressedSizes[dataIndex] = decodedData.length;\n        const fullSize = event.numberOfItems *\n          this.#decompressedSizes[dataIndex];\n        try {\n          this.#finalBufferStore[dataIndex] =\n            new decodedData.constructor(fullSize);\n        } catch (error) {\n          if (error instanceof RangeError) {\n            const powerOf2 = Math.floor(Math.log(fullSize) / Math.log(2));\n            logger.error('Cannot allocate ' +\n              decodedData.constructor.name +\n              ' of size: ' +\n              fullSize + ' (>2^' + powerOf2 + ') for decompressed data.');\n          }\n          // abort\n          this.#pixelDecoder.abort();\n          // send events\n          this.onerror({\n            error: error,\n            source: origin\n          });\n          this.onloadend({\n            source: origin\n          });\n          // exit\n          return;\n        }\n      }\n      // hoping for all items to have the same size...\n      if (decodedData.length !== this.#decompressedSizes[dataIndex]) {\n        logger.warn('Unsupported varying decompressed data size: ' +\n          decodedData.length + ' != ' + this.#decompressedSizes[dataIndex]);\n      }\n      // set buffer item data\n      this.#finalBufferStore[dataIndex].set(\n        decodedData, this.#decompressedSizes[dataIndex] * event.itemNumber);\n    } else {\n      this.#finalBufferStore[dataIndex] = decodedData;\n    }\n\n    // create image for the first item\n    if (event.itemNumber === 0) {\n      this.#generateData(dataIndex, origin);\n    }\n  }\n\n  /**\n   * Handle non image data.\n   *\n   * @param {number} index The data index.\n   * @param {string} origin The data origin.\n   */\n  #handleNonImageData(index, origin) {\n    // generate single data\n    this.#generateSingleData(index, origin);\n  }\n\n  /**\n   * Handle image data.\n   *\n   * @param {number} index The data index.\n   * @param {string} origin The data origin.\n   */\n  #handleImageData(index, origin) {\n    const dicomParser = this.#dicomParserStore[index];\n\n    const pixelBuffer = dicomParser.getDicomElements()['7FE00010'].value;\n    // help GC: discard pixel buffer from elements\n    dicomParser.getDicomElements()['7FE00010'].value = [];\n    this.#finalBufferStore[index] = pixelBuffer[0];\n\n    // transfer syntax (always there)\n    const syntax = dicomParser.getDicomElements()['00020010'].value[0];\n    const algoName = getSyntaxDecompressionName(syntax);\n    const needDecompression = typeof algoName !== 'undefined';\n\n    if (needDecompression) {\n      // generate image\n      this.#generateImageCompressed(\n        index,\n        pixelBuffer,\n        algoName);\n    } else {\n      this.#generateImageUncompressed(index, origin);\n    }\n  }\n\n  /**\n   * Get data from an input buffer using a DICOM parser.\n   *\n   * @param {ArrayBuffer} buffer The input data buffer.\n   * @param {string} origin The data origin.\n   * @param {number} dataIndex The data index.\n   */\n  convert(buffer, origin, dataIndex) {\n    // start event\n    this.onloadstart({\n      source: origin,\n      index: dataIndex\n    });\n\n    // DICOM parser\n    const dicomParser = new DicomParser();\n\n    if (typeof this.#options.defaultCharacterSet !== 'undefined') {\n      dicomParser.setDefaultCharacterSet(this.#options.defaultCharacterSet);\n    }\n    // parse the buffer\n    let factory;\n    try {\n      dicomParser.parse(buffer);\n      // check elements\n      factory = this.#getFactory(dicomParser.getDicomElements());\n      if (typeof factory !== 'undefined') {\n        factory.checkElements(dicomParser.getDicomElements());\n      }\n    } catch (error) {\n      this.onerror({\n        error: error,\n        source: origin\n      });\n      this.onloadend({\n        source: origin\n      });\n      return;\n    }\n\n    // store\n    this.#dicomParserStore[dataIndex] = dicomParser;\n    this.#factories[dataIndex] = factory;\n\n    // handle parsed data\n    if (factory instanceof AnnotationGroupFactory) {\n      this.#handleNonImageData(dataIndex, origin);\n    } else {\n      this.#handleImageData(dataIndex, origin);\n    }\n  }\n\n  /**\n   * Abort a conversion.\n   */\n  abort() {\n    // abort decoding, will trigger pixelDecoder.onabort\n    if (this.#pixelDecoder) {\n      this.#pixelDecoder.abort();\n    }\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n  /**\n   * Handle a load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class DicomBufferToView\n","import {MultiProgressHandler} from '../utils/progress';\nimport {loaderList} from './loaderList';\n\n/**\n * Memory loader.\n */\nexport class MemoryLoader {\n\n  /**\n   * Input data.\n   *\n   * @type {Array}\n   */\n  #inputData = null;\n\n  /**\n   * Data loader.\n   *\n   * @type {object}\n   */\n  #runningLoader = null;\n\n  /**\n   * Number of loaded data.\n   *\n   * @type {number}\n   */\n  #nLoad = 0;\n\n  /**\n   * Number of load end events.\n   *\n   * @type {number}\n   */\n  #nLoadend = 0;\n\n  /**\n   * The default character set (optional).\n   *\n   * @type {string}\n   */\n  #defaultCharacterSet;\n\n  /**\n   * Get the default character set.\n   *\n   * @returns {string} The default character set.\n   */\n  getDefaultCharacterSet() {\n    return this.#defaultCharacterSet;\n  }\n\n  /**\n   * Set the default character set.\n   *\n   * @param {string} characterSet The character set.\n   */\n  setDefaultCharacterSet(characterSet) {\n    this.#defaultCharacterSet = characterSet;\n  }\n\n  /**\n   * Store the current input.\n   *\n   * @param {object} data The input data.\n   */\n  #storeInputData(data) {\n    this.#inputData = data;\n    // reset counters\n    this.#nLoad = 0;\n    this.#nLoadend = 0;\n    // clear storage\n    this.#clearStoredLoader();\n  }\n\n  /**\n   * Store the launched loader.\n   *\n   * @param {object} loader The launched loader.\n   */\n  #storeLoader(loader) {\n    this.#runningLoader = loader;\n  }\n\n  /**\n   * Clear the stored loader.\n   *\n   */\n  #clearStoredLoader() {\n    this.#runningLoader = null;\n  }\n\n  /**\n   * Increment the number of loaded data\n   *   and call onload if loaded all data.\n   *\n   * @param {object} _event The load data event.\n   */\n  #addLoad = (_event) => {\n    this.#nLoad++;\n    // call onload when all is loaded\n    // (not using the input event since it is not the\n    //   general load)\n    if (this.#nLoad === this.#inputData.length) {\n      this.onload({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * Increment the counter of load end events\n   *   and run callbacks when all done, erroneus or not.\n   *\n   * @param {object} _event The load end event.\n   */\n  #addLoadend = (_event) => {\n    this.#nLoadend++;\n    // call onloadend when all is run\n    // (not using the input event since it is not the\n    //   general load end)\n    if (this.#nLoadend === this.#inputData.length) {\n      this.onloadend({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * Load a list of buffers.\n   *\n   * @param {Array} data The list of buffers to load.\n   */\n  load(data) {\n    // check input\n    if (typeof data === 'undefined' || data.length === 0) {\n      return;\n    }\n    this.#storeInputData(data);\n\n    // send start event\n    this.onloadstart({\n      source: data\n    });\n\n    // create prgress handler\n    const mproghandler = new MultiProgressHandler(this.onprogress);\n    mproghandler.setNToLoad(data.length);\n    mproghandler.setNumberOfDimensions(1);\n\n    // create loaders\n    const loaders = [];\n    for (let m = 0; m < loaderList.length; ++m) {\n      loaders.push(new loaderList[m]());\n    }\n\n    // find an appropriate loader\n    let dataElement = data[0];\n    let loader = null;\n    let foundLoader = false;\n    for (let l = 0; l < loaders.length; ++l) {\n      loader = loaders[l];\n      if (loader.canLoadMemory(dataElement)) {\n        foundLoader = true;\n        // load options\n        loader.setOptions({\n          numberOfFiles: data.length,\n          defaultCharacterSet: this.getDefaultCharacterSet()\n        });\n        // set loader callbacks\n        // loader.onloadstart: nothing to do\n        loader.onprogress = mproghandler.getUndefinedMonoProgressHandler(0);\n        loader.onloaditem = this.onloaditem;\n        loader.onload = this.#addLoad;\n        loader.onloadend = this.#addLoadend;\n        loader.onerror = this.onerror;\n        loader.onabort = this.onabort;\n\n        // store loader\n        this.#storeLoader(loader);\n        // exit\n        break;\n      }\n    }\n    if (!foundLoader) {\n      throw new Error('No loader found for data: ' + dataElement.filename);\n    }\n\n    // loop on I/O elements\n    for (let i = 0; i < data.length; ++i) {\n      dataElement = data[i];\n      // check loader\n      if (!loader.canLoadMemory(dataElement)) {\n        throw new Error('Input data of different type: ' +\n          dataElement.filename);\n      }\n      // read\n      loader.load(dataElement.data, dataElement.filename, i);\n    }\n  }\n\n  /**\n   * Abort a load.\n   */\n  abort() {\n    // abort loader\n    if (this.#runningLoader && this.#runningLoader.isLoading()) {\n      this.#runningLoader.abort();\n    }\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle a load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class MemoryLoader\n","import {Size} from '../image/size';\nimport {Spacing} from '../image/spacing';\nimport {Geometry} from '../image/geometry';\nimport {Image} from '../image/image';\nimport {Point3D} from '../math/point';\n\n/**\n * Convert a string into an UID.\n *\n * @param {string} str The input string.\n * @returns {string} The input string converted to numbers\n *   using parseInt with a 36 radix\n *   (10 digits from 0 to 9 + 26 digits from a to z).\n */\nfunction toUID(str) {\n  return parseInt(str, 36).toString();\n}\n\n/**\n * Create a simple array buffer from an ImageData buffer.\n *\n * @param {object} imageData The ImageData taken from a context.\n * @returns {Uint8Array} The image buffer.\n */\nfunction imageDataToBuffer(imageData) {\n  // remove alpha\n  // TODO support passing the full image data\n  const dataLen = imageData.data.length;\n  const buffer = new Uint8Array((dataLen / 4) * 3);\n  let j = 0;\n  for (let i = 0; i < dataLen; i += 4) {\n    buffer[j] = imageData.data[i];\n    buffer[j + 1] = imageData.data[i + 1];\n    buffer[j + 2] = imageData.data[i + 2];\n    j += 3;\n  }\n  return buffer;\n}\n\n/**\n * Get an image from an input context imageData.\n *\n * @param {number} width The width of the coresponding image.\n * @param {number} height The height of the coresponding image.\n * @param {number} sliceIndex The slice index of the imageData.\n * @param {object} imageBuffer The image buffer.\n * @param {number} numberOfFrames The final number of frames.\n * @param {string} imageUid The image UID.\n * @returns {object} The corresponding view.\n */\nfunction getDefaultImage(\n  width, height, sliceIndex,\n  imageBuffer, numberOfFrames,\n  imageUid) {\n  // image size\n  const imageSize = new Size([width, height, 1]);\n  // default spacing\n  // TODO: misleading...\n  const imageSpacing = new Spacing([1, 1, 1]);\n  // default origin\n  const origin = new Point3D(0, 0, sliceIndex);\n  // create image\n  const geometry = new Geometry([origin], imageSize, imageSpacing);\n  const image = new Image(geometry, imageBuffer, [imageUid]);\n  image.setPhotometricInterpretation('RGB');\n  // meta information\n  const meta = {};\n  meta.BitsStored = 8;\n  if (typeof numberOfFrames !== 'undefined') {\n    meta.numberOfFiles = numberOfFrames;\n  }\n  image.setMeta(meta);\n  // return\n  return image;\n}\n\n/**\n * Get data from an input image using a canvas.\n *\n * @param {HTMLImageElement} domImage The DOM Image,\n *   an HTMLImageElement with extra info.\n * @param {string|File} origin The data origin.\n * @param {number} index The data index.\n * @returns {object} A load data event.\n */\nexport function getViewFromDOMImage(domImage, origin, index) {\n  // image size\n  const width = domImage.width;\n  const height = domImage.height;\n\n  // draw the image in the canvas in order to get its data\n  const canvas = document.createElement('canvas');\n  canvas.width = width;\n  canvas.height = height;\n  const ctx = canvas.getContext('2d');\n  ctx.drawImage(domImage, 0, 0);\n  // get the image data\n  const imageData = ctx.getImageData(0, 0, width, height);\n\n  // image properties\n  const info = {};\n  let seriesUID;\n  if (typeof origin === 'string') {\n    info['origin'] = {value: origin};\n    seriesUID = toUID(origin);\n  } else {\n    info['fileName'] = {value: origin.name};\n    seriesUID = toUID(origin.name);\n    info['fileType'] = {value: origin.type};\n    info['fileLastModifiedDate'] = {value: origin.lastModified};\n  }\n  info['imageWidth'] = {value: width};\n  info['imageHeight'] = {value: height};\n\n  // image identifier (~UID like)\n  const sliceIndex = index ? index : 0;\n  info['imageUid'] = {value: sliceIndex};\n  // series identifier (~UID like)\n  info['seriesUid'] = {value: seriesUID};\n\n  // create view\n  const imageBuffer = imageDataToBuffer(imageData);\n  const image = getDefaultImage(\n    width, height, sliceIndex, imageBuffer, 1, sliceIndex.toString());\n\n  // add seriesUID to meta\n  const meta = image.getMeta();\n  meta.SeriesInstanceUID = seriesUID;\n  image.setMeta(meta);\n\n  // return\n  return {\n    data: {\n      image: image,\n      meta: info\n    },\n    source: origin\n  };\n}\n\n/**\n * Get data from an input image using a canvas.\n *\n * @param {object} video The DOM Video, an HTMLVideoElement with extra info.\n * @param {Function} onloaditem On load callback.\n * @param {object} onload The function to call once the data is loaded.\n * @param {object} onprogress The function to call to report progress.\n * @param {object} onloadend The function to call to report load end.\n * @param {string|File} origin The data origin.\n * @param {number} dataIndex The data index.\n */\nexport function getViewFromDOMVideo(\n  video, onloaditem, onload, onprogress, onloadend,\n  origin, dataIndex) {\n  // video size\n  const width = video.videoWidth;\n  const height = video.videoHeight;\n\n  // default frame rate...\n  const frameRate = 30;\n  // number of frames\n  const numberOfFrames = Math.ceil(video.duration * frameRate);\n\n  // video properties\n  const info = {};\n  let seriesUID;\n  if (typeof origin === 'string') {\n    info['origin'] = {value: origin};\n    seriesUID = toUID(origin);\n  } else {\n    info['fileName'] = {value: origin.name};\n    seriesUID = toUID(origin.name);\n    info['fileType'] = {value: origin.type};\n    info['fileLastModifiedDate'] = {value: origin.lastModified};\n  }\n  info['imageWidth'] = {value: width};\n  info['imageHeight'] = {value: height};\n  info['numberOfFrames'] = {value: numberOfFrames};\n\n  // image identifier (~UID like)\n  info['imageUid'] = {value: 0};\n  // series identifier (~UID like)\n  info['seriesUid'] = {value: seriesUID};\n\n  // draw the image in the canvas in order to get its data\n  const canvas = document.createElement('canvas');\n  canvas.width = width;\n  canvas.height = height;\n  const ctx = canvas.getContext('2d');\n\n  // using seeked to loop through all video frames\n  video.addEventListener('seeked', onseeked, false);\n\n  // current frame index\n  let frameIndex = 0;\n  // video image\n  let image = null;\n\n  /**\n   * Draw the context and store it as a frame.\n   */\n  function storeFrame() {\n    // send progress\n    onprogress({\n      lengthComputable: true,\n      loaded: frameIndex,\n      total: numberOfFrames,\n      index: dataIndex,\n      source: origin\n    });\n    // draw image\n    ctx.drawImage(video, 0, 0);\n    // context to image buffer\n    const imgBuffer = imageDataToBuffer(\n      ctx.getImageData(0, 0, width, height));\n    if (frameIndex === 0) {\n      // create view\n      image = getDefaultImage(\n        width, height, 1, imgBuffer, numberOfFrames, dataIndex.toString());\n      // add seriesUID to meta\n      const meta = image.getMeta();\n      meta.SeriesInstanceUID = seriesUID;\n      image.setMeta(meta);\n      // call callback\n      onloaditem({\n        data: {\n          image: image,\n          meta: info\n        },\n        source: origin\n      });\n    } else {\n      image.appendFrameBuffer(imgBuffer, frameIndex);\n    }\n    // increment index\n    ++frameIndex;\n  }\n\n  let nextTime = 0;\n\n  /**\n   * Handle seeked event.\n   *\n   * @param {object} event The seeked event.\n   */\n  function onseeked(event) {\n    // store\n    storeFrame();\n    // set the next time\n    // (not using currentTime, it seems to get offseted)\n    nextTime += 1 / frameRate;\n    if (nextTime <= event.target.duration) {\n      this.currentTime = nextTime;\n    } else {\n      onload({\n        source: origin\n      });\n      onloadend({\n        source: origin\n      });\n      // stop listening\n      video.removeEventListener('seeked', onseeked);\n    }\n  }\n\n  // trigger the first seek\n  video.currentTime = nextTime;\n}\n","import {DicomDataLoader} from './dicomDataLoader';\nimport {JSONTextLoader} from './jsonTextLoader';\nimport {MultipartLoader} from './multipartLoader';\nimport {RawImageLoader} from './rawImageLoader';\nimport {RawVideoLoader} from './rawVideoLoader';\nimport {ZipLoader} from './zipLoader';\n\nexport const loaderList = [\n  DicomDataLoader,\n  JSONTextLoader,\n  MultipartLoader,\n  RawImageLoader,\n  RawVideoLoader,\n  ZipLoader\n];\n","import {startsWith, getFileExtension} from '../utils/string';\nimport {getUrlFromUri} from '../utils/uri';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\nimport {DicomBufferToView} from '../image/dicomBufferToView';\n\n/**\n * DICOM data loader.\n */\nexport class DicomDataLoader {\n\n  /**\n   * Loader options.\n   *\n   * @type {object}\n   */\n  #options = {};\n\n  /**\n   * Loading flag.\n   *\n   * @type {boolean}\n   */\n  #isLoading = false;\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} opt The input options.\n   */\n  setOptions(opt) {\n    this.#options = opt;\n  }\n\n  /**\n   * Is the load ongoing?\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return this.#isLoading;\n  }\n\n  /**\n   * DICOM buffer to View (asynchronous).\n   *\n   */\n  #db2v = new DicomBufferToView();\n\n  /**\n   * Load data.\n   *\n   * @param {object} buffer The DICOM buffer.\n   * @param {string} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(buffer, origin, index) {\n    // setup db2v ony once\n    if (!this.#isLoading) {\n      // pass options\n      this.#db2v.setOptions(this.#options);\n      // connect handlers\n      this.#db2v.onloadstart = this.onloadstart;\n      this.#db2v.onprogress = this.onprogress;\n      this.#db2v.onloaditem = this.onloaditem;\n      this.#db2v.onload = this.onload;\n      this.#db2v.onloadend = (event) => {\n        // reset loading flag\n        this.#isLoading = false;\n        // call listeners\n        this.onloadend(event);\n      };\n      this.#db2v.onerror = (event) => {\n        event.source = origin;\n        this.onerror(event);\n      };\n      this.#db2v.onabort = this.onabort;\n    }\n\n    // set loading flag\n    this.#isLoading = true;\n    // convert\n    this.#db2v.convert(buffer, origin, index);\n  }\n\n  /**\n   * Abort load.\n   */\n  abort() {\n    // reset loading flag\n    this.#isLoading = false;\n    // abort conversion, will trigger db2v.onabort\n    this.#db2v.abort();\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * True if one of the folowing conditions is true:\n   * - the file has a 'dcm' extension,\n   * - the file has no extension.\n   *\n   * @param {File} file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(file) {\n    const ext = getFileExtension(file.name);\n    const hasNoExt = (ext === null);\n    const hasDcmExt = (ext === 'dcm');\n    return hasNoExt || hasDcmExt;\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'dicom',\n   * - the `options.requestHeaders` contains a 'Accept: application/dicom',\n   * - the url has a 'contentType' and it is 'application/dicom'\n   *   (as in wado urls),\n   * - the url has no 'contentType' and no extension or the extension is 'dcm'.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'dicom') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'application/dicom' and no '+'\n          const acceptValue = 'application/dicom';\n          return startsWith(acceptHeader.value, acceptValue) &&\n            acceptHeader.value[acceptValue.length] !== '+';\n        }\n      }\n    }\n\n    const urlObjext = getUrlFromUri(url);\n    // extension\n    const ext = getFileExtension(urlObjext.pathname);\n    const hasNoExt = (ext === null);\n    const hasDcmExt = (ext === 'dcm');\n    // content type (for wado url)\n    const contentType = urlObjext.searchParams.get('contentType');\n    const hasContentType = contentType !== null &&\n      typeof contentType !== 'undefined';\n    const hasDicomContentType = (contentType === 'application/dicom');\n\n    return hasContentType ? hasDicomContentType : (hasNoExt || hasDcmExt);\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} mem The memory object.\n   * @returns {boolean} True if the object can be loaded.\n   */\n  canLoadMemory(mem) {\n    const contentType = mem['Content-Type'];\n    if (typeof contentType !== 'undefined' &&\n      contentType.startsWith('application/dicom')) {\n      return true;\n    }\n    if (typeof mem.filename !== 'undefined') {\n      const tmpFile = new File(['from memory'], mem.filename);\n      return this.canLoadFile(tmpFile);\n    }\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class DicomDataLoader\n","import {startsWith, getFileExtension} from '../utils/string';\nimport {getUrlFromUri} from '../utils/uri';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\n\n/**\n * JSON text loader.\n */\nexport class JSONTextLoader {\n\n  /**\n   * Loading flag.\n   *\n   * @type {boolean}\n   */\n  #isLoading = false;\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} _opt The input options.\n   */\n  setOptions(_opt) {\n    // does nothing\n  }\n\n  /**\n   * Is the load ongoing?\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return this.#isLoading;\n  }\n\n  /**\n   * Load data.\n   *\n   * @param {object} text The input text.\n   * @param {string} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(text, origin, index) {\n    // set loading flag\n    this.#isLoading = true;\n    this.onloadstart({\n      source: origin\n    });\n\n    try {\n      this.onprogress({\n        lengthComputable: true,\n        loaded: 100,\n        total: 100,\n        index: index,\n        source: origin\n      });\n      const data = {\n        data: text,\n        source: origin\n      };\n      // only expecting one item\n      this.onloaditem(data);\n      this.onload(data);\n    } catch (error) {\n      this.onerror({\n        error: error,\n        source: origin\n      });\n    } finally {\n      // reset loading flag\n      this.#isLoading = false;\n      this.onloadend({\n        source: origin\n      });\n    }\n  }\n\n  /**\n   * Abort load: pass to listeners.\n   */\n  abort() {\n    // reset loading flag\n    this.#isLoading = false;\n    // call listeners\n    this.onabort({});\n    this.onloadend({});\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * True if the file has a 'json' extension.\n   *\n   * @param {File} file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(file) {\n    const ext = getFileExtension(file.name);\n    return (ext === 'json');\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'json',\n   * - the `options.requestHeaders` contains a 'Accept: application/json' or\n   *   'Accept: application/dicom+json',\n   * - the url has a 'json' extension.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'json') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'application/json' or 'application/dicom+json\n          return startsWith(acceptHeader.value, 'application/json') ||\n            startsWith(acceptHeader.value, 'application/dicom+json');\n        }\n      }\n    }\n\n    const urlObjext = getUrlFromUri(url);\n    const ext = getFileExtension(urlObjext.pathname);\n    return (ext === 'json');\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} mem The memory object.\n   * @returns {boolean} True if the object can be loaded.\n   */\n  canLoadMemory(mem) {\n    const contentType = mem['Content-Type'];\n    if (typeof contentType !== 'undefined' &&\n      contentType.startsWith('application/json')) {\n      return true;\n    }\n    if (typeof mem.filename !== 'undefined') {\n      const tmpFile = new File(['from memory'], mem.filename);\n      return this.canLoadFile(tmpFile);\n    }\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.Text;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.Text;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class JSONTextLoader\n","import {startsWith} from '../utils/string';\nimport {parseMultipart} from '../utils/array';\nimport {MemoryLoader} from './memoryLoader';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\n\n/**\n * Multipart data loader.\n */\nexport class MultipartLoader {\n\n  /**\n   * Loading flag.\n   *\n   * @type {boolean}\n   */\n  #isLoading = false;\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} _opt The input options.\n   */\n  setOptions(_opt) {\n    // does nothing\n  }\n\n  /**\n   * Is the load ongoing?\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return this.#isLoading;\n  }\n\n  /**\n   * Load data.\n   *\n   * @param {object} buffer The DICOM buffer.\n   * @param {string} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(buffer, origin, index) {\n    // send start event\n    this.onloadstart({\n      source: origin\n    });\n    // set loading flag\n    this.#isLoading = true;\n\n    const memoryIO = new MemoryLoader();\n    // memoryIO.onloadstart: nothing to do\n    memoryIO.onprogress = (progress) => {\n      // add 50% to take into account the un-Multipartping\n      progress.loaded = 50 + progress.loaded / 2;\n      // set data index\n      progress.index = index;\n      this.onprogress(progress);\n    };\n    memoryIO.onloaditem = this.onloaditem;\n    memoryIO.onload = this.onload;\n    memoryIO.onloadend = (event) => {\n      // reset loading flag\n      this.#isLoading = false;\n      // call listeners\n      this.onloadend(event);\n    };\n    memoryIO.onerror = this.onerror;\n    memoryIO.onabort = this.onabort;\n    // launch\n    memoryIO.load(parseMultipart(buffer));\n  }\n\n  /**\n   * Abort load: pass to listeners.\n   */\n  abort() {\n    // reset loading flag\n    this.#isLoading = false;\n    // call listeners\n    this.onabort({});\n    this.onloadend({});\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * Always returns false.\n   *\n   * @param {File} _file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(_file) {\n    return false;\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'multipart',\n   * - the `options.requestHeaders` contains a 'Accept: multipart/related'.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'multipart') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'multipart/related'\n          return startsWith(acceptHeader.value, 'multipart/related');\n        }\n      }\n    }\n\n    return false;\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} _mem The memory object.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadMemory(_mem) {\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class MultipartLoader\n","import {startsWith, getFileExtension} from '../utils/string';\nimport {getUrlFromUri} from '../utils/uri';\nimport {getViewFromDOMImage} from '../image/domReader';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\n\n/**\n * Raw image loader.\n */\nexport class RawImageLoader {\n\n  /**\n   * If abort is triggered, all image.onload callbacks have to be cancelled.\n   *\n   * @type {boolean}\n   */\n  #aborted = false;\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} _opt The input options.\n   */\n  setOptions(_opt) {\n    // does nothing\n  }\n\n  /**\n   * Is the load ongoing? TODO...\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return true;\n  }\n\n  /**\n   * Create a Data URI from an HTTP request response.\n   *\n   * @param {ArrayBuffer} response The HTTP request response.\n   * @param {string} dataType The data type.\n   * @returns {string} The data URI.\n   */\n  #createDataUri(response, dataType) {\n    // image type\n    let imageType = dataType;\n    if (!imageType || imageType === 'jpg') {\n      imageType = 'jpeg';\n    }\n    // create uri\n    const file = new Blob([response], {type: 'image/' + imageType});\n    return window.URL.createObjectURL(file);\n  }\n\n  /**\n   * Load data.\n   *\n   * @param {ArrayBuffer|string} buffer The read data.\n   * @param {string|File} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(buffer, origin, index) {\n    this.#aborted = false;\n    // create a DOM image\n    const image = new Image();\n    // triggered by ctx.drawImage\n    image.onload = (/*event*/) => {\n      try {\n        if (!this.#aborted) {\n          this.onprogress({\n            lengthComputable: true,\n            loaded: 100,\n            total: 100,\n            index: index,\n            source: origin\n          });\n          const data = getViewFromDOMImage(image, origin, index);\n          // only expecting one item\n          this.onloaditem(data);\n          this.onload(data);\n        }\n      } catch (error) {\n        this.onerror({\n          error: error,\n          source: origin\n        });\n      } finally {\n        this.onloadend({\n          source: origin\n        });\n      }\n    };\n    // storing values to pass them on\n    if (typeof buffer === 'string') {\n      // file case\n      image.src = buffer;\n    } else if (typeof origin === 'string') {\n      // url case\n      const ext = origin.split('.').pop().toLowerCase();\n      image.src = this.#createDataUri(buffer, ext);\n    }\n  }\n\n  /**\n   * Abort load.\n   */\n  abort() {\n    this.#aborted = true;\n    this.onabort({});\n    this.onloadend({});\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * True for files with type 'image.*'.\n   *\n   * @param {File} file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(file) {\n    return (typeof file.type !== 'undefined' &&\n      file.type.match('image.*') !== null);\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'rawimage',\n   * - the `options.requestHeaders` contains an item\n   *   starting with 'Accept: image/'.\n   * - the url has a 'contentType' and it is 'image/jpeg', 'image/png'\n   *   or 'image/gif' (as in wado urls),\n   * - the url has no 'contentType' and the extension is 'jpeg', 'jpg',\n   *   'png' or 'gif'.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'rawimage') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'image/'\n          return startsWith(acceptHeader.value, 'image/');\n        }\n      }\n    }\n\n    const urlObjext = getUrlFromUri(url);\n    // extension\n    const ext = getFileExtension(urlObjext.pathname);\n    const hasImageExt = (ext === 'jpeg') || (ext === 'jpg') ||\n      (ext === 'png') || (ext === 'gif');\n    // content type (for wado url)\n    const contentType = urlObjext.searchParams.get('contentType');\n    const hasContentType = contentType !== null &&\n      typeof contentType !== 'undefined';\n    const hasImageContentType = (contentType === 'image/jpeg') ||\n      (contentType === 'image/png') ||\n      (contentType === 'image/gif');\n\n    return hasContentType ? hasImageContentType : hasImageExt;\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} mem The memory object.\n   * @returns {boolean} True if the object can be loaded.\n   */\n  canLoadMemory(mem) {\n    if (typeof mem.filename !== 'undefined') {\n      const tmpFile = new File(['from memory'], mem.filename);\n      return this.canLoadFile(tmpFile);\n    }\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.DataURL;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class RawImageLoader","import {startsWith, getFileExtension} from '../utils/string';\nimport {getUrlFromUri} from '../utils/uri';\nimport {getViewFromDOMVideo} from '../image/domReader';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\n\n/**\n * Raw video loader.\n *\n * Url example (cors enabled):\n *   {@link https://raw.githubusercontent.com/clappr/clappr/master/test/fixtures/SampleVideo_360x240_1mb.mp4}.\n */\nexport class RawVideoLoader {\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} _opt The input options.\n   */\n  setOptions(_opt) {\n    // does nothing\n  }\n\n  /**\n   * Is the load ongoing? TODO...\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return true;\n  }\n\n  /**\n   * Create a Data URI from an HTTP request response.\n   *\n   * @param {object} response The HTTP request response.\n   * @param {string} dataType The data type.\n   * @returns {string} The data URI.\n   */\n  #createDataUri(response, dataType) {\n    // image data as string\n    const bytes = new Uint8Array(response);\n    let videoDataStr = '';\n    for (let i = 0; i < bytes.byteLength; ++i) {\n      videoDataStr += String.fromCharCode(bytes[i]);\n    }\n    // create uri\n    const uri = 'data:video/' + dataType +\n      ';base64,' + window.btoa(videoDataStr);\n    return uri;\n  }\n\n  /**\n   * Internal Data URI load.\n   *\n   * @param {object} buffer The read data.\n   * @param {string} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(buffer, origin, index) {\n    // create a DOM video\n    const video = document.createElement('video');\n    if (typeof origin === 'string') {\n      // url case\n      const ext = origin.split('.').pop().toLowerCase();\n      video.src = this.#createDataUri(buffer, ext);\n    } else {\n      video.src = buffer;\n    }\n    // onload handler\n    video.onloadedmetadata = (event) => {\n      try {\n        getViewFromDOMVideo(event.target,\n          this.onloaditem, this.onload,\n          this.onprogress, this.onloadend,\n          origin, index);\n      } catch (error) {\n        this.onerror({\n          error: error,\n          source: origin\n        });\n        this.onloadend({\n          source: origin\n        });\n      }\n    };\n  }\n\n  /**\n   * Abort load.\n   */\n  abort() {\n    this.onabort({});\n    this.onloadend({});\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * True for files with type 'video.*'.\n   *\n   * @param {File} file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(file) {\n    return (typeof file.type !== 'undefined' &&\n      file.type.match('video.*') !== null);\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'rawvideo',\n   * - the `options.requestHeaders` contains an item\n   *   starting with 'Accept: video/'.\n   * - the url has a 'mp4', 'ogg' or 'webm' extension.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'rawvideo') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'video/'\n          return startsWith(acceptHeader.value, 'video/');\n        }\n      }\n    }\n\n    const urlObjext = getUrlFromUri(url);\n    const ext = getFileExtension(urlObjext.pathname);\n    return (ext === 'mp4') ||\n      (ext === 'ogg') ||\n      (ext === 'webm');\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} mem The memory object.\n   * @returns {boolean} True if the object can be loaded.\n   */\n  canLoadMemory(mem) {\n    if (typeof mem.filename !== 'undefined') {\n      const tmpFile = new File(['from memory'], mem.filename);\n      return this.canLoadFile(tmpFile);\n    }\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.DataURL;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   * when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   * when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class RawVideoLoader\n","import {startsWith, getFileExtension} from '../utils/string';\nimport {getUrlFromUri} from '../utils/uri';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\nimport {MemoryLoader} from './memoryLoader';\n\n/**\n * The zip library.\n *\n * Ref: {@link https://github.com/Stuk/jszip}.\n *\n * @external JSZip\n */\nimport JSZip from 'jszip';\n\n/**\n * ZIP data loader.\n */\nexport class ZipLoader {\n\n  /**\n   * Loading flag.\n   *\n   * @type {boolean}\n   */\n  #isLoading = false;\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} _opt The input options.\n   */\n  setOptions(_opt) {\n    // does nothing\n  }\n\n  /**\n   * Is the load ongoing?\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return this.#isLoading;\n  }\n\n  #filename = '';\n  #files = [];\n  #zobjs = null;\n\n  /**\n   * JSZip.async callback.\n   *\n   * @param {ArrayBuffer} content Unzipped file image.\n   * @param {object} origin The origin of the file.\n   * @param {number} index The data index.\n   */\n  #zipAsyncCallback(content, origin, index) {\n    this.#files.push({filename: this.#filename, data: content});\n\n    // sent un-ziped progress with the data index\n    // (max 50% to take into account the memory loading)\n    const unzipPercent = this.#files.length * 100 / this.#zobjs.length;\n    this.onprogress({\n      lengthComputable: true,\n      loaded: (unzipPercent / 2),\n      total: 100,\n      index: index,\n      item: {\n        loaded: unzipPercent,\n        total: 100,\n        source: origin\n      }\n    });\n\n    // recursively call until we have all the files\n    if (this.#files.length < this.#zobjs.length) {\n      const num = this.#files.length;\n      this.#filename = this.#zobjs[num].name;\n      this.#zobjs[num].async('arrayBuffer').then((content) => {\n        this.#zipAsyncCallback(content, origin, index);\n      });\n    } else {\n      const memoryIO = new MemoryLoader();\n      // memoryIO.onloadstart: nothing to do\n      memoryIO.onprogress = (progress) => {\n        // add 50% to take into account the un-zipping\n        progress.loaded = 50 + progress.loaded / 2;\n        // set data index\n        progress.index = index;\n        this.onprogress(progress);\n      };\n      memoryIO.onloaditem = this.onloaditem;\n      memoryIO.onload = this.onload;\n      memoryIO.onloadend = (event) => {\n        // reset loading flag\n        this.#isLoading = false;\n        // call listeners\n        this.onloadend(event);\n      };\n      memoryIO.onerror = this.onerror;\n      memoryIO.onabort = this.onabort;\n      // launch\n      memoryIO.load(this.#files);\n    }\n  }\n\n  /**\n   * Load data.\n   *\n   * @param {object} buffer The DICOM buffer.\n   * @param {string} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(buffer, origin, index) {\n    // send start event\n    this.onloadstart({\n      source: origin\n    });\n    // set loading flag\n    this.#isLoading = true;\n\n    JSZip.loadAsync(buffer).then((zip) => {\n      this.#files = [];\n      this.#zobjs = zip.file(/.*\\.dcm/);\n      // recursively load zip files into the files array\n      const num = this.#files.length;\n      this.#filename = this.#zobjs[num].name;\n      this.#zobjs[num].async('arrayBuffer').then((content) => {\n        this.#zipAsyncCallback(content, origin, index);\n      });\n    });\n  }\n\n  /**\n   * Abort load: pass to listeners.\n   */\n  abort() {\n    // reset loading flag\n    this.#isLoading = false;\n    // call listeners\n    this.onabort({});\n    this.onloadend({});\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * True if the file has a 'zip' extension.\n   *\n   * @param {File} file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(file) {\n    const ext = getFileExtension(file.name);\n    return (ext === 'zip');\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'zip',\n   * - the `options.requestHeaders` contains an item\n   *   starting with 'Accept: application/zip'.\n   * - the url has a 'zip' extension.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'zip') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'application/zip'\n          return startsWith(acceptHeader.value, 'application/zip');\n        }\n      }\n    }\n\n    const urlObjext = getUrlFromUri(url);\n    const ext = getFileExtension(urlObjext.pathname);\n    return (ext === 'zip');\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} mem The memory object.\n   * @returns {boolean} True if the object can be loaded.\n   */\n  canLoadMemory(mem) {\n    const contentType = mem['Content-Type'];\n    if (typeof contentType !== 'undefined' &&\n      contentType.startsWith('application/zip')) {\n      return true;\n    }\n    if (typeof mem.filename !== 'undefined') {\n      const tmpFile = new File(['from memory'], mem.filename);\n      return this.canLoadFile(tmpFile);\n    }\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class ZipLoader\n","import {MultiProgressHandler} from '../utils/progress';\nimport {loaderList} from './loaderList';\n\n// file content types\nexport const fileContentTypes = {\n  Text: 0,\n  ArrayBuffer: 1,\n  DataURL: 2\n};\n\n/**\n * Files loader.\n */\nexport class FilesLoader {\n\n  /**\n   * Input data.\n   *\n   * @type {File[]}\n   */\n  #inputData = null;\n\n  /**\n   * Array of launched file readers.\n   *\n   * @type {FileReader[]}\n   */\n  #readers = [];\n\n  /**\n   * Data loader.\n   *\n   * @type {object}\n   */\n  #runningLoader = null;\n\n  /**\n   * Number of loaded data.\n   *\n   * @type {number}\n   */\n  #nLoad = 0;\n\n  /**\n   * Number of load end events.\n   *\n   * @type {number}\n   */\n  #nLoadend = 0;\n\n  /**\n   * The default character set (optional).\n   *\n   * @type {string}\n   */\n  #defaultCharacterSet;\n\n  /**\n   * Get the default character set.\n   *\n   * @returns {string} The default character set.\n   */\n  getDefaultCharacterSet() {\n    return this.#defaultCharacterSet;\n  }\n\n  /**\n   * Set the default character set.\n   *\n   * @param {string} characterSet The character set.\n   */\n  setDefaultCharacterSet(characterSet) {\n    this.#defaultCharacterSet = characterSet;\n  }\n\n  /**\n   * Store the current input.\n   *\n   * @param {File[]} data The input data.\n   */\n  #storeInputData(data) {\n    this.#inputData = data;\n    // reset counters\n    this.#nLoad = 0;\n    this.#nLoadend = 0;\n    // clear storage\n    this.#clearStoredReaders();\n    this.#clearStoredLoader();\n  }\n\n  /**\n   * Store a launched reader.\n   *\n   * @param {FileReader} reader The launched reader.\n   */\n  #storeReader(reader) {\n    this.#readers.push(reader);\n  }\n\n  /**\n   * Clear the stored readers.\n   *\n   */\n  #clearStoredReaders() {\n    this.#readers = [];\n  }\n\n  /**\n   * Store the launched loader.\n   *\n   * @param {object} loader The launched loader.\n   */\n  #storeLoader(loader) {\n    this.#runningLoader = loader;\n  }\n\n  /**\n   * Clear the stored loader.\n   *\n   */\n  #clearStoredLoader() {\n    this.#runningLoader = null;\n  }\n\n  /**\n   * Increment the number of loaded data\n   *   and call onload if loaded all data.\n   *\n   * @param {object} _event The load data event.\n   */\n  #addLoad = (_event) => {\n    this.#nLoad++;\n    // call onload when all is loaded\n    // (not using the input event since it is\n    //   an individual load)\n    if (this.#nLoad === this.#inputData.length) {\n      this.onload({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * Increment the counter of load end events\n   *   and run callbacks when all done, erroneus or not.\n   *\n   * @param {object} _event The load end event.\n   */\n  #addLoadend = (_event) => {\n    this.#nLoadend++;\n    // call onloadend when all is run\n    // (not using the input event since it is\n    //   an individual load end)\n    if (this.#nLoadend === this.#inputData.length) {\n      this.onloadend({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * @callback eventFn\n   * @param {object} event The event.\n   */\n\n  /**\n   * Augment a callback event with a srouce.\n   *\n   * @param {object} callback The callback to augment its event.\n   * @param {object} source The source to add to the event.\n   * @returns {eventFn} The augmented callback.\n   */\n  #augmentCallbackEvent(callback, source) {\n    return (event) => {\n      event.source = source;\n      callback(event);\n    };\n  }\n\n  /**\n   * Get a load handler for a data element.\n   *\n   * @param {object} loader The associated loader.\n   * @param {File} dataElement The data element.\n   * @param {number} i The index of the element.\n   * @returns {eventFn} A load handler.\n   */\n  #getLoadHandler(loader, dataElement, i) {\n    return (event) => {\n      loader.load(event.target.result, dataElement, i);\n    };\n  }\n\n\n  /**\n   * Load a list of files.\n   *\n   * @param {File[]} data The list of files to load.\n   */\n  load(data) {\n    // check input\n    if (typeof data === 'undefined' || data.length === 0) {\n      return;\n    }\n    this.#storeInputData(data);\n\n    // send start event\n    this.onloadstart({\n      source: data\n    });\n\n    // create prgress handler\n    const mproghandler = new MultiProgressHandler(this.onprogress);\n    mproghandler.setNToLoad(data.length);\n\n    // create loaders\n    const loaders = [];\n    for (let m = 0; m < loaderList.length; ++m) {\n      loaders.push(new loaderList[m]());\n    }\n\n    // find an appropriate loader\n    let dataElement = data[0];\n    let loader = null;\n    let foundLoader = false;\n    for (let l = 0; l < loaders.length; ++l) {\n      loader = loaders[l];\n      if (loader.canLoadFile(dataElement)) {\n        foundLoader = true;\n        // load options\n        loader.setOptions({\n          numberOfFiles: data.length,\n          defaultCharacterSet: this.getDefaultCharacterSet()\n        });\n        // set loader callbacks\n        // loader.onloadstart: nothing to do\n        loader.onprogress = mproghandler.getUndefinedMonoProgressHandler(1);\n        loader.onloaditem = this.onloaditem;\n        loader.onload = this.#addLoad;\n        loader.onloadend = this.#addLoadend;\n        loader.onerror = this.onerror;\n        loader.onabort = this.onabort;\n\n        // store loader\n        this.#storeLoader(loader);\n        // exit\n        break;\n      }\n    }\n    if (!foundLoader) {\n      throw new Error('No loader found for file: ' + dataElement.name);\n    }\n\n    // loop on I/O elements\n    for (let i = 0; i < data.length; ++i) {\n      dataElement = data[i];\n\n      // check loader\n      if (!loader.canLoadFile(dataElement)) {\n        throw new Error('Input file of different type: ' + dataElement);\n      }\n\n      /**\n       * The file reader.\n       *\n       * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/FileReader}.\n       *\n       * @external FileReader\n       */\n      const reader = new FileReader();\n      // store reader\n      this.#storeReader(reader);\n\n      // set reader callbacks\n      // reader.onloadstart: nothing to do\n      reader.onprogress = this.#augmentCallbackEvent(\n        mproghandler.getMonoProgressHandler(i, 0), dataElement);\n      reader.onload = this.#getLoadHandler(loader, dataElement, i);\n      // reader.onloadend: nothing to do\n      const errorCallback =\n        this.#augmentCallbackEvent(this.onerror, dataElement);\n      reader.onerror = (event) => {\n        this.#addLoadend();\n        errorCallback(event);\n      };\n      const abortCallback =\n        this.#augmentCallbackEvent(this.onabort, dataElement);\n      reader.onabort = (event) => {\n        this.#addLoadend();\n        abortCallback(event);\n      };\n      // read\n      if (loader.loadFileAs() === fileContentTypes.Text) {\n        reader.readAsText(dataElement);\n      } else if (loader.loadFileAs() === fileContentTypes.DataURL) {\n        reader.readAsDataURL(dataElement);\n      } else if (loader.loadFileAs() === fileContentTypes.ArrayBuffer) {\n        reader.readAsArrayBuffer(dataElement);\n      }\n    }\n  }\n\n  /**\n   * Abort a load.\n   */\n  abort() {\n    // abort readers\n    for (let i = 0; i < this.#readers.length; ++i) {\n      // 0: EMPTY, 1: LOADING, 2: DONE\n      if (this.#readers[i].readyState === 1) {\n        this.#readers[i].abort();\n      }\n    }\n    // abort loader\n    if (this.#runningLoader && this.#runningLoader.isLoading()) {\n      this.#runningLoader.abort();\n    }\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle a load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class FilesLoader\n","import {FilesLoader} from '../io/filesLoader';\nimport {MemoryLoader} from '../io/memoryLoader';\nimport {UrlsLoader} from '../io/urlsLoader';\n\n/**\n * Load controller.\n */\nexport class LoadController {\n\n  /**\n   * The default character set.\n   *\n   * @type {string}\n   */\n  #defaultCharacterSet;\n\n  /**\n   * List of current loaders.\n   *\n   * @type {object}\n   */\n  #currentLoaders = {};\n\n  /**\n   * @param {string} defaultCharacterSet The default character set.\n   */\n  constructor(defaultCharacterSet) {\n    this.#defaultCharacterSet = defaultCharacterSet;\n  }\n\n  /**\n   * Load a list of files. Can be image files or a state file.\n   *\n   * @param {File[]} files The list of files to load.\n   * @param {string} dataId The data Id.\n   */\n  loadFiles(files, dataId) {\n    // has been checked for emptiness.\n    const ext = files[0].name.split('.').pop().toLowerCase();\n    if (ext === 'json') {\n      this.#loadStateFile(files[0], dataId);\n    } else {\n      this.#loadImageFiles(files, dataId);\n    }\n  }\n\n  /**\n   * Load a list of URLs. Can be image files or a state file.\n   *\n   * @param {string[]} urls The list of urls to load.\n   * @param {string} dataId The data Id.\n   * @param {object} [options] The load options:\n   * - requestHeaders: an array of {name, value} to use as request headers.\n   * - withCredentials: credentials flag to pass to the request.\n   */\n\n  loadURLs(urls, dataId, options) {\n    // has been checked for emptiness.\n    const ext = urls[0].split('.').pop().toLowerCase();\n    if (ext === 'json') {\n      this.#loadStateUrl(urls[0], dataId, options);\n    } else {\n      this.#loadImageUrls(urls, dataId, options);\n    }\n  }\n\n  /**\n   * Load a list of ArrayBuffers.\n   *\n   * @param {Array} data The list of ArrayBuffers to load\n   *   in the form of [{name: '', filename: '', data: data}].\n   * @param {string} dataId The data Id.\n   */\n  loadImageObject(data, dataId) {\n    // create IO\n    const memoryIO = new MemoryLoader();\n    // load data\n    this.#loadData(data, memoryIO, 'image', dataId);\n  }\n\n  /**\n   * Get the currently loaded data ids.\n   *\n   * @returns {string[]} The data ids.\n   */\n  getLoadingDataIds() {\n    return Object.keys(this.#currentLoaders);\n  }\n\n  /**\n   * Abort an individual current loader.\n   *\n   * @param {string} dataId The data to stop loading.\n   */\n  abort(dataId) {\n    if (typeof this.#currentLoaders[dataId] !== 'undefined') {\n      this.#currentLoaders[dataId].loader.abort();\n      delete this.#currentLoaders[dataId];\n    }\n  }\n\n  // private ----------------------------------------------------------------\n\n  /**\n   * Load a list of image files.\n   *\n   * @param {File[]} files The list of image files to load.\n   * @param {string} dataId The data Id.\n   */\n  #loadImageFiles(files, dataId) {\n    // create IO\n    const fileIO = new FilesLoader();\n    fileIO.setDefaultCharacterSet(this.#defaultCharacterSet);\n    // load data\n    this.#loadData(files, fileIO, 'image', dataId);\n  }\n\n  /**\n   * Load a list of image URLs.\n   *\n   * @param {string[]} urls The list of urls to load.\n   * @param {string} [dataId] The data Id.\n   * @param {object} [options] The load options:\n   * - requestHeaders: an array of {name, value} to use as request headers.\n   * - withCredentials: credentials flag to pass to the request.\n   */\n  #loadImageUrls(urls, dataId, options) {\n    // create IO\n    const urlIO = new UrlsLoader();\n    urlIO.setDefaultCharacterSet(this.#defaultCharacterSet);\n    // load data\n    this.#loadData(urls, urlIO, 'image', dataId, options);\n  }\n\n  /**\n   * Load a State file.\n   *\n   * @param {File} file The state file to load.\n   * @param {string} dataId The data Id.\n   */\n  #loadStateFile(file, dataId) {\n    // create IO\n    const fileIO = new FilesLoader();\n    // load data\n    this.#loadData([file], fileIO, 'state', dataId);\n  }\n\n\n  /**\n   * Load a State url.\n   *\n   * @param {string} url The state url to load.\n   * @param {string} [dataId] The data Id.\n   * @param {object} [options] The load options:\n   * - requestHeaders: an array of {name, value} to use as request headers.\n   * - withCredentials: credentials flag to pass to the request.\n   */\n  #loadStateUrl(url, dataId, options) {\n    // create IO\n    const urlIO = new UrlsLoader();\n    // load data\n    this.#loadData([url], urlIO, 'state', dataId, options);\n  }\n\n  /**\n   * Load a list of data.\n   *\n   * @param {string[]|File[]|Array} data Array of data to load.\n   * @param {object} loader The data loader.\n   * @param {string} loadType The data load type: 'image' or 'state'.\n   * @param {string} dataId The data id.\n   * @param {object} [options] Options passed to the final loader.\n   */\n  #loadData(data, loader, loadType, dataId, options) {\n    const eventInfo = {\n      loadtype: loadType,\n      dataid: dataId\n    };\n\n    // set callbacks\n    loader.onloadstart = (event) => {\n      // store loader to allow abort\n      this.#currentLoaders[dataId] = {\n        loader: loader,\n        isFirstItem: true\n      };\n      // callback\n      this.#augmentCallbackEvent(this.onloadstart, eventInfo)(event);\n    };\n    loader.onprogress = this.#augmentCallbackEvent(this.onprogress, eventInfo);\n    loader.onloaditem = (event) => {\n      const eventInfoItem = {\n        loadtype: loadType,\n        dataid: dataId\n      };\n      if (typeof this.#currentLoaders[dataId] !== 'undefined') {\n        eventInfoItem.isfirstitem = this.#currentLoaders[dataId].isFirstItem;\n      }\n      // callback\n      this.#augmentCallbackEvent(this.onloaditem, eventInfoItem)(event);\n      // update loader\n      if (typeof this.#currentLoaders[dataId] !== 'undefined' &&\n        this.#currentLoaders[dataId].isFirstItem) {\n        this.#currentLoaders[dataId].isFirstItem = false;\n      }\n    };\n    loader.onload = this.#augmentCallbackEvent(this.onload, eventInfo);\n    loader.onloadend = (event) => {\n      // reset current loader\n      delete this.#currentLoaders[dataId];\n      // callback\n      this.#augmentCallbackEvent(this.onloadend, eventInfo)(event);\n    };\n    loader.onerror = this.#augmentCallbackEvent(this.onerror, eventInfo);\n    loader.onabort = this.#augmentCallbackEvent(this.onabort, eventInfo);\n    if (typeof loader.ontimeout !== 'undefined') {\n      loader.ontimeout = this.#augmentCallbackEvent(this.ontimeout, eventInfo);\n    }\n    // launch load\n    try {\n      loader.load(data, options);\n    } catch (error) {\n      this.onerror({\n        error: error,\n        dataid: dataId\n      });\n      this.onloadend({\n        dataid: dataId\n      });\n      return;\n    }\n  }\n\n  /**\n   * Augment a callback event: adds loadtype to the event\n   *  passed to a callback.\n   *\n   * @param {object} callback The callback to update.\n   * @param {object} info Info object to append to the event.\n   * @returns {object} A function representing the modified callback.\n   */\n  #augmentCallbackEvent(callback, info) {\n    return function (event) {\n      const keys = Object.keys(info);\n      for (let i = 0; i < keys.length; ++i) {\n        const key = keys[i];\n        event[key] = info[key];\n      }\n      callback(event);\n    };\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when an item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle a timeout event.\n   * Default does nothing.\n   *\n   * @param {object} _event The timeout event.\n   */\n  ontimeout(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class LoadController\n","import {ListenerHandler} from '../utils/listen';\nimport {getReverseOrientation} from '../dicom/dicomParser';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get a number toprecision function with the provided precision.\n *\n * @param {number} precision The precision to achieve.\n * @returns {Function} The to precision function.\n */\nfunction getNumberToPrecision(precision) {\n  return function (num) {\n    return Number(num).toPrecision(precision);\n  };\n}\n\n/**\n * Create a default replace format from a given length.\n * For example: '{v0}, {v1}'.\n *\n * @param {number} length The length of the format.\n * @returns {string} A replace format.\n */\nfunction createDefaultReplaceFormat(length) {\n  let res = '';\n  for (let i = 0; i < length; ++i) {\n    if (i !== 0) {\n      res += ', ';\n    }\n    res += '{v' + i + '}';\n  }\n  return res;\n}\n\n/**\n * Replace flags in a input string. Flags are keywords surrounded with curly\n * braces in the form: '{v0}, {v1}'.\n *\n * @param {string} inputStr The input string.\n * @param {string[]} values An array of strings.\n * @example\n *    var values = [\"a\", \"b\"];\n *    var str = \"The length is: {v0}. The size is: {v1}\";\n *    var res = replaceFlags(str, values);\n *    // \"The length is: a. The size is: b\"\n * @returns {string} The result string.\n */\nfunction replaceFlags(inputStr, values) {\n  let res = inputStr;\n  for (let i = 0; i < values.length; ++i) {\n    res = res.replace('{v' + i + '}', values[i]);\n  }\n  return res;\n}\n\n/**\n * DICOM Header overlay info.\n */\nexport class OverlayData {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Associated data id.\n   *\n   * @type {string}\n   */\n  #dataId;\n\n  /**\n   * Overlay config.\n   *\n   * @type {object}\n   */\n  #configs;\n\n  /**\n   * List of event used by the config.\n   *\n   * @type {string[]}\n   */\n  #eventNames = [];\n\n  /**\n   * Flag to know if listening to app.\n   *\n   * @type {boolean}\n   */\n  #isListening;\n\n  /**\n   * Overlay data.\n   *\n   * @type {Array}\n   */\n  #data = [];\n\n  /**\n   * Current data uid: set on pos change.\n   *\n   * @type {number}\n   */\n  #currentDataUid;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * @param {App} app The associated application.\n   * @param {string} dataId The associated data id.\n   * @param {object} configs The overlay config.\n   */\n  constructor(app, dataId, configs) {\n    this.#app = app;\n    this.#dataId = dataId;\n    this.#configs = configs;\n\n    // parse overlays to get the list of events to listen to\n    const keys = Object.keys(this.#configs);\n    for (let i = 0; i < keys.length; ++i) {\n      const config = this.#configs[keys[i]];\n      for (let j = 0; j < config.length; ++j) {\n        const eventType = config[j].event;\n        if (typeof eventType !== 'undefined') {\n          if (!this.#eventNames.includes(eventType)) {\n            this.#eventNames.push(eventType);\n          }\n        }\n      }\n    }\n    // add app listeners\n    this.addAppListeners();\n  }\n\n  /**\n   * Reset the data.\n   */\n  reset() {\n    this.#data = [];\n    this.#currentDataUid = undefined;\n  }\n\n  /**\n   * Handle a new loaded item event.\n   *\n   * @param {object} data The item meta data.\n   */\n  addItemMeta(data) {\n    // create and store overlay data\n    let dataUid;\n    // check if dicom data (00020010: transfer syntax)\n    if (typeof data['00020010'] !== 'undefined') {\n      if (typeof data['00080018'] !== 'undefined') {\n        // SOP instance UID\n        dataUid = data['00080018'].value[0];\n      } else {\n        dataUid = data.length;\n      }\n      this.#data[dataUid] = createOverlayData(data, this.#configs);\n    } else {\n      // image file case\n      const keys = Object.keys(data);\n      for (let d = 0; d < keys.length; ++d) {\n        const obj = data[keys[d]];\n        if (keys[d] === 'imageUid') {\n          dataUid = obj.value;\n          break;\n        }\n      }\n      this.#data[dataUid] = createOverlayDataForDom(data, this.#configs);\n    }\n    // store uid\n    this.#currentDataUid = dataUid;\n  }\n\n  /**\n   * Handle a changed slice event.\n   *\n   * @param {object} event The slicechange event.\n   */\n  #onSliceChange = (event) => {\n    if (event.dataid !== this.#dataId) {\n      return;\n    }\n    if (typeof event.data !== 'undefined' &&\n      typeof event.data.imageUid !== 'undefined' &&\n      this.#currentDataUid !== event.data.imageUid) {\n      this.#currentDataUid = event.data.imageUid;\n      this.#updateData(event);\n    }\n  };\n\n  /**\n   * Update the overlay data.\n   *\n   * @param {object} event An event defined by the overlay map and\n   *   registered in toggleListeners.\n   */\n  #updateData = (event) => {\n    if (event.dataid !== this.#dataId) {\n      return;\n    }\n\n    const sliceOverlayData = this.#data[this.#currentDataUid];\n    if (typeof sliceOverlayData === 'undefined') {\n      console.warn('No slice overlay data for: ' + this.#currentDataUid);\n      return;\n    }\n\n    for (let n = 0; n < sliceOverlayData.length; ++n) {\n      let text = undefined;\n      if (typeof sliceOverlayData[n].tags !== 'undefined') {\n        // update tags only on slice change\n        if (event.type === 'positionchange') {\n          text = sliceOverlayData[n].value;\n        }\n      } else {\n        // update text if the value is an event type\n        if (typeof sliceOverlayData[n].event !== 'undefined' &&\n          sliceOverlayData[n].event === event.type) {\n          const format = sliceOverlayData[n].format;\n          let values = event.value;\n          // optional number precision\n          if (typeof sliceOverlayData[n].precision !== 'undefined') {\n            let mapFunc = null;\n            if (sliceOverlayData[n].precision === 'round') {\n              mapFunc = Math.round;\n            } else {\n              mapFunc = getNumberToPrecision(sliceOverlayData[n].precision);\n            }\n            values = values.map(mapFunc);\n          }\n          text = replaceFlags(format, values);\n        }\n      }\n      if (typeof text !== 'undefined') {\n        sliceOverlayData[n].value = text;\n      }\n    }\n\n    /**\n     * Value change event.\n     *\n     * @event OverlayData#valuechange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} data The value of the overlay data.\n     */\n    this.#fireEvent({\n      type: 'valuechange',\n      data: sliceOverlayData\n    });\n  };\n\n  /**\n   * Is this class listening to app events.\n   *\n   * @returns {boolean} True is listening to app events.\n   */\n  isListening() {\n    return this.#isListening;\n  }\n\n  /**\n   * Toggle info listeners.\n   */\n  addAppListeners() {\n    // listen to update tags data\n    this.#app.addEventListener('positionchange', this.#onSliceChange);\n    // add event listeners\n    for (let i = 0; i < this.#eventNames.length; ++i) {\n      this.#app.addEventListener(this.#eventNames[i], this.#updateData);\n    }\n    // update flag\n    this.#isListening = true;\n  }\n\n  /**\n   * Toggle info listeners.\n   */\n  removeAppListeners() {\n    // stop listening to update tags data\n    this.#app.removeEventListener('positionchange', this.#onSliceChange);\n    // remove event listeners\n    for (let i = 0; i < this.#eventNames.length; ++i) {\n      this.#app.removeEventListener(this.#eventNames[i], this.#updateData);\n    }\n    // update flag\n    this.#isListening = false;\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {object} callback The method associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {object} callback The method associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent(event) {\n    this.#listenerHandler.fireEvent(event);\n  }\n\n} // class OverlayData\n\n/**\n * Create overlay data array for a DICOM image.\n *\n * @param {object} dicomElements DICOM elements of the image.\n * @param {object} configs The overlay data configs.\n * @returns {Array} Overlay data array.\n */\nfunction createOverlayData(dicomElements, configs) {\n  const overlays = [];\n  let modality;\n  const modElement = dicomElements['00080060'];\n  if (typeof modElement !== 'undefined') {\n    modality = modElement.value[0];\n  } else {\n    return overlays;\n  }\n  const config = configs[modality] || configs['*'];\n  if (!config) {\n    return overlays;\n  }\n\n  for (let n = 0; n < config.length; ++n) {\n    // deep copy\n    const overlay = JSON.parse(JSON.stringify(config[n]));\n\n    // add tag values\n    const tags = overlay.tags;\n    if (typeof tags !== 'undefined' && tags.length !== 0) {\n      // get values\n      const values = [];\n      for (let i = 0; i < tags.length; ++i) {\n        const elem = dicomElements[tags[i]];\n        if (typeof elem !== 'undefined') {\n          values.push(dicomElements[tags[i]].value);\n        } else {\n          values.push('');\n        }\n      }\n      // format\n      if (typeof overlay.format === 'undefined' || overlay.format === null) {\n        overlay.format = createDefaultReplaceFormat(values.length);\n      }\n      overlay.value = replaceFlags(overlay.format, values).trim();\n    }\n\n    // store\n    overlays.push(overlay);\n  }\n\n  // (0020,0020) Patient Orientation\n  const poElement = dicomElements['00200020'];\n  if (typeof poElement !== 'undefined' &&\n    poElement.value.length === 2\n  ) {\n    const po0 = poElement.value[0];\n    const po1 = poElement.value[1];\n    overlays.push({\n      pos: 'cr', value: po0, format: '{v0}'\n    });\n    overlays.push({\n      pos: 'cl', value: getReverseOrientation(po0), format: '{v0}'\n    });\n    overlays.push({\n      pos: 'bc', value: po1, format: '{v0}'\n    });\n    overlays.push({\n      pos: 'tc', value: getReverseOrientation(po1), format: '{v0}'\n    });\n  }\n\n  return overlays;\n}\n\n/**\n * Create overlay data array for a DOM image.\n *\n * @param {object} info Meta data.\n * @param {object} configs The overlay data configs.\n * @returns {Array} Overlay data array.\n */\nfunction createOverlayDataForDom(info, configs) {\n  const overlays = [];\n  const config = configs.DOM;\n  if (!config) {\n    return overlays;\n  }\n\n  const infoKeys = Object.keys(info);\n\n  for (let n = 0; n < config.length; ++n) {\n    // deep copy\n    const overlay = JSON.parse(JSON.stringify(config[n]));\n\n    // add tag values\n    const tags = overlay.tags;\n    if (typeof tags !== 'undefined' && tags.length !== 0) {\n      // get values\n      const values = [];\n      for (let i = 0; i < tags.length; ++i) {\n        for (let j = 0; j < infoKeys.length; ++j) {\n          if (tags[i] === infoKeys[j]) {\n            values.push(info[infoKeys[j]].value);\n          }\n        }\n      }\n      // format\n      if (typeof overlay.format === 'undefined' || overlay.format === null) {\n        overlay.format = createDefaultReplaceFormat(values.length);\n      }\n      overlay.value = replaceFlags(overlay.format, values).trim();\n    }\n\n    // store\n    overlays.push(overlay);\n  }\n\n  return overlays;\n}\n","import {viewEventNames} from '../image/view';\nimport {ViewFactory} from '../image/viewFactory';\nimport {\n  getMatrixFromName,\n  getOrientationStringLPS,\n  Orientation,\n  getViewOrientation\n} from '../math/orientation';\nimport {Point3D} from '../math/point';\nimport {Stage} from '../gui/stage';\nimport {Style} from '../gui/style';\nimport {getLayerDetailsFromLayerDivId} from '../gui/layerGroup';\nimport {ListenerHandler} from '../utils/listen';\nimport {State} from '../io/state';\nimport {logger} from '../utils/logger';\nimport {getUriQuery, decodeQuery} from '../utils/uri';\nimport {UndoStack} from '../utils/undoStack';\nimport {ToolboxController} from './toolboxController';\nimport {LoadController} from './loadController';\nimport {DataController} from './dataController';\nimport {OverlayData} from '../gui/overlayData';\nimport {\n  toolList,\n  defaultToolList,\n  toolOptions,\n  defaultToolOptions\n} from '../tools';\nimport {binderList} from '../gui/stage';\nimport {WindowLevel} from '../image/windowLevel';\nimport {PlaneHelper} from '../image/planeHelper';\nimport {AnnotationGroup} from '../image/annotationGroup';\nimport {konvaToAnnotation} from '../gui/drawLayer';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {LayerGroup} from '../gui/layerGroup';\nimport {ViewLayer} from '../gui/viewLayer';\nimport {DrawLayer} from '../gui/drawLayer';\nimport {Image} from '../image/image';\nimport {Matrix33} from '../math/matrix';\nimport {DataElement} from '../dicom/dataElement';\nimport {Scalar3D} from '../math/scalar';\nimport {DicomData} from './dataController';\n/* eslint-enable no-unused-vars */\n\n/**\n * View configuration: mainly defines the ´divId´\n * of the associated HTML div.\n */\nexport class ViewConfig {\n  /**\n   * Associated HTML div id.\n   *\n   * @type {string}\n   */\n  divId;\n  /**\n   * Optional orientation of the data; 'axial', 'coronal' or 'sagittal'.\n   * If undefined, will use the data aquisition plane.\n   *\n   * @type {string|undefined}\n   */\n  orientation;\n  /**\n   * Optional view colour map name.\n   *\n   * @type {string|undefined}\n   */\n  colourMap;\n  /**\n   * Optional layer opacity; in [0, 1] range.\n   *\n   * @type {number|undefined}\n   */\n  opacity;\n  /**\n   * Optional layer window level preset name.\n   * If present, the preset name will be used and\n   * the window centre and width ignored.\n   *\n   * @type {string|undefined}\n   */\n  wlPresetName;\n  /**\n   * Optional layer window center.\n   *\n   * @type {number|undefined}\n   */\n  windowCenter;\n  /**\n   * Optional layer window width.\n   *\n   * @type {number|undefined}\n   */\n  windowWidth;\n\n  /**\n   * @param {string} divId The associated HTML div id.\n   */\n  constructor(divId) {\n    this.divId = divId;\n  }\n}\n\n/**\n * Tool configuration.\n */\nexport class ToolConfig {\n  /**\n   * Optional tool options.\n   * For Draw: list of shape names.\n   * For Filter: list of filter names.\n   *\n   * @type {string[]|undefined}\n   */\n  options;\n\n  /**\n   * @param {string[]} [options] Optional tool options.\n   */\n  constructor(options) {\n    this.options = options;\n  }\n}\n\n/**\n * Application options.\n */\nexport class AppOptions {\n  /**\n   * DataId indexed object containing the data view configurations.\n   *\n   * @type {Object<string, ViewConfig[]>|undefined}\n   */\n  dataViewConfigs;\n  /**\n   * Tool name indexed object containing individual tool configurations.\n   *\n   * @type {Object<string, ToolConfig>|undefined}\n   */\n  tools;\n  /**\n   * Optional array of layerGroup binder names.\n   *\n   * @type {string[]|undefined}\n   */\n  binders;\n  /**\n   * Optional boolean flag to trigger the first data render\n   *   after the first loaded data or not. Defaults to true.\n   *\n   * @type {boolean|undefined}\n   */\n  viewOnFirstLoadItem;\n  /**\n   * Optional default chraracterset string used for DICOM parsing if\n   *   not passed in DICOM file.\n   *\n   * Valid values: {@link https://developer.mozilla.org/en-US/docs/Web/API/Encoding_API/Encodings}.\n   *\n   * @type {string|undefined}\n   */\n  defaultCharacterSet;\n  /**\n   * Optional overlay config.\n   *\n   * @type {object|undefined}\n   */\n  overlayConfig;\n  /**\n   * DOM root document.\n   *\n   * @type {DocumentFragment}\n   */\n  rootDocument;\n\n  /**\n   * @param {Object<string, ViewConfig[]>} [dataViewConfigs] Optional dataId\n   *   indexed object containing the data view configurations.\n   */\n  constructor(dataViewConfigs) {\n    this.dataViewConfigs = dataViewConfigs;\n  }\n}\n\n/**\n * List of ViewConfigs indexed by dataIds.\n *\n * @typedef {Object<string, ViewConfig[]>} DataViewConfigs\n */\n\n/**\n * Main application class.\n *\n * @example\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * app.init(options);\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n */\nexport class App {\n\n  /**\n   * App options.\n   *\n   * @type {AppOptions}\n   */\n  #options = null;\n\n  /**\n   * Data controller.\n   *\n   * @type {DataController}\n   */\n  #dataController = null;\n\n  /**\n   * Toolbox controller.\n   *\n   * @type {ToolboxController}\n   */\n  #toolboxController = null;\n\n  /**\n   * Load controller.\n   *\n   * @type {LoadController}\n   */\n  #loadController = null;\n\n  /**\n   * Stage.\n   *\n   * @type {Stage}\n   */\n  #stage = null;\n\n  /**\n   * Undo stack.\n   *\n   * @type {UndoStack}\n   */\n  #undoStack = null;\n\n  /**\n   * Style.\n   *\n   * @type {Style}\n   */\n  #style = new Style();\n\n  // overlay datas\n  #overlayDatas = {};\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Get a DicomData.\n   *\n   * @param {string} dataId The data id.\n   * @returns {DicomData|undefined} The data.\n   */\n  getData(dataId) {\n    return this.#dataController.get(dataId);\n  }\n\n  /**\n   * Get the image.\n   *\n   * @param {string} dataId The data id.\n   * @returns {Image|undefined} The associated image.\n   * @deprecated Since v0.34, please use the getData method.\n   */\n  getImage(dataId) {\n    let res;\n    if (typeof this.getData(dataId) !== 'undefined') {\n      res = this.getData(dataId).image;\n    }\n    return res;\n  }\n\n  /**\n   * Set the image at the given id.\n   *\n   * @param {string} dataId The data id.\n   * @param {Image} img The associated image.\n   */\n  setImage(dataId, img) {\n    this.#dataController.setImage(dataId, img);\n  }\n\n  /**\n   * Add a new DicomData.\n   *\n   * @param {DicomData} data The new data.\n   * @returns {string} The data id.\n   */\n  addData(data) {\n    // get a new dataId\n    const dataId = this.#dataController.getNextDataId();\n    // add image to data controller\n    this.#dataController.add(\n      dataId,\n      data\n    );\n    // optional render\n    // if (this.#options.viewOnFirstLoadItem) {\n    //   this.render(dataId);\n    // }\n    // return\n    return dataId;\n  }\n\n  /**\n   * Get the meta data.\n   *\n   * @param {string} dataId The data id.\n   * @returns {Object<string, DataElement>|undefined} The list of meta data.\n   */\n  getMetaData(dataId) {\n    let res;\n    if (typeof this.#dataController.get(dataId) !== 'undefined') {\n      res = this.#dataController.get(dataId).meta;\n    }\n    return res;\n  }\n\n  /**\n   * Get the list of ids in the data storage.\n   *\n   * @returns {string[]} The list of data ids.\n   */\n  getDataIds() {\n    return this.#dataController.getDataIds();\n  }\n\n  /**\n   * Get the list of dataIds that contain the input UIDs.\n   *\n   * @param {string[]} uids A list of UIDs.\n   * @returns {string[]} The list of dataIds that contain the UIDs.\n   */\n  getDataIdsFromSopUids(uids) {\n    return this.#dataController.getDataIdsFromSopUids(uids);\n  }\n\n  /**\n   * Can the data (of the active view of the active layer) be scrolled?\n   *\n   * @returns {boolean} True if the data has a third dimension greater than one.\n   * @deprecated Since v0.33, please use the ViewController\n   *   equivalent directly instead.\n   */\n  canScroll() {\n    const viewLayer = this.#stage.getActiveLayerGroup().getActiveViewLayer();\n    const controller = viewLayer.getViewController();\n    return controller.canScroll();\n  }\n\n  /**\n   * Can window and level be applied to the data\n   * (of the active view of the active layer)?\n   *\n   * @returns {boolean} True if the data is monochrome.\n   * @deprecated Since v0.33, please use the ViewController\n   *   equivalent directly instead.\n   */\n  canWindowLevel() {\n    const viewLayer = this.#stage.getActiveLayerGroup().getActiveViewLayer();\n    const controller = viewLayer.getViewController();\n    return controller.canWindowLevel();\n  }\n\n  /**\n   * Get the active layer group scale on top of the base scale.\n   *\n   * @returns {Scalar3D} The scale as {x,y,z}.\n   */\n  getAddedScale() {\n    return this.#stage.getActiveLayerGroup().getAddedScale();\n  }\n\n  /**\n   * Get the base scale of the active layer group.\n   *\n   * @returns {Scalar3D} The scale as {x,y,z}.\n   */\n  getBaseScale() {\n    return this.#stage.getActiveLayerGroup().getBaseScale();\n  }\n\n  /**\n   * Get the layer offset of the active layer group.\n   *\n   * @returns {Scalar3D} The offset as {x,y,z}.\n   */\n  getOffset() {\n    return this.#stage.getActiveLayerGroup().getOffset();\n  }\n\n  /**\n   * Get the toolbox controller.\n   *\n   * @returns {ToolboxController} The controller.\n   */\n  getToolboxController() {\n    return this.#toolboxController;\n  }\n\n  /**\n   * Get the active layer group.\n   * The layer is available after the first loaded item.\n   *\n   * @returns {LayerGroup|undefined} The layer group.\n   */\n  getActiveLayerGroup() {\n    return this.#stage.getActiveLayerGroup();\n  }\n\n  /**\n   * Set the active layer group.\n   *\n   * @param {number} index The layer group index.\n   */\n  setActiveLayerGroup(index) {\n    this.#stage.setActiveLayerGroup(index);\n  }\n\n  /**\n   * Get the view layers associated to a data id.\n   * The layer are available after the first loaded item.\n   *\n   * @param {string} dataId The data id.\n   * @returns {ViewLayer[]} The layers.\n   */\n  getViewLayersByDataId(dataId) {\n    return this.#stage.getViewLayersByDataId(dataId);\n  }\n\n  /**\n   * Get a list of view layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a ViewLayer as input and returns a boolean. If undefined,\n   *   returns all view layers.\n   * @returns {ViewLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getViewLayers(callbackFn) {\n    return this.#stage.getViewLayers(callbackFn);\n  }\n\n  /**\n   * Get the draw layers associated to a data id.\n   * The layer are available after the first loaded item.\n   *\n   * @param {string} dataId The data id.\n   * @returns {DrawLayer[]} The layers.\n   */\n  getDrawLayersByDataId(dataId) {\n    return this.#stage.getDrawLayersByDataId(dataId);\n  }\n\n  /**\n   * Get a list of draw layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a DrawLayer as input and returns a boolean. If undefined,\n   *   returns all draw layers.\n   * @returns {DrawLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getDrawLayers(callbackFn) {\n    return this.#stage.getDrawLayers(callbackFn);\n  }\n\n  /**\n   * Get a layer group by div id.\n   * The layer is available after the first loaded item.\n   *\n   * @param {string} divId The div id.\n   * @returns {LayerGroup|undefined} The layer group.\n   */\n  getLayerGroupByDivId(divId) {\n    return this.#stage.getLayerGroupByDivId(divId);\n  }\n\n  /**\n   * Get the number of layer groups.\n   *\n   * @returns {number} The number of groups.\n   */\n  getNumberOfLayerGroups() {\n    return this.#stage.getNumberOfLayerGroups();\n  }\n\n  /**\n   * Get the app style.\n   *\n   * @returns {object} The app style.\n   */\n  getStyle() {\n    return this.#style;\n  }\n\n  /**\n   * Add a command to the undo stack.\n   *\n   * @param {object} cmd The command to add.\n   * @fires UndoStack#undoadd\n   * @function\n   */\n  addToUndoStack = (cmd) => {\n    if (this.#undoStack !== null) {\n      this.#undoStack.add(cmd);\n    }\n  };\n\n  /**\n   * Remove a command from the undo stack.\n   *\n   * @param {string} name The name of the command to remove.\n   * @returns {boolean} True if the command was found and removed.\n   * @fires UndoStack#undoremove\n   * @function\n   */\n  removeFromUndoStack = (name) => {\n    let res = false;\n    if (this.#undoStack !== null) {\n      res = this.#undoStack.remove(name);\n    }\n    return res;\n  };\n\n  /**\n   * Initialise the application.\n   *\n   * @param {AppOptions} opt The application options.\n   * @example\n   * // create the dwv app\n   * const app = new dwv.App();\n   * // initialise\n   * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n   * const viewConfigs = {'*': [viewConfig0]};\n   * const options = new dwv.AppOptions(viewConfigs);\n   * options.viewOnFirstLoadItem = false;\n   * app.init(options);\n   * // render button\n   * const button = document.createElement('button');\n   * button.id = 'render';\n   * button.disabled = true;\n   * button.appendChild(document.createTextNode('render'));\n   * document.body.appendChild(button);\n   * app.addEventListener('load', function () {\n   *   const button = document.getElementById('render');\n   *   button.disabled = false;\n   *   button.onclick = function () {\n   *     // render data #0\n   *     app.render(0);\n   *   };\n   * });\n   * // load dicom data\n   * app.loadURLs([\n   *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n   * ]);\n   */\n  init(opt) {\n    // store\n    this.#options = opt;\n    // defaults\n    if (typeof this.#options.viewOnFirstLoadItem === 'undefined') {\n      this.#options.viewOnFirstLoadItem = true;\n    }\n    if (typeof this.#options.dataViewConfigs === 'undefined') {\n      this.#options.dataViewConfigs = {};\n    }\n    if (typeof this.#options.rootDocument === 'undefined') {\n      this.#options.rootDocument = document;\n    }\n\n    // undo stack\n    this.#undoStack = new UndoStack();\n    this.#undoStack.addEventListener('undoadd', this.#fireEvent);\n    this.#undoStack.addEventListener('undo', this.#fireEvent);\n    this.#undoStack.addEventListener('redo', this.#fireEvent);\n\n    // tools\n    if (typeof this.#options.tools !== 'undefined') {\n      // setup the tool list\n      const appToolList = {};\n      const keys = Object.keys(this.#options.tools);\n      for (let t = 0; t < keys.length; ++t) {\n        const toolName = keys[t];\n        // find the tool in the default tool list\n        let toolClass = defaultToolList[toolName];\n        // or use external one\n        if (typeof toolClass === 'undefined') {\n          toolClass = toolList[toolName];\n        }\n        if (typeof toolClass !== 'undefined') {\n          // create tool instance\n          appToolList[toolName] = new toolClass(this);\n          // register listeners\n          if (typeof appToolList[toolName].addEventListener !== 'undefined') {\n            const names = appToolList[toolName].getEventNames();\n            for (let j = 0; j < names.length; ++j) {\n              appToolList[toolName].addEventListener(names[j], this.#fireEvent);\n            }\n          }\n          // tool options\n          const toolParams = this.#options.tools[toolName];\n          if (typeof toolParams.options !== 'undefined' &&\n            toolParams.options.length !== 0) {\n            let type = 'raw';\n            if (typeof appToolList[toolName].getOptionsType !== 'undefined') {\n              type = appToolList[toolName].getOptionsType();\n            }\n            let appToolOptions;\n            if (type === 'instance' || type === 'factory') {\n              appToolOptions = {};\n              for (let i = 0; i < toolParams.options.length; ++i) {\n                const optionName = toolParams.options[i];\n                let optionClassName = optionName;\n                if (type === 'factory') {\n                  optionClassName += 'Factory';\n                }\n                const toolNamespace = toolName.charAt(0).toLowerCase() +\n                  toolName.slice(1);\n                // find the option in the external tool list\n                let tOptions = toolOptions[toolNamespace];\n                let optionClass;\n                if (typeof tOptions !== 'undefined') {\n                  optionClass = tOptions[optionClassName];\n                }\n                // or use the default one\n                if (typeof optionClass === 'undefined') {\n                  tOptions = defaultToolOptions[toolNamespace];\n                  if (typeof tOptions !== 'undefined') {\n                    optionClass = tOptions[optionClassName];\n                  }\n                }\n                if (typeof optionClass !== 'undefined') {\n                  appToolOptions[optionName] = optionClass;\n                } else {\n                  logger.warn('Could not find option class for: ' +\n                    optionName);\n                }\n              }\n            } else {\n              appToolOptions = toolParams.options;\n            }\n            appToolList[toolName].setOptions(appToolOptions);\n          }\n        } else {\n          logger.warn('Could not initialise unknown tool: ' + toolName);\n        }\n      }\n      // add tools to the controller\n      this.#toolboxController = new ToolboxController(appToolList);\n    }\n\n    // create load controller\n    this.#loadController =\n      new LoadController(this.#options.defaultCharacterSet);\n    this.#loadController.onloadstart = this.#onloadstart;\n    this.#loadController.onprogress = this.#onloadprogress;\n    this.#loadController.onloaditem = this.#onloaditem;\n    this.#loadController.onload = this.#onload;\n    this.#loadController.onloadend = this.#onloadend;\n    this.#loadController.onerror = this.#onloaderror;\n    this.#loadController.ontimeout = this.#onloadtimeout;\n    this.#loadController.onabort = this.#onloadabort;\n\n    // create data controller\n    this.#dataController = new DataController();\n    // propagate data events\n    this.#dataController.addEventListener('dataadd', this.#fireEvent);\n    this.#dataController.addEventListener('dataremove', this.#fireEvent);\n    this.#dataController.addEventListener('dataimageset', this.#fireEvent);\n    this.#dataController.addEventListener('dataupdate', this.#fireEvent);\n    // propage individual data events\n    this.#dataController.addEventListener(\n      'imagecontentchange', this.#fireEvent);\n    this.#dataController.addEventListener(\n      'imagegeometrychange', this.#fireEvent);\n    this.#dataController.addEventListener('annotationadd', this.#fireEvent);\n    this.#dataController.addEventListener('annotationupdate', this.#fireEvent);\n    this.#dataController.addEventListener('annotationremove', this.#fireEvent);\n    this.#dataController.addEventListener(\n      'annotationgroupeditablechange', this.#fireEvent);\n    // create stage\n    this.#stage = new Stage();\n    if (typeof this.#options.binders !== 'undefined') {\n      this.#stage.setBinders(this.#options.binders);\n    }\n  }\n\n  /**\n   * Reset the application.\n   */\n  reset() {\n    // clear objects\n    this.#stage.empty();\n    this.#overlayDatas = {};\n    // reset undo/redo\n    if (this.#undoStack) {\n      this.#undoStack = new UndoStack();\n      this.#undoStack.addEventListener('undoadd', this.#fireEvent);\n      this.#undoStack.addEventListener('undo', this.#fireEvent);\n      this.#undoStack.addEventListener('redo', this.#fireEvent);\n    }\n  }\n\n  /**\n   * Reset the layout of the application.\n   */\n  resetLayout() {\n    this.#stage.reset();\n    this.#stage.draw();\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  // load API [begin] -------------------------------------------------------\n\n  /**\n   * Load a list of files. Can be image files or a state file.\n   *\n   * @param {File[]} files The list of files to load.\n   * @fires App#loadstart\n   * @fires App#loadprogress\n   * @fires App#loaditem\n   * @fires App#loadend\n   * @fires App#error\n   * @fires App#abort\n   * @function\n   */\n  loadFiles = (files) => {\n    // Get new data id\n    const dataId = this.#dataController.getNextDataId();\n    if (files.length === 0) {\n      logger.warn('Ignoring empty input file list.');\n      return;\n    }\n    this.#loadController.loadFiles(files, dataId);\n  };\n\n  /**\n   * Load a list of URLs. Can be image files or a state file.\n   *\n   * @param {string[]} urls The list of urls to load.\n   * @param {object} [options] The options object, can contain:\n   * - requestHeaders: an array of {name, value} to use as request headers,\n   * - withCredentials: boolean xhr.withCredentials flag to pass to the request,\n   * - batchSize: the size of the request url batch.\n   * @fires App#loadstart\n   * @fires App#loadprogress\n   * @fires App#loaditem\n   * @fires App#loadend\n   * @fires App#error\n   * @fires App#abort\n   * @function\n   */\n  loadURLs = (urls, options) => {\n    // Get new data id\n    const dataId = this.#dataController.getNextDataId();\n    if (urls.length === 0) {\n      logger.warn('Ignoring empty input url list.');\n      return;\n    }\n    this.#loadController.loadURLs(urls, dataId, options);\n  };\n\n  /**\n   * Load from an input uri.\n   *\n   * @param {string} uri The input uri, for example: 'window.location.href'.\n   * @param {object} [options] Optional url request options.\n   * @function\n   */\n  loadFromUri = (uri, options) => {\n    const query = getUriQuery(uri);\n\n    // load end callback: loads the state.\n    const onLoadEnd = (/*event*/) => {\n      this.removeEventListener('loadend', onLoadEnd);\n      this.loadURLs([query.state]);\n    };\n\n    // check query\n    if (query && typeof query.input !== 'undefined') {\n      // optional display state\n      if (typeof query.state !== 'undefined') {\n        // queue after main data load\n        this.addEventListener('loadend', onLoadEnd);\n      }\n      // load base image\n      decodeQuery(query, this.loadURLs, options);\n    }\n    // no else to allow for empty uris\n  };\n\n  /**\n   * Load a list of ArrayBuffers.\n   *\n   * @param {Array} data The list of ArrayBuffers to load\n   *   in the form of [{name: \"\", filename: \"\", data: data}].\n   * @fires App#loadstart\n   * @fires App#loadprogress\n   * @fires App#loaditem\n   * @fires App#loadend\n   * @fires App#error\n   * @fires App#abort\n   * @function\n   */\n  loadImageObject = (data) => {\n    // Get new data id\n    const dataId = this.#dataController.getNextDataId();\n    this.#loadController.loadImageObject(data, dataId);\n  };\n\n  /**\n   * Abort all the current loads.\n   */\n  abortAllLoads() {\n    const ids = this.#loadController.getLoadingDataIds();\n    for (const id of ids) {\n      this.abortLoad(id);\n    }\n  }\n\n  /**\n   * Abort an individual data load.\n   *\n   * @param {string} dataId The data to stop loading.\n   */\n  abortLoad(dataId) {\n    // abort load\n    this.#loadController.abort(dataId);\n    // remove data\n    this.#dataController.remove(dataId);\n    // clean up stage\n    this.#stage.removeLayersByDataId(dataId);\n  }\n\n  // load API [end] ---------------------------------------------------------\n\n  /**\n   * Fit the display to the data of each layer group.\n   * To be called once the image is loaded.\n   */\n  fitToContainer() {\n    this.#stage.fitToContainer();\n  }\n\n  /**\n   * Init the Window/Level display\n   * (of the active layer of the active layer group).\n   *\n   * @deprecated Since v0.33, please set the opacity\n   *   of the desired view layer directly.\n   */\n  initWLDisplay() {\n    const viewLayer = this.#stage.getActiveLayerGroup().getActiveViewLayer();\n    const controller = viewLayer.getViewController();\n    controller.initialise();\n  }\n\n  /**\n   * Set the imageSmoothing flag value. Default is false.\n   *\n   * @param {boolean} flag True to enable smoothing.\n   */\n  setImageSmoothing(flag) {\n    this.#stage.setImageSmoothing(flag);\n    this.#stage.draw();\n  }\n\n  /**\n   * Get the layer group configuration from a data id.\n   *\n   * @param {string} dataId The data id.\n   * @param {boolean} [excludeStarConfig] Exclude the star config\n   *  (default to false).\n   * @returns {ViewConfig[]} The list of associated configs.\n   */\n  getViewConfigs(dataId, excludeStarConfig) {\n    if (typeof excludeStarConfig === 'undefined') {\n      excludeStarConfig = false;\n    }\n    // check options\n    if (this.#options.dataViewConfigs === null ||\n      typeof this.#options.dataViewConfigs === 'undefined') {\n      throw new Error('No available data view configuration');\n    }\n    let configs = [];\n    if (typeof this.#options.dataViewConfigs[dataId] !== 'undefined') {\n      configs = this.#options.dataViewConfigs[dataId];\n    } else if (!excludeStarConfig &&\n      typeof this.#options.dataViewConfigs['*'] !== 'undefined') {\n      configs = this.#options.dataViewConfigs['*'];\n    }\n    return configs;\n  }\n\n  /**\n   * Get the layer group configuration for a data id and group\n   * div id.\n   *\n   * @param {string} dataId The data id.\n   * @param {string} groupDivId The layer group div id.\n   * @param {boolean} [excludeStarConfig] Exclude the star config\n   *  (default to false).\n   * @returns {ViewConfig|undefined} The associated config.\n   */\n  getViewConfig(dataId, groupDivId, excludeStarConfig) {\n    const configs = this.getViewConfigs(dataId, excludeStarConfig);\n    return configs.find(function (item) {\n      return item.divId === groupDivId;\n    });\n  }\n\n  /**\n   * Get the data view config.\n   * Carefull, returns a reference, do not modify without resetting.\n   *\n   * @returns {Object<string, ViewConfig[]>} The configuration list.\n   */\n  getDataViewConfigs() {\n    return this.#options.dataViewConfigs;\n  }\n\n  /**\n   * Set the data view configuration.\n   * Resets the stage and recreates all the views.\n   *\n   * @param {Object<string, ViewConfig[]>} configs The configuration list.\n   */\n  setDataViewConfigs(configs) {\n    // clean up\n    this.#stage.empty();\n    // set new\n    this.#options.dataViewConfigs = configs;\n    // create layer groups\n    this.#createLayerGroups(configs);\n  }\n\n  /**\n   * Add a data view config.\n   *\n   * @param {string} dataId The data id.\n   * @param {ViewConfig} config The view configuration.\n   */\n  addDataViewConfig(dataId, config) {\n    // add to list\n    const configs = this.#options.dataViewConfigs;\n    if (typeof configs[dataId] === 'undefined') {\n      configs[dataId] = [];\n    }\n    const equalDivId = function (item) {\n      return item.divId === config.divId;\n    };\n    const itemIndex = configs[dataId].findIndex(equalDivId);\n    if (itemIndex === -1) {\n      this.#options.dataViewConfigs[dataId].push(config);\n    } else {\n      throw new Error('Duplicate view config for data ' + dataId +\n        ' and div ' + config.divId);\n    }\n\n    // add layer group if not done\n    if (typeof this.#stage.getLayerGroupByDivId(config.divId) === 'undefined') {\n      this.#createLayerGroup(config);\n    }\n\n    // render (will create layers)\n    if (typeof this.#dataController.get(dataId) !== 'undefined') {\n      this.render(dataId, [config]);\n    }\n  }\n\n  /**\n   * Remove a data view config.\n   *\n   * @param {string} dataId The data id.\n   * @param {string} divId The div id.\n   */\n  removeDataViewConfig(dataId, divId) {\n    // remove from list\n    const configs = this.#options.dataViewConfigs;\n    if (typeof configs[dataId] === 'undefined') {\n      // no config for dataId\n      return;\n    }\n    const equalDivId = function (item) {\n      return item.divId === divId;\n    };\n    const itemIndex = configs[dataId].findIndex(equalDivId);\n    if (itemIndex === -1) {\n      // no config for divId\n      return;\n    }\n    configs[dataId].splice(itemIndex, 1);\n    if (configs[dataId].length === 0) {\n      delete configs[dataId];\n    }\n\n    // data is loaded, remove view\n    if (typeof this.#dataController.get(dataId) !== 'undefined') {\n      const lg = this.#stage.getLayerGroupByDivId(divId);\n      if (typeof lg !== 'undefined') {\n        const vls = lg.getViewLayersByDataId(dataId);\n        if (vls.length === 1) {\n          lg.removeLayer(vls[0]);\n        }\n        const dls = lg.getDrawLayersByDataId(dataId);\n        if (dls.length === 1) {\n          lg.removeLayer(dls[0]);\n        }\n        if (vls.length === 0 && dls.length === 0) {\n          throw new Error('Expected one layer, got none');\n        }\n        if (lg.getNumberOfLayers() === 0) {\n          this.#stage.removeLayerGroup(lg);\n        }\n      }\n    }\n  }\n\n  /**\n   * Update an existing data view config.\n   * Removes and re-creates the layer if found.\n   *\n   * @param {string} dataId The data id.\n   * @param {string} divId The div id.\n   * @param {ViewConfig} config The view configuration.\n   */\n  updateDataViewConfig(dataId, divId, config) {\n    const configs = this.#options.dataViewConfigs;\n    // check data id\n    if (typeof configs[dataId] === 'undefined') {\n      throw new Error('No config for dataId: ' + dataId);\n    }\n    // check div id\n    const equalDivId = function (item) {\n      return item.divId === divId;\n    };\n    const itemIndex = configs[dataId].findIndex(equalDivId);\n    if (itemIndex === -1) {\n      throw new Error('No config for dataId: ' +\n        dataId + ' and divId: ' + divId);\n    }\n    // update config\n    const configToUpdate = configs[dataId][itemIndex];\n    for (const prop in config) {\n      configToUpdate[prop] = config[prop];\n    }\n\n    // remove previous layers\n    const lg = this.#stage.getLayerGroupByDivId(configToUpdate.divId);\n    if (typeof lg !== 'undefined') {\n      const vls = lg.getViewLayersByDataId(dataId);\n      if (vls.length === 1) {\n        lg.removeLayer(vls[0]);\n      }\n      const dls = lg.getDrawLayersByDataId(dataId);\n      if (dls.length === 1) {\n        lg.removeLayer(dls[0]);\n      }\n      if (vls.length === 0 && dls.length === 0) {\n        throw new Error('Expected one layer, got none');\n      }\n    }\n\n    // render (will create layer)\n    if (typeof this.#dataController.get(dataId) !== 'undefined') {\n      this.render(dataId, [configToUpdate]);\n    }\n  }\n\n  /**\n   * Create layer groups according to a data view config:\n   * adds them to stage and binds them.\n   *\n   * @param {DataViewConfigs} dataViewConfigs The data view config.\n   */\n  #createLayerGroups(dataViewConfigs) {\n    const dataKeys = Object.keys(dataViewConfigs);\n    const divIds = [];\n    for (let i = 0; i < dataKeys.length; ++i) {\n      const viewConfigs = dataViewConfigs[dataKeys[i]];\n      for (let j = 0; j < viewConfigs.length; ++j) {\n        const viewConfig = viewConfigs[j];\n        // view configs can contain the same divIds, avoid duplicating\n        if (!divIds.includes(viewConfig.divId)) {\n          this.#createLayerGroup(viewConfig);\n          divIds.push(viewConfig.divId);\n        }\n      }\n    }\n  }\n\n  /**\n   * Create a layer group according to a view config:\n   * adds it to stage and binds it.\n   *\n   * @param {ViewConfig} viewConfig The view config.\n   */\n  #createLayerGroup(viewConfig) {\n    // create new layer group\n    const element = this.#options.rootDocument.getElementById(viewConfig.divId);\n    const layerGroup = this.#stage.addLayerGroup(element);\n    // bind events\n    this.#bindLayerGroupToApp(layerGroup);\n  }\n\n  /**\n   * Set the layer groups binders.\n   *\n   * @param {string[]} list The list of binder names.\n   */\n  setLayerGroupsBinders(list) {\n    // create instances\n    const instances = [];\n    for (let i = 0; i < list.length; ++i) {\n      if (typeof binderList[list[i]] !== 'undefined') {\n        instances.push(new binderList[list[i]]);\n      }\n    }\n    // pass to stage\n    this.#stage.setBinders(instances);\n  }\n\n  /**\n   * Render the current data.\n   *\n   * @param {string} dataId The data id to render.\n   * @param {ViewConfig[]} [viewConfigs] The list of configs to render.\n   */\n  render(dataId, viewConfigs) {\n    if (typeof dataId === 'undefined' || dataId === null) {\n      throw new Error('Cannot render without data id');\n    }\n    // guess data type\n    const isImage =\n      typeof this.getData(dataId).image !== 'undefined';\n    const isMeasurement =\n      typeof this.getData(dataId).annotationGroup !== 'undefined';\n\n    // create layer groups if not done yet\n    // (create all to allow for ratio sync)\n    if (this.#stage.getNumberOfLayerGroups() === 0) {\n      this.#createLayerGroups(this.#options.dataViewConfigs);\n    }\n\n    // use options list if non provided\n    if (typeof viewConfigs === 'undefined') {\n      viewConfigs = this.getViewConfigs(dataId);\n    }\n\n    // nothing to do if no view config\n    if (viewConfigs.length === 0) {\n      logger.info('Not rendering data: ' + dataId +\n        ' (no data view config)');\n      return;\n    }\n\n    // loop on configs\n    for (let i = 0; i < viewConfigs.length; ++i) {\n      const config = viewConfigs[i];\n      const layerGroup =\n        this.#stage.getLayerGroupByDivId(config.divId);\n      // layer group must exist\n      if (!layerGroup) {\n        throw new Error('No layer group for ' + config.divId);\n      }\n      // create layer if needed\n      // warn: needs a loaded DOM\n      if (typeof this.#dataController.get(dataId) !== 'undefined') {\n        if (isImage &&\n          layerGroup.getViewLayersByDataId(dataId).length === 0\n        ) {\n          this.#addViewLayer(dataId, config);\n        } else if (isMeasurement &&\n          layerGroup.getDrawLayersByDataId(dataId).length === 0\n        ) {\n          this.addDrawLayer(dataId, config);\n        }\n      }\n      // draw\n      layerGroup.draw();\n    }\n  }\n\n  /**\n   * Zoom the layers of the active layer group.\n   *\n   * @param {number} step The step to add to the current zoom.\n   * @param {number} cx The zoom center X coordinate.\n   * @param {number} cy The zoom center Y coordinate.\n   */\n  zoom(step, cx, cy) {\n    const layerGroup = this.#stage.getActiveLayerGroup();\n    const viewController = layerGroup.getBaseViewLayer().getViewController();\n    const k = viewController.getCurrentScrollPosition();\n    const center = new Point3D(cx, cy, k);\n    layerGroup.addScale(step, center);\n    layerGroup.draw();\n  }\n\n  /**\n   * Apply a translation to the layers of the active layer group.\n   *\n   * @param {number} tx The translation along X.\n   * @param {number} ty The translation along Y.\n   */\n  translate(tx, ty) {\n    const layerGroup = this.#stage.getActiveLayerGroup();\n    layerGroup.addTranslation({x: tx, y: ty, z: 0});\n    layerGroup.draw();\n  }\n\n  /**\n   * Set the active view layer (of the active layer group) opacity.\n   *\n   * @param {number} alpha The opacity ([0:1] range).\n   * @deprecated Since v0.33, pplease set the opacity\n   *   of the desired view layer directly.\n   */\n  setOpacity(alpha) {\n    const viewLayer = this.#stage.getActiveLayerGroup().getActiveViewLayer();\n    viewLayer.setOpacity(alpha);\n    viewLayer.draw();\n  }\n\n  /**\n   * Set the drawings of the active layer group.\n   *\n   * @deprecated Since v0.34, please switch to DICOM SR annotations.\n   * @param {Array} drawings An array of drawings.\n   * @param {Array} drawingsDetails An array of drawings details.\n   * @param {string} dataId The converted data id.\n   */\n  setDrawings(drawings, drawingsDetails, dataId) {\n    const layerGroup = this.#stage.getActiveLayerGroup();\n    const viewLayer = layerGroup.getBaseViewLayer();\n    const refDataId = viewLayer.getDataId();\n    const viewController = viewLayer.getViewController();\n\n    // convert konva to annotation\n    const annotations = konvaToAnnotation(drawings, drawingsDetails);\n    // create data\n    const data = this.createAnnotationData(refDataId);\n    // add annotations to data\n    for (const annotation of annotations) {\n      annotation.setViewController(viewController);\n      data.annotationGroup.add(annotation);\n    }\n    // add to data controller\n    this.#dataController.add(dataId, data);\n    // render\n    this.render(dataId);\n  }\n\n  /**\n   * Apply a JSON state to this app.\n   *\n   * @deprecated Since v0.34, please switch to DICOM SR\n   *   for annotations.\n   * @param {string} jsonState The state of the app as a JSON string.\n   * @param {string} dataId The state data id.\n   */\n  applyJsonState(jsonState, dataId) {\n    const state = new State(dataId);\n    state.apply(this, state.fromJSON(jsonState));\n  }\n\n  // Handler Methods -----------------------------------------------------------\n\n  /**\n   * Handle resize: fit the display to the window.\n   * To be called once the image is loaded.\n   * Can be connected to a window 'resize' event.\n   *\n   * @function\n   */\n  onResize = () => {\n    this.fitToContainer();\n  };\n\n  /**\n   * Key down callback. Meant to be used in tools.\n   *\n   * @param {KeyboardEvent} event The key down event.\n   * @fires App#keydown\n   * @function\n   */\n  onKeydown = (event) => {\n    /**\n     * Key down event.\n     *\n     * @event App#keydown\n     * @type {KeyboardEvent}\n     * @property {string} type The event type: keydown.\n     * @property {string} context The tool where the event originated.\n     */\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Key down event handler example.\n   * - CRTL-Z: undo,\n   * - CRTL-Y: redo,\n   * - CRTL-ARROW_LEFT: next element on fourth dim,\n   * - CRTL-ARROW_UP: next element on third dim,\n   * - CRTL-ARROW_RIGHT: previous element on fourth dim,\n   * - CRTL-ARROW_DOWN: previous element on third dim.\n   *\n   * Applies to the active view of the active layer group.\n   *\n   * @param {KeyboardEvent} event The key down event.\n   * @fires UndoStack#undo\n   * @fires UndoStack#redo\n   * @function\n   */\n  defaultOnKeydown = (event) => {\n    if (event.ctrlKey) {\n      if (event.shiftKey) {\n        const layerGroup = this.#stage.getActiveLayerGroup();\n        const positionHelper = layerGroup.getPositionHelper();\n        if (event.key === 'ArrowLeft') { // crtl-shift-arrow-left\n          if (layerGroup.moreThanOne(3)) {\n            positionHelper.decrementPosition(3);\n          }\n        } else if (event.key === 'ArrowUp') { // crtl-shift-arrow-up\n          if (layerGroup.canScroll()) {\n            positionHelper.incrementPositionAlongScroll();\n          }\n        } else if (event.key === 'ArrowRight') { // crtl-shift-arrow-right\n          if (layerGroup.moreThanOne(3)) {\n            positionHelper.incrementPosition(3);\n          }\n        } else if (event.key === 'ArrowDown') { // crtl-shift-arrow-down\n          if (layerGroup.canScroll()) {\n            positionHelper.decrementPositionAlongScroll();\n          }\n        }\n      } else if (event.key === 'y') { // crtl-y\n        this.#undoStack.redo();\n      } else if (event.key === 'z') { // crtl-z\n        this.#undoStack.undo();\n      } else if (event.key === ' ') { // crtl-space\n        for (let i = 0; i < this.#stage.getNumberOfLayerGroups(); ++i) {\n          this.#stage.getLayerGroup(i).setShowCrosshair(\n            !this.#stage.getLayerGroup(i).getShowCrosshair()\n          );\n        }\n      }\n    }\n  };\n\n  // Internal members shortcuts-----------------------------------------------\n\n  /**\n   * Reset the display.\n   */\n  resetDisplay() {\n    this.resetLayout();\n    this.initWLDisplay();\n  }\n\n  /**\n   * Reset the app zoom.\n   */\n  resetZoom() {\n    this.resetLayout();\n  }\n\n  /**\n   * Set the colour map of the active view of the active layer group.\n   *\n   * @param {string} name The colour map name.\n   * @deprecated Since v0.33, please use the ViewController\n   *   equivalent directly instead.\n   */\n  setColourMap(name) {\n    const viewController =\n      this.#stage.getActiveLayerGroup()\n        .getActiveViewLayer().getViewController();\n    viewController.setColourMap(name);\n  }\n\n  /**\n   * Set the window/level preset of the active view of the active layer group.\n   *\n   * @param {string} preset The window/level preset.\n   * @deprecated Since v0.33, please use the ViewController\n   *   equivalent directly instead.\n   */\n  setWindowLevelPreset(preset) {\n    const viewController =\n      this.#stage.getActiveLayerGroup()\n        .getActiveViewLayer().getViewController();\n    viewController.setWindowLevelPreset(preset);\n  }\n\n  /**\n   * Set the tool.\n   *\n   * @param {string} tool The tool.\n   */\n  setTool(tool) {\n    // bind tool to active layer\n    for (let i = 0; i < this.#stage.getNumberOfLayerGroups(); ++i) {\n      const layerGroup = this.#stage.getLayerGroup(i);\n      const layer = layerGroup.getActiveLayer();\n      if (typeof layer !== 'undefined') {\n        this.#toolboxController.bindLayerGroup(layerGroup, layer);\n      }\n    }\n    // set toolbox tool\n    this.#toolboxController.setSelectedTool(tool);\n  }\n\n  /**\n   * Set the tool live features.\n   *\n   * @param {object} list The list of features.\n   */\n  setToolFeatures(list) {\n    this.#toolboxController.setToolFeatures(list);\n  }\n\n  /**\n   * Undo the last action.\n   *\n   * @fires UndoStack#undo\n   */\n  undo() {\n    this.#undoStack.undo();\n  }\n\n  /**\n   * Redo the last action.\n   *\n   * @fires UndoStack#redo\n   */\n  redo() {\n    this.#undoStack.redo();\n  }\n\n  /**\n   * Get the undo stack size.\n   *\n   * @returns {number} The size of the stack.\n   */\n  getStackSize() {\n    return this.#undoStack.getStackSize();\n  }\n\n  /**\n   * Get the current undo stack index.\n   *\n   * @returns {number} The stack index.\n   */\n  getCurrentStackIndex() {\n    return this.#undoStack.getCurrentStackIndex();\n  }\n\n  /**\n   * Get the overlay data for a data id.\n   *\n   * @param {string} dataId The data id.\n   * @returns {OverlayData|undefined} The overlay data.\n   */\n  getOverlayData(dataId) {\n    let data;\n    if (typeof this.#overlayDatas !== 'undefined') {\n      data = this.#overlayDatas[dataId];\n    }\n    return data;\n  }\n\n  /**\n   * Toggle overlay listeners.\n   *\n   * @param {string} dataId The data id.\n   */\n  toggleOverlayListeners(dataId) {\n    const data = this.getOverlayData(dataId);\n    if (typeof data !== 'undefined') {\n      if (data.isListening()) {\n        data.removeAppListeners();\n      } else {\n        data.addAppListeners();\n      }\n    }\n  }\n\n  /**\n   * Create new annotation data based on the data of\n   *   the active view layer.\n   *\n   * @param {string} refDataId The reference data id.\n   * @returns {DicomData} The new data.\n   */\n  createAnnotationData(refDataId) {\n    const refData = this.getData(refDataId);\n    const refMeta = refData.image.getMeta();\n\n    const data = new DicomData({});\n    data.annotationGroup = new AnnotationGroup();\n    data.annotationGroup.setMetaValue('Modality', 'SR');\n    data.annotationGroup.setMetaValue(\n      'PatientID', refMeta.PatientID);\n    data.annotationGroup.setMetaValue(\n      'StudyInstanceUID', refMeta.StudyInstanceUID);\n    data.annotationGroup.setMetaValue(\n      'ReferencedSeriesSequence', {\n        value: [{\n          SeriesInstanceUID: refMeta.SeriesInstanceUID\n        }]\n      });\n    return data;\n  }\n\n  /**\n   * Add new data and render it with a simple new data view config.\n   *\n   * @param {DicomData} data The data to add.\n   * @param {string} divId The div where to draw.\n   * @param {string} refDataId The reference data id.\n   */\n  addAndRenderAnnotationData(data, divId, refDataId) {\n    // add new data\n    const dataId = this.addData(data);\n    // add data view config based on reference data\n    const refDataViewConfigs = this.getViewConfigs(refDataId);\n    const refDataViewConfig = refDataViewConfigs.find(\n      element => element.divId === divId);\n    if (typeof refDataViewConfig === 'undefined') {\n      throw new Error('No reference data view config for draw');\n    }\n    const drawDataViewConfig = new ViewConfig(divId);\n    drawDataViewConfig.orientation = refDataViewConfig.orientation;\n    this.addDataViewConfig(dataId, drawDataViewConfig);\n    // render (will create draw layer)\n    this.render(dataId);\n  }\n\n  // Private Methods -----------------------------------------------------------\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  /**\n   * Data load start callback.\n   *\n   * @param {object} event The load start event.\n   */\n  #onloadstart = (event) => {\n    // create overlay data\n    if (typeof this.#options.overlayConfig !== 'undefined') {\n      this.#overlayDatas[event.dataid] = new OverlayData(\n        this, event.dataid, this.#options.overlayConfig);\n    }\n    /**\n     * Load start event.\n     *\n     * @event App#loadstart\n     * @type {object}\n     * @property {string} type The event type: loadstart.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     */\n    event.type = 'loadstart';\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load progress callback.\n   *\n   * @param {object} event The progress event.\n   */\n  #onloadprogress = (event) => {\n    /**\n     * Load progress event.\n     *\n     * @event App#loadprogress\n     * @type {object}\n     * @property {string} type The event type: loadprogress.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     * @property {number} loaded The loaded percentage.\n     * @property {number} total The total percentage.\n     */\n    event.type = 'loadprogress';\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load callback.\n   *\n   * @param {object} event The load event.\n   */\n  #onloaditem = (event) => {\n    // check event\n    if (typeof event.data === 'undefined') {\n      logger.error('Missing loaditem event data.');\n    }\n    if (typeof event.loadtype === 'undefined') {\n      logger.error('Missing loaditem event load type.');\n    }\n\n    const isFirstLoadItem = event.isfirstitem;\n\n    let eventMetaData = null;\n    if (event.loadtype === 'image') {\n      if (isFirstLoadItem) {\n        this.#dataController.add(event.dataid, event.data);\n      } else {\n        this.#dataController.update(event.dataid, event.data);\n      }\n      eventMetaData = event.data.meta;\n    } else if (event.loadtype === 'state') {\n      this.applyJsonState(event.data, event.dataid);\n      eventMetaData = 'state';\n    }\n\n    /**\n     * Load item event: fired when a load item is successfull.\n     *\n     * @event App#loaditem\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     * @property {object} data The loaded meta data.\n     */\n    this.#fireEvent({\n      type: 'loaditem',\n      data: eventMetaData,\n      source: event.source,\n      loadtype: event.loadtype,\n      dataid: event.dataid,\n      isfirstitem: event.isfirstitem,\n      warn: event.warn\n    });\n\n    // update overlay data if present\n    if (typeof this.#overlayDatas !== 'undefined' &&\n      typeof this.#overlayDatas[event.dataid] !== 'undefined') {\n      this.#overlayDatas[event.dataid].addItemMeta(eventMetaData);\n    }\n\n    // render if first and flag allows\n    if (event.loadtype === 'image' &&\n      this.getViewConfigs(event.dataid).length !== 0 &&\n      isFirstLoadItem && this.#options.viewOnFirstLoadItem) {\n      this.render(event.dataid);\n    }\n  };\n\n  /**\n   * Data load callback.\n   *\n   * @param {object} event The load event.\n   */\n  #onload = (event) => {\n    /**\n     * Load event: fired when a load finishes successfully.\n     *\n     * @event App#load\n     * @type {object}\n     * @property {string} type The event type: load.\n     * @property {string} loadType The load type: image or state.\n     */\n    event.type = 'load';\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load end callback.\n   *\n   * @param {object} event The load end event.\n   */\n  #onloadend = (event) => {\n    /**\n     * Main load end event: fired when the load finishes,\n     *   successfully or not.\n     *\n     * @event App#loadend\n     * @type {object}\n     * @property {string} type The event type: loadend.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     */\n    event.type = 'loadend';\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load error callback.\n   *\n   * @param {object} event The error event.\n   */\n  #onloaderror = (event) => {\n    /**\n     * Load error event.\n     *\n     * @event App#error\n     * @type {object}\n     * @property {string} type The event type: error.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     * @property {object} error The error.\n     * @property {object} target The event target.\n     */\n    if (typeof event.type === 'undefined') {\n      event.type = 'error';\n    }\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load timeout callback.\n   *\n   * @param {object} event The timeout event.\n   */\n  #onloadtimeout = (event) => {\n    /**\n     * Load timeout event.\n     *\n     * @event App#timeout\n     * @type {object}\n     * @property {string} type The event type: timeout.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: an url as a string.\n     * @property {object} target The event target.\n     */\n    if (typeof event.type === 'undefined') {\n      event.type = 'timeout';\n    }\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load abort callback.\n   *\n   * @param {object} event The abort event.\n   */\n  #onloadabort = (event) => {\n    /**\n     * Load abort event.\n     *\n     * @event App#abort\n     * @type {object}\n     * @property {string} type The event type: abort.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     */\n    if (typeof event.type === 'undefined') {\n      event.type = 'abort';\n    }\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Bind layer group events to app.\n   *\n   * @param {LayerGroup} group The layer group.\n   */\n  #bindLayerGroupToApp(group) {\n    // propagate layer group events\n    group.addEventListener('zoomchange', this.#fireEvent);\n    group.addEventListener('offsetchange', this.#fireEvent);\n    // propagate viewLayer events\n    group.addEventListener('renderstart', this.#fireEvent);\n    group.addEventListener('renderend', this.#fireEvent);\n    // propagate view events\n    for (let j = 0; j < viewEventNames.length; ++j) {\n      group.addEventListener(viewEventNames[j], this.#fireEvent);\n    }\n    // propagate drawLayer events\n    if (this.#toolboxController && this.#toolboxController.hasTool('Draw')) {\n      group.addEventListener('drawcreate', this.#fireEvent);\n      group.addEventListener('drawdelete', this.#fireEvent);\n    }\n    // updata data view config\n    group.addEventListener('wlchange', (event) => {\n      const layerDetails = getLayerDetailsFromLayerDivId(event.srclayerid);\n      const groupId = layerDetails.groupDivId;\n      const config = this.getViewConfig(event.dataid, groupId, true);\n      if (typeof config !== 'undefined') {\n        // reset previous values\n        config.windowCenter = undefined;\n        config.windowWidth = undefined;\n        config.wlPresetName = undefined;\n        // window width, center and name\n        if (event.value.length === 3) {\n          config.windowCenter = event.value[0];\n          config.windowWidth = event.value[1];\n          config.wlPresetName = event.value[2];\n        }\n      }\n    });\n    group.addEventListener('opacitychange', (event) => {\n      const layerDetails = getLayerDetailsFromLayerDivId(event.srclayerid);\n      const groupId = layerDetails.groupDivId;\n      const config = this.getViewConfig(event.dataid, groupId, true);\n      if (typeof config !== 'undefined') {\n        config.opacity = event.value[0];\n      }\n    });\n    group.addEventListener('colourmapchange', (event) => {\n      const layerDetails = getLayerDetailsFromLayerDivId(event.srclayerid);\n      const groupId = layerDetails.groupDivId;\n      const config = this.getViewConfig(event.dataid, groupId, true);\n      if (typeof config !== 'undefined') {\n        config.colourMap = event.value[0];\n      }\n    });\n  }\n\n  /**\n   * Add a view layer.\n   *\n   * @param {string} dataId The data id.\n   * @param {ViewConfig} viewConfig The data view config.\n   */\n  #addViewLayer(dataId, viewConfig) {\n    const data = this.#dataController.get(dataId);\n    if (!data) {\n      throw new Error('Cannot initialise layer with missing data, id: ' +\n        dataId);\n    }\n    const layerGroup = this.#stage.getLayerGroupByDivId(viewConfig.divId);\n    if (!layerGroup) {\n      throw new Error('Cannot initialise layer with missing group, id: ' +\n        viewConfig.divId);\n    }\n    const imageGeometry = data.image.getGeometry();\n\n    // un-bind\n    this.#stage.unbindLayerGroups();\n\n    // create and setup view\n    const viewFactory = new ViewFactory();\n    const view = viewFactory.create(data.meta, data.image);\n    const viewOrientation = getViewOrientation(\n      imageGeometry.getOrientation(),\n      getMatrixFromName(viewConfig.orientation)\n    );\n    view.setOrientation(viewOrientation);\n\n    // make pixel of value 0 transparent for segmentation\n    // (assuming RGB data)\n    if (data.image.getMeta().Modality === 'SEG') {\n      view.setAlphaFunction(function (value /*, index*/) {\n        if (value === 0) {\n          return 0;\n        } else {\n          return 0xff;\n        }\n      });\n    }\n\n    // do we have more than one layer\n    // (the layer has not been added to the layer group yet)\n    const isBaseLayer = layerGroup.getNumberOfViewLayers() === 0;\n\n    // opacity\n    let opacity = 1;\n    if (typeof viewConfig.opacity !== 'undefined') {\n      opacity = viewConfig.opacity;\n    } else {\n      if (!isBaseLayer) {\n        opacity = 0.5;\n      }\n    }\n\n    // view layer\n    const viewLayer = layerGroup.addViewLayer();\n    viewLayer.setView(view, dataId);\n    const size2D = imageGeometry.getSize(viewOrientation).get2D();\n    const spacing2D = imageGeometry.getSpacing(viewOrientation).get2D();\n    viewLayer.initialise(size2D, spacing2D, opacity);\n\n    // view controller\n    const viewController = viewLayer.getViewController();\n    // window/level\n    if (typeof viewConfig.wlPresetName !== 'undefined') {\n      viewController.setWindowLevelPreset(viewConfig.wlPresetName);\n    } else if (typeof viewConfig.windowCenter !== 'undefined' &&\n      typeof viewConfig.windowWidth !== 'undefined') {\n      const wl = new WindowLevel(\n        viewConfig.windowCenter, viewConfig.windowWidth);\n      viewController.setWindowLevel(wl);\n    }\n    // colour map\n    if (typeof viewConfig.colourMap !== 'undefined') {\n      viewController.setColourMap(viewConfig.colourMap);\n    } else {\n      if (!isBaseLayer) {\n        if (data.image.getMeta().Modality === 'PT') {\n          viewController.setColourMap('hot');\n        } else {\n          viewController.setColourMap('rainbow');\n        }\n      }\n    }\n\n    // listen to image set\n    this.#dataController.addEventListener(\n      'dataimageset', viewLayer.onimageset);\n\n    // sync layers position\n    const value = [\n      viewController.getCurrentIndex().getValues(),\n      viewController.getCurrentPosition().getValues()\n    ];\n    layerGroup.updateLayersToPositionChange({\n      value: value,\n      srclayerid: viewLayer.getId()\n    });\n\n    // sync layer groups\n    this.#stage.fitToContainer();\n\n    // layer offset (done before scale)\n    viewLayer.setOffset(layerGroup.getOffset());\n\n    // get and apply flip flags\n    const flipFlags = this.#getViewFlipFlags(\n      imageGeometry.getOrientation(),\n      viewConfig.orientation);\n    this.#applyFlipFlags(flipFlags, viewLayer);\n\n    // layer scale (done after possible flip)\n    if (!isBaseLayer) {\n      // use zoom offset of base layer\n      const baseViewLayer = layerGroup.getBaseViewLayer();\n      viewLayer.initScale(\n        layerGroup.getScale(),\n        baseViewLayer.getAbsoluteZoomOffset()\n      );\n    } else {\n      viewLayer.setScale(layerGroup.getScale());\n    }\n\n    // bind\n    this.#stage.bindLayerGroups();\n    if (this.#toolboxController) {\n      this.#toolboxController.bindLayerGroup(layerGroup, viewLayer);\n    }\n\n    /**\n     * Add view layer event.\n     *\n     * @event App#viewlayeradd\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} layerid The layer id.\n     * @property {string} layergroupid The layer group id.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'viewlayeradd',\n      layerid: viewLayer.getId(),\n      layergroupid: layerGroup.getDivId(),\n      dataid: dataId\n    });\n\n    // initialise the toolbox for base\n    if (isBaseLayer) {\n      if (this.#toolboxController) {\n        this.#toolboxController.init();\n      }\n    }\n  }\n\n  /**\n   * Add a draw layer.\n   *\n   * @param {string} dataId The data id.\n   * @param {ViewConfig} viewConfig The data view config.\n   */\n  addDrawLayer(dataId, viewConfig) {\n    const layerGroup = this.#stage.getLayerGroupByDivId(viewConfig.divId);\n    if (!layerGroup) {\n      throw new Error('Cannot initialise layer with missing group, id: ' +\n        viewConfig.divId);\n    }\n\n    // reference is the data of the view layer with the\n    //   same StudyInstanceUID\n    const data = this.#dataController.get(dataId);\n    if (!data) {\n      throw new Error('Cannot initialise layer with missing data, id: ' +\n        dataId);\n    }\n    const refSeriesSeq =\n      data.annotationGroup.getMetaValue('ReferencedSeriesSequence');\n    const refSeriesInstanceUID = refSeriesSeq.value[0].SeriesInstanceUID;\n    const viewLayers = layerGroup.searchViewLayers({\n      SeriesInstanceUID: refSeriesInstanceUID\n    });\n    if (viewLayers.length === 0) {\n      console.warn(\n        'No loaded data that matches the measurement reference series UID');\n      return;\n    }\n    const refViewLayer = viewLayers[0];\n    const refDataId = refViewLayer.getDataId();\n\n    // un-bind\n    this.#stage.unbindLayerGroups();\n\n    // set annotation view controller (allows quantification)\n    const refViewController = refViewLayer.getViewController();\n    data.annotationGroup.setViewController(refViewController);\n\n    // reference data to use as base for layer properties\n    const refData = this.#dataController.get(refDataId);\n    if (!refData) {\n      throw new Error(\n        'Cannot initialise layer without reference data, id: ' +\n        refDataId);\n    }\n    const imageGeometry = refData.image.getGeometry();\n\n    const viewOrientation = getViewOrientation(\n      imageGeometry.getOrientation(),\n      getMatrixFromName(viewConfig.orientation)\n    );\n    const size2D = imageGeometry.getSize(viewOrientation).get2D();\n    const spacing2D = imageGeometry.getSpacing(viewOrientation).get2D();\n\n    const drawLayer = layerGroup.addDrawLayer();\n    drawLayer.initialise(size2D, spacing2D, refViewLayer.getId());\n\n    const planeHelper = new PlaneHelper(\n      imageGeometry,\n      viewOrientation\n    );\n    drawLayer.setPlaneHelper(planeHelper);\n\n    // sync layers position\n    const value = [\n      refViewController.getCurrentIndex().getValues(),\n      refViewController.getCurrentPosition().getValues()\n    ];\n    layerGroup.updateLayersToPositionChange({\n      value: value,\n      srclayerid: drawLayer.getId()\n    });\n\n    // sync layer groups\n    this.#stage.fitToContainer();\n\n    // layer offset (done before scale)\n    drawLayer.setOffset(layerGroup.getOffset());\n\n    // get and apply flip flags\n    const flipFlags = this.#getViewFlipFlags(\n      imageGeometry.getOrientation(),\n      viewConfig.orientation);\n    this.#applyFlipFlags(flipFlags, drawLayer);\n\n    // layer scale (done after possible flip)\n    // use zoom offset of ref layer\n    drawLayer.initScale(\n      layerGroup.getScale(),\n      refViewLayer.getAbsoluteZoomOffset()\n    );\n\n    // add possible existing data\n    drawLayer.setAnnotationGroup(\n      data.annotationGroup,\n      dataId,\n      this.addToUndoStack);\n\n    drawLayer.setCurrentPosition(\n      refViewController.getCurrentPosition(),\n      refViewController.getCurrentIndex()\n    );\n\n    // bind\n    this.#stage.bindLayerGroups();\n    if (this.#toolboxController) {\n      this.#toolboxController.bindLayerGroup(layerGroup, drawLayer);\n    }\n\n    /**\n     * Add draw layer event.\n     *\n     * @event App#drawlayeradd\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} layerid The layer id.\n     * @property {string} layergroupid The layer group id.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'drawlayeradd',\n      layerid: drawLayer.getId(),\n      layergroupid: layerGroup.getDivId(),\n      dataid: dataId\n    });\n  }\n\n  /**\n   * Get the view flip flags: offset (x, y) and scale (x, y, z) flags.\n   *\n   * @param {Matrix33} imageOrientation The image orientation.\n   * @param {string} viewConfigOrientation The view config orientation.\n   * @returns {object} Offset and scale flip flags.\n   */\n  #getViewFlipFlags(imageOrientation, viewConfigOrientation) {\n    // 'simple' orientation code (does not take into account angles)\n    const orientationCode =\n      getOrientationStringLPS(imageOrientation.asOneAndZeros());\n    if (typeof orientationCode === 'undefined') {\n      throw new Error('Unsupported undefined orientation code');\n    }\n\n    // view orientation flags\n    const isViewUndefined = typeof viewConfigOrientation === 'undefined';\n    const isViewAxial = !isViewUndefined &&\n      viewConfigOrientation === Orientation.Axial;\n    const isViewCoronal = !isViewUndefined &&\n      viewConfigOrientation === Orientation.Coronal;\n    const isViewSagittal = !isViewUndefined &&\n      viewConfigOrientation === Orientation.Sagittal;\n\n    // default flags\n    const flipOffset = {\n      x: false,\n      y: false\n    };\n    const flipScale = {\n      x: false,\n      y: false,\n      z: false\n    };\n\n    if (orientationCode === 'LPS') {\n      // axial\n      if (isViewCoronal || isViewSagittal) {\n        flipScale.z = true;\n        flipOffset.y = true;\n      }\n    } else if (orientationCode === 'LAI') {\n      // axial\n      if (isViewUndefined || isViewAxial) {\n        flipOffset.y = true;\n      } else if (isViewCoronal) {\n        flipScale.z = true;\n      } else if (isViewSagittal) {\n        flipScale.z = true;\n        flipOffset.x = true;\n      }\n    } else if (orientationCode === 'RPI') {\n      // axial\n      if (isViewUndefined || isViewAxial) {\n        flipOffset.x = true;\n      } else if (isViewCoronal) {\n        flipScale.z = true;\n        flipOffset.x = true;\n      } else if (isViewSagittal) {\n        flipScale.z = true;\n      }\n    } else if (orientationCode === 'RAS') {\n      // axial\n      flipOffset.x = true;\n      flipOffset.y = true;\n      if (isViewCoronal || isViewSagittal) {\n        flipScale.z = true;\n      }\n    } else if (orientationCode === 'LSA') {\n      // coronal\n      flipOffset.y = true;\n      if (isViewUndefined || isViewCoronal) {\n        flipScale.z = true;\n      } else if (isViewAxial) {\n        flipScale.y = true;\n      } else if (isViewSagittal) {\n        flipOffset.x = true;\n        flipScale.y = true;\n        flipScale.z = true;\n      }\n    // } else if (orientationCode === 'LIP') { // nothing to do\n    } else if (orientationCode === 'RSP') {\n      // coronal\n      if (isViewUndefined || isViewCoronal) {\n        flipOffset.x = true;\n        flipOffset.y = true;\n        flipScale.x = true;\n        flipScale.z = true;\n      } else if (isViewAxial) {\n        flipOffset.x = true;\n        flipScale.x = true;\n      } else if (isViewSagittal) {\n        flipOffset.y = true;\n        flipScale.z = true;\n      }\n    } else if (orientationCode === 'RIA') {\n      // coronal\n      flipOffset.x = true;\n      if (isViewUndefined || isViewCoronal) {\n        flipScale.x = true;\n      } else if (isViewAxial) {\n        flipOffset.y = true;\n        flipScale.x = true;\n        flipScale.y = true;\n      } else if (isViewSagittal) {\n        flipScale.y = true;\n      }\n    } else if (orientationCode === 'PSL') {\n      // sagittal\n      flipScale.z = true;\n      if (isViewUndefined || isViewSagittal) {\n        flipOffset.y = true;\n      } else if (isViewCoronal) {\n        flipOffset.y = true;\n      }\n    } else if (orientationCode === 'PIR') {\n      // sagittal\n      flipScale.z = true;\n      if (isViewAxial || isViewCoronal) {\n        flipOffset.x = true;\n      }\n    } else if (orientationCode === 'ASR') {\n      // sagittal\n      flipOffset.x = true;\n      flipOffset.y = true;\n      if (isViewUndefined || isViewSagittal) {\n        flipScale.z = true;\n      } else if (isViewCoronal) {\n        flipScale.z = true;\n      }\n    } else if (orientationCode === 'AIL') {\n      // sagittal\n      if (isViewUndefined || isViewSagittal) {\n        flipOffset.x = true;\n        flipScale.z = true;\n      } else if (isViewAxial) {\n        flipOffset.y = true;\n      } else if (isViewCoronal) {\n        flipScale.z = true;\n      }\n    } else {\n      logger.warn('Unsupported orientation code: ' +\n        orientationCode + ', display could be incorrect');\n    }\n\n    return {\n      scale: flipScale,\n      offset: flipOffset\n    };\n  }\n\n  #applyFlipFlags(flipFlags, layer) {\n    if (flipFlags.offset.x) {\n      layer.addFlipOffsetX();\n    }\n    if (flipFlags.offset.y) {\n      layer.addFlipOffsetY();\n    }\n    if (flipFlags.scale.x) {\n      layer.flipScaleX();\n    }\n    if (flipFlags.scale.y) {\n      layer.flipScaleY();\n    }\n    if (flipFlags.scale.z) {\n      layer.flipScaleZ();\n    }\n  }\n\n} // class App\n","import {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {MaskSegment} from '../dicom/dicomSegment';\n/* eslint-enable no-unused-vars */\n\n/**\n * Mask segment helper: helps handling the segments list,\n *   but does *NOT* update the associated mask (use special commands\n *   for that such as DeleteSegmentCommand, ChangeSegmentColourCommand...).\n */\nexport class MaskSegmentHelper {\n\n  /**\n   * The associated mask.\n   *\n   * @type {Image}\n   */\n  #mask;\n\n  /**\n   * The segments: array of segment description.\n   *\n   * @type {MaskSegment[]}\n   */\n  #segments;\n\n  /**\n   * @param {Image} mask The associated mask image.\n   */\n  constructor(mask) {\n    this.#mask = mask;\n    // check segments in meta\n    const meta = mask.getMeta();\n    if (typeof meta.custom === 'undefined') {\n      meta.custom = {};\n    }\n    if (typeof meta.custom.segments === 'undefined') {\n      meta.custom.segments = [];\n    }\n    this.#segments = meta.custom.segments;\n  }\n\n  /**\n   * Find the index of a segment in the segments list.\n   *\n   * @param {number} segmentNumber The number to find.\n   * @returns {number} The index in the segments list, -1 if not found.\n   */\n  #findSegmentIndex(segmentNumber) {\n    return this.#segments.findIndex(function (item) {\n      return item.number === segmentNumber;\n    });\n  }\n\n  /**\n   * Check if a segment is part of the segments list.\n   *\n   * @param {number} segmentNumber The segment number.\n   * @returns {boolean} True if the segment is included.\n   */\n  hasSegment(segmentNumber) {\n    return this.#findSegmentIndex(segmentNumber) !== -1;\n  }\n\n  /**\n   * Get the number of segments of the segmentation.\n   *\n   * @returns {number} The number of segments.\n   */\n  getNumberOfSegments() {\n    return this.#segments.length;\n  }\n\n  /**\n   * Check if a segment is present in a mask image.\n   *\n   * @param {number[]} numbers Array of segment numbers.\n   * @returns {boolean[]} Array of boolean set to true\n   *   if the segment is present in the mask.\n   */\n  maskHasSegments(numbers) {\n    // create values using displayValue\n    const values = [];\n    const unknowns = [];\n    for (let i = 0; i < numbers.length; ++i) {\n      const segment = this.getSegment(numbers[i]);\n      if (typeof segment !== 'undefined') {\n        if (typeof segment.displayValue !== 'undefined') {\n          values.push(segment.displayValue);\n        } else {\n          values.push(segment.number);\n        }\n      } else {\n        logger.warn('Unknown segment in maskHasSegments: ' + numbers[i]);\n        unknowns.push(i);\n      }\n    }\n    const res = this.#mask.hasValues(values);\n    // insert unknowns as false in result\n    for (let j = 0; j < unknowns.length; ++j) {\n      res.splice(unknowns[j], 0, false);\n    }\n    return res;\n  }\n\n  /**\n   * Get a segment from the inner segment list.\n   *\n   * @param {number} segmentNumber The segment number.\n   * @returns {MaskSegment|undefined} The segment or undefined if not found.\n   */\n  getSegment(segmentNumber) {\n    let segment;\n    const index = this.#findSegmentIndex(segmentNumber);\n    if (index !== -1) {\n      segment = this.#segments[index];\n    }\n    return segment;\n  }\n\n  /**\n   * Add a segment to the segments list.\n   *\n   * @param {MaskSegment} segment The segment to add.\n   */\n  addSegment(segment) {\n    const index = this.#findSegmentIndex(segment.number);\n    if (index === -1) {\n      this.#segments.push(segment);\n      // update palette colour map\n      if (typeof segment.displayRGBValue !== 'undefined') {\n        this.#mask.updatePaletteColourMap(\n          segment.number, segment.displayRGBValue);\n      }\n    } else {\n      logger.warn(\n        'Not adding segment, it is allready in the segments list: ' +\n          segment.number);\n    }\n  }\n\n  /**\n   * Remove a segment from the segments list.\n   *\n   * @param {number} segmentNumber The segment number.\n   */\n  removeSegment(segmentNumber) {\n    const index = this.#findSegmentIndex(segmentNumber);\n    if (index !== -1) {\n      this.#segments.splice(index, 1);\n    } else {\n      logger.warn(\n        'Cannot remove segment, it is not in the segments list: ' +\n          segmentNumber);\n    }\n  }\n\n  /**\n   * Update a segment of the segments list.\n   *\n   * @param {MaskSegment} segment The segment to update.\n   */\n  updateSegment(segment) {\n    const index = this.#findSegmentIndex(segment.number);\n    if (index !== -1) {\n      this.#segments[index] = segment;\n    } else {\n      logger.warn(\n        'Cannot update segment, it is not in the segments list: ' +\n          segment.number);\n    }\n  }\n\n} // class MaskSegmentHelper\n","import {MaskSegmentHelper} from './maskSegmentHelper';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {MaskSegment} from '../dicom/dicomSegment';\n/* eslint-enable no-unused-vars */\n\n/**\n * Delete segment command.\n */\nexport class DeleteSegmentCommand {\n\n  /**\n   * The associated mask.\n   *\n   * @type {Image}\n   */\n  #mask;\n\n  /**\n   * The segment to remove.\n   *\n   * @type {MaskSegment}\n   */\n  #segment;\n\n  /**\n   * Flag to send creation events.\n   *\n   * @type {boolean}\n   */\n  #isSilent;\n\n  /**\n   * List of offsets.\n   *\n   * @type {number[]}\n   */\n  #offsets;\n\n  /**\n   * @param {Image} mask The mask image.\n   * @param {MaskSegment} segment The segment to remove.\n   * @param {boolean} [silent] Whether to send a creation event or not.\n   */\n  constructor(mask, segment, silent) {\n    this.#mask = mask;\n    this.#segment = segment;\n    this.#isSilent = (typeof silent === 'undefined') ? false : silent;\n    // list of offsets with the colour to delete\n    if (typeof segment.displayRGBValue !== 'undefined') {\n      this.#offsets = mask.getOffsets(segment.number);\n    } else {\n      this.#offsets = mask.getOffsets(segment.displayValue);\n    }\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'Delete-segment';\n  }\n\n  /**\n   * Check if a command is valid and can be executed.\n   *\n   * @returns {boolean} True if the command is valid.\n   */\n  isValid() {\n    // check that input segment is still there\n    const segments = this.#mask.getMeta().custom.segments;\n    return segments.some(segmentItem =>\n      segmentItem.number === this.#segment.number\n    );\n  }\n\n  /**\n   * Execute the command.\n   *\n   * @fires DeleteSegmentCommand#masksegmentdelete\n   */\n  execute() {\n    if (this.#offsets.length !== 0) {\n      // remove from image\n      this.#mask.setAtOffsets(this.#offsets, 0);\n    }\n\n    // remove from segments\n    const segHelper = new MaskSegmentHelper(this.#mask);\n    segHelper.removeSegment(this.#segment.number);\n\n    // callback\n    if (!this.#isSilent) {\n      /**\n       * Segment delete event.\n       *\n       * @event DeleteSegmentCommand#masksegmentdelete\n       * @type {object}\n       * @property {number} segmentnumber The segment number.\n       */\n      this.onExecute({\n        type: 'masksegmentdelete',\n        segmentnumber: this.#segment.number\n      });\n    }\n  }\n\n  /**\n   * Undo the command.\n   *\n   * @fires DeleteSegmentCommand#masksegmentredraw\n   */\n  undo() {\n    if (this.#offsets.length !== 0) {\n      // re-draw in image\n      if (typeof this.#segment.displayRGBValue !== 'undefined') {\n        this.#mask.setAtOffsets(this.#offsets, this.#segment.number);\n      } else {\n        this.#mask.setAtOffsets(this.#offsets, this.#segment.displayValue);\n      }\n    }\n    // add back to segments\n    const segHelper = new MaskSegmentHelper(this.#mask);\n    segHelper.addSegment(this.#segment);\n\n    // callback\n    /**\n     * Segment redraw event.\n     *\n     * @event DeleteSegmentCommand#masksegmentredraw\n     * @type {object}\n     * @property {number} segmentnumber The segment number.\n     */\n    this.onUndo({\n      type: 'masksegmentredraw',\n      segmentnumber: this.#segment.number\n    });\n  }\n\n  /**\n   * Handle an execute event.\n   *\n   * @param {object} _event The execute event with type and id.\n   */\n  onExecute(_event) {\n    // default does nothing.\n  }\n\n  /**\n   * Handle an undo event.\n   *\n   * @param {object} _event The undo event with type and id.\n   */\n  onUndo(_event) {\n    // default does nothing.\n  }\n\n} // DeleteSegmentCommand class\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {MaskSegment} from '../dicom/dicomSegment';\nimport {RGB} from '../utils/colour';\n/* eslint-enable no-unused-vars */\n\n/**\n * Change segment colour command.\n */\nexport class ChangeSegmentColourCommand {\n\n  /**\n   * The associated mask.\n   *\n   * @type {Image}\n   */\n  #mask;\n\n  /**\n   * The segment to modify.\n   *\n   * @type {MaskSegment}\n   */\n  #segment;\n\n  /**\n   * The new segment colour.\n   *\n   * @type {RGB|number}\n   */\n  #newColour;\n\n  /**\n   * The previous segment colour.\n   *\n   * @type {RGB|number}\n   */\n  #previousColour;\n\n  /**\n   * Flag to send creation events.\n   *\n   * @type {boolean}\n   */\n  #isSilent;\n\n  /**\n   * List of offsets.\n   *\n   * @type {number[]}\n   */\n  #offsets;\n\n  /**\n   * @param {Image} mask The mask image.\n   * @param {MaskSegment} segment The segment to modify.\n   * @param {RGB|number} newColour The new segment colour.\n   * @param {boolean} [silent] Whether to send a creation event or not.\n   */\n  constructor(mask, segment, newColour, silent) {\n    this.#mask = mask;\n    this.#segment = segment;\n    this.#newColour = newColour;\n\n    this.#isSilent = (typeof silent === 'undefined') ? false : silent;\n    // list of offsets with the colour to delete\n    if (typeof segment.displayRGBValue !== 'undefined') {\n      this.#previousColour = segment.displayRGBValue;\n    } else {\n      this.#previousColour = segment.displayValue;\n      this.#offsets = mask.getOffsets(this.#previousColour);\n    }\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'Change-segment-colour';\n  }\n\n  /**\n   * Check if a command is valid and can be executed.\n   *\n   * @returns {boolean} True if the command is valid.\n   */\n  isValid() {\n    let valid = true;\n    if (typeof this.#offsets !== 'undefined') {\n      valid = this.#offsets.length !== 0;\n    }\n    return valid;\n  }\n\n  /**\n   * Execute the command.\n   *\n   * @fires ChangeSegmentColourCommand#changemasksegmentcolour\n   */\n  execute() {\n    // update segment property\n    if (typeof this.#newColour === 'number') {\n      // remove\n      this.#mask.setAtOffsets(this.#offsets, this.#newColour);\n      // update segment\n      this.#segment.displayValue = this.#newColour;\n    } else {\n      // update palette colour map (sends update event)\n      this.#mask.updatePaletteColourMap(\n        this.#segment.number,\n        this.#newColour\n      );\n      // update segment\n      this.#segment.displayRGBValue = this.#newColour;\n    }\n\n    // callback\n    if (!this.#isSilent) {\n      /**\n       * Segment delete event.\n       *\n       * @event ChangeSegmentColourCommand#changemasksegmentcolour\n       * @type {object}\n       * @property {number} segmentnumber The segment number.\n       */\n      this.onExecute({\n        type: 'changemasksegmentcolour',\n        segmentnumber: this.#segment.number,\n        value: [this.#newColour]\n      });\n    }\n  }\n\n  /**\n   * Undo the command.\n   *\n   * @fires ChangeSegmentColourCommand#changemasksegmentcolour\n   */\n  undo() {\n    // update segment property\n    if (typeof this.#previousColour === 'number') {\n      // update values\n      this.#mask.setAtOffsets(this.#offsets, this.#previousColour);\n      // update segment\n      this.#segment.displayValue = this.#previousColour;\n    } else {\n      // update palette colour map (sends update event)\n      this.#mask.updatePaletteColourMap(\n        this.#segment.number,\n        this.#previousColour\n      );\n      // udpate segment\n      this.#segment.displayRGBValue = this.#previousColour;\n    }\n\n    // callback\n    /**\n     * Segment redraw event.\n     *\n     * @event ChangeSegmentColourCommand#changemasksegmentcolour\n     * @type {object}\n     * @property {number} segmentnumber The segment number.\n     */\n    this.onUndo({\n      type: 'changemasksegmentcolour',\n      segmentnumber: this.#segment.number,\n      value: [this.#previousColour]\n    });\n  }\n\n  /**\n   * Handle an execute event.\n   *\n   * @param {object} _event The execute event with type and id.\n   */\n  onExecute(_event) {\n    // default does nothing.\n  }\n\n  /**\n   * Handle an undo event.\n   *\n   * @param {object} _event The undo event with type and id.\n   */\n  onUndo(_event) {\n    // default does nothing.\n  }\n\n} // ChangeSegmentColourCommand class\n","import {logger} from '../utils/logger';\n\n/**\n * Mask segment view helper: handles hidden segments.\n */\nexport class MaskSegmentViewHelper {\n\n  /**\n   * List of hidden segment numbers.\n   *\n   * @type {number[]}\n   */\n  #hiddenNumbers = [];\n\n  /**\n   * Get the index of a segment in the hidden list.\n   *\n   * @param {number} segmentNumber The segment number.\n   * @returns {number} The index in the array, -1 if not found.\n   */\n  #findHiddenIndex(segmentNumber) {\n    return this.#hiddenNumbers.indexOf(segmentNumber);\n  }\n\n  /**\n   * Check if a segment is in the hidden list.\n   *\n   * @param {number} segmentNumber The segment number.\n   * @returns {boolean} True if the segment is in the list.\n   */\n  isHidden(segmentNumber) {\n    return this.#findHiddenIndex(segmentNumber) !== -1;\n  }\n\n  /**\n   * Add a segment to the hidden list.\n   *\n   * @param {number} segmentNumber The segment number.\n   */\n  addToHidden(segmentNumber) {\n    if (!this.isHidden(segmentNumber)) {\n      this.#hiddenNumbers.push(segmentNumber);\n    } else {\n      logger.warn(\n        'Not hidding segment, it is allready in the hidden list: ' +\n          segmentNumber);\n    }\n  }\n\n  /**\n   * Remove a segment from the hidden list.\n   *\n   * @param {number} segmentNumber The segment number.\n   */\n  removeFromHidden(segmentNumber) {\n    const index = this.#findHiddenIndex(segmentNumber);\n    if (index !== -1) {\n      this.#hiddenNumbers.splice(index, 1);\n    } else {\n      logger.warn(\n        'Cannot remove segment, it is not in the hidden list: ' +\n          segmentNumber);\n    }\n  }\n\n  /**\n   * @callback alphaFn\n   * @param {number|number[]} value The pixel value.\n   * @param {number} index The values' index.\n   * @returns {number} The opacity of the input value.\n   */\n\n  /**\n   * Get the alpha function to apply hidden colors.\n   *\n   * @returns {alphaFn} The corresponding alpha function.\n   */\n  getAlphaFunc() {\n    // create alpha function\n    // (zero is hidden by default)\n    return (value/*, index*/) => {\n      if (!Array.isArray(value) && (\n        value === 0 ||\n        this.#hiddenNumbers.includes(value))) {\n        return 0;\n      }\n      // default\n      return 255;\n    };\n  }\n}","/**\n * Mutable 2D scalar ({x,y}).\n */\nexport class Scalar2D {\n  /**\n   * X value.\n   *\n   * @type {number}\n   */\n  x;\n\n  /**\n   * Y value.\n   *\n   * @type {number}\n   */\n  y;\n}\n\n/**\n * Mutable 3D scalar ({x,y,z}).\n */\nexport class Scalar3D {\n  /**\n   * X value.\n   *\n   * @type {number}\n   */\n  x;\n\n  /**\n   * Y value.\n   *\n   * @type {number}\n   */\n  y;\n\n  /**\n   * Z value.\n   *\n   * @type {number}\n   */\n  z;\n}"],"names":["root","factory","exports","module","require","define","amd","this","__WEBPACK_EXTERNAL_MODULE__944__","__WEBPACK_EXTERNAL_MODULE__324__","__WEBPACK_EXTERNAL_MODULE__654__","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","n","getter","__esModule","d","a","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","r","Symbol","toStringTag","value","Index","constructor","values","Error","length","every","val","isNaN","i","toString","getValues","slice","canCompare","rhs","equals","leni","compare","diffDims","push","add","dim","console","warn","next","previous","getWithNew2D","j","l","lenl","ModalityLut","rsi","bitsStored","isID","Math","pow","Float32Array","apply","getRSI","getLength","getValue","offset","logger","levels","TRACE","DEBUG","INFO","WARN","ERROR","level","trace","msg","debug","info","error","WindowLevel","center","width","VoiLut","wl","getWindowLevel","c","setSignedOffset","WindowLut","modalityLut","isSigned","isDiscrete","size","getVoiLut","getModalityLut","setVoiLut","lut","getSlope","Uint8ClampedArray","floor","buildLut","func","id","invId","lut_range_max","ColourMap","red","green","blue","luts","plain","invPlain","rainbow","hot","third","hot_iron","pet","hot_metal_blue","pet_20step","RGB","g","b","isEqualRgb","c1","c2","labToUintLab","triplet","d65","x","y","z","srgbToCielab","labFunc","res","illuminant","fy","ciexyzToCielab","invGammaFunc","rl","gl","bl","srgbToCiexyz","colourNameToHex","name","dict","Yellow","Red","White","Green","Blue","Lime","Fuchsia","Black","custom","wlPresets","labelTexts","openRoiDialog","getTagTime","getTagPixelUnit","Vector3D","getX","getY","getZ","norm","sqrt","crossProduct","vector3D","dotProduct","isCodirectional","Number","EPSILON","REAL_WORLD_EPSILON","isSimilar","tol","abs","Matrix33","row","col","getInverse","m","m00","m01","m02","m10","m11","m12","m20","m21","m22","a1212","a2012","a0112","det","getMatrixInverse","p","str","multiply","tmp","k","getAbs","multiplyArray3D","array3D","multiplyVector3D","multiplyPoint3D","point3D","Point3D","multiplyIndex3D","index3D","getRowAbsMax","absMax","max","index","indexOf","getColAbsMax","asOneAndZeros","sign","getThirdColMajorDirection","getIdentityMat33","isIdentityMat33","mat33","Point2D","getCentroid","getDistance","point2D","dx","dy","dz","getClosest","pointList","minIndex","minDist","dist","minus","Point","get3D","values0","values1","mergeWith3D","i18n","t","props","split","mm","cm2","degree","startsWith","search","rawPos","pos","substring","endsWith","getFlags","inputStr","flags","regex","match","exec","getFileExtension","filePath","ext","pathSplit","toLowerCase","pop","test","includes","stringToUint8Array","arr","Uint8Array","charCodeAt","precisionRound","number","precision","factor","delta","round","toStringId","dims","arraySortEquals","arr0","arr1","arrayEquals","sort","element","uint8ArrayToString","String","fromCharCode","findInArraySubset","callbackFn","start","end","getFindArrayInArrayCallback","buildMultipart","parts","boundary","lineBreak","partsSize","headers","headerStr","partKeys","keys","header","byteLength","data","trailer","buffer","set","dictionary","addTagsToDictionary","group","tags","tagGroups","vr32bitVL","OB","OD","OF","OL","OV","OW","SQ","SV","UC","UN","UR","UT","UV","ox","is32bitVLVR","vr","vrCharSetString","SH","LO","ST","LT","PN","isCharSetStringVR","vrTypes","AE","AS","AT","CS","DA","DS","DT","FL","FD","IS","SL","SS","TM","UI","UL","US","transferSyntaxes","transferSyntaxKeywords","Tag","getGroup","getElement","getKey","getNameFromDictionary","getGroupName","isWithVR","isPrivate","parseInt","getVrFromDictionary","tagCompareFunction","getTagFromKey","getItemTag","isItemTag","tag","isItemDelimitationItemTag","isSequenceDelimitationItemTag","getPixelDataTag","isPixelDataTag","getTagFromDictionary","tagName","keys0","keys1","foundTag","k0","lenK0","k1","lenK1","DataElement","vl","undefinedLength","startOffset","endOffset","items","safeGet","flipArrayEndianness","array","blen","u8","byteOffset","bpe","BYTES_PER_ELEMENT","DataReader","Int8Array","Int16Array","isNativeLittleEndian","isLittleEndian","DataView","readUint16","getUint16","readInt16","getInt16","readUint32","getUint32","readBigUint64","getBigUint64","readInt32","getInt32","readBigInt64","getBigInt64","readFloat32","getFloat32","readFloat64","getFloat64","readBinaryArray","bitArray","byteArrayLength","bitNumber","bitIndex","readUint8Array","readInt8Array","readUint16Array","Uint16Array","arraySize","readInt16Array","readUint32Array","Uint32Array","readUint64Array","BigUint64Array","readInt32Array","Int32Array","readInt64Array","BigInt64Array","readFloat32Array","readFloat64Array","Float64Array","readHex","toUpperCase","getDwvVersion","hasDicomPrefix","reduce","current","ZWS","DefaultTextDecoder","decode","result","getReverseOrientation","ori","rlabels","L","R","A","P","H","F","rori","isImplicitTransferSyntax","syntax","isBigEndianTransferSyntax","isJpegBaselineTransferSyntax","isJpegLosslessTransferSyntax","isJpeg2000TransferSyntax","isRleTransferSyntax","getTypedArray","bitsAllocated","pixelRepresentation","RangeError","powerOf2","log","getDataElementPrefixByteSize","isImplicit","TagKeys","DicomParser","getDefaultCharacterSet","setDefaultCharacterSet","characterSet","setDecoderCharacterSet","TextDecoder","getDicomElements","reader","implicit","itemData","item","isSeqDelim","isItemDelim","offsetTableVl","untilTag","readTagRes","is32bitVL","concat","isKnownVR","pixItemData","sqEndOffset","vrType","Array","from","stream","lastIndex","trim","cleanString","raw","stri","stri1","sqBitsAllocated","sqPixelRepresentation","dataElement","subElement","elements","parse","metaReader","dataReader","magicword","metaEnd","tsElement","firstDataElement","oEightGroupLittleEndian","vr0","vr1","guessTransferSyntax","isReadSupportedTransferSyntax","getTransferSyntaxName","reachedUntilTag","charSetTerm","label","getUtfLabel","numberOfFrames","pixItems","nItemPerFrame","newPixItems","f","newBuffer","fragOffset","ListenerHandler","type","callback","remove","nFound","splice","fireEvent","event","stack","range","dataAccessor","maxIter","increment","blockMaxIter","blockIncrement","reverse1","reverse2","nextIndex","finalBlockIncrement","mainCount","blockCount","done","getIteratorValues","iterator","ival","getSliceIterator","image","isRescaled","viewOrientation","getGeometry","getSize","dirMax2Index","posValues","posStart","map","indexToOffset","getRescaledValueAtOffset","getValueAtOffset","ncols","nrows","nslices","sliceSize","getDimSize","ncomp","getNumberOfComponents","isPlanar","getPlanarConfiguration","getRange","iters","r0","r1","r2","range3d","rangeObj","dirMax0","dirMax2","simpleRange","componentIncrement","nextIndex1","nextIndex2","simpleRange3d","valueRange","nextValueIndex","RescaleSlopeAndIntercept","slope","intercept","getIntercept","Size","moreThanOne","dimension","canScroll3D","canScroll","getTotalSize","isInBounds","dirs","offsetToIndex","off","dimSize","get2D","Statistics","min","mean","stdDev","median","p25","p75","getStats","includesFullStatsFlags","stats","getBasicStats","getPercentile","getFullStats","sum","sumSqr","variance","ratio","i0","v0","guid","random","NumberRange","Spacing","Geometry","origins","spacing","orientation","time","getInitialTime","getCurrentTotalNumberOfSlices","count","hasSlicesAtTime","getCurrentNumberOfSlicesBeforeTime","getOrigin","getOrigins","includesOrigin","getOrientedArray3D","geoSliceSpacing","spacings","origin1","origin2","sliceSpacing","getSliceGeometrySpacing","getSpacing","orientedValues","getRealSpacing","getOrientation","getSliceIndex","point","localOrigins","closestOriginIndex","closestOrigin","pointDir","appendOrigin","origin","equalToOrigin","find","appendFrame","sizeValues","spacingValues","isIndexInBounds","worldToIndex","nDims","minValues","fill","maxIndex","indexToWorld","orientedPoint3D","pointToWorld","worldToPoint","getDeOrientedArray3D","padZeroTwoDigit","getDate","daValue","monthBeginIndex","dayBeginIndex","year","monthIndex","day","getTime","tmValue","tmHours","tmMinutes","tmSeconds","tmFracSecondsStr","hours","minutes","seconds","milliseconds","dateToDateObj","date","getFullYear","getMonth","dateToTimeObj","getHours","getMinutes","getSeconds","getDicomDate","dateObj","getDicomTime","getCoronalMat33","Orientation","Axial","Coronal","Sagittal","getMatrixFromName","matrix","getOrientationStringLPS","v1","v2","getVectorStringLPS","vector","orientationX","orientationY","orientationZ","threshold","getOrientationName","cosines","orientMatrix","getOrientationFromCosines","code","orientStr","getLPSGroup","orientationMatrix","rowCosines","colCosines","normal","getViewOrientation","imageOrientation","targetOrientation","getImage2DSize","rows","columns","getSpacingFromMeasure","dataElements","pixelSpacing","parseFloat","isMonochrome","photometricInterpretation","checkTag","warning","ImageFactory","getWarning","checkElements","modality","syntaxElement","spp","samplesPerPixel","photo","jpeg2000","jpegBase","jpegLoss","getPhotometricInterpretation","SOPClassUID","getSopClassUid","isSecondatyCapture","suvFactor","patWeight","patWeightEl","weight","decayedDose","seriesDateObj","totalDose","halfLife","radioStart","radioInfoSq","totalDoseStr","totalDoseEl","dose","halfLifeStr","halfLifeEl","hl","radioStartDateTimeEl","radioStartDateObj","radioStartTimeObj","radioStartDateTime","dtValue","dateDataElement","dtDate","timeDataElement","getDateTime","Date","seriesTimeObj","scanStart","acqDateEl","acqTimeEl","acqDateObj","acqTimeObj","acqDate","frameRefTime","frameRefTimeElStr","frameRefTimeEl","actualFrameDuration","actualFrameDurationElStr","actualFrameDurationEl","decayConstant","decayDuringFrame","offsetSeconds","exp","decayTime","getDecayedDose","getSuvFactor","create","pixelBuffer","numberOfFiles","size2D","numberOfFramesEl","rowSpacing","columnSpacing","getPixelSpacing","imagePositionPatient","slicePosition","imageOrientationPatient","getOrientationMatrix","geometry","sopInstanceUid","siu","bufferSize","Image","setPhotometricInterpretation","planarConfiguration","setPlanarConfiguration","rescaleSlope","rescaleIntercept","meta","Modality","isPetWithSuv","intensityFactor","setRescaleSlopeAndIntercept","safeGetLocal","TransferSyntaxUID","MediaStorageSOPClassUID","ImageType","SamplesPerPixel","PhotometricInterpretation","PixelRepresentation","BitsAllocated","BitsStored","HighBit","StudyDate","StudyTime","StudyInstanceUID","StudyID","SeriesInstanceUID","SeriesNumber","ReferringPhysicianName","PatientName","PatientID","PatientBirthDate","PatientSex","Manufacturer","ManufacturerModelName","DeviceSerialNumber","SoftwareVersions","ImageOrientationPatient","FrameOfReferenceUID","IsSigned","pixelUnit","unit","defaultGetTagPixelUnit","windowPresets","windowCenter","windowWidth","windowCWExplanation","redLutElement","greenLutElement","blueLutElement","redLut","greenLut","blueLut","descriptor","doScale","descSize","vlSize","scaleTo8","clone","setPaletteColourMap","recommendedDisplayFrameRate","RecommendedDisplayFrameRate","setMeta","DataWriter","writeUint8","setUint8","writeInt8","setInt8","writeUint16","setUint16","writeInt16","setInt16","writeUint32","setUint32","writeUint64","setBigUint64","writeInt32","setInt32","writeInt64","setBigInt64","writeFloat32","setFloat32","writeFloat64","setFloat64","writeHex","writeBinaryArray","byte","len","writeUint8Array","writeInt8Array","writeUint16Array","writeInt16Array","writeUint32Array","writeUint64Array","writeInt32Array","writeInt64Array","writeFloat32Array","writeFloat64Array","_uidCount","WriterRule","action","writerActions","copy","clear","replace","getUID","prefix","getDwvUIDPrefix","uid","datePart","toISOString","countPart","nonTagLength","tagNumber","isEven","isStringVr","uint8ArrayPush","newArr","DefaultTextEncoder","encode","DicomWriter","default","setUseUnVrForPrivateSq","flag","setFixUnknownVR","setRules","rules","addMissingTags","rule","tagKey","isKey","useSpecialTextEncoder","TextEncoder","getElementToWrite","groupName","writer","itemTag","subItem","itemElement","itemDelimElement","hexString","hexString1","hexString2","atValue","diff","message","finalValue","initialArray","initialArrayLength","arrayLength","flattenendArrayLength","flattenedArray","indexFlattenedArray","flattenArrayOfTypedArrays","isTagWithVR","undefinedLengthSequence","undefinedLengthItem","seqDelimElement","getBuffer","isBigEndian","oldscs","totalSize","localSize","metaElements","rawElements","metaLength","fmiglTag","fmivTag","icUIDTag","ivnTag","missingTags","originalElement","checkAndFixUnknownVR","fmiv","getDataElement","fmivSize","icUID","icUIDSize","icUIDValue","ivn","ivnSize","ivnValue","elemSortFunc","fmigl","fmiglSize","ArrayBuffer","metaWriter","dataWriter","lenj","metaOffset","lenk","newItems","oldItemElements","newItemElements","subSize","itemKeys","itemKey","padStr","pad","getVrPad","join","padOBValue","isTypedArrayVr","isArray","itemPrefixSize","getBpeForVrType","dictVr","getUint8ToVrValue","getElementsFromJSONTags","simpleTags","simpleTag","CodeValue","CodingSchemeDesignator","CodeMeaning","LongCodeValue","URNCodeValue","DicomCode","meaning","longValue","urnValue","schemeDesignator","isEqualCode","code1","code2","getCode","getDicomCodeItem","DcmCodes","SctCodes","UcumCodes","deg","getDicomCode","scheme","getMeasurementGroupCode","getReferenceGeometryCode","getSourceImageCode","getTrackingIdentifierCode","getShortLabelCode","getReferencePointsCode","getColourCode","QuantificationName2DictItem","angle","surface","height","radius","stddev","getQuantificationName","propKey","QuantificationUnit2UcumKey","HU","MGML","ED","PCT","CNTS","NONE","CM2","CM2ML","PCNT","CPS","BQML","MGMINML","UMOLMINML","MLMING","MLG","UMOLML","PROPCNTS","PROPCPS","MLMINML","MLML","GML","SUV","getQuantificationUnit","ucumKey","MaskSegment","algorithmType","algorithmName","displayValue","displayRGBValue","propertyTypeCode","propertyCategoryCode","trackingUid","trackingId","getSegment","segment","cielabElement","rgb","gammaFunc","ciexyzToSrgb","invLabFunc","l0","cielabToCiexyz","cielabToSrgb","getDicomSegmentItem","algoType","segmentItem","SegmentNumber","SegmentLabel","SegmentAlgorithmType","SegmentAlgorithmName","cieLab","RecommendedDisplayCIELabValue","RecommendedDisplayGrayscaleValue","SegmentedPropertyCategoryCodeSequence","SegmentedPropertyTypeCodeSequence","TrackingID","TrackingUID","DicomSegmentFrameInfo","dimIndex","imagePosPat","derivationImages","refSegmentNumber","getSegmentFrameInfo","derivationImageSq","sourceImages","sourceImageSq","sourceImage","referencedSOPClassUID","referencedSOPInstanceUID","segmentIdSq","frameInfo","framePlaneOrientationSeq","frameImageOrientation","framePixelMeasuresSeq","frameSpacing","getDicomSegmentFrameInfoItem","FrameContentSequence","DimensionIndexValues","PlanePositionSequence","ImagePositionPatient","SegmentIdentificationSequence","ReferencedSegmentNumber","sourceImgPurposeOfReferenceCode","segDerivationCode","derivationImageItems","derivationImage","PurposeOfReferenceCodeSequence","ReferencedSOPClassUID","ReferencedSOPInstanceUID","DerivationCodeSequence","SourceImageSequence","DerivationImageSequence","equalPosPat","pos1","pos2","JSON","stringify","tagDefinition","tagValue","enum","createRoiSliceBuffers","segments","sliceOffset","buffers","inputOffset","pixelValue","segmentIndex","RequiredDicomSegTags","getDefaultDicomSegJson","reqTag","MaskFactory","_dicomElements","frames","framesElem","orgSq","orgUID","indices","indexSqElem","indexSq","indexPointer","indexOrg","DimensionOrganizationUID","DimensionIndexPointer","DimensionDescriptionLabel","organizations","getDimensionOrganization","segSequence","paletteColourMap","hasDisplayRGBValue","sharedFunctionalGroupsSeq","funcGroup0","planeOrientationSeq","pixelMeasuresSeq","includesPosPat","some","arrVal","findIndexPosPat","findIndex","perFrameFuncGroupSequence","frameInfos","framePosPats","ii","invOrientation","p1","p2","getComparePosPat","point3DFromArray","frameOrigins","tmpGeometry","isAboveEpsilon","posPats","sliceIndex","frameOrigin","distPrevious","numberOfSlices","uids","getFindSegmentFunc","frameOffset","frameSegment","SeriesDate","SeriesTime","DimensionOrganizationSequence","DimensionIndexSequence","SOPInstanceUID","frameOfReferenceUID","lossyImageCompression","LossyImageCompression","toDicom","extraTags","getMeta","Rows","Columns","now","ContentDate","ContentTime","segmentItems","SegmentSequence","SharedFunctionalGroupsSequence","PlaneOrientationSequence","PixelMeasuresSequence","SpacingBetweenSlices","PixelSpacing","roiBuffers","key0","createRoiBuffers","finalBuffers","referencedSOPs","number40","number4","key1","posPat","posPatArray","sourceIndex","getImageUid","NumberOfFrames","frameInfosTag","PerFrameFunctionalGroupsSequence","refSeriesTag","ReferencedInstanceSequence","ReferencedSeriesSequence","tags1","tags2","keys2","tagName2","mergeTags","dicomElements","pixVl","de","createImage","createMaskImage","imageUids","getSecondaryOffset","getOriginForImageUid","uidIndex","includesImageUid","containsImageUids","itemArr1","arrayContains","canQuantify","canWindowLevel","nFiles","getRescaleSlopeAndIntercept","isConstantRSI","inRsi","isIdentityRSI","interp","getPaletteColourMap","updatePaletteColourMap","colour","config","getOffsets","bufferValue","offsets","equal","hasValues","finalValues","equalFunc","getEqualCallback","valuesToFind","indicesToRemove","v","clonedBuffer","tmpBuffer","appendSlice","rhsSize","rhsRange","getDataRange","rhsResRange","getRescaledDataRange","resRange","timeId","isNewFrame","volumeGeometry","sliceGeometry","fullBufferSize","fullSliceIndex","indexOffset","maxOffset","subarray","numberOfImages","rhsPresets","pkey","rhsPreset","windowPreset","perslice","appendFrameBuffer","frameBuffer","frameIndex","frameSize","calculateDataRange","calculateRescaledDataRange","getHistogram","calculateHistogram","dataRange","rescaledDataRange","histogram","addEventListener","removeEventListener","setAtOffsets","setAtOffsetsAndGetOriginals","offsetsLists","originalValuesLists","previousValue","originalValues","currentValue","setAtOffsetsWithIterator","isValueArray","getValueAtIndex","getRescaledValue","getRescaledValueAtIndex","resmin","resmax","rmin","rmax","rvalue","histo","convolute2D","weights","newImage","imgSize","dimOffset","convoluteBuffer","componentOffset","wOff","wOff00","wOff0x","wOff0n","wOffx0","wOffxn","wOffn0","wOffnx","wOffnn","pixelOffset","newValue","wOffFinal","wi","transform","operator","compose","defaultWlPresets","CT","mediastinum","lung","bone","brain","head","ViewFactory","view","View","setColourMap","minmax","preset","setWindowPresets","init","viewEventNames","createView","getCurrentIndex","setCurrentIndex","getImage","setImage","inImage","setOrientation","setInitialIndex","getPlaybackMilliseconds","_value","_index","getAlphaFunction","setAlphaFunction","currentIndex","sliceWl","setWindowLevel","setWindowLevelPresetById","voiLut","voiLutWl","getWindowPresets","getWindowPresetsNames","presets","addWindowPresets","getCurrentWindowPresetName","getColourMap","getCurrentPosition","position","getCurrentImageUid","isPositionInBounds","getScrollDimIndex","originIndex","silent","setCurrentPosition","valid","minLen","maxLen","posEvent","imageUid","pixValue","isNewWl","isNewName","manual","wc","ww","skipGenerate","setWindowLevelPreset","getWindowLevelMinMax","setWindowLevelMinMax","generateImageData","photoInterpretation","alphaFunc","windowLut","colourMap","pxValue","generateImageDataMonochrome","is16BitsStored","to8","generateImageDataPaletteColor","generateImageDataRgb","cb","cr","generateImageDataYbrFull","isAquisitionOrientation","PlaneHelper","imageGeometry","getTargetOrientation","getOffset3DFromPlaneOffset","offset2D","planeOffset","getTargetDeOrientedVector3D","getPlaneOffsetFromOffset3D","offset3D","getTargetOrientedVector3D","planeVector","getTargetDeOrientedPoint3D","planePoint","getImageOrientedVector3D","getImageOrientedPoint3D","getImageDeOrientedVector3D","getImageDeOrientedPoint3D","getPositionFromPlanePoint","getPlanePointFromPosition","getCosines","getPlanePoints","snapPosition","planeOrigin","imageOrigin","pValues","iValues","scrollDimIndex","getNativeScrollDimIndex","getTargetOrientedPositiveXYZ","ViewPositionAccessor","PositionHelper","getMaximumDimValue","getMaximumScrollValue","getCurrentPositionDimValue","getCurrentPositionScrollValue","getCurrentPositionAtDimValue","getCurrentPositionAtScrollValue","setCurrentPositionSafe","merge","geometry1","geometry2","minByIndex","array1","array2","newSize","newSpacing","range1","range2","newOrigins","mergeGeometries","getIncrementPosition","getDecrementPosition","previousIndex","incrementPosition","decrementPosition","incrementPositionAlongScroll","decrementPositionAlongScroll","ViewController","getPlaneHelper","isMask","initialise","getModality","getWindowLevelPresetsNames","addWindowLevelPresets","isPlaying","getPositionHelper","getCurrentOrientedIndex","getCurrentIndexScrollValue","getCurrentScrollPosition","img","get2DSpacing","getRescaledImageValue","getPixelUnit","sliceValues","sliceOrigin","getImageRegionValues","imageIndex","rescaled","iter","rangeNumberOfColumns","regionSize","regionOffset","regionElementCount","rangeRegion","getRegionSliceIterator","getImageVariableRegionValues","regions","offsetRegions","region","regionIndex","regionCount","rangeRegions","getVariableRegionSliceIterator","canQuantifyImage","getImageSize","getImageWorldSize","getImageRescaledDataRange","equalImageMeta","imageMeta","metaKeys","metaKey","getPlanePositionFromPosition","getIndexFromPosition","getPlanePositionFromPlanePoint","play","window","setInterval","canDoMore","stop","clearInterval","setViewAlphaFunction","bindImageAndLayer","viewLayer","onimagecontentchange","onimagegeometrychange","unbindImageAndLayer","InteractionEventNames","getTouchesPositions","touches","offsetLeft","offsetTop","target","offsetParent","positions","pageX","pageY","getTouchPoints","targetTouches","changedTouches","getMousePoint","offsetX","offsetY","canCreateCanvas","testCvs","document","createElement","cropCvs","testCtx","getContext","cropCtx","fillRect","drawImage","getImageData","ViewLayer","containerDiv","className","getDataId","getScale","getAbsoluteZoomOffset","setImageSmoothing","setView","dataId","bindImage","getViewController","onimageset","dataid","unbindImage","draw","vcSize","origin0","scrollOffset","setBaseOffset","getId","removeFromDOM","getBaseSize","getOpacity","setOpacity","alpha","addFlipOffsetX","addFlipOffsetY","flipScaleX","flipScaleY","flipScaleZ","setScale","newScale","helper","orientedNewScale","finalNewScale","resetOffset","worldCenter","newOffset","getScaledOffset","newZoomOffset","initScale","absoluteZoomOffset","layerGroupOrigin","layerGroupOrigin0","needsUpdate","setOffset","planeNewOffset","displayToPlaneIndex","planePos","displayToPlanePos","displayToPlaneScale","deScaled","planePosToDisplay","posX","posY","displayToMainPlanePos","display","style","isVisible","layerid","globalAlpha","setTransform","imageSmoothingEnabled","appendChild","alert","clearRect","createImageData","fitToContainer","containerSize","divToWorldSizeRatio","fitOffset","needsDraw","divToImageSizeRatio","newViewOffset","scaledImageSize","newFlipOffset","bindInteraction","pointerEvents","names","eventName","passive","unbindInteraction","srclayerid","putImageData","dims3D","indexScrollDimIndex","filter","save","restore","ScrollSum","getSum","wheelDeltaY","deltaY","getSpinY","isTick","ScrollWheel","app","wheel","up","preventDefault","layerDetails","getLayerDetailsFromEvent","layerGroup","getLayerGroupByDivId","groupDivId","positionHelper","Line","begin","getBegin","getEnd","getDeltaX","getDeltaY","getWorldLength","spacing2D","wlen","dxs","dys","getMidpoint","getInclination","atan2","PI","quantify","viewController","quant","getAngle","line0","line1","dx0","dy0","dx1","dy1","dot","areOrthogonal","getPerpendicularLine","line","perpSlope","getLineFromEquation","getPerpendicularLineAtDistance","distance","lineFromEq","startPoint","minX","maxX","minY","maxY","isPointInLineRange","beginX","beginY","endX","endY","sx2","sy2","AddAnnotationCommand","annotation","drawController","getName","execute","addAnnotation","undo","removeAnnotation","RemoveAnnotationCommand","UpdateAnnotationCommand","originaProps","newProps","updateAnnotation","Style","getFontFamily","getFontSize","getStrokeWidth","getTextColour","getLineColour","setLineColour","setBaseScale","scale","setZoomScale","getBaseScale","getZoomScale","applyZoomScale","applyZoomRatio","getShadowOffset","getTagOpacity","getTextPadding","getFontStr","getLineHeight","getScaledFontSize","getScaledStrokeWidth","getShadowLineColour","hexColour","hexStr","defaultLabelTexts","arrow","circle","ellipse","protractor","rectangle","roi","ruler","isNodeNameLabel","node","isNodeNameShape","isPositionNode","getLineShape","kshape","getChildren","Konva","getAnchorShape","isNodeWithId","getDefaultAnchor","absRadius","stroke","strokeWidth","strokeScaleEnabled","radiusX","radiusY","dragOnTop","draggable","visible","getAnchorIndex","DrawShapeEditor","eventCallback","setShape","inshape","drawLayer","getFactory","getShape","getAnnotation","isActive","enable","getLayer","disable","reset","resetAnchors","getParent","forEach","anchor","setAnchorsActive","anchors","getAnchors","getStyle","originalProps","on","cancelBubble","mathShape","referencePoints","stageSize","changed","boundNodePosition","validateAnchorPosition","constrainAnchorMove","updateAnnotationOnAnchorMove","updateShapeGroupOnAnchorMove","command","getDrawController","addToUndoStack","moveToTop","DrawTrash","createTrashIcon","trashLine1","points","trashLine2","activate","stage","getKonvaStage","konvaLayer","getKonvaLayer","invscale","changeChildrenColourOnTrashHover","eventPosition","shapeGroup","originalShapeColour","isOverTrash","changeGroupChildrenColour","tshape","trashHalfWidth","scaleX","trashHalfHeight","scaleY","DrawShapeHandler","setEditorShape","shape","isAnnotationGroupEditable","getEditorShapeGroup","getEditorAnnotation","disableAndResetEditor","storeMouseOverCursor","cursor","body","opacity","onMouseOutShapeGroup","addShapeGroupListeners","originalTextExpr","textExpr","onSaveCallback","newTextExpr","prompt","defaultOpenRoiDialog","dragStartPos","previousPos","getShapePositionRange","boundRect","getClientRect","relativeTo","isShapeInRange","children","labelWithDefaultPosition","labelPosition","child","move","updateAnnotationOnTranslation","updateLabelContent","updateConnector","mousePoint","evt","eventPos","translation","originalLabelPosition","newLabelPosition","removeShapeListeners","ROI","getPoint","getPoints","addPoint","addPoints","cx","cy","pi","pi1","ai","a1","Path","inputPointArray","inputControlPointIndexArray","pointArray","controlPointIndexArray","isControlPoint","addControlPoint","newPointArray","appenPath","other","oldSize","indexArray","BucketQueue","bits","cost_functor","bucketCount","mask","loc","cost","buckets","buildArray","bucket","getBucket","ret","isEmpty","__twothirdpi","gradUnitVector","gradX","gradY","px","py","out","oy","gvm","Scissors","curPoint","searchGranBits","searchGran","pointsPerPost","greyscale","laplace","gradient","parents","working","trained","trainingPoints","edgeWidth","trainingLength","edgeGran","edgeTraining","gradPointsNeeded","gradGran","gradTraining","insideGran","insideTraining","outsideGran","outsideTraining","getTrainingIdx","granularity","getTrainedEdge","edge","getTrainedGrad","grad","getTrainedInside","inside","getTrainedOutside","outside","setWorking","setDimensions","setData","gradMagnitude","lap","computeGreyscale","computeLaplace","computeGradient","computeGradX","computeGradY","sides","guv","ix","iy","computeSides","findTrainingPoints","resetTraining","doTraining","calculateTraining","addInStaticGrad","input","output","maxVal","idx","gaussianBlur","have","need","gradDirection","qx","qy","__dgpuv","__gdquv","dp","dq","SQRT1_2","acos","dir","adj","list","sx","sy","ex","ey","setPoint","sp","visited","MAX_VALUE","pq","doWork","timeout","pointCount","newPoints","adjList","q","pqCost","LabelFactory","positionGetter","getPosition","ktext","fontSize","fontFamily","padding","shadowColor","shadowOffset","labelText","getText","setText","zoomScale","labelScale","klabel","updatePosition","getLabelAnchorsPosition","lx","ly","getClosestPoints","points1","points2","point1","point2","getConnector","connectorsPos","labelAnchorsPos","anchorPoints","dash","kconnect","updateContent","text","Circle","centre","getCenter","getRadius","getSurface","getWorldSurface","mulABC","getRound","centerX","centerY","rSquare","transX","quantif","Ellipse","getA","getB","radiusRatio","rySquare","getEllipseIndices","centerValues","radiusI","radiusJ","radiusJ2","di","dj","jmax","jmin","imax","imin","Protractor","_viewController","_flags","Rectangle","getRealWidth","getRealHeight","getWidth","getHeight","getRectangleIndices","sizeI","halfSizeI","sizeJ","halfSizeJ","ThresholdFilter","getMin","setMin","getMax","setMax","setOriginalImage","getOriginalImage","update","imageMin","SharpenFilter","SobelFilter","RunFilterCommand","render","onExecute","onUndo","_event","toolList","toolOptions","defaultToolList","divId","getActiveViewLayer","diffX","diffY","pixelToIntensity","WindowLevelValues","mousedown","mousemove","mouseup","mouseout","touchstart","touchPoints","touchmove","touchend","dblclick","getData","keydown","context","onKeydown","_bool","setFeatures","_features","Scroll","getActiveDrawLayer","getViewLayerById","getReferenceLayerId","yMove","xMove","setTimeout","clearTimeout","showTooltip","removeTooltipDiv","features","displayTooltip","ZoomAndPan","tx","ty","addTranslation","#twoTouchUpdate","lineRatio","zoom","addScale","step","Opacity","layer","getActiveLayer","op","Draw","refDataId","seriesInstanceUID","createAnnotationData","addAndRenderAnnotationData","setShapeHandler","setActiveLayerByDataId","getAnnotationGroup","isEditable","getIntersection","selectedShape","annotationid","getNPoints","timer","getTimeout","getActiveLayerGroup","destroy","tmpPoints","colours","drawLayerId","layerId","Annotation","groupColour","getColour","setAnnotationMathShape","createShapeGroup","setLabelVisibility","listening","finalPoints","activateCurrentPositionShapes","drawLayers","getDrawLayers","setOptions","options","getOptionsType","autoShapeColour","shapeColour","shapeName","hasShape","mouseOverCursor","withScroll","blacklist","getEventNames","listener","Filter","bool","getSelectedFilter","filterName","hasFilter","run","args","runArgs","getFilterList","Floodfill","setExtend","getExtend","#getIndex","simple","bytes","MagicWand","cs","icsl","newMathShape","originalMathShape","extend","ini","imageSize","jl","onThresholdChange","getAbsoluteScale","movedpoint","Livewire","pn","p0","results","_p","_q","defaultToolOptions","ArrowFactory","supports","setTextExpr","updateQuantification","extras","extra","_anchor","kline","pointBegin","pointEnd","endPoint","newBegin","newEnd","_style","linePerp0","linePerp1","hitFunc","beginPath","moveTo","lineTo","closePath","fillStrokeShape","perpLine","closed","ktriangle","_annotation","_group","CircleFactory","left","right","bottom","top","anchorPoint","newRadius","newCenter","swapX","swapY","kshadow","pixelLine","EllipseFactory","ProtractorFactory","mid","pointMid","newPointList","inclination","innerRadius","outerRadius","rotation","midX","midY","karc","arcPos","RectangleFactory","topLeft","bottomRight","pointTopLeft","pointBottomRight","krect","topRight","bottomLeft","rWidth","rHeight","RoiFactory","kroi","newPoint","RulerFactory","ktick0","ktick1","Threshold","Sobel","Sharpen","referenceSopUID","quantification","planePoints","isCompatibleView","planeHelper","cosine1","cosine2","setViewController","originPoint","valueObj","valueStr","toPrecision","replaceFlags","fac","factoryName","AnnotationGroup","getList","setEditable","setColour","propKeys","hasMeta","getMetaValue","setMetaValue","DrawController","setAnnotationGroupEditable","removeAnnotationWithCommand","exeCallback","updateAnnotationWithCommand","removeAllAnnotationsWithCommand","hasAnnotationMeta","setAnnotationMeta","DrawLayer","handler","getLayers","setPlaneHelper","refLayerId","container","getContent","setAttribute","setAnnotationGroup","annotationGroup","allPosGroups","posGroup","shapeGroups","posGroupId","layerChildren","posChildren","isAnnotationVisible","setAnnotationVisibility","setLabelsVisibility","posGroups","connector","deleteDraw","_id","_exeCallback","deleteDraws","getNumberOfDraws","findOne","ratioX","ratioY","labels","getLayerDetailsFromLayerDivId","idString","layerIndex","layerDiv","closest","indexCenter","LayerGroup","getShowCrosshair","setShowCrosshair","getDivId","getAddedScale","getOffset","getNumberOfLayers","getViewLayers","someViewLayer","hasOne","getNumberOfViewLayers","activeLayer","getBaseViewLayer","baseLayer","layers","getViewLayersByDataId","searchViewLayers","getViewDataIndices","getDrawLayerById","getDrawLayersByDataId","setActiveLayer","addViewLayer","viewLayerIndex","div","append","addDrawLayer","updateLayersToPositionChange","empty","getElementsByClassName","removeLayersByDataId","removeLayer","displayPos","lineH","offsetWidth","lineV","offsetHeight","span","createTextNode","viewLayerOffsets","baseViewLayerOrigin0","baseViewLayerOrigin","hasSetOffset","vc","scrollDiff","planeDiff","scroll","plane","refOffsets","hasSetPos","getDivToWorldSizeRatio","maxWorldSize","getMaxWorldSize","maxSize","scaleStep","binderList","WindowLevelBinder","getEventType","getCallback","viewLayers","PositionBinder","pointValues","currentPos","currentDims","inputDims","ZoomBinder","OffsetBinder","OpacityBinder","ColourMapBinder","Stage","getLayerGroup","getNumberOfLayerGroups","setActiveLayerGroup","addLayerGroup","htmlElement","isBound","unbindLayerGroups","bindLayerGroups","setBinders","removeLayerGroup","minRatio","hasRatio","binder","binderObj","elem","State","fromJSON","json","version","baseScale","scaleCenter","originX","originY","oldTx","oldTy","setDrawings","drawings","drawingsDetails","v02DAndD","inputDrawings","newDrawings","drawGroups","drawGroup","lenf","newFrameDrawings","leng","karcs","ktexts","toObject","txtLen","longText","v01Tov02DrawingsAndDetails","v02Tov03Drawings","v03Tov04DrawingsDetails","v04Tov05Data","v04Tov05Drawings","details","groupDetails","v02Tov03DrawingsDetails","groupShapes","parentGroup","groupDrawings","currentPosition","gnode","detail","ids","attrs","sliceNumber","frameNumber","newId","getUrlFromUri","uri","base","location","URL","splitUri","sepIndex","hashIndex","query","pairs","pair","splitKeyValueString","UndoStack","getStackSize","getCurrentStackIndex","cmd","redo","ToolboxController","enableShortcuts","getToolList","hasTool","getSelectedTool","getSelectedToolEventHandler","eventType","setSelectedTool","setToolFeatures","bindLayerGroup","layerGroupDivId","applySelectedTool","MultiProgressHandler","setNumberOfDimensions","num","setNToLoad","onprogress","lengthComputable","subindex","percent","loaded","total","source","lenprog","getMonoProgressHandler","getUndefinedMonoProgressHandler","UrlsLoader","request","loader","onload","onloadend","load","onloadstart","status","onerror","responseURL","statusText","response","mproghandler","loaders","loaderList","foundLoader","canLoadUrl","defaultCharacterSet","onloaditem","onabort","lastRunRequestIndex","requestOnLoadEnd","send","XMLHttpRequest","open","requestHeaders","setRequestHeader","withCredentials","errorCallback","timeoutCallback","ontimeout","abortCallback","loadUrlAs","responseType","batchSize","dicomDirUrl","urls","parser","dirSeq","records","series","study","recType","refFileIds","getFileListFromDicomDir","rootUrl","fullUrls","abort","readyState","isLoading","ThreadPool","poolSize","taskQueue","freeThreads","WorkerThread","runningThreads","addWorkerTask","workerTask","onworkstart","workerThread","shift","onworkend","onTaskEnd","onwork","handleWorkerError","onworkitem","parentPool","runningTask","worker","Worker","script","onmessage","postMessage","startMessage","terminate","itemNumber","numberOfItems","WorkerTask","hasJpegBaselineDecoder","JpegImage","hasJpegLosslessDecoder","jpeg","lossless","hasJpeg2000Decoder","JpxImage","decoderScripts","rle","AsynchPixelBufferDecoder","_numberOfData","pixelMeta","ondecodestart","ondecodeditem","ondecoded","ondecodeend","SynchPixelBufferDecoder","algoName","numberOfData","decoder","decodedBuffer","buf","Decoder","decoded","tiles","dwvdecoder","RleDecoder","PixelBufferDecoder","NumericValue","FloatingPointValue","RationalNumeratorValue","RationalDenominatorValue","MeasurementUnitsCodeSequence","MeasuredValue","numericValue","floatingPointValue","rationalNumeratorValue","rationalDenominatorValue","measurementUnitsCode","getDicomMeasuredValueItem","MeasuredValueSequence","NumericValueQualifierCodeSequence","NumericMeasurement","measuredValue","numericValueQualifierCode","getDicomNumericMeasurementItem","measurement","SopInstanceReference","getSopInstanceReference","ref","getDicomSopInstanceReferenceItem","ReferencedFrameNumber","ReferencedSOPSequence","ImageReference","referencedSOPSequence","referencedFrameNumber","referencedSegmentNumber","fiducialUID","getDicomImageReferenceItem","PixelOriginInterpretation","GraphicData","GraphicType","FiducialUID","GraphicTypes","SpatialCoordinate","graphicData","graphicType","pixelOriginInterpretation","getDicomSpatialCoordinateItem","scoord","ReferencedFrameofReferenceUID","SpatialCoordinate3D","referencedFrameofReferenceUID","getDicomSpatialCoordinate3DItem","RelationshipType","ValueType","ConceptNameCodeSequence","ConceptCodeSequence","ContentSequence","DateTime","Time","UID","PersonName","TextValue","ContinuityOfContent","RelationshipTypes","ValueTypes","datetime","uidref","pname","composite","waveform","scoord3d","tcoord","table","ValueTypeValueTagName","TEXT","DATE","TIME","DATETIME","UIDREF","PNAME","CONTAINER","DicomSRContent","valueType","conceptNameCode","relationshipType","contentSequence","getSRContent","content","getMeasuredValue","getNumericMeasurement","getImageReference","getSpatialCoordinate","getSpatialCoordinate3D","valueTagName","getDicomSRContentItem","contentItem","getSRContentFromValue","getConceptNameCode","measure","getMeasurementUnitsCode","numMeasure","AnnotationGroupFactory","srContent","dataLength","isClosed","numberOfPoints","firstPoint","lastPoint","line2","line3","getShapeFromScoord","subsubItem","nPoints","quantifName","quantifUnit","annotations","seriesElement","srScoord","pointPerimeter","getScoordFromShape","itemContentSequence","srImage","sopRef","imageRef","srUid","shortLabel","labelPosScoord","refPointsScoord","pointsScoord","quatifContent","CompletionFlag","VerificationFlag","DicomData","DataController","getNextDataId","getDataIds","getDataIdsFromSopUids","dataToUpdate","idKey","obj1","obj2","valueKey","mergedObj1","merged","id1","id2","value1","subValue1","value2","subValue2","mergeObjects","DicomBufferToView","opt","modalityElement","dicomParser","columnsElement","rowsElement","samplesPerPixelElement","planarConfigurationElement","dataIndex","decodedData","fullSize","algo","getSyntaxDecompressionName","convert","MemoryLoader","canLoadMemory","filename","toUID","imageDataToBuffer","imageData","dataLen","getDefaultImage","imageBuffer","imageSpacing","canLoadFile","file","url","forceLoader","isNameAccept","acceptHeader","acceptValue","urlObjext","pathname","hasNoExt","hasDcmExt","contentType","searchParams","mem","tmpFile","File","loadFileAs","fileContentTypes","_opt","Text","memoryIO","progress","u8Array","partHeaderEndCb","partHeaderEndIndex","lines","boundaryStr","boundaryCb","boundaryLen","nextBoundaryIndex","part","partHeaderLines","semiColonIndex","dataBeginIndex","dataEndIndex","parseMultipart","_file","_mem","dataType","imageType","Blob","createObjectURL","domImage","canvas","ctx","seriesUID","lastModified","getViewFromDOMImage","src","hasImageExt","DataURL","videoDataStr","btoa","video","onloadedmetadata","videoWidth","videoHeight","ceil","duration","onseeked","imgBuffer","storeFrame","nextTime","currentTime","getViewFromDOMVideo","unzipPercent","async","then","JSZip","zip","FilesLoader","FileReader","readAsText","readAsDataURL","readAsArrayBuffer","LoadController","loadFiles","files","loadURLs","loadImageObject","getLoadingDataIds","fileIO","urlIO","loadType","eventInfo","loadtype","isFirstItem","eventInfoItem","isfirstitem","getNumberToPrecision","createDefaultReplaceFormat","OverlayData","configs","addAppListeners","addItemMeta","dataUid","overlays","modElement","overlay","format","poElement","po0","po1","createOverlayData","DOM","infoKeys","createOverlayDataForDom","sliceOverlayData","mapFunc","isListening","removeAppListeners","ViewConfig","wlPresetName","ToolConfig","AppOptions","dataViewConfigs","tools","binders","viewOnFirstLoadItem","overlayConfig","rootDocument","App","addData","getMetaData","getToolboxController","removeFromUndoStack","appToolList","toolName","toolClass","toolParams","appToolOptions","optionName","optionClassName","toolNamespace","charAt","optionClass","tOptions","resetLayout","loadFromUri","getUriQuery","onLoadEnd","state","protocol","host","decodeURIComponent","manifest","rootURL","getElementsByTagName","getAttribute","patientList","studyList","studyUID","seriesList","instanceList","link","decodeManifest","responseXML","decodeManifestQuery","replaceMode","repeatKeyReplaceMode","queryUri","inputQueryPairs","repeatKey","repeatList","baseUrl","gotOneArg","decodeKeyValueUri","dwvReplaceMode","decodeQuery","abortAllLoads","abortLoad","initWLDisplay","getViewConfigs","excludeStarConfig","getViewConfig","getDataViewConfigs","setDataViewConfigs","addDataViewConfig","removeDataViewConfig","itemIndex","lg","vls","dls","updateDataViewConfig","configToUpdate","dataKeys","divIds","viewConfigs","viewConfig","getElementById","setLayerGroupsBinders","instances","isImage","isMeasurement","translate","statePosGroups","statePosKids","stateGroup","pointsArray","absPosition","absolutePosition","konvaToAnnotation","applyJsonState","jsonState","onResize","defaultOnKeydown","ctrlKey","shiftKey","resetDisplay","resetZoom","setTool","tool","getOverlayData","toggleOverlayListeners","refMeta","refDataViewConfig","drawDataViewConfig","isFirstLoadItem","eventMetaData","groupId","isBaseLayer","flipFlags","baseViewLayer","layergroupid","refSeriesInstanceUID","refViewLayer","refViewController","refData","viewConfigOrientation","orientationCode","isViewUndefined","isViewAxial","isViewCoronal","isViewSagittal","flipOffset","flipScale","MaskSegmentHelper","segmentNumber","hasSegment","getNumberOfSegments","maskHasSegments","numbers","unknowns","addSegment","removeSegment","updateSegment","DeleteSegmentCommand","isValid","segmentnumber","ChangeSegmentColourCommand","newColour","MaskSegmentViewHelper","isHidden","addToHidden","removeFromHidden","getAlphaFunc","Scalar2D","Scalar3D"],"sourceRoot":""}
\ No newline at end of file
+{"version":3,"file":"dwv.min.js","mappings":"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AK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAC35BD,MAAO,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,GACllCD,IAAK,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,MAK9lCO,IAAK,CACHP,IAAKN,GAtIT,SAAyBlE,GACvB,MAAMF,EAAU,EAAJE,EACZ,OAAIF,EAAMwE,IACDA,IAEFxE,CACT,IAiII2E,MAAOP,GAvHX,SAA0BlE,GACxB,MAAMgF,EAvCc,IAuCU,EAC9B,IAAIlF,EAAM,EACV,OAAIE,GAAKgF,IACPlF,EAAoB,GAAbE,EAAIgF,GACPlF,EAAMwE,KACDA,IAGJxE,CACT,IA8GI4E,KAAMR,GArGV,SAAyBlE,GACvB,MAAMgF,EA1Dc,IA0DU,EAC9B,IAAIlF,EAAM,EACV,OAAIE,GAAK,EAAIgF,IACXlF,EAAwB,GAAjBE,EAAI,EAAIgF,GACXlF,EAAMwE,KACDA,IAGJxE,CACT,KAgGEmF,SAAU,CACRT,IAAK,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC1sCC,MAAO,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC58BC,KAAM,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,MAM12BQ,IAAK,CACHV,IAAK,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC1kCC,MAAO,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC9lCC,KAAM,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,MAMrpCS,eAAgB,CACdX,IAAK,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC7iCC,MAAO,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC19BC,KAAM,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,MAMxmCU,WAAY,CACVZ,IAAK,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KACpnCC,MAAO,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAC3lCC,KAAM,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GA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","sources":["webpack://dwv/webpack/universalModuleDefinition","webpack://dwv/external umd {\"root\":\"JSZip\",\"commonjs\":\"jszip\",\"commonjs2\":\"jszip\",\"amd\":\"jszip\"}","webpack://dwv/external umd {\"root\":\"Konva\",\"commonjs\":\"konva\",\"commonjs2\":\"konva\",\"amd\":\"konva\"}","webpack://dwv/external umd {\"root\":\"MagicWand\",\"commonjs\":\"magic-wand-tool\",\"commonjs2\":\"magic-wand-tool\",\"amd\":\"konmagic-wand-tool\"}","webpack://dwv/webpack/bootstrap","webpack://dwv/webpack/runtime/compat get default export","webpack://dwv/webpack/runtime/define property getters","webpack://dwv/webpack/runtime/hasOwnProperty shorthand","webpack://dwv/webpack/runtime/make namespace object","webpack://dwv/./src/math/index.js","webpack://dwv/./src/image/modalityLut.js","webpack://dwv/./src/utils/logger.js","webpack://dwv/./src/image/windowLevel.js","webpack://dwv/./src/image/voiLut.js","webpack://dwv/./src/image/windowLut.js","webpack://dwv/./src/image/luts.js","webpack://dwv/./src/utils/colour.js","webpack://dwv/./src/app/custom.js","webpack://dwv/./src/math/vector.js","webpack://dwv/./src/math/matrix.js","webpack://dwv/./src/math/point.js","webpack://dwv/./src/utils/i18n.js","webpack://dwv/./src/utils/string.js","webpack://dwv/./src/utils/array.js","webpack://dwv/./src/dicom/dictionary.js","webpack://dwv/./src/dicom/dicomTag.js","webpack://dwv/./src/dicom/dataElement.js","webpack://dwv/./src/dicom/dataReader.js","webpack://dwv/./src/dicom/dicomParser.js","webpack://dwv/./src/utils/listen.js","webpack://dwv/./src/image/iterator.js","webpack://dwv/./src/image/rsi.js","webpack://dwv/./src/image/size.js","webpack://dwv/./src/math/stats.js","webpack://dwv/./src/image/spacing.js","webpack://dwv/./src/image/geometry.js","webpack://dwv/./src/dicom/dicomDate.js","webpack://dwv/./src/math/orientation.js","webpack://dwv/./src/dicom/dicomElementsWrapper.js","webpack://dwv/./src/image/imageFactory.js","webpack://dwv/./src/dicom/dataWriter.js","webpack://dwv/./src/dicom/dicomWriter.js","webpack://dwv/./src/dicom/dicomCode.js","webpack://dwv/./src/dicom/dicomSegment.js","webpack://dwv/./src/dicom/dicomSegmentFrameInfo.js","webpack://dwv/./src/image/maskFactory.js","webpack://dwv/./src/image/image.js","webpack://dwv/./src/image/viewFactory.js","webpack://dwv/./src/image/view.js","webpack://dwv/./src/image/viewMonochrome.js","webpack://dwv/./src/image/viewPaletteColor.js","webpack://dwv/./src/image/viewRgb.js","webpack://dwv/./src/image/viewYbrFull.js","webpack://dwv/./src/image/planeHelper.js","webpack://dwv/./src/image/positionHelper.js","webpack://dwv/./src/app/viewController.js","webpack://dwv/./src/gui/generic.js","webpack://dwv/./src/gui/viewLayer.js","webpack://dwv/./src/tools/scrollWheel.js","webpack://dwv/./src/math/line.js","webpack://dwv/./src/tools/drawCommands.js","webpack://dwv/./src/gui/style.js","webpack://dwv/./src/tools/drawBounds.js","webpack://dwv/./src/tools/drawShapeEditor.js","webpack://dwv/./src/tools/drawTrash.js","webpack://dwv/./src/tools/drawShapeHandler.js","webpack://dwv/./src/math/roi.js","webpack://dwv/./src/math/path.js","webpack://dwv/./src/math/bucketQueue.js","webpack://dwv/./src/math/scissors.js","webpack://dwv/./src/tools/labelFactory.js","webpack://dwv/./src/math/circle.js","webpack://dwv/./src/math/ellipse.js","webpack://dwv/./src/math/protractor.js","webpack://dwv/./src/math/rectangle.js","webpack://dwv/./src/image/filter.js","webpack://dwv/./src/tools/filter.js","webpack://dwv/./src/tools/index.js","webpack://dwv/./src/tools/windowLevel.js","webpack://dwv/./src/tools/scroll.js","webpack://dwv/./src/tools/zoomPan.js","webpack://dwv/./src/tools/opacity.js","webpack://dwv/./src/tools/draw.js","webpack://dwv/./src/tools/floodfill.js","webpack://dwv/./src/tools/livewire.js","webpack://dwv/./src/tools/arrow.js","webpack://dwv/./src/tools/circle.js","webpack://dwv/./src/tools/ellipse.js","webpack://dwv/./src/tools/protractor.js","webpack://dwv/./src/tools/rectangle.js","webpack://dwv/./src/tools/roi.js","webpack://dwv/./src/tools/ruler.js","webpack://dwv/./src/image/annotation.js","webpack://dwv/./src/image/annotationGroup.js","webpack://dwv/./src/app/drawController.js","webpack://dwv/./src/gui/drawLayer.js","webpack://dwv/./src/gui/layerGroup.js","webpack://dwv/./src/gui/stage.js","webpack://dwv/./src/io/state.js","webpack://dwv/./src/utils/uri.js","webpack://dwv/./src/utils/undoStack.js","webpack://dwv/./src/app/toolboxController.js","webpack://dwv/./src/utils/progress.js","webpack://dwv/./src/io/urlsLoader.js","webpack://dwv/./src/utils/thread.js","webpack://dwv/./src/image/decoder.js","webpack://dwv/./src/dicom/dicomMeasuredValue.js","webpack://dwv/./src/dicom/dicomNumericMeasurement.js","webpack://dwv/./src/dicom/dicomSopInstanceReference.js","webpack://dwv/./src/dicom/dicomImageReference.js","webpack://dwv/./src/dicom/dicomSpatialCoordinate.js","webpack://dwv/./src/dicom/dicomSpatialCoordinate3D.js","webpack://dwv/./src/dicom/dicomSRContent.js","webpack://dwv/./src/image/annotationGroupFactory.js","webpack://dwv/./src/app/dataController.js","webpack://dwv/./src/utils/operator.js","webpack://dwv/./src/image/dicomBufferToView.js","webpack://dwv/./src/io/memoryLoader.js","webpack://dwv/./src/image/domReader.js","webpack://dwv/./src/io/loaderList.js","webpack://dwv/./src/io/dicomDataLoader.js","webpack://dwv/./src/io/jsonTextLoader.js","webpack://dwv/./src/io/multipartLoader.js","webpack://dwv/./src/io/rawImageLoader.js","webpack://dwv/./src/io/rawVideoLoader.js","webpack://dwv/./src/io/zipLoader.js","webpack://dwv/./src/io/filesLoader.js","webpack://dwv/./src/app/loadController.js","webpack://dwv/./src/gui/overlayData.js","webpack://dwv/./src/app/application.js","webpack://dwv/./src/image/maskSegmentHelper.js","webpack://dwv/./src/image/deleteSegmentCommand.js","webpack://dwv/./src/image/changeSegmentColourCommand.js","webpack://dwv/./src/image/maskSegmentViewHelper.js","webpack://dwv/./src/math/scalar.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"konva\"), require(\"magic-wand-tool\"), require(\"jszip\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"konva\", \"konmagic-wand-tool\", \"jszip\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"dwv\"] = factory(require(\"konva\"), require(\"magic-wand-tool\"), require(\"jszip\"));\n\telse\n\t\troot[\"dwv\"] = factory(root[\"Konva\"], root[\"MagicWand\"], root[\"JSZip\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE__944__, __WEBPACK_EXTERNAL_MODULE__324__, __WEBPACK_EXTERNAL_MODULE__654__) {\nreturn ","module.exports = __WEBPACK_EXTERNAL_MODULE__654__;","module.exports = __WEBPACK_EXTERNAL_MODULE__944__;","module.exports = __WEBPACK_EXTERNAL_MODULE__324__;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/**\n * Immutable index.\n * Warning: the input array is NOT cloned, modifying it will\n *  modify the index values.\n */\nexport class Index {\n\n  /**\n   * Index values.\n   *\n   * @type {number[]}\n   */\n  #values;\n\n  /**\n   * @param {number[]} values The index values.\n   */\n  constructor(values) {\n    if (!values || typeof values === 'undefined') {\n      throw new Error('Cannot create index with no values.');\n    }\n    if (values.length === 0) {\n      throw new Error('Cannot create index with empty values.');\n    }\n    const valueCheck = function (val) {\n      return !isNaN(val);\n    };\n    if (!values.every(valueCheck)) {\n      throw new Error('Cannot create index with non number values.');\n    }\n    this.#values = values;\n  }\n\n  /**\n   * Get the index value at the given array index.\n   *\n   * @param {number} i The index to get.\n   * @returns {number|undefined} The value or undefined if not in range.\n   */\n  get(i) {\n    return this.#values[i];\n  }\n\n  /**\n   * Get the length of the index.\n   *\n   * @returns {number} The length.\n   */\n  length() {\n    return this.#values.length;\n  }\n\n  /**\n   * Get a string representation of the Index.\n   *\n   * @returns {string} The Index as a string.\n   */\n  toString() {\n    return '(' + this.#values.toString() + ')';\n  }\n\n  /**\n   * Get the values of this index.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return this.#values.slice();\n  }\n\n  /**\n   * Check if the input index can be compared to this one.\n   *\n   * @param {Index} rhs The index to compare to.\n   * @returns {boolean} True if both indices are comparable.\n   */\n  canCompare(rhs) {\n    // check input\n    if (!rhs) {\n      return false;\n    }\n    // check length\n    if (this.length() !== rhs.length()) {\n      return false;\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Check for Index equality.\n   *\n   * @param {Index} rhs The index to compare to.\n   * @returns {boolean} True if both indices are equal.\n   */\n  equals(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return false;\n    }\n    // check values\n    for (let i = 0, leni = this.length(); i < leni; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        return false;\n      }\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Compare indices and return different dimensions.\n   *\n   * @param {Index} rhs The index to compare to.\n   * @returns {number[]} The list of different dimensions.\n   */\n  compare(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return null;\n    }\n    // check values\n    const diffDims = [];\n    for (let i = 0, leni = this.length(); i < leni; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        diffDims.push(i);\n      }\n    }\n    return diffDims;\n  }\n\n  /**\n   * Add another index to this one and return\n   *   the result as a new index.\n   *\n   * @param {Index} rhs The index to add.\n   * @returns {Index} The index representing the sum of both indices.\n   */\n  add(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return null;\n    }\n    // add values\n    const values = [];\n    for (let i = 0, leni = this.length(); i < leni; ++i) {\n      values.push(this.get(i) + rhs.get(i));\n    }\n    // seems ok!\n    return new Index(values);\n  }\n\n  /**\n   * Add the input value to this index at the given\n   *   dimension number and return the result\n   *   as a new index.\n   *\n   * @param {number} dim The dimension number.\n   * @param {number} value The value to add.\n   * @returns {Index} The result index.\n   */\n  #addToDim(dim, value) {\n    const values = this.#values.slice();\n    if (dim < values.length) {\n      values[dim] += value;\n    } else {\n      console.warn('Cannot add to given dimension: ', dim, values.length);\n    }\n    return new Index(values);\n  }\n\n  /**\n   * Increment this index by 1 at the given dimension\n   *   and return the result as a new index.\n   *\n   * @param {number} dim The dimension number.\n   * @returns {Index} The result index.\n   */\n  next(dim) {\n    return this.#addToDim(dim, 1);\n  }\n\n  /**\n   * Decrement this index by 1 at the given dimension\n   *   and return the result as a new index.\n   *\n   * @param {number} dim The dimension number.\n   * @returns {Index} The result index.\n   */\n  previous(dim) {\n    return this.#addToDim(dim, -1);\n  }\n\n  /**\n   * Get the current index with a new 2D base\n   *   and return the result as a new index.\n   *\n   * @param {number} i The new 0 index.\n   * @param {number} j The new 1 index.\n   * @returns {Index} The new index.\n   */\n  getWithNew2D(i, j) {\n    const values = [i, j];\n    for (let l = 2, lenl = this.length(); l < lenl; ++l) {\n      values.push(this.get(l));\n    }\n    return new Index(values);\n  }\n\n} // Index class\n\n/**\n * Get an index with values set to 0 and the input size.\n *\n * @param {number} size The size of the index.\n * @returns {Index} The zero index.\n */\nexport function getZeroIndex(size) {\n  const values = new Array(size);\n  values.fill(0);\n  return new Index(values);\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {RescaleSlopeAndIntercept} from './rsi';\n/* eslint-enable no-unused-vars */\n\n/**\n * Modality LUT class: compensates for any modality-specific presentation.\n * Typically consists of a rescale slope and intercept to\n * rescale the data range.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.11.html}.\n */\nexport class ModalityLut {\n\n  /**\n   * The rescale slope.\n   *\n   * @type {RescaleSlopeAndIntercept}\n   */\n  #rsi;\n\n  /**\n   * Is the RSI an identity one.\n   *\n   * @type {boolean}\n   */\n  #isIdRsi;\n\n  /**\n   * The size of the LUT array.\n   *\n   * @type {number}\n   */\n  #length;\n\n  /**\n   * The internal LUT array.\n   *\n   * @type {Float32Array}\n   */\n  #lut;\n\n  /**\n   * @param {RescaleSlopeAndIntercept} rsi The rescale slope and intercept.\n   * @param {number} bitsStored The number of bits used to store the data.\n   */\n  constructor(rsi, bitsStored) {\n    this.#rsi = rsi;\n    this.#isIdRsi = rsi.isID();\n\n    this.#length = Math.pow(2, bitsStored);\n\n    // create lut if not identity RSI\n    if (!this.#isIdRsi) {\n      this.#lut = new Float32Array(this.#length);\n      for (let i = 0; i < this.#length; ++i) {\n        this.#lut[i] = this.#rsi.apply(i);\n      }\n    }\n  }\n\n  /**\n   * Get the Rescale Slope and Intercept (RSI).\n   *\n   * @returns {RescaleSlopeAndIntercept} The rescale slope and intercept object.\n   */\n  getRSI() {\n    return this.#rsi;\n  }\n\n  /**\n   * Get the length of the LUT array.\n   *\n   * @returns {number} The length of the LUT array.\n   */\n  getLength() {\n    return this.#length;\n  }\n\n  /**\n   * Get the value of the LUT at the given offset.\n   *\n   * @param {number} offset The input offset in [0,2^bitsStored] range\n   *   or full range for ID rescale.\n   * @returns {number} The float32 value of the LUT at the given offset.\n   */\n  getValue(offset) {\n    return this.#isIdRsi ? offset : this.#lut[offset];\n  }\n\n} // class ModalityLut\n","export const logger = {\n  /**\n   * Available log levels.\n   * Note: need to activate verbose level in\n   *   Chrome console to see DEBUG messages.\n   */\n  levels: {\n    TRACE: 0,\n    DEBUG: 1,\n    INFO: 2,\n    WARN: 3,\n    ERROR: 4\n  },\n\n  /**\n   * Logger level: default to WARN.\n   */\n  level: 3,\n\n  /**\n   * Log a trace message.\n   *\n   * @param {string} msg The message to log.\n   */\n  trace: function (msg) {\n    if (this.level <= this.levels.TRACE) {\n      console.trace(msg);\n    }\n  },\n\n  /**\n   * Log a debug message.\n   * Careful: depends on console settings.\n   *\n   * @param {string} msg The message to log.\n   */\n  debug: function (msg) {\n    if (this.level <= this.levels.DEBUG) {\n      console.debug(msg);\n    }\n  },\n\n  /**\n   * Log an info message.\n   *\n   * @param {string} msg The message to log.\n   */\n  info: function (msg) {\n    if (this.level <= this.levels.INFO) {\n      console.info(msg);\n    }\n  },\n\n  /**\n   * Log a warn message.\n   *\n   * @param {string} msg The message to log.\n   */\n  warn: function (msg) {\n    if (this.level <= this.levels.WARN) {\n      console.warn(msg);\n    }\n  },\n\n  /**\n   * Log an error message.\n   *\n   * @param {string} msg The message to log.\n   */\n  error: function (msg) {\n    if (this.level <= this.levels.ERROR) {\n      console.error(msg);\n    }\n  }\n\n}; // logger\n","import {logger} from '../utils/logger';\n\n/**\n * Minimum window width value.\n *\n * Ref: {@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.11.2.html#sect_C.11.2.1.2}.\n */\nconst minWindowWidth = 1;\n\n/**\n * Validate an input window width.\n *\n * @param {number} value The value to test.\n * @returns {number} A valid window width.\n */\nexport function validateWindowWidth(value) {\n  return value < minWindowWidth ? minWindowWidth : value;\n}\n\n/**\n * Window and Level also known as window width and center.\n */\nexport class WindowLevel {\n  /**\n   * The window center.\n   *\n   * @type {number}\n   */\n  center;\n\n  /**\n   * The window width.\n   *\n   * @type {number}\n   */\n  width;\n\n  /**\n   * @param {number} center The window center.\n   * @param {number} width The window width.\n   */\n  constructor(center, width) {\n    // check width\n    if (width < minWindowWidth) {\n      logger.warn('Using minimum window width since input is not valid: ' +\n        width);\n      width = minWindowWidth;\n    }\n    this.center = center;\n    this.width = width;\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {WindowLevel} rhs The other object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      typeof rhs !== 'undefined' &&\n      this.center === rhs.center &&\n      this.width === rhs.width;\n  }\n\n} // WindowLevel class\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {WindowLevel} from './windowLevel';\n/* eslint-enable no-unused-vars */\n\n/**\n * VOI (Values of Interest) LUT class: apply window centre and width.\n *\n * ```\n * if (x <= c - 0.5 - (w-1)/2) then y = ymin\n * else if (x > c - 0.5 + (w-1)/2) then y = ymax\n * else y = ((x - (c - 0.5)) / (w-1) + 0.5) * (ymax - ymin) + ymin\n * ```\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.11.2.html}.\n */\nexport class VoiLut {\n\n  /**\n   * The window and level.\n   *\n   * @type {WindowLevel}\n   */\n  #windowLevel;\n\n  /**\n   * Signed data offset. Defaults to 0.\n   *\n   * @type {number}\n   */\n  #signedOffset = 0;\n\n  /**\n   * Output value minimum. Defaults to 0.\n   *\n   * @type {number}\n   */\n  #ymin = 0;\n\n  /**\n   * Output value maximum. Defaults to 255.\n   *\n   * @type {number}\n   */\n  #ymax = 255;\n\n  /**\n   * Input value minimum (calculated).\n   *\n   * @type {number}\n   */\n  #xmin = null;\n\n  /**\n   * Input value maximum (calculated).\n   *\n   * @type {number}\n   */\n  #xmax = null;\n\n  /**\n   * Window level equation slope (calculated).\n   *\n   * @type {number}\n   */\n  #slope = null;\n\n  /**\n   * Window level equation intercept (calculated).\n   *\n   * @type {number}\n   */\n  #inter = null;\n\n  /**\n   * @param {WindowLevel} wl The window center and width.\n   */\n  constructor(wl) {\n    this.#windowLevel = wl;\n    this.#init();\n  }\n\n  /**\n   * Get the window and level.\n   *\n   * @returns {WindowLevel} The window center and width.\n   */\n  getWindowLevel() {\n    return this.#windowLevel;\n  }\n\n  /**\n   * Initialise members. Called at construction.\n   *\n   */\n  #init() {\n    const center = this.#windowLevel.center;\n    const width = this.#windowLevel.width;\n    const c = center + this.#signedOffset;\n    // from the standard\n    this.#xmin = c - 0.5 - ((width - 1) / 2);\n    this.#xmax = c - 0.5 + ((width - 1) / 2);\n    // develop the equation:\n    // y = ( ( x - (c - 0.5) ) / (w-1) + 0.5 ) * (ymax - ymin) + ymin\n    // y = ( x / (w-1) ) * (ymax - ymin) +\n    //     ( -(c - 0.5) / (w-1) + 0.5 ) * (ymax - ymin) + ymin\n    this.#slope = (this.#ymax - this.#ymin) / (width - 1);\n    this.#inter = (-(c - 0.5) / (width - 1) + 0.5) *\n      (this.#ymax - this.#ymin) + this.#ymin;\n  }\n\n  /**\n   * Set the signed offset.\n   *\n   * @param {number} offset The signed data offset,\n   *   typically: slope * ( size / 2).\n   */\n  setSignedOffset(offset) {\n    this.#signedOffset = offset;\n    // re-initialise\n    this.#init();\n  }\n\n  /**\n   * Apply the window level on an input value.\n   *\n   * @param {number} value The value to rescale as an integer.\n   * @returns {number} The leveled value, in the\n   *  [ymin, ymax] range (default [0,255]).\n   */\n  apply(value) {\n    if (value <= this.#xmin) {\n      return this.#ymin;\n    } else if (value > this.#xmax) {\n      return this.#ymax;\n    } else {\n      return (value * this.#slope) + this.#inter;\n    }\n  }\n\n} // class VoiLut\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {ModalityLut} from './modalityLut';\nimport {VoiLut} from './voiLut';\n/* eslint-enable no-unused-vars */\n\n/**\n * Window LUT class: combines a modality LUT and a VOI LUT.\n */\nexport class WindowLut {\n\n  /**\n   * The modality LUT.\n   *\n   * @type {ModalityLut}\n   */\n  #modalityLut;\n\n  /**\n   * The VOI LUT.\n   *\n   * @type {VoiLut}\n   */\n  #voiLut;\n\n  /**\n   * The internal LUT array: Uint8ClampedArray clamps between 0 and 255.\n   *\n   * @type {Uint8ClampedArray}\n   */\n  #lut;\n\n  /**\n   * Shift for signed data.\n   *\n   * @type {number}\n   */\n  #signedShift = 0;\n\n  /**\n   * Is the RSI discrete.\n   *\n   * @type {boolean}\n   */\n  #isDiscrete = true;\n\n  /**\n   * Construct a window LUT object, VOI LUT is set with\n   *   the 'setVoiLut' method.\n   *\n   * @param {ModalityLut} modalityLut The associated rescale LUT.\n   * @param {boolean} isSigned Flag to know if the data is signed or not.\n   * @param {boolean} isDiscrete Flag to know if the input data is discrete.\n   */\n  constructor(modalityLut, isSigned, isDiscrete) {\n    this.#modalityLut = modalityLut;\n\n    if (isSigned) {\n      const size = this.#modalityLut.getLength();\n      this.#signedShift = size / 2;\n    } else {\n      this.#signedShift = 0;\n    }\n\n    this.#isDiscrete = isDiscrete;\n  }\n\n  /**\n   * Get the VOI LUT.\n   *\n   * @returns {VoiLut} The VOI LUT.\n   */\n  getVoiLut() {\n    return this.#voiLut;\n  }\n\n  /**\n   * Get the modality LUT.\n   *\n   * @returns {ModalityLut} The modality LUT.\n   */\n  getModalityLut() {\n    return this.#modalityLut;\n  }\n\n  /**\n   * Set the VOI LUT.\n   *\n   * @param {VoiLut} lut The VOI LUT.\n   */\n  setVoiLut(lut) {\n    // store the window values\n    this.#voiLut = lut;\n\n    // possible signed shift (LUT indices are positive)\n    this.#voiLut.setSignedOffset(\n      this.#modalityLut.getRSI().getSlope() * this.#signedShift);\n\n    // create lut if not continous\n    if (this.#isDiscrete) {\n      const size = this.#modalityLut.getLength();\n      // use clamped array (polyfilled in env.js)\n      this.#lut = new Uint8ClampedArray(size);\n      // by default WindowLevel returns a value in the [0,255] range\n      // this is ok with regular Arrays and ClampedArray.\n      for (let i = 0; i < size; ++i) {\n        this.#lut[i] = this.#voiLut.apply(this.#modalityLut.getValue(i));\n      }\n    }\n  }\n\n  /**\n   * Get the value of the LUT at the given offset.\n   *\n   * @param {number} offset The input offset in [0,2^bitsStored] range\n   *   for discrete data or full range for non discrete.\n   * @returns {number} The integer value (default [0,255]) of the LUT\n   *   at the given offset.\n   */\n  getValue(offset) {\n    if (this.#isDiscrete) {\n      return this.#lut[offset + this.#signedShift];\n    } else {\n      return Math.floor(this.#voiLut.apply(offset + this.#signedShift));\n    }\n  }\n\n} // class WindowLut\n","/**\n * Lookup tables for image colour display.\n */\n\nconst lut_range_max = 256;\n\n/**\n * Build a LUT of size lut_range_max.\n *\n * @param {Function} func The i to lut function.\n * @returns {number[]} The LUT.\n */\nfunction buildLut(func) {\n  const lut = [];\n  for (let i = 0; i < lut_range_max; ++i) {\n    lut.push(func(i));\n  }\n  return lut;\n}\n\n/**\n * Ramp to lut_range_max minus one on the first third values.\n *\n * @param {number} i The input index.\n * @returns {number} The lut value.\n */\nfunction toMaxFirstThird(i) {\n  const val = i * 3;\n  if (val > lut_range_max - 1) {\n    return lut_range_max - 1;\n  }\n  return val;\n}\n\n/**\n * Ramp to lut_range_max minus one on the second third values,\n *   otherwise return 0 for the first third and\n *   lut_range_max minus one for the last third.\n *\n * @param {number} i The input index.\n * @returns {number} The lut value.\n */\nfunction toMaxSecondThird(i) {\n  const third = lut_range_max / 3;\n  let val = 0;\n  if (i >= third) {\n    val = (i - third) * 3;\n    if (val > lut_range_max - 1) {\n      return lut_range_max - 1;\n    }\n  }\n  return val;\n}\n\n/**\n * Ramp to lut_range_max minus one on the last third values,\n *   otherwise return 0.\n *\n * @param {number} i The input index.\n * @returns {number} The lut value.\n */\nfunction toMaxThirdThird(i) {\n  const third = lut_range_max / 3;\n  let val = 0;\n  if (i >= 2 * third) {\n    val = (i - 2 * third) * 3;\n    if (val > lut_range_max - 1) {\n      return lut_range_max - 1;\n    }\n  }\n  return val;\n}\n\n/**\n * Identity, returns i.\n *\n * @param {number} i The input index.\n * @returns {number} The lut value.\n */\nfunction id(i) {\n  return i;\n}\n\n/**\n * Returns lut_range_max minus one minus i.\n *\n * @param {number} i The input index.\n * @returns {number} The lut value.\n */\nfunction invId(i) {\n  return (lut_range_max - 1) - i;\n}\n\n/**\n * Colour map: red, green and blue components\n *   to associate with intensity values.\n */\nexport class ColourMap {\n  /**\n   * Red component: 256 values in the [0, 255] range.\n   *\n   * @type {number[]}\n   */\n  red;\n  /**\n   * Green component: 256 values in the [0, 255] range.\n   *\n   * @type {number[]}\n   */\n  green;\n  /**\n   * Blue component: 256 values in the [0, 255] range.\n   *\n   * @type {number[]}\n   */\n  blue;\n\n  /**\n   * @param {number[]} red Red component.\n   * @param {number[]} green Green component.\n   * @param {number[]} blue Blue component.\n   */\n  constructor(red, green, blue) {\n    this.red = red;\n    this.green = green;\n    this.blue = blue;\n  }\n}\n\n/**\n * List of available lookup tables (lut).\n *\n * @type {Object<string, ColourMap>}\n */\nexport const luts = {\n  // plain\n  plain: {\n    red: buildLut(id),\n    green: buildLut(id),\n    blue: buildLut(id)\n  },\n\n  // inverse plain\n  invPlain: {\n    red: buildLut(invId),\n    green: buildLut(invId),\n    blue: buildLut(invId)\n  },\n\n  // rainbow\n  /* eslint-disable @stylistic/js/max-len */\n  rainbow: {\n    blue: [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, 252, 255, 247, 239, 231, 223, 215, 207, 199, 191, 183, 175, 167, 159, 151, 143, 135, 127, 119, 111, 103, 95, 87, 79, 71, 63, 55, 47, 39, 31, 23, 15, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n    green: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, 240, 248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 251, 249, 247, 245, 243, 241, 239, 237, 235, 233, 231, 229, 227, 225, 223, 221, 219, 217, 215, 213, 211, 209, 207, 205, 203, 201, 199, 197, 195, 193, 192, 189, 186, 183, 180, 177, 174, 171, 168, 165, 162, 159, 156, 153, 150, 147, 144, 141, 138, 135, 132, 129, 126, 123, 120, 117, 114, 111, 108, 105, 102, 99, 96, 93, 90, 87, 84, 81, 78, 75, 72, 69, 66, 63, 60, 57, 54, 51, 48, 45, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3],\n    red: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 62, 60, 58, 56, 54, 52, 50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]\n  },\n  /* eslint-enable @stylistic/js/max-len */\n\n  // hot\n  hot: {\n    red: buildLut(toMaxFirstThird),\n    green: buildLut(toMaxSecondThird),\n    blue: buildLut(toMaxThirdThird)\n  },\n\n  // hot iron\n  /* eslint-disable @stylistic/js/max-len */\n  hot_iron: {\n    red: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],\n    green: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 255],\n    blue: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 252, 255]\n  },\n  /* eslint-enable @stylistic/js/max-len */\n\n  // pet\n  /* eslint-disable @stylistic/js/max-len */\n  pet: {\n    red: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],\n    green: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 128, 126, 124, 122, 120, 118, 116, 114, 112, 110, 108, 106, 104, 102, 100, 98, 96, 94, 92, 90, 88, 86, 84, 82, 80, 78, 76, 74, 72, 70, 68, 66, 64, 63, 61, 59, 57, 55, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3, 1, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 255],\n    blue: [0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 252, 248, 244, 240, 236, 232, 228, 224, 220, 216, 212, 208, 204, 200, 196, 192, 188, 184, 180, 176, 172, 168, 164, 160, 156, 152, 148, 144, 140, 136, 132, 128, 124, 120, 116, 112, 108, 104, 100, 96, 92, 88, 84, 80, 76, 72, 68, 64, 60, 56, 52, 48, 44, 40, 36, 32, 28, 24, 20, 16, 12, 8, 4, 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 255]\n  },\n  /* eslint-enable @stylistic/js/max-len */\n\n  // hot metal blue\n  /* eslint-disable @stylistic/js/max-len */\n  hot_metal_blue: {\n    red: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 9, 12, 15, 18, 21, 24, 26, 29, 32, 35, 38, 41, 44, 47, 50, 52, 55, 57, 59, 62, 64, 66, 69, 71, 74, 76, 78, 81, 83, 85, 88, 90, 93, 96, 99, 102, 105, 108, 111, 114, 116, 119, 122, 125, 128, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, 166, 169, 172, 175, 178, 181, 184, 187, 190, 194, 198, 201, 205, 209, 213, 217, 221, 224, 228, 232, 236, 240, 244, 247, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],\n    green: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 6, 8, 9, 11, 13, 15, 17, 19, 21, 23, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41, 43, 45, 47, 49, 51, 53, 55, 56, 58, 60, 62, 64, 66, 68, 70, 72, 73, 75, 77, 79, 81, 83, 85, 87, 88, 90, 92, 94, 96, 98, 100, 102, 104, 105, 107, 109, 111, 113, 115, 117, 119, 120, 122, 124, 126, 128, 130, 132, 134, 136, 137, 139, 141, 143, 145, 147, 149, 151, 152, 154, 156, 158, 160, 162, 164, 166, 168, 169, 171, 173, 175, 177, 179, 181, 183, 184, 186, 188, 190, 192, 194, 196, 198, 200, 201, 203, 205, 207, 209, 211, 213, 215, 216, 218, 220, 222, 224, 226, 228, 229, 231, 233, 235, 237, 239, 240, 242, 244, 246, 248, 250, 251, 253, 255],\n    blue: [0, 2, 4, 6, 8, 10, 12, 14, 16, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 184, 186, 188, 190, 192, 194, 196, 198, 200, 197, 194, 191, 188, 185, 182, 179, 176, 174, 171, 168, 165, 162, 159, 156, 153, 150, 144, 138, 132, 126, 121, 115, 109, 103, 97, 91, 85, 79, 74, 68, 62, 56, 50, 47, 44, 41, 38, 35, 32, 29, 26, 24, 21, 18, 15, 12, 9, 6, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 6, 9, 12, 15, 18, 21, 24, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 76, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 126, 129, 132, 135, 138, 141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 176, 179, 182, 185, 188, 191, 194, 197, 200, 203, 206, 210, 213, 216, 219, 223, 226, 229, 232, 236, 239, 242, 245, 249, 252, 255]\n  },\n  /* eslint-enable @stylistic/js/max-len */\n\n  // pet 20 step\n  /* eslint-disable @stylistic/js/max-len */\n  pet_20step: {\n    red: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],\n    green: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 208, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],\n    blue: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]\n  }\n  /* eslint-enable @stylistic/js/max-len */\n};\n","// example implementation: dcmtk/dcmiod/libsrc/cielabutil.cc\n// https://github.com/DCMTK/dcmtk/blob/DCMTK-3.6.6/dcmiod/libsrc/cielabutil.cc\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Scalar3D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * RGB colour class.\n */\nexport class RGB {\n  /**\n   * Red component.\n   *\n   * @type {number}\n   */\n  r;\n  /**\n   * Green component.\n   *\n   * @type {number}\n   */\n  g;\n  /**\n   * Blue component.\n   *\n   * @type {number}\n   */\n  b;\n  /**\n   * @param {number} r Red component.\n   * @param {number} g Green component.\n   * @param {number} b Blue component.\n   */\n  constructor(r, g, b) {\n    this.r = r;\n    this.g = g;\n    this.b = b;\n  }\n}\n\n/**\n * Check if two rgb objects are equal.\n *\n * @param {RGB} c1 The first colour.\n * @param {RGB} c2 The second colour.\n * @returns {boolean} True if both colour are equal.\n */\nexport function isEqualRgb(c1, c2) {\n  return c1 !== null &&\n    c2 !== null &&\n    typeof c1 !== 'undefined' &&\n    typeof c2 !== 'undefined' &&\n    c1.r === c2.r &&\n    c1.g === c2.g &&\n    c1.b === c2.b;\n}\n\n/**\n * Convert YBR to RGB.\n *\n * Ref:\n * - {@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2},\n * - {@link https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion}.\n *\n * @param {number} y The Y component.\n * @param {number} cb The Cb component.\n * @param {number} cr The Cr component.\n * @returns {RGB} RGB equivalent as {r,g,b}.\n */\nexport function ybrToRgb(y, cb, cr) {\n  return {\n    r: y + 1.402 * (cr - 128),\n    g: y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128),\n    b: y + 1.772 * (cb - 128)\n  };\n}\n\n/**\n * Convert a hex color into RGB.\n *\n * @param {string} hexStr The hex color as '#ab01ef'.\n * @returns {RGB} The RGB values as {r,g,b}.\n */\nexport function hexToRgb(hexStr) {\n  return {\n    r: parseInt(hexStr.substring(1, 3), 16),\n    g: parseInt(hexStr.substring(3, 5), 16),\n    b: parseInt(hexStr.substring(5, 7), 16)\n  };\n}\n\n/**\n * Convert RGB to its hex equivalent.\n *\n * @param {RGB} rgb The RGB object as {r,g,b}.\n * @returns {string} A string representing the hex color as '#ab01ef'.\n */\nexport function rgbToHex(rgb) {\n  return '#' +\n    ((1 << 24) + (rgb.r << 16) + (rgb.g << 8) + rgb.b).toString(16).slice(1);\n}\n\n/**\n * Get the brightness of a RGB colour: calculates\n * the luma (Y) of the YIQ colour space.\n *\n * Ref: {@link https://en.wikipedia.org/wiki/YIQ#From_RGB_to_YIQ}.\n *\n * @param {RGB} rgb RGB triplet.\n * @returns {number} The brightness ([0,1]).\n */\nexport function getBrightness(rgb) {\n  // 0.001172549 = 0.299 / 255\n  // 0.002301961 = 0.587 / 255\n  // 0.000447059 = 0.114 / 255\n  return rgb.r * 0.001172549 +\n    rgb.g * 0.002301961 +\n    rgb.b * 0.000447059;\n}\n\n/**\n * Check if a colour given in hexadecimal format is dark.\n *\n * @param {string} hexColour The colour (as '#ab01ef').\n * @returns {boolean} True if the colour is dark (brightness < 0.5).\n */\nexport function isDarkColour(hexColour) {\n  return getBrightness(hexToRgb(hexColour)) < 0.5;\n}\n\n/**\n * Get the shadow colour of an input colour.\n *\n * @param {string} hexColour The colour (as '#ab01ef').\n * @returns {string} The shadow colour (white or black).\n */\nexport function getShadowColour(hexColour) {\n  return isDarkColour(hexColour) ? '#fff' : '#000';\n}\n\n/**\n * Unsigned int CIE LAB value ([0, 65535]) to CIE LAB value\n *   (L: [0, 100], a: [-128, 127], b: [-128, 127]).\n *\n * @param {object} triplet CIE LAB triplet as {l,a,b} with unsigned range.\n * @returns {object} CIE LAB triplet as {l,a,b} with CIE LAB range.\n */\nexport function uintLabToLab(triplet) {\n  // 0.001525902 = 100 / 65535\n  // 0.003891051 = 255 / 65535\n  return {\n    l: 0.001525902 * triplet.l,\n    a: 0.003891051 * triplet.a - 128,\n    b: 0.003891051 * triplet.b - 128,\n  };\n}\n\n/**\n * CIE LAB value (L: [0, 100], a: [-128, 127], b: [-128, 127]) to\n *   unsigned int CIE LAB ([0, 65535]).\n *\n * @param {object} triplet CIE XYZ triplet as {l,a,b} with CIE LAB range.\n * @returns {object} CIE LAB triplet as {l,a,b} with unsigned range.\n */\nexport function labToUintLab(triplet) {\n  // 655.35 = 65535 / 100\n  // aUint = (a + 128) * 65535 / 255\n  // 257 = 65535 / 255\n  // 32896 = 257 * 128\n  return {\n    l: 655.35 * triplet.l,\n    a: 257 * triplet.a + 32896,\n    b: 257 * triplet.b + 32896,\n  };\n}\n\n/**\n * CIE Standard Illuminant D65, standard 2° observer.\n *\n * Ref: {@link https://en.wikipedia.org/wiki/Illuminant_D65}.\n */\nconst d65 = {\n  x: 95.0489,\n  y: 100,\n  z: 108.884\n};\n\n/**\n * Convert CIE LAB to CIE XYZ (standard illuminant D65, 2degree 1931).\n *\n * Ref: {@link https://en.wikipedia.org/wiki/CIELAB_color_space#From_CIELAB_to_CIEXYZ}.\n *\n * @param {object} triplet CIE LAB triplet as {l,a,b}.\n * @returns {Scalar3D} CIE XYZ triplet as {x,y,z}.\n */\nexport function cielabToCiexyz(triplet) {\n  /**\n   * Apply the inverse lab function.\n   *\n   * @param {number} x The input value.\n   * @returns {number} The result.\n   */\n  function invLabFunc(x) {\n    let res = null;\n    // delta = 6 / 29 = 0.206896552\n    if (x > 0.206896552) {\n      res = Math.pow(x, 3);\n    } else {\n      // 0.128418549 = 3 * delta^2\n      // 0.017712903 = 3 * delta^2 * (4 / 29)\n      res = 0.128418549 * x - 0.017712903;\n    }\n    return res;\n  }\n\n  const illuminant = d65;\n  const l0 = (triplet.l + 16) / 116;\n\n  return {\n    x: illuminant.x * invLabFunc(l0 + triplet.a / 500),\n    y: illuminant.y * invLabFunc(l0),\n    z: illuminant.z * invLabFunc(l0 - triplet.b / 200)\n  };\n}\n\n/**\n * Convert CIE XYZ to CIE LAB (standard illuminant D65, 2degree 1931).\n *\n * Ref: {@link https://en.wikipedia.org/wiki/CIELAB_color_space#From_CIEXYZ_to_CIELAB}.\n *\n * @param {Scalar3D} triplet CIE XYZ triplet as {x,y,z}.\n * @returns {object} CIE LAB triplet as {l,a,b}.\n */\nexport function ciexyzToCielab(triplet) {\n  /**\n   * Apply the lab function.\n   *\n   * @param {number} x The input value.\n   * @returns {number} The result.\n   */\n  function labFunc(x) {\n    let res = null;\n    // delta = 6 / 29 = 0.206896552\n    // delta^3 = 0.008856452\n    if (x > 0.008856452) {\n      res = Math.pow(x, 0.333333333);\n    } else {\n      // 7.787037037 = 1 / 3 * delta^2\n      // 0.137931034 = 4 / 29\n      res = 7.787037037 * x + 0.137931034;\n    }\n    return res;\n  }\n\n  const illuminant = d65;\n  const fy = labFunc(triplet.y / illuminant.y);\n\n  return {\n    l: 116 * fy - 16,\n    a: 500 * (labFunc(triplet.x / illuminant.x) - fy),\n    b: 200 * (fy - labFunc(triplet.z / illuminant.z))\n  };\n}\n\n/**\n * Convert CIE XYZ to sRGB.\n *\n * Ref: {@link https://en.wikipedia.org/wiki/SRGB#From_CIE_XYZ_to_sRGB}.\n *\n * @param {Scalar3D} triplet CIE XYZ triplet as {x,y,z}.\n * @returns {RGB} 'sRGB' triplet as {r,g,b}.\n */\nexport function ciexyzToSrgb(triplet) {\n  /**\n   * Apply the gamma function.\n   *\n   * @param {number} x The input value.\n   * @returns {number} The result.\n   */\n  function gammaFunc(x) {\n    let res = null;\n    if (x <= 0.0031308) {\n      res = 12.92 * x;\n    } else {\n      // 0.416666667 = 1 / 2.4\n      res = 1.055 * Math.pow(x, 0.416666667) - 0.055;\n    }\n    // clip [0,1]\n    return Math.min(1, Math.max(0, res));\n  }\n\n  const x = triplet.x / 100;\n  const y = triplet.y / 100;\n  const z = triplet.z / 100;\n\n  return {\n    r: Math.round(255 * gammaFunc(3.2406 * x - 1.5372 * y - 0.4986 * z)),\n    g: Math.round(255 * gammaFunc(-0.9689 * x + 1.8758 * y + 0.0415 * z)),\n    b: Math.round(255 * gammaFunc(0.0557 * x - 0.2040 * y + 1.0570 * z))\n  };\n}\n\n/**\n * Convert sRGB to CIE XYZ.\n *\n * Ref: {@link https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ}.\n *\n * @param {RGB} triplet 'sRGB' triplet as {r,g,b}.\n * @returns {Scalar3D} CIE XYZ triplet as {x,y,z}.\n */\nexport function srgbToCiexyz(triplet) {\n  /**\n   * Apply the inverse gamma function.\n   *\n   * @param {number} x The input value.\n   * @returns {number} The result.\n   */\n  function invGammaFunc(x) {\n    let res = null;\n    if (x <= 0.04045) {\n      res = x / 12.92;\n    } else {\n      res = Math.pow((x + 0.055) / 1.055, 2.4);\n    }\n    return res;\n  }\n\n  const rl = invGammaFunc(triplet.r / 255);\n  const gl = invGammaFunc(triplet.g / 255);\n  const bl = invGammaFunc(triplet.b / 255);\n\n  return {\n    x: 100 * (0.4124 * rl + 0.3576 * gl + 0.1805 * bl),\n    y: 100 * (0.2126 * rl + 0.7152 * gl + 0.0722 * bl),\n    z: 100 * (0.0193 * rl + 0.1192 * gl + 0.9505 * bl)\n  };\n}\n\n/**\n * Convert CIE LAB to sRGB (standard illuminant D65).\n *\n * @param {object} triplet CIE LAB triplet as {l,a,b}.\n * @returns {RGB} 'sRGB' triplet as {r,g,b}.\n */\nexport function cielabToSrgb(triplet) {\n  return ciexyzToSrgb(cielabToCiexyz(triplet));\n}\n\n/**\n * Convert sRGB to CIE LAB (standard illuminant D65).\n *\n * @param {RGB} triplet 'sRGB' triplet as {r,g,b}.\n * @returns {object} CIE LAB triplet as {l,a,b}.\n */\nexport function srgbToCielab(triplet) {\n  return ciexyzToCielab(srgbToCiexyz(triplet));\n}\n\n/**\n * Get the hex code of a string colour for a colour used in pre dwv v0.17.\n *\n * @param {string} name The name of a colour.\n * @returns {string} The hex representing the colour.\n */\nexport function colourNameToHex(name) {\n  // default colours used in dwv version < 0.17\n  const dict = {\n    Yellow: '#ffff00',\n    Red: '#ff0000',\n    White: '#ffffff',\n    Green: '#008000',\n    Blue: '#0000ff',\n    Lime: '#00ff00',\n    Fuchsia: '#ff00ff',\n    Black: '#000000'\n  };\n  let res = '#ffff00';\n  if (typeof dict[name] !== 'undefined') {\n    res = dict[name];\n  }\n  return res;\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {WindowLevel} from '../image/windowLevel';\n/* eslint-enable no-unused-vars */\n\n/**\n * Overridalbe custom object for client defined items.\n */\nexport const custom = {\n  /**\n   * List of default window level presets. Indexed bu modality\n   * and then by preset name. For example `wlPresets.MR.mediastimun`.\n   * No need to redefine all, just overrides is enough. Defaults\n   * are used if `custom.wlPresets[modality]` is undefined.\n   *\n   * @type {Object.<string, Object.<string, WindowLevel>>}\n   */\n  wlPresets: undefined,\n\n  /**\n   * List of default shape label texts. Indexed by shape name\n   * and then by modality. For example `labelTexts.arrow.MR`.\n   * No need to redefine all, just overrides is enough. Defaults\n   * are used if `custom.labelTexts[shapeName]` is undefined.\n   *\n   * @type {Object.<string, Object.<string, string>>}\n   */\n  labelTexts: undefined,\n\n  /**\n   * Open a dialogue to edit roi data. Defaults to window.prompt.\n   *\n   * @param {Annotation} annotation The roi data.\n   * @param {Function} callback The callback to launch on dialogue exit.\n   */\n  openRoiDialog: undefined,\n\n  /**\n   * Get the time from a list of dicom tags.\n   *\n   * @param {Object<string, DataElement>} elements The DICOM elements.\n   * @returns {number|undefined} The time value if available.\n   */\n  getTagTime: undefined,\n\n  /**\n   * Get the pixel data unit from a list of dicom tags.\n   * Not used for PET data with SUV values.\n   *\n   * @param {Object<string, DataElement>} elements The DICOM elements.\n   * @returns {string|undefined} The unit value if available.\n   */\n  getTagPixelUnit: undefined,\n\n\n};","/**\n * Immutable 3D vector.\n */\nexport class Vector3D {\n\n  /**\n   * X coordinate.\n   *\n   * @type {number}\n   */\n  #x;\n\n  /**\n   * Y coordinate.\n   *\n   * @type {number}\n   */\n  #y;\n\n  /**\n   * Z coordinate.\n   *\n   * @type {number}\n   */\n  #z;\n\n  /**\n   * @param {number} x The X component of the vector.\n   * @param {number} y The Y component of the vector.\n   * @param {number} z The Z component of the vector.\n   */\n  constructor(x, y, z) {\n    this.#x = x;\n    this.#y = y;\n    this.#z = z;\n  }\n\n  /**\n   * Get the X component of the vector.\n   *\n   * @returns {number} The X component of the vector.\n   */\n  getX() {\n    return this.#x;\n  }\n\n  /**\n   * Get the Y component of the vector.\n   *\n   * @returns {number} The Y component of the vector.\n   */\n  getY() {\n    return this.#y;\n  }\n\n  /**\n   * Get the Z component of the vector.\n   *\n   * @returns {number} The Z component of the vector.\n   */\n  getZ() {\n    return this.#z;\n  }\n\n  /**\n   * Check for Vector3D equality.\n   *\n   * @param {Vector3D} rhs The other vector to compare to.\n   * @returns {boolean} True if both vectors are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.#x === rhs.getX() &&\n      this.#y === rhs.getY() &&\n      this.#z === rhs.getZ();\n  }\n\n  /**\n   * Get a string representation of the Vector3D.\n   *\n   * @returns {string} The vector as a string.\n   */\n  toString() {\n    return '(' + this.#x +\n      ', ' + this.#y +\n      ', ' + this.#z + ')';\n  }\n\n  /**\n   * Get the norm of the vector.\n   *\n   * @returns {number} The norm.\n   */\n  norm() {\n    return Math.sqrt(\n      (this.#x * this.#x) +\n      (this.#y * this.#y) +\n      (this.#z * this.#z)\n    );\n  }\n\n  /**\n   * Get the cross product with another Vector3D, ie the\n   * vector that is perpendicular to both a and b.\n   * If both vectors are parallel, the cross product is a zero vector.\n   *\n   * Ref: {@link https://en.wikipedia.org/wiki/Cross_product}.\n   *\n   * @param {Vector3D} vector3D The input vector.\n   * @returns {Vector3D} The result vector.\n   */\n  crossProduct(vector3D) {\n    return new Vector3D(\n      (this.#y * vector3D.getZ()) - (vector3D.getY() * this.#z),\n      (this.#z * vector3D.getX()) - (vector3D.getZ() * this.#x),\n      (this.#x * vector3D.getY()) - (vector3D.getX() * this.#y));\n  }\n\n  /**\n   * Get the dot product with another Vector3D.\n   *\n   * Ref: {@link https://en.wikipedia.org/wiki/Dot_product}.\n   *\n   * @param {Vector3D} vector3D The input vector.\n   * @returns {number} The dot product.\n   */\n  dotProduct(vector3D) {\n    return (this.#x * vector3D.getX()) +\n      (this.#y * vector3D.getY()) +\n      (this.#z * vector3D.getZ());\n  }\n\n  /**\n   * Is this vector codirectional to an input one.\n   *\n   * @param {Vector3D} vector3D The vector to test.\n   * @returns {boolean} True if codirectional, false is opposite.\n   */\n  isCodirectional(vector3D) {\n    // a.dot(b) = ||a|| * ||b|| * cos(theta)\n    // (https://en.wikipedia.org/wiki/Dot_product#Geometric_definition)\n    // -> the sign of the dot product depends on the cosinus of\n    //    the angle between the vectors\n    //   -> >0 => vectors are codirectional\n    //   -> <0 => vectors are opposite\n    return this.dotProduct(vector3D) > 0;\n  }\n\n} // Vector3D class","import {Vector3D} from './vector';\nimport {Point3D} from './point';\nimport {Index} from './index';\nimport {logger} from '../utils/logger';\n\n// Number.EPSILON is difference between 1 and the smallest\n// floating point number greater than 1\n// -> ~2e-16\n// BIG_EPSILON -> ~2e-12\nexport const BIG_EPSILON = Number.EPSILON * 1e4;\n// 'real world', for example when comparing positions\nexport const REAL_WORLD_EPSILON = 1e-4;\n\n/**\n * Check if two numbers are similar.\n *\n * @param {number} a The first number.\n * @param {number} b The second number.\n * @param {number} tol The comparison tolerance,\n *   default to Number.EPSILON.\n * @returns {boolean} True if similar.\n */\nexport function isSimilar(a, b, tol) {\n  if (typeof tol === 'undefined') {\n    tol = Number.EPSILON;\n  }\n  return Math.abs(a - b) < tol;\n}\n\n/**\n * Immutable 3x3 Matrix.\n */\nexport class Matrix33 {\n\n  /**\n   * Matrix values.\n   *\n   * @type {number[]}\n   */\n  #values;\n\n  /**\n   * Matrix inverse, calculated at first ask.\n   *\n   * @type {Matrix33}\n   */\n  #inverse;\n\n  /**\n   * @param {number[]} values Row-major ordered 9 values.\n   */\n  constructor(values) {\n    this.#values = values;\n  }\n\n  /**\n   * Get a value of the matrix.\n   *\n   * @param {number} row The row at wich to get the value.\n   * @param {number} col The column at wich to get the value.\n   * @returns {number|undefined} The value at the position.\n   */\n  get(row, col) {\n    return this.#values[row * 3 + col];\n  }\n\n  /**\n   * Get the inverse of this matrix.\n   *\n   * @returns {Matrix33|undefined} The inverse matrix or undefined\n   *   if the determinant is zero.\n   */\n  getInverse() {\n    if (typeof this.#inverse === 'undefined') {\n      this.#inverse = getMatrixInverse(this);\n    }\n    return this.#inverse;\n  }\n\n  /**\n   * Check for Matrix33 equality.\n   *\n   * @param {Matrix33} rhs The other matrix to compare to.\n   * @param {number} [p] A numeric expression for the precision to use in check\n   *   (ex: 0.001). Defaults to Number.EPSILON if not provided.\n   * @returns {boolean} True if both matrices are equal.\n   */\n  equals(rhs, p) {\n    // TODO: add type check\n    // check values\n    for (let i = 0; i < 3; ++i) {\n      for (let j = 0; j < 3; ++j) {\n        if (!isSimilar(this.get(i, j), rhs.get(i, j), p)) {\n          return false;\n        }\n      }\n    }\n    return true;\n  }\n\n  /**\n   * Get a string representation of the Matrix33.\n   *\n   * @returns {string} The matrix as a string.\n   */\n  toString() {\n    let str = '[';\n    for (let i = 0; i < 3; ++i) {\n      if (i !== 0) {\n        str += ', \\n ';\n      }\n      for (let j = 0; j < 3; ++j) {\n        if (j !== 0) {\n          str += ', ';\n        }\n        str += this.get(i, j);\n      }\n    }\n    str += ']';\n    return str;\n  }\n\n  /**\n   * Multiply this matrix by another.\n   *\n   * @param {Matrix33} rhs The matrix to multiply by.\n   * @returns {Matrix33} The product matrix.\n   */\n  multiply(rhs) {\n    const values = [];\n    for (let i = 0; i < 3; ++i) {\n      for (let j = 0; j < 3; ++j) {\n        let tmp = 0;\n        for (let k = 0; k < 3; ++k) {\n          tmp += this.get(i, k) * rhs.get(k, j);\n        }\n        values.push(tmp);\n      }\n    }\n    return new Matrix33(values);\n  }\n\n  /**\n   * Get the absolute value of this matrix.\n   *\n   * @returns {Matrix33} The result matrix.\n   */\n  getAbs() {\n    const values = [];\n    for (let i = 0; i < 3; ++i) {\n      for (let j = 0; j < 3; ++j) {\n        values.push(Math.abs(this.get(i, j)));\n      }\n    }\n    return new Matrix33(values);\n  }\n\n  /**\n   * Multiply this matrix by a 3D array.\n   *\n   * @param {number[]} array3D The input 3D array.\n   * @returns {number[]} The result 3D array.\n   */\n  multiplyArray3D(array3D) {\n    if (array3D.length !== 3) {\n      throw new Error('Cannot multiply 3x3 matrix with non 3D array: ' +\n        array3D.length);\n    }\n    const values = [];\n    for (let i = 0; i < 3; ++i) {\n      let tmp = 0;\n      for (let j = 0; j < 3; ++j) {\n        tmp += this.get(i, j) * array3D[j];\n      }\n      values.push(tmp);\n    }\n    return values;\n  }\n\n  /**\n   * Multiply this matrix by a 3D vector.\n   *\n   * @param {Vector3D} vector3D The input 3D vector.\n   * @returns {Vector3D} The result 3D vector.\n   */\n  multiplyVector3D(vector3D) {\n    const array3D = this.multiplyArray3D(\n      [vector3D.getX(), vector3D.getY(), vector3D.getZ()]\n    );\n    return new Vector3D(array3D[0], array3D[1], array3D[2]);\n  }\n\n  /**\n   * Multiply this matrix by a 3D point.\n   *\n   * @param {Point3D} point3D The input 3D point.\n   * @returns {Point3D} The result 3D point.\n   */\n  multiplyPoint3D(point3D) {\n    const array3D = this.multiplyArray3D(\n      [point3D.getX(), point3D.getY(), point3D.getZ()]\n    );\n    return new Point3D(array3D[0], array3D[1], array3D[2]);\n  }\n\n  /**\n   * Multiply this matrix by a 3D index.\n   *\n   * @param {Index} index3D The input 3D index.\n   * @returns {Index} The result 3D index.\n   */\n  multiplyIndex3D(index3D) {\n    const array3D = this.multiplyArray3D(index3D.getValues());\n    return new Index(array3D);\n  }\n\n  /**\n   * Get the index of the maximum in absolute value of a row.\n   *\n   * @param {number} row The row to get the maximum from.\n   * @returns {object} The {value,index} of the maximum.\n   */\n  getRowAbsMax(row) {\n    const values = [\n      Math.abs(this.get(row, 0)),\n      Math.abs(this.get(row, 1)),\n      Math.abs(this.get(row, 2))\n    ];\n    const absMax = Math.max.apply(null, values);\n    const index = values.indexOf(absMax);\n    return {\n      value: this.get(row, index),\n      index: index\n    };\n  }\n\n  /**\n   * Get the index of the maximum in absolute value of a column.\n   *\n   * @param {number} col The column to get the maximum from.\n   * @returns {object} The {value,index} of the maximum.\n   */\n  getColAbsMax(col) {\n    const values = [\n      Math.abs(this.get(0, col)),\n      Math.abs(this.get(1, col)),\n      Math.abs(this.get(2, col))\n    ];\n    const absMax = Math.max.apply(null, values);\n    const index = values.indexOf(absMax);\n    return {\n      value: this.get(index, col),\n      index: index\n    };\n  }\n\n  /**\n   * Get this matrix with only zero and +/- ones instead of the maximum.\n   *\n   * @returns {Matrix33} The simplified matrix.\n   */\n  asOneAndZeros() {\n    const res = [];\n    for (let j = 0; j < 3; ++j) {\n      const max = this.getRowAbsMax(j);\n      const sign = max.value > 0 ? 1 : -1;\n      for (let i = 0; i < 3; ++i) {\n        if (i === max.index) {\n          res.push(1 * sign);\n        } else {\n          res.push(0);\n        }\n      }\n    }\n    return new Matrix33(res);\n  }\n\n  /**\n   * Get the third column direction index of an orientation matrix.\n   *\n   * @returns {number} The index of the absolute maximum of the last column.\n   */\n  getThirdColMajorDirection() {\n    return this.getColAbsMax(2).index;\n  }\n\n} // Matrix33\n\n/**\n * Get the inverse of an input 3*3 matrix.\n *\n * Ref:\n * - {@link https://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_3_%C3%97_3_matrices},\n * - {@link https://github.com/willnode/N-Matrix-Programmer}.\n *\n * @param {Matrix33} m The input matrix.\n * @returns {Matrix33|undefined} The inverse matrix or undefined\n *   if the determinant is zero.\n */\nfunction getMatrixInverse(m) {\n  const m00 = m.get(0, 0);\n  const m01 = m.get(0, 1);\n  const m02 = m.get(0, 2);\n  const m10 = m.get(1, 0);\n  const m11 = m.get(1, 1);\n  const m12 = m.get(1, 2);\n  const m20 = m.get(2, 0);\n  const m21 = m.get(2, 1);\n  const m22 = m.get(2, 2);\n\n  const a1212 = m11 * m22 - m12 * m21;\n  const a2012 = m12 * m20 - m10 * m22;\n  const a0112 = m10 * m21 - m11 * m20;\n\n  let det = m00 * a1212 + m01 * a2012 + m02 * a0112;\n  if (det === 0) {\n    logger.warn('Cannot invert 3*3 matrix with zero determinant.');\n    return undefined;\n  }\n  det = 1 / det;\n\n  const values = [\n    det * a1212,\n    det * (m02 * m21 - m01 * m22),\n    det * (m01 * m12 - m02 * m11),\n    det * a2012,\n    det * (m00 * m22 - m02 * m20),\n    det * (m02 * m10 - m00 * m12),\n    det * a0112,\n    det * (m01 * m20 - m00 * m21),\n    det * (m00 * m11 - m01 * m10)\n  ];\n\n  return new Matrix33(values);\n}\n\n/**\n * Create a 3x3 identity matrix.\n *\n * @returns {Matrix33} The identity matrix.\n */\nexport function getIdentityMat33() {\n  /* eslint-disable @stylistic/js/array-element-newline */\n  return new Matrix33([\n    1, 0, 0,\n    0, 1, 0,\n    0, 0, 1\n  ]);\n  /* eslint-enable @stylistic/js/array-element-newline */\n}\n\n/**\n * Check if a matrix is a 3x3 identity matrix.\n *\n * @param {Matrix33} mat33 The matrix to test.\n * @returns {boolean} True if identity.\n */\nexport function isIdentityMat33(mat33) {\n  return mat33.equals(getIdentityMat33());\n}\n","import {isSimilar} from './matrix';\nimport {Vector3D} from './vector';\n\n/**\n * Immutable 2D point.\n */\nexport class Point2D {\n\n  /**\n   * X position.\n   *\n   * @type {number}\n   */\n  #x;\n\n  /**\n   * Y position.\n   *\n   * @type {number}\n   */\n  #y;\n\n  /**\n   * @param {number} x The X coordinate for the point.\n   * @param {number} y The Y coordinate for the point.\n   */\n  constructor(x, y) {\n    this.#x = x;\n    this.#y = y;\n  }\n\n  /**\n   * Get the X position of the point.\n   *\n   * @returns {number} The X position of the point.\n   */\n  getX() {\n    return this.#x;\n  }\n\n  /**\n   * Get the Y position of the point.\n   *\n   * @returns {number} The Y position of the point.\n   */\n  getY() {\n    return this.#y;\n  }\n\n  /**\n   * Get the values of this point.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return [this.#x, this.#y];\n  }\n\n  /**\n   * Get the centroid of the point, ie itself.\n   *\n   * @returns {Point2D} The centroid point.\n   */\n  getCentroid() {\n    return this;\n  }\n\n  /**\n   * Check for Point2D equality.\n   *\n   * @param {Point2D} rhs The other point to compare to.\n   * @returns {boolean} True if both points are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      typeof rhs !== 'undefined' &&\n      this.#x === rhs.getX() &&\n      this.#y === rhs.getY();\n  }\n\n  /**\n   * Get a string representation of the Point2D.\n   *\n   * @returns {string} The point as a string.\n   */\n  toString() {\n    return '(' + this.#x + ', ' + this.#y + ')';\n  }\n\n  /**\n   * Get the distance to another Point2D.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {number} Ths distance to the input point.\n   */\n  getDistance(point2D) {\n    const dx = this.#x - point2D.getX();\n    const dy = this.#y - point2D.getY();\n    return Math.sqrt(dx * dx + dy * dy);\n  }\n\n} // Point2D class\n\n/**\n * Immutable 3D point.\n */\nexport class Point3D {\n\n  /**\n   * X position.\n   *\n   * @type {number}\n   */\n  #x;\n\n  /**\n   * Y position.\n   *\n   * @type {number}\n   */\n  #y;\n\n  /**\n   * Z position.\n   *\n   * @type {number}\n   */\n  #z;\n\n  /**\n   * @param {number} x The X coordinate for the point.\n   * @param {number} y The Y coordinate for the point.\n   * @param {number} z The Z coordinate for the point.\n   */\n  constructor(x, y, z) {\n    this.#x = x;\n    this.#y = y;\n    this.#z = z;\n  }\n\n  /**\n   * Get the X position of the point.\n   *\n   * @returns {number} The X position of the point.\n   */\n  getX() {\n    return this.#x;\n  }\n\n  /**\n   * Get the Y position of the point.\n   *\n   * @returns {number} The Y position of the point.\n   */\n  getY() {\n    return this.#y;\n  }\n\n  /**\n   * Get the Z position of the point.\n   *\n   * @returns {number} The Z position of the point.\n   */\n  getZ() {\n    return this.#z;\n  }\n\n  /**\n   * Get the values of this point.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return [this.#x, this.#y, this.#z];\n  }\n\n  /**\n   * Check for Point3D equality.\n   *\n   * @param {Point3D} rhs The other point to compare to.\n   * @returns {boolean} True if both points are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.#x === rhs.getX() &&\n      this.#y === rhs.getY() &&\n      this.#z === rhs.getZ();\n  }\n\n  /**\n   * Check for Point3D similarity.\n   *\n   * @param {Point3D} rhs The other point to compare to.\n   * @param {number} tol Optional comparison tolerance,\n   *   default to Number.EPSILON.\n   * @returns {boolean} True if both points are equal.\n   */\n  isSimilar(rhs, tol) {\n    return rhs !== null &&\n      isSimilar(this.#x, rhs.getX(), tol) &&\n      isSimilar(this.#y, rhs.getY(), tol) &&\n      isSimilar(this.#z, rhs.getZ(), tol);\n  }\n\n  /**\n   * Get a string representation of the Point3D.\n   *\n   * @returns {string} The point as a string.\n   */\n  toString() {\n    return '(' + this.#x +\n      ', ' + this.#y +\n      ', ' + this.#z + ')';\n  }\n\n  /**\n   * Get the distance to another Point3D.\n   *\n   * @param {Point3D} point3D The input point.\n   * @returns {number} Ths distance to the input point.\n   */\n  getDistance(point3D) {\n    return Math.sqrt(this.#getSquaredDistance(point3D));\n  }\n\n  /**\n   * Get the square of the distance between this and\n   * an input point. Used for sorting.\n   *\n   * @param {Point3D} point3D The input point.\n   * @returns {number} The square of the distance.\n   */\n  #getSquaredDistance(point3D) {\n    const dx = this.#x - point3D.getX();\n    const dy = this.#y - point3D.getY();\n    const dz = this.#z - point3D.getZ();\n    return dx * dx + dy * dy + dz * dz;\n  }\n\n  /**\n   * Get the closest point to this in a Point3D list.\n   *\n   * @param {Point3D[]} pointList The list to check.\n   * @returns {number} The index of the closest point in the input list.\n   */\n  getClosest(pointList) {\n    let minIndex = 0;\n    // the order between squared distances and distances is the same\n    let minDist = this.#getSquaredDistance(pointList[minIndex]);\n    for (let i = 0; i < pointList.length; ++i) {\n      const dist = this.#getSquaredDistance(pointList[i]);\n      if (dist < minDist) {\n        minIndex = i;\n        minDist = dist;\n      }\n    }\n    return minIndex;\n  }\n\n  /**\n   * Get the difference to another Point3D.\n   *\n   * @param {Point3D} point3D The input point.\n   * @returns {Vector3D} The 3D vector from the input point to this one.\n   */\n  minus(point3D) {\n    return new Vector3D(\n      (this.#x - point3D.getX()),\n      (this.#y - point3D.getY()),\n      (this.#z - point3D.getZ()));\n  }\n\n} // Point3D class\n\n/**\n * Get an array find callback for an equal input point.\n *\n * @param {Point3D} point The point to compare to.\n * @returns {Function} A function that compares, using `equals`,\n *   its input point to the one given as input to this function.\n */\nexport function getEqualPoint3DFunction(point) {\n  return function (element) {\n    return element.equals(point);\n  };\n}\n\n/**\n * Immutable point.\n * Warning: the input array is NOT cloned, modifying it will\n *  modify the point values.\n */\nexport class Point {\n\n  /**\n   * Point values.\n   *\n   * @type {number[]}\n   */\n  #values;\n\n  /**\n   * @param {number[]} values The point values.\n   */\n  constructor(values) {\n    if (!values || typeof values === 'undefined') {\n      throw new Error('Cannot create point with no values.');\n    }\n    if (values.length === 0) {\n      throw new Error('Cannot create point with empty values.');\n    }\n    const valueCheck = function (val) {\n      return !isNaN(val);\n    };\n    if (!values.every(valueCheck)) {\n      throw new Error('Cannot create point with non number values.');\n    }\n    this.#values = values;\n  }\n\n  /**\n   * Get the point value at the given array index.\n   *\n   * @param {number} i The index to get.\n   * @returns {number} The value.\n   */\n  get(i) {\n    return this.#values[i];\n  }\n\n  /**\n   * Get the length of the point.\n   *\n   * @returns {number} The length.\n   */\n  length() {\n    return this.#values.length;\n  }\n\n  /**\n   * Get a string representation of the point.\n   *\n   * @returns {string} The point as a string.\n   */\n  toString() {\n    return '(' + this.#values.toString() + ')';\n  }\n\n  /**\n   * Get the values of this point.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return this.#values.slice();\n  }\n\n  /**\n   * Check if the input point can be compared to this one.\n   *\n   * @param {Point} rhs The point to compare to.\n   * @returns {boolean} True if both points are comparable.\n   */\n  canCompare(rhs) {\n    // check input\n    if (!rhs) {\n      return false;\n    }\n    // check length\n    if (this.length() !== rhs.length()) {\n      return false;\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Check for Point equality.\n   *\n   * @param {Point} rhs The point to compare to.\n   * @returns {boolean} True if both points are equal.\n   */\n  equals(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return false;\n    }\n    // check values\n    for (let i = 0, leni = this.length(); i < leni; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        return false;\n      }\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Compare points and return different dimensions.\n   *\n   * @param {Point} rhs The point to compare to.\n   * @returns {number[]} The list of different dimensions.\n   */\n  compare(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return null;\n    }\n    // check values\n    const diffDims = [];\n    for (let i = 0, leni = this.length(); i < leni; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        diffDims.push(i);\n      }\n    }\n    return diffDims;\n  }\n\n  /**\n   * Get the 3D part of this point.\n   *\n   * @returns {Point3D} The Point3D.\n   */\n  get3D() {\n    return new Point3D(this.get(0), this.get(1), this.get(2));\n  }\n\n  /**\n   * Add another point to this one.\n   *\n   * @param {Point} rhs The point to add.\n   * @returns {Point} The point representing the sum of both points.\n   */\n  add(rhs) {\n    // check if can compare\n    if (!this.canCompare(rhs)) {\n      return null;\n    }\n    const values = [];\n    const values0 = this.getValues();\n    const values1 = rhs.getValues();\n    for (let i = 0; i < values0.length; ++i) {\n      values.push(values0[i] + values1[i]);\n    }\n    return new Point(values);\n  }\n\n  /**\n   * Merge this point with a Point3D to create a new point.\n   *\n   * @param {Point3D} rhs The Point3D to merge with.\n   * @returns {Point} The merge result.\n   */\n  mergeWith3D(rhs) {\n    const values = this.getValues();\n    values[0] = rhs.getX();\n    values[1] = rhs.getY();\n    values[2] = rhs.getZ();\n    return new Point(values);\n  }\n\n} // Point class\n","/**\n * Namespace for translation function\n *   (in a namespace to allow for override from client).\n */\nexport const i18n = {\n\n  /**\n   * Get the translated text.\n   *\n   * @param {string} key The key to the text entry.\n   * @returns {string|undefined} The translated text.\n   */\n  t(key) {\n    let res = key;\n    const props = key.split('.');\n    // defaut units look like 'unit.cm2'\n    if (props.length === 2 &&\n      props[0] === 'unit') {\n      const units = {\n        mm: 'mm',\n        cm2: 'cm²',\n        degree: '°'\n      };\n      res = units[props[1]];\n    }\n    return res;\n  }\n\n};\n","\nimport {i18n} from './i18n';\n\n/**\n * Capitalise the first letter of a string.\n *\n * @param {string} string The string to capitalise the first letter.\n * @returns {string} The new string.\n */\nexport function capitaliseFirstLetter(string) {\n  let res = string;\n  if (string) {\n    res = string.charAt(0).toUpperCase() + string.slice(1);\n  }\n  return res;\n}\n\n/**\n * Check if a string starts with the input element.\n *\n * @param {string} str The input string.\n * @param {string} search The searched start.\n * @param {number} [rawPos] The position in this string at which to begin\n *  searching for searchString. Defaults to 0.\n * @returns {boolean} True if the input string starts with the searched string.\n */\nexport function startsWith(str, search, rawPos) {\n  if (typeof str === 'undefined' || str === null ||\n    typeof search === 'undefined' || search === null) {\n    return false;\n  }\n  const pos = rawPos > 0 ? rawPos | 0 : 0;\n  return str.substring(pos, pos + search.length) === search;\n}\n\n/**\n * Check if a string ends with the input element.\n *\n * @param {string} str The input string.\n * @param {string} search The searched ending.\n * @returns {boolean} True if the input string ends with the searched string.\n */\nexport function endsWith(str, search) {\n  if (typeof str === 'undefined' || str === null ||\n    typeof search === 'undefined' || search === null) {\n    return false;\n  }\n  return str.substring(str.length - search.length) === search;\n}\n\n/**\n * Split key/value string: `key0=val00&key0=val01&key1=val10\n *   will return `{key0 : [val00, val01], key1 : val1}`.\n *\n * @param {string} inputStr The string to split.\n * @returns {object} The split string.\n */\nexport function splitKeyValueString(inputStr) {\n  // result\n  const result = {};\n  // check input string\n  if (inputStr) {\n    // split key/value pairs\n    const pairs = inputStr.split('&');\n    for (let i = 0; i < pairs.length; ++i) {\n      const pair = pairs[i].split('=');\n      // if the key does not exist, create it\n      if (!result[pair[0]]) {\n        result[pair[0]] = pair[1];\n      } else {\n        // make it an array\n        if (!(result[pair[0]] instanceof Array)) {\n          result[pair[0]] = [result[pair[0]]];\n        }\n        result[pair[0]].push(pair[1]);\n      }\n    }\n  }\n  return result;\n}\n\n/**\n * Get flags from an input string. Flags are words surrounded with curly\n * braces.\n *\n * @param {string} inputStr The input string.\n * @returns {string[]} An array of found flags.\n */\nexport function getFlags(inputStr) {\n  const flags = [];\n  // check input string\n  if (inputStr === null || typeof inputStr === 'undefined') {\n    return flags;\n  }\n\n  // word surrounded by curly braces\n  const regex = /{(\\w+)}/g;\n\n  let match = regex.exec(inputStr);\n  while (match) {\n    flags.push(match[1]); // first matching group\n    match = regex.exec(inputStr);\n  }\n  return flags;\n}\n\n/**\n * Replace flags in a input string. Flags are keywords surrounded with curly\n * braces.\n *\n * @param {string} inputStr The input string.\n * @param {object} values A object of {value, unit}.\n * @returns {string} The result string.\n */\nexport function replaceFlags(inputStr, values) {\n  let res = '';\n  // check input string\n  if (inputStr === null || typeof inputStr === 'undefined') {\n    return res;\n  }\n  res = inputStr;\n  // check values\n  if (values === null || typeof values === 'undefined') {\n    return res;\n  }\n\n  // loop through flags\n  const keys = getFlags(inputStr);\n  for (let i = 0; i < keys.length; ++i) {\n    const valueObj = values[keys[i]];\n    if (valueObj !== null && typeof valueObj !== 'undefined' &&\n      valueObj.value !== null && typeof valueObj.value !== 'undefined') {\n      // value string\n      let valueStr = valueObj.value.toPrecision(4);\n      // add unit if available\n      // space or no space? Yes apart from degree...\n      // check: https://en.wikipedia.org/wiki/Space_(punctuation)#Spaces_and_unit_symbols\n      if (valueObj.unit !== null &&\n        typeof valueObj.unit !== 'undefined' &&\n        valueObj.unit.length !== 0) {\n        if (valueObj.unit !== 'unit.degree') {\n          valueStr += ' ';\n        }\n        valueStr += i18n.t(valueObj.unit);\n      }\n      // flag to replace\n      const flag = '{' + keys[i] + '}';\n      // replace\n      res = res.replace(flag, valueStr);\n    }\n  }\n  // return\n  return res;\n}\n\n/**\n * Get the root of an input path.\n * Splits using `/` as separator.\n *\n * @param {string} path The input path.\n * @returns {string} The input path without its last part.\n */\nexport function getRootPath(path) {\n  return path.split('/').slice(0, -1).join('/');\n}\n\n/**\n * Get a file extension: anything after the last dot.\n * File name starting with a dot are discarded.\n * Extensions are expected to contain at least one letter.\n *\n * @param {string} filePath The file path containing the file name.\n * @returns {string} The lower case file extension or null for none.\n */\nexport function getFileExtension(filePath) {\n  let ext = null;\n  if (typeof filePath !== 'undefined' &&\n    filePath !== null &&\n    filePath[0] !== '.') {\n    const pathSplit = filePath.toLowerCase().split('.');\n    if (pathSplit.length !== 1) {\n      ext = pathSplit.pop();\n      // extension should contain at least one letter and no slash\n      const regExp = /[a-z]/;\n      if (!regExp.test(ext) || ext.includes('/')) {\n        ext = null;\n      }\n    }\n  }\n  return ext;\n}\n\n/**\n * Convert a string to a Uint8Array.\n *\n * @param {string} str The string to convert.\n * @returns {Uint8Array} The Uint8Array.\n */\nexport function stringToUint8Array(str) {\n  const arr = new Uint8Array(str.length);\n  for (let i = 0, leni = str.length; i < leni; i++) {\n    arr[i] = str.charCodeAt(i);\n  }\n  return arr;\n}\n\n/**\n * Round a float number to a given precision.\n *\n * Inspired from {@link https://stackoverflow.com/a/49729715/3639892}.\n *\n * Can be a solution to not have trailing zero as when\n *   using toFixed or toPrecision.\n * '+number.toFixed(precision)' does not pass all the tests...\n *\n * @param {number} number The number to round.\n * @param {number} precision The rounding precision.\n * @returns {number} The rounded number.\n */\nexport function precisionRound(number, precision) {\n  const factor = Math.pow(10, precision);\n  const delta = 0.01 / factor; // fixes precisionRound(1.005, 2)\n  return Math.round(number * factor + delta) / factor;\n}\n","import {stringToUint8Array} from './string';\n\n/**\n * Get a string id from array values in the form of: '#0-1_#1-2'.\n *\n * @param {Array} arr The input array.\n * @param {number[]} [dims] Optional list of dimensions to use.\n * @returns {string} The string id.\n */\nexport function toStringId(arr, dims) {\n  // use all dims if not as input\n  if (typeof dims === 'undefined') {\n    dims = [];\n    for (let i = 0; i < arr.length; ++i) {\n      dims.push(i);\n    }\n  }\n  // check dims\n  for (let i = 0; i < dims.length; ++i) {\n    if (dims[i] >= arr.length) {\n      throw new Error('Non valid dimension for toStringId');\n    }\n  }\n  // build string\n  let res = '';\n  for (let i = 0; i < dims.length; ++i) {\n    if (i !== 0) {\n      res += '_';\n    }\n    res += '#' + dims[i] + '-' + arr[dims[i]];\n  }\n  return res;\n}\n\n/**\n * Get an array from an id string in the form of: '#0-1_#1-2'\n * (result of toStringId).\n *\n * @param {string} inputStr The input string.\n * @returns {Array} The corresponding array (minimum size is 3D).\n */\nexport function getArrayFromStringId(inputStr) {\n  // split ids\n  const strIds = inputStr.split('_');\n  // get the size of the index (minimum 3)\n  let numberOfDims = 3;\n  let dim;\n  for (let i = 0; i < strIds.length; ++i) {\n    // expecting dim < 10\n    dim = parseInt(strIds[i].substring(1, 2), 10);\n    // dim is zero based\n    if (dim + 1 > numberOfDims) {\n      numberOfDims = dim + 1;\n    }\n  }\n  // default values\n  const values = new Array(numberOfDims);\n  values.fill(0);\n  // get other values from the input string\n  for (let j = 0; j < strIds.length; ++j) {\n    // expecting dim < 10\n    dim = parseInt(strIds[j].substring(1, 2), 10);\n    const value = parseInt(strIds[j].substring(3), 10);\n    values[dim] = value;\n  }\n\n  return values;\n}\n\n/**\n * Check if the first input array contains all the\n * elements of the second input array.\n *\n * @param {string[]} arr0 The test array.\n * @param {string[]} arr1 The elements to check in the first array.\n * @returns {boolean} True if all the elements of arr1 are included in arr0.\n */\nexport function arrayContains(arr0, arr1) {\n  // check input\n  if (arr0 === null ||\n    arr1 === null ||\n    typeof arr0 === 'undefined' ||\n    typeof arr1 === 'undefined') {\n    return false;\n  }\n  if (arr0.length === 0 ||\n    arr1.length === 0 ||\n    arr1.length > arr0.length) {\n    return false;\n  }\n  // check values\n  for (const itemArr1 of arr1) {\n    if (!arr0.includes(itemArr1)) {\n      return false;\n    }\n  }\n  return true;\n}\n\n/**\n * Check for array equality after sorting.\n *\n * @param {Array} arr0 First array.\n * @param {Array} arr1 Second array.\n * @returns {boolean} True if both array are defined and contain same values.\n */\nexport function arraySortEquals(arr0, arr1) {\n  if (arr0 === null ||\n    arr1 === null ||\n    typeof arr0 === 'undefined' ||\n    typeof arr1 === 'undefined') {\n    return false;\n  }\n  const arr0sorted = arr0.slice().sort();\n  const arr1sorted = arr1.slice().sort();\n  return arrayEquals(arr0sorted, arr1sorted);\n}\n\n/**\n * Check for array equality.\n *\n * @param {Array} arr0 First array.\n * @param {Array} arr1 Second array.\n * @returns {boolean} True if both array are defined and contain same values.\n */\nexport function arrayEquals(arr0, arr1) {\n  if (arr0 === null ||\n    arr1 === null ||\n    typeof arr0 === 'undefined' ||\n    typeof arr1 === 'undefined') {\n    return false;\n  }\n  if (arr0.length !== arr1.length) {\n    return false;\n  }\n  return arr0.every(function (element, index) {\n    return element === arr1[index];\n  });\n}\n\n/**\n * Convert a Uint8Array to a string.\n *\n * @param {Uint8Array} arr The array to convert.\n * @returns {string} The array as string.\n */\nexport function uint8ArrayToString(arr) {\n  return String.fromCharCode.apply(String, arr);\n}\n\n/**\n * Array find in a subset of the input array.\n * Equivalent to: `arr.slice(start, end).find(callbackFn)`.\n *\n * @param {Uint8Array} arr The input array to search.\n * @param {Function} callbackFn The find function.\n * @param {number|undefined} start The array start index.\n * @param {number|undefined} [end] The array end index.\n * @returns {number|undefined} The index where the element was found.\n */\nexport function findInArraySubset(arr, callbackFn, start, end) {\n  // check inputs\n  if (typeof start === 'undefined' ||\n    start < 0 ||\n    start >= arr.length\n  ) {\n    start = 0;\n  }\n  if (typeof end === 'undefined' ||\n    end <= start ||\n    end > arr.length) {\n    end = arr.length;\n  }\n  // run\n  for (let i = start; i < end; ++i) {\n    if (callbackFn(arr[i], i, arr)) {\n      return i;\n    }\n  }\n  return undefined;\n}\n\n/**\n * Get a find in array callback.\n *\n * @param {Uint8Array} arr1 The array to find.\n * @returns {Function} The find callback function.\n */\nexport function getFindArrayInArrayCallback(arr1) {\n  return function (element, index, arr0) {\n    for (let i = 0; i < arr1.length; ++i) {\n      if (arr0[index + i] !== arr1[i]) {\n        return false;\n      }\n    }\n    return true;\n  };\n}\n\n/**\n * Extract each element of a multipart ArrayBuffer.\n *\n * Ref: {@link https://en.wikipedia.org/wiki/MIME#Multipart_messages}.\n *\n * @param {ArrayBuffer} arr The multipart array.\n * @returns {Array} The multipart parts as an array of object as\n *   {'Content-Type', ..., data} (depending on header tags).\n */\nexport function parseMultipart(arr) {\n  const u8Array = new Uint8Array(arr);\n\n  const parts = [];\n  // check input\n  if (u8Array.length === 0) {\n    return parts;\n  }\n\n  // \\r\\n\\r\\n\n  const doubleReturnNew = new Uint8Array([0x0d, 0x0a, 0x0d, 0x0a]);\n  const partHeaderEndCb = getFindArrayInArrayCallback(doubleReturnNew);\n\n  // look for boundary in first part header\n  let partHeaderEndIndex = findInArraySubset(\n    u8Array, partHeaderEndCb, 0\n  );\n  if (typeof partHeaderEndIndex === 'undefined') {\n    throw new Error('Can\\'t find the end of the first multipart header');\n  }\n  const firstPartHeader = u8Array.slice(0, partHeaderEndIndex);\n  // switch to string to use split\n  const lines = uint8ArrayToString(firstPartHeader).split('\\r\\n');\n  // boundary should start with '--'\n  let boundaryStr;\n  for (let i = 0; i < lines.length; ++i) {\n    if (lines[i][0] === '-' && lines[i][1] === '-') {\n      boundaryStr = lines[i];\n      break;\n    }\n  }\n  if (typeof boundaryStr === 'undefined') {\n    throw new Error('Can\\'t find the boundary between multi-parts');\n  }\n  const boundary = stringToUint8Array(boundaryStr);\n  const boundaryCb = getFindArrayInArrayCallback(boundary);\n  const boundaryLen = boundaryStr.length;\n\n  // skip mime header\n  let nextBoundaryIndex = findInArraySubset(\n    u8Array, boundaryCb, 0\n  );\n\n  // loop through content\n  while (typeof partHeaderEndIndex !== 'undefined') {\n    const part = {};\n\n    // header\n    const partHeader = u8Array.slice(\n      nextBoundaryIndex + boundaryLen, partHeaderEndIndex);\n    // split into object\n    const partHeaderLines =\n      uint8ArrayToString(partHeader).split('\\r\\n');\n    for (let l = 0; l < partHeaderLines.length; ++l) {\n      const line = partHeaderLines[l];\n      const semiColonIndex = line.indexOf(':');\n      if (semiColonIndex !== -1) {\n        const key = line.substring(0, semiColonIndex).trim();\n        const val = line.substring(semiColonIndex + 1).trim();\n        part[key] = val;\n      }\n    }\n\n    // find next boundary\n    nextBoundaryIndex = findInArraySubset(\n      u8Array, boundaryCb, partHeaderEndIndex\n    );\n    // exit if none\n    if (typeof nextBoundaryIndex === 'undefined') {\n      break;\n    }\n\n    // get part\n    // partHeaderEndIndex plus the size of the '\\r\\n\\r\\n' separator\n    const dataBeginIndex = partHeaderEndIndex + 4;\n    // nextBoundaryIndex minus the previous '\\r\\n'\n    const dataEndIndex = nextBoundaryIndex - 2;\n    if (dataBeginIndex < dataEndIndex) {\n      part.data = u8Array.slice(dataBeginIndex, dataEndIndex).buffer;\n    } else {\n      part.data = new Uint8Array();\n    }\n\n    // store part\n    parts.push(part);\n\n    // find next part header end\n    partHeaderEndIndex = findInArraySubset(\n      u8Array, partHeaderEndCb,\n      nextBoundaryIndex + boundaryLen\n    );\n  }\n\n  return parts;\n}\n\n/**\n * Build a multipart message.\n *\n * Ref:\n * - {@link https://en.wikipedia.org/wiki/MIME#Multipart_messages},\n * - {@link https://hg.orthanc-server.com/orthanc-dicomweb/file/tip/Resources/Samples/JavaScript/stow-rs.js}.\n *\n * @param {Array} parts The message parts as an array of object containing\n *   content headers and messages as the data property (as returned by parse).\n * @param {string} boundary The message boundary.\n * @returns {Uint8Array} The full multipart message.\n */\nexport function buildMultipart(parts, boundary) {\n  const lineBreak = '\\r\\n';\n  // build headers and calculate size\n  let partsSize = 0;\n  const headers = [];\n  for (let i = 0; i < parts.length; ++i) {\n    let headerStr = '';\n    if (i !== 0) {\n      headerStr += lineBreak;\n    }\n    headerStr += '--' + boundary + lineBreak;\n    const partKeys = Object.keys(parts[i]);\n    for (let k = 0; k < partKeys.length; ++k) {\n      const key = partKeys[k];\n      if (key !== 'data') {\n        headerStr += key + ': ' + parts[i][key] + lineBreak;\n      }\n    }\n    headerStr += lineBreak;\n    const header = stringToUint8Array(headerStr);\n    headers.push(header);\n    partsSize += header.byteLength + parts[i].data.byteLength;\n  }\n  // build trailer\n  const trailerStr = lineBreak + '--' + boundary + '--' + lineBreak;\n  const trailer = stringToUint8Array(trailerStr);\n\n  // final buffer\n  const buffer = new Uint8Array(partsSize + trailer.byteLength);\n  let offset = 0;\n  // concatenate parts\n  for (let j = 0; j < parts.length; ++j) {\n    buffer.set(headers[j], offset);\n    offset += headers[j].byteLength;\n    buffer.set(new Uint8Array(parts[j].data), offset);\n    offset += parts[j].data.byteLength;\n  }\n  // end buffer with trailer\n  buffer.set(trailer, offset);\n\n  // return\n  return buffer;\n}\n","/* eslint-disable @stylistic/js/quote-props */\n/* eslint @stylistic/js/max-len:0 */\n\n/**\n * DICOM tag dictionary 2022a.\n * Generated using xml standard conversion from {@link https://github.com/ivmartel/dcmStdToJs} v0.1.0.\n *\n * Conversion changes:\n * - (vr) 'See Note' -> 'NONE',\n * - (vr) 'OB or OW' -> 'ox',\n * - (vr) 'US or SS' -> 'xs',\n * - (vr) 'US or OW' -> 'xx',\n * - (vr) 'US or SS or OW' -> 'xs',\n * - added 'GenericGroupLength' element to each group.\n *\n * Local changes:\n * - tag numbers with 'xx' were replaced with '00', 'xxx' with '001' and\n *  'xxxx' with '0004'.\n *\n * @type {Object<string, Object<string, string[]>>}\n */\nexport const dictionary = {\n  '0000': {\n    '0000': ['UL', '1', 'CommandGroupLength'],\n    '0001': ['UL', '1', 'CommandLengthToEnd'],\n    '0002': ['UI', '1', 'AffectedSOPClassUID'],\n    '0003': ['UI', '1', 'RequestedSOPClassUID'],\n    '0010': ['SH', '1', 'CommandRecognitionCode'],\n    '0100': ['US', '1', 'CommandField'],\n    '0110': ['US', '1', 'MessageID'],\n    '0120': ['US', '1', 'MessageIDBeingRespondedTo'],\n    '0200': ['AE', '1', 'Initiator'],\n    '0300': ['AE', '1', 'Receiver'],\n    '0400': ['AE', '1', 'FindLocation'],\n    '0600': ['AE', '1', 'MoveDestination'],\n    '0700': ['US', '1', 'Priority'],\n    '0800': ['US', '1', 'CommandDataSetType'],\n    '0850': ['US', '1', 'NumberOfMatches'],\n    '0860': ['US', '1', 'ResponseSequenceNumber'],\n    '0900': ['US', '1', 'Status'],\n    '0901': ['AT', '1-n', 'OffendingElement'],\n    '0902': ['LO', '1', 'ErrorComment'],\n    '0903': ['US', '1', 'ErrorID'],\n    '1000': ['UI', '1', 'AffectedSOPInstanceUID'],\n    '1001': ['UI', '1', 'RequestedSOPInstanceUID'],\n    '1002': ['US', '1', 'EventTypeID'],\n    '1005': ['AT', '1-n', 'AttributeIdentifierList'],\n    '1008': ['US', '1', 'ActionTypeID'],\n    '1020': ['US', '1', 'NumberOfRemainingSuboperations'],\n    '1021': ['US', '1', 'NumberOfCompletedSuboperations'],\n    '1022': ['US', '1', 'NumberOfFailedSuboperations'],\n    '1023': ['US', '1', 'NumberOfWarningSuboperations'],\n    '1030': ['AE', '1', 'MoveOriginatorApplicationEntityTitle'],\n    '1031': ['US', '1', 'MoveOriginatorMessageID'],\n    '4000': ['LT', '1', 'DialogReceiver'],\n    '4010': ['LT', '1', 'TerminalType'],\n    '5010': ['SH', '1', 'MessageSetID'],\n    '5020': ['SH', '1', 'EndMessageID'],\n    '5110': ['LT', '1', 'DisplayFormat'],\n    '5120': ['LT', '1', 'PagePositionID'],\n    '5130': ['CS', '1', 'TextFormatID'],\n    '5140': ['CS', '1', 'NormalReverse'],\n    '5150': ['CS', '1', 'AddGrayScale'],\n    '5160': ['CS', '1', 'Borders'],\n    '5170': ['IS', '1', 'Copies'],\n    '5180': ['CS', '1', 'CommandMagnificationType'],\n    '5190': ['CS', '1', 'Erase'],\n    '51A0': ['CS', '1', 'Print'],\n    '51B0': ['US', '1-n', 'Overlays']\n  },\n  '0002': {\n    '0000': ['UL', '1', 'FileMetaInformationGroupLength'],\n    '0001': ['OB', '1', 'FileMetaInformationVersion'],\n    '0002': ['UI', '1', 'MediaStorageSOPClassUID'],\n    '0003': ['UI', '1', 'MediaStorageSOPInstanceUID'],\n    '0010': ['UI', '1', 'TransferSyntaxUID'],\n    '0012': ['UI', '1', 'ImplementationClassUID'],\n    '0013': ['SH', '1', 'ImplementationVersionName'],\n    '0016': ['AE', '1', 'SourceApplicationEntityTitle'],\n    '0017': ['AE', '1', 'SendingApplicationEntityTitle'],\n    '0018': ['AE', '1', 'ReceivingApplicationEntityTitle'],\n    '0026': ['UR', '1', 'SourcePresentationAddress'],\n    '0027': ['UR', '1', 'SendingPresentationAddress'],\n    '0028': ['UR', '1', 'ReceivingPresentationAddress'],\n    '0031': ['OB', '1', 'RTVMetaInformationVersion'],\n    '0032': ['UI', '1', 'RTVCommunicationSOPClassUID'],\n    '0033': ['UI', '1', 'RTVCommunicationSOPInstanceUID'],\n    '0035': ['OB', '1', 'RTVSourceIdentifier'],\n    '0036': ['OB', '1', 'RTVFlowIdentifier'],\n    '0037': ['UL', '1', 'RTVFlowRTPSamplingRate'],\n    '0038': ['FD', '1', 'RTVFlowActualFrameDuration'],\n    '0100': ['UI', '1', 'PrivateInformationCreatorUID'],\n    '0102': ['OB', '1', 'PrivateInformation']\n  },\n  '0004': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '1130': ['CS', '1', 'FileSetID'],\n    '1141': ['CS', '1-8', 'FileSetDescriptorFileID'],\n    '1142': ['CS', '1', 'SpecificCharacterSetOfFileSetDescriptorFile'],\n    '1200': ['UL', '1', 'OffsetOfTheFirstDirectoryRecordOfTheRootDirectoryEntity'],\n    '1202': ['UL', '1', 'OffsetOfTheLastDirectoryRecordOfTheRootDirectoryEntity'],\n    '1212': ['US', '1', 'FileSetConsistencyFlag'],\n    '1220': ['SQ', '1', 'DirectoryRecordSequence'],\n    '1400': ['UL', '1', 'OffsetOfTheNextDirectoryRecord'],\n    '1410': ['US', '1', 'RecordInUseFlag'],\n    '1420': ['UL', '1', 'OffsetOfReferencedLowerLevelDirectoryEntity'],\n    '1430': ['CS', '1', 'DirectoryRecordType'],\n    '1432': ['UI', '1', 'PrivateRecordUID'],\n    '1500': ['CS', '1-8', 'ReferencedFileID'],\n    '1504': ['UL', '1', 'MRDRDirectoryRecordOffset'],\n    '1510': ['UI', '1', 'ReferencedSOPClassUIDInFile'],\n    '1511': ['UI', '1', 'ReferencedSOPInstanceUIDInFile'],\n    '1512': ['UI', '1', 'ReferencedTransferSyntaxUIDInFile'],\n    '151A': ['UI', '1-n', 'ReferencedRelatedGeneralSOPClassUIDInFile'],\n    '1600': ['UL', '1', 'NumberOfReferences']\n  },\n  '0008': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['UL', '1', 'LengthToEnd'],\n    '0005': ['CS', '1-n', 'SpecificCharacterSet'],\n    '0006': ['SQ', '1', 'LanguageCodeSequence'],\n    '0008': ['CS', '2-n', 'ImageType'],\n    '0010': ['SH', '1', 'RecognitionCode'],\n    '0012': ['DA', '1', 'InstanceCreationDate'],\n    '0013': ['TM', '1', 'InstanceCreationTime'],\n    '0014': ['UI', '1', 'InstanceCreatorUID'],\n    '0015': ['DT', '1', 'InstanceCoercionDateTime'],\n    '0016': ['UI', '1', 'SOPClassUID'],\n    '0018': ['UI', '1', 'SOPInstanceUID'],\n    '001A': ['UI', '1-n', 'RelatedGeneralSOPClassUID'],\n    '001B': ['UI', '1', 'OriginalSpecializedSOPClassUID'],\n    '0020': ['DA', '1', 'StudyDate'],\n    '0021': ['DA', '1', 'SeriesDate'],\n    '0022': ['DA', '1', 'AcquisitionDate'],\n    '0023': ['DA', '1', 'ContentDate'],\n    '0024': ['DA', '1', 'OverlayDate'],\n    '0025': ['DA', '1', 'CurveDate'],\n    '002A': ['DT', '1', 'AcquisitionDateTime'],\n    '0030': ['TM', '1', 'StudyTime'],\n    '0031': ['TM', '1', 'SeriesTime'],\n    '0032': ['TM', '1', 'AcquisitionTime'],\n    '0033': ['TM', '1', 'ContentTime'],\n    '0034': ['TM', '1', 'OverlayTime'],\n    '0035': ['TM', '1', 'CurveTime'],\n    '0040': ['US', '1', 'DataSetType'],\n    '0041': ['LO', '1', 'DataSetSubtype'],\n    '0042': ['CS', '1', 'NuclearMedicineSeriesType'],\n    '0050': ['SH', '1', 'AccessionNumber'],\n    '0051': ['SQ', '1', 'IssuerOfAccessionNumberSequence'],\n    '0052': ['CS', '1', 'QueryRetrieveLevel'],\n    '0053': ['CS', '1', 'QueryRetrieveView'],\n    '0054': ['AE', '1-n', 'RetrieveAETitle'],\n    '0055': ['AE', '1', 'StationAETitle'],\n    '0056': ['CS', '1', 'InstanceAvailability'],\n    '0058': ['UI', '1-n', 'FailedSOPInstanceUIDList'],\n    '0060': ['CS', '1', 'Modality'],\n    '0061': ['CS', '1-n', 'ModalitiesInStudy'],\n    '0062': ['UI', '1-n', 'SOPClassesInStudy'],\n    '0063': ['SQ', '1', 'AnatomicRegionsInStudyCodeSequence'],\n    '0064': ['CS', '1', 'ConversionType'],\n    '0068': ['CS', '1', 'PresentationIntentType'],\n    '0070': ['LO', '1', 'Manufacturer'],\n    '0080': ['LO', '1', 'InstitutionName'],\n    '0081': ['ST', '1', 'InstitutionAddress'],\n    '0082': ['SQ', '1', 'InstitutionCodeSequence'],\n    '0090': ['PN', '1', 'ReferringPhysicianName'],\n    '0092': ['ST', '1', 'ReferringPhysicianAddress'],\n    '0094': ['SH', '1-n', 'ReferringPhysicianTelephoneNumbers'],\n    '0096': ['SQ', '1', 'ReferringPhysicianIdentificationSequence'],\n    '009C': ['PN', '1-n', 'ConsultingPhysicianName'],\n    '009D': ['SQ', '1', 'ConsultingPhysicianIdentificationSequence'],\n    '0100': ['SH', '1', 'CodeValue'],\n    '0101': ['LO', '1', 'ExtendedCodeValue'],\n    '0102': ['SH', '1', 'CodingSchemeDesignator'],\n    '0103': ['SH', '1', 'CodingSchemeVersion'],\n    '0104': ['LO', '1', 'CodeMeaning'],\n    '0105': ['CS', '1', 'MappingResource'],\n    '0106': ['DT', '1', 'ContextGroupVersion'],\n    '0107': ['DT', '1', 'ContextGroupLocalVersion'],\n    '0108': ['LT', '1', 'ExtendedCodeMeaning'],\n    '0109': ['SQ', '1', 'CodingSchemeResourcesSequence'],\n    '010A': ['CS', '1', 'CodingSchemeURLType'],\n    '010B': ['CS', '1', 'ContextGroupExtensionFlag'],\n    '010C': ['UI', '1', 'CodingSchemeUID'],\n    '010D': ['UI', '1', 'ContextGroupExtensionCreatorUID'],\n    '010E': ['UR', '1', 'CodingSchemeURL'],\n    '010F': ['CS', '1', 'ContextIdentifier'],\n    '0110': ['SQ', '1', 'CodingSchemeIdentificationSequence'],\n    '0112': ['LO', '1', 'CodingSchemeRegistry'],\n    '0114': ['ST', '1', 'CodingSchemeExternalID'],\n    '0115': ['ST', '1', 'CodingSchemeName'],\n    '0116': ['ST', '1', 'CodingSchemeResponsibleOrganization'],\n    '0117': ['UI', '1', 'ContextUID'],\n    '0118': ['UI', '1', 'MappingResourceUID'],\n    '0119': ['UC', '1', 'LongCodeValue'],\n    '0120': ['UR', '1', 'URNCodeValue'],\n    '0121': ['SQ', '1', 'EquivalentCodeSequence'],\n    '0122': ['LO', '1', 'MappingResourceName'],\n    '0123': ['SQ', '1', 'ContextGroupIdentificationSequence'],\n    '0124': ['SQ', '1', 'MappingResourceIdentificationSequence'],\n    '0201': ['SH', '1', 'TimezoneOffsetFromUTC'],\n    '0202': ['', '', ''],\n    '0220': ['SQ', '1', 'ResponsibleGroupCodeSequence'],\n    '0221': ['CS', '1', 'EquipmentModality'],\n    '0222': ['LO', '1', 'ManufacturerRelatedModelGroup'],\n    '0300': ['SQ', '1', 'PrivateDataElementCharacteristicsSequence'],\n    '0301': ['US', '1', 'PrivateGroupReference'],\n    '0302': ['LO', '1', 'PrivateCreatorReference'],\n    '0303': ['CS', '1', 'BlockIdentifyingInformationStatus'],\n    '0304': ['US', '1-n', 'NonidentifyingPrivateElements'],\n    '0305': ['SQ', '1', 'DeidentificationActionSequence'],\n    '0306': ['US', '1-n', 'IdentifyingPrivateElements'],\n    '0307': ['CS', '1', 'DeidentificationAction'],\n    '0308': ['US', '1', 'PrivateDataElement'],\n    '0309': ['UL', '1-3', 'PrivateDataElementValueMultiplicity'],\n    '030A': ['CS', '1', 'PrivateDataElementValueRepresentation'],\n    '030B': ['UL', '1-2', 'PrivateDataElementNumberOfItems'],\n    '030C': ['UC', '1', 'PrivateDataElementName'],\n    '030D': ['UC', '1', 'PrivateDataElementKeyword'],\n    '030E': ['UT', '1', 'PrivateDataElementDescription'],\n    '030F': ['UT', '1', 'PrivateDataElementEncoding'],\n    '0310': ['SQ', '1', 'PrivateDataElementDefinitionSequence'],\n    '1000': ['AE', '1', 'NetworkID'],\n    '1010': ['SH', '1', 'StationName'],\n    '1030': ['LO', '1', 'StudyDescription'],\n    '1032': ['SQ', '1', 'ProcedureCodeSequence'],\n    '103E': ['LO', '1', 'SeriesDescription'],\n    '103F': ['SQ', '1', 'SeriesDescriptionCodeSequence'],\n    '1040': ['LO', '1', 'InstitutionalDepartmentName'],\n    '1041': ['SQ', '1', 'InstitutionalDepartmentTypeCodeSequence'],\n    '1048': ['PN', '1-n', 'PhysiciansOfRecord'],\n    '1049': ['SQ', '1', 'PhysiciansOfRecordIdentificationSequence'],\n    '1050': ['PN', '1-n', 'PerformingPhysicianName'],\n    '1052': ['SQ', '1', 'PerformingPhysicianIdentificationSequence'],\n    '1060': ['PN', '1-n', 'NameOfPhysiciansReadingStudy'],\n    '1062': ['SQ', '1', 'PhysiciansReadingStudyIdentificationSequence'],\n    '1070': ['PN', '1-n', 'OperatorsName'],\n    '1072': ['SQ', '1', 'OperatorIdentificationSequence'],\n    '1080': ['LO', '1-n', 'AdmittingDiagnosesDescription'],\n    '1084': ['SQ', '1', 'AdmittingDiagnosesCodeSequence'],\n    '1090': ['LO', '1', 'ManufacturerModelName'],\n    '1100': ['SQ', '1', 'ReferencedResultsSequence'],\n    '1110': ['SQ', '1', 'ReferencedStudySequence'],\n    '1111': ['SQ', '1', 'ReferencedPerformedProcedureStepSequence'],\n    '1115': ['SQ', '1', 'ReferencedSeriesSequence'],\n    '1120': ['SQ', '1', 'ReferencedPatientSequence'],\n    '1125': ['SQ', '1', 'ReferencedVisitSequence'],\n    '1130': ['SQ', '1', 'ReferencedOverlaySequence'],\n    '1134': ['SQ', '1', 'ReferencedStereometricInstanceSequence'],\n    '113A': ['SQ', '1', 'ReferencedWaveformSequence'],\n    '1140': ['SQ', '1', 'ReferencedImageSequence'],\n    '1145': ['SQ', '1', 'ReferencedCurveSequence'],\n    '114A': ['SQ', '1', 'ReferencedInstanceSequence'],\n    '114B': ['SQ', '1', 'ReferencedRealWorldValueMappingInstanceSequence'],\n    '1150': ['UI', '1', 'ReferencedSOPClassUID'],\n    '1155': ['UI', '1', 'ReferencedSOPInstanceUID'],\n    '1156': ['SQ', '1', 'DefinitionSourceSequence'],\n    '115A': ['UI', '1-n', 'SOPClassesSupported'],\n    '1160': ['IS', '1-n', 'ReferencedFrameNumber'],\n    '1161': ['UL', '1-n', 'SimpleFrameList'],\n    '1162': ['UL', '3-3n', 'CalculatedFrameList'],\n    '1163': ['FD', '2', 'TimeRange'],\n    '1164': ['SQ', '1', 'FrameExtractionSequence'],\n    '1167': ['UI', '1', 'MultiFrameSourceSOPInstanceUID'],\n    '1190': ['UR', '1', 'RetrieveURL'],\n    '1195': ['UI', '1', 'TransactionUID'],\n    '1196': ['US', '1', 'WarningReason'],\n    '1197': ['US', '1', 'FailureReason'],\n    '1198': ['SQ', '1', 'FailedSOPSequence'],\n    '1199': ['SQ', '1', 'ReferencedSOPSequence'],\n    '119A': ['SQ', '1', 'OtherFailuresSequence'],\n    '1200': ['SQ', '1', 'StudiesContainingOtherReferencedInstancesSequence'],\n    '1250': ['SQ', '1', 'RelatedSeriesSequence'],\n    '2110': ['CS', '1', 'LossyImageCompressionRetired'],\n    '2111': ['ST', '1', 'DerivationDescription'],\n    '2112': ['SQ', '1', 'SourceImageSequence'],\n    '2120': ['SH', '1', 'StageName'],\n    '2122': ['IS', '1', 'StageNumber'],\n    '2124': ['IS', '1', 'NumberOfStages'],\n    '2127': ['SH', '1', 'ViewName'],\n    '2128': ['IS', '1', 'ViewNumber'],\n    '2129': ['IS', '1', 'NumberOfEventTimers'],\n    '212A': ['IS', '1', 'NumberOfViewsInStage'],\n    '2130': ['DS', '1-n', 'EventElapsedTimes'],\n    '2132': ['LO', '1-n', 'EventTimerNames'],\n    '2133': ['SQ', '1', 'EventTimerSequence'],\n    '2134': ['FD', '1', 'EventTimeOffset'],\n    '2135': ['SQ', '1', 'EventCodeSequence'],\n    '2142': ['IS', '1', 'StartTrim'],\n    '2143': ['IS', '1', 'StopTrim'],\n    '2144': ['IS', '1', 'RecommendedDisplayFrameRate'],\n    '2200': ['CS', '1', 'TransducerPosition'],\n    '2204': ['CS', '1', 'TransducerOrientation'],\n    '2208': ['CS', '1', 'AnatomicStructure'],\n    '2218': ['SQ', '1', 'AnatomicRegionSequence'],\n    '2220': ['SQ', '1', 'AnatomicRegionModifierSequence'],\n    '2228': ['SQ', '1', 'PrimaryAnatomicStructureSequence'],\n    '2229': ['SQ', '1', 'AnatomicStructureSpaceOrRegionSequence'],\n    '2230': ['SQ', '1', 'PrimaryAnatomicStructureModifierSequence'],\n    '2240': ['SQ', '1', 'TransducerPositionSequence'],\n    '2242': ['SQ', '1', 'TransducerPositionModifierSequence'],\n    '2244': ['SQ', '1', 'TransducerOrientationSequence'],\n    '2246': ['SQ', '1', 'TransducerOrientationModifierSequence'],\n    '2251': ['SQ', '1', 'AnatomicStructureSpaceOrRegionCodeSequenceTrial'],\n    '2253': ['SQ', '1', 'AnatomicPortalOfEntranceCodeSequenceTrial'],\n    '2255': ['SQ', '1', 'AnatomicApproachDirectionCodeSequenceTrial'],\n    '2256': ['ST', '1', 'AnatomicPerspectiveDescriptionTrial'],\n    '2257': ['SQ', '1', 'AnatomicPerspectiveCodeSequenceTrial'],\n    '2258': ['ST', '1', 'AnatomicLocationOfExaminingInstrumentDescriptionTrial'],\n    '2259': ['SQ', '1', 'AnatomicLocationOfExaminingInstrumentCodeSequenceTrial'],\n    '225A': ['SQ', '1', 'AnatomicStructureSpaceOrRegionModifierCodeSequenceTrial'],\n    '225C': ['SQ', '1', 'OnAxisBackgroundAnatomicStructureCodeSequenceTrial'],\n    '3001': ['SQ', '1', 'AlternateRepresentationSequence'],\n    '3002': ['UI', '1-n', 'AvailableTransferSyntaxUID'],\n    '3010': ['UI', '1-n', 'IrradiationEventUID'],\n    '3011': ['SQ', '1', 'SourceIrradiationEventSequence'],\n    '3012': ['UI', '1', 'RadiopharmaceuticalAdministrationEventUID'],\n    '4000': ['LT', '1', 'IdentifyingComments'],\n    '9007': ['CS', '4', 'FrameType'],\n    '9092': ['SQ', '1', 'ReferencedImageEvidenceSequence'],\n    '9121': ['SQ', '1', 'ReferencedRawDataSequence'],\n    '9123': ['UI', '1', 'CreatorVersionUID'],\n    '9124': ['SQ', '1', 'DerivationImageSequence'],\n    '9154': ['SQ', '1', 'SourceImageEvidenceSequence'],\n    '9205': ['CS', '1', 'PixelPresentation'],\n    '9206': ['CS', '1', 'VolumetricProperties'],\n    '9207': ['CS', '1', 'VolumeBasedCalculationTechnique'],\n    '9208': ['CS', '1', 'ComplexImageComponent'],\n    '9209': ['CS', '1', 'AcquisitionContrast'],\n    '9215': ['SQ', '1', 'DerivationCodeSequence'],\n    '9237': ['SQ', '1', 'ReferencedPresentationStateSequence'],\n    '9410': ['SQ', '1', 'ReferencedOtherPlaneSequence'],\n    '9458': ['SQ', '1', 'FrameDisplaySequence'],\n    '9459': ['FL', '1', 'RecommendedDisplayFrameRateInFloat'],\n    '9460': ['CS', '1', 'SkipFrameRangeFlag']\n  },\n  '0010': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['PN', '1', 'PatientName'],\n    '0020': ['LO', '1', 'PatientID'],\n    '0021': ['LO', '1', 'IssuerOfPatientID'],\n    '0022': ['CS', '1', 'TypeOfPatientID'],\n    '0024': ['SQ', '1', 'IssuerOfPatientIDQualifiersSequence'],\n    '0026': ['SQ', '1', 'SourcePatientGroupIdentificationSequence'],\n    '0027': ['SQ', '1', 'GroupOfPatientsIdentificationSequence'],\n    '0028': ['US', '3', 'SubjectRelativePositionInImage'],\n    '0030': ['DA', '1', 'PatientBirthDate'],\n    '0032': ['TM', '1', 'PatientBirthTime'],\n    '0033': ['LO', '1', 'PatientBirthDateInAlternativeCalendar'],\n    '0034': ['LO', '1', 'PatientDeathDateInAlternativeCalendar'],\n    '0035': ['CS', '1', 'PatientAlternativeCalendar'],\n    '0040': ['CS', '1', 'PatientSex'],\n    '0050': ['SQ', '1', 'PatientInsurancePlanCodeSequence'],\n    '0101': ['SQ', '1', 'PatientPrimaryLanguageCodeSequence'],\n    '0102': ['SQ', '1', 'PatientPrimaryLanguageModifierCodeSequence'],\n    '0200': ['CS', '1', 'QualityControlSubject'],\n    '0201': ['SQ', '1', 'QualityControlSubjectTypeCodeSequence'],\n    '0212': ['UC', '1', 'StrainDescription'],\n    '0213': ['LO', '1', 'StrainNomenclature'],\n    '0214': ['LO', '1', 'StrainStockNumber'],\n    '0215': ['SQ', '1', 'StrainSourceRegistryCodeSequence'],\n    '0216': ['SQ', '1', 'StrainStockSequence'],\n    '0217': ['LO', '1', 'StrainSource'],\n    '0218': ['UT', '1', 'StrainAdditionalInformation'],\n    '0219': ['SQ', '1', 'StrainCodeSequence'],\n    '0221': ['SQ', '1', 'GeneticModificationsSequence'],\n    '0222': ['UC', '1', 'GeneticModificationsDescription'],\n    '0223': ['LO', '1', 'GeneticModificationsNomenclature'],\n    '0229': ['SQ', '1', 'GeneticModificationsCodeSequence'],\n    '1000': ['LO', '1-n', 'OtherPatientIDs'],\n    '1001': ['PN', '1-n', 'OtherPatientNames'],\n    '1002': ['SQ', '1', 'OtherPatientIDsSequence'],\n    '1005': ['PN', '1', 'PatientBirthName'],\n    '1010': ['AS', '1', 'PatientAge'],\n    '1020': ['DS', '1', 'PatientSize'],\n    '1021': ['SQ', '1', 'PatientSizeCodeSequence'],\n    '1022': ['DS', '1', 'PatientBodyMassIndex'],\n    '1023': ['DS', '1', 'MeasuredAPDimension'],\n    '1024': ['DS', '1', 'MeasuredLateralDimension'],\n    '1030': ['DS', '1', 'PatientWeight'],\n    '1040': ['LO', '1', 'PatientAddress'],\n    '1050': ['LO', '1-n', 'InsurancePlanIdentification'],\n    '1060': ['PN', '1', 'PatientMotherBirthName'],\n    '1080': ['LO', '1', 'MilitaryRank'],\n    '1081': ['LO', '1', 'BranchOfService'],\n    '1090': ['LO', '1', 'MedicalRecordLocator'],\n    '1100': ['SQ', '1', 'ReferencedPatientPhotoSequence'],\n    '2000': ['LO', '1-n', 'MedicalAlerts'],\n    '2110': ['LO', '1-n', 'Allergies'],\n    '2150': ['LO', '1', 'CountryOfResidence'],\n    '2152': ['LO', '1', 'RegionOfResidence'],\n    '2154': ['SH', '1-n', 'PatientTelephoneNumbers'],\n    '2155': ['LT', '1', 'PatientTelecomInformation'],\n    '2160': ['SH', '1', 'EthnicGroup'],\n    '2180': ['SH', '1', 'Occupation'],\n    '21A0': ['CS', '1', 'SmokingStatus'],\n    '21B0': ['LT', '1', 'AdditionalPatientHistory'],\n    '21C0': ['US', '1', 'PregnancyStatus'],\n    '21D0': ['DA', '1', 'LastMenstrualDate'],\n    '21F0': ['LO', '1', 'PatientReligiousPreference'],\n    '2201': ['LO', '1', 'PatientSpeciesDescription'],\n    '2202': ['SQ', '1', 'PatientSpeciesCodeSequence'],\n    '2203': ['CS', '1', 'PatientSexNeutered'],\n    '2210': ['CS', '1', 'AnatomicalOrientationType'],\n    '2292': ['LO', '1', 'PatientBreedDescription'],\n    '2293': ['SQ', '1', 'PatientBreedCodeSequence'],\n    '2294': ['SQ', '1', 'BreedRegistrationSequence'],\n    '2295': ['LO', '1', 'BreedRegistrationNumber'],\n    '2296': ['SQ', '1', 'BreedRegistryCodeSequence'],\n    '2297': ['PN', '1', 'ResponsiblePerson'],\n    '2298': ['CS', '1', 'ResponsiblePersonRole'],\n    '2299': ['LO', '1', 'ResponsibleOrganization'],\n    '4000': ['LT', '1', 'PatientComments'],\n    '9431': ['FL', '1', 'ExaminedBodyThickness']\n  },\n  '0012': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['LO', '1', 'ClinicalTrialSponsorName'],\n    '0020': ['LO', '1', 'ClinicalTrialProtocolID'],\n    '0021': ['LO', '1', 'ClinicalTrialProtocolName'],\n    '0030': ['LO', '1', 'ClinicalTrialSiteID'],\n    '0031': ['LO', '1', 'ClinicalTrialSiteName'],\n    '0040': ['LO', '1', 'ClinicalTrialSubjectID'],\n    '0042': ['LO', '1', 'ClinicalTrialSubjectReadingID'],\n    '0050': ['LO', '1', 'ClinicalTrialTimePointID'],\n    '0051': ['ST', '1', 'ClinicalTrialTimePointDescription'],\n    '0052': ['FD', '1', 'LongitudinalTemporalOffsetFromEvent'],\n    '0053': ['CS', '1', 'LongitudinalTemporalEventType'],\n    '0060': ['LO', '1', 'ClinicalTrialCoordinatingCenterName'],\n    '0062': ['CS', '1', 'PatientIdentityRemoved'],\n    '0063': ['LO', '1-n', 'DeidentificationMethod'],\n    '0064': ['SQ', '1', 'DeidentificationMethodCodeSequence'],\n    '0071': ['LO', '1', 'ClinicalTrialSeriesID'],\n    '0072': ['LO', '1', 'ClinicalTrialSeriesDescription'],\n    '0081': ['LO', '1', 'ClinicalTrialProtocolEthicsCommitteeName'],\n    '0082': ['LO', '1', 'ClinicalTrialProtocolEthicsCommitteeApprovalNumber'],\n    '0083': ['SQ', '1', 'ConsentForClinicalTrialUseSequence'],\n    '0084': ['CS', '1', 'DistributionType'],\n    '0085': ['CS', '1', 'ConsentForDistributionFlag'],\n    '0086': ['DA', '1', 'EthicsCommitteeApprovalEffectivenessStartDate'],\n    '0087': ['DA', '1', 'EthicsCommitteeApprovalEffectivenessEndDate']\n  },\n  '0014': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0023': ['ST', '1', 'CADFileFormat'],\n    '0024': ['ST', '1', 'ComponentReferenceSystem'],\n    '0025': ['ST', '1', 'ComponentManufacturingProcedure'],\n    '0028': ['ST', '1', 'ComponentManufacturer'],\n    '0030': ['DS', '1-n', 'MaterialThickness'],\n    '0032': ['DS', '1-n', 'MaterialPipeDiameter'],\n    '0034': ['DS', '1-n', 'MaterialIsolationDiameter'],\n    '0042': ['ST', '1', 'MaterialGrade'],\n    '0044': ['ST', '1', 'MaterialPropertiesDescription'],\n    '0045': ['ST', '1', 'MaterialPropertiesFileFormatRetired'],\n    '0046': ['LT', '1', 'MaterialNotes'],\n    '0050': ['CS', '1', 'ComponentShape'],\n    '0052': ['CS', '1', 'CurvatureType'],\n    '0054': ['DS', '1', 'OuterDiameter'],\n    '0056': ['DS', '1', 'InnerDiameter'],\n    '0100': ['LO', '1-n', 'ComponentWelderIDs'],\n    '0101': ['CS', '1', 'SecondaryApprovalStatus'],\n    '0102': ['DA', '1', 'SecondaryReviewDate'],\n    '0103': ['TM', '1', 'SecondaryReviewTime'],\n    '0104': ['PN', '1', 'SecondaryReviewerName'],\n    '0105': ['ST', '1', 'RepairID'],\n    '0106': ['SQ', '1', 'MultipleComponentApprovalSequence'],\n    '0107': ['CS', '1-n', 'OtherApprovalStatus'],\n    '0108': ['CS', '1-n', 'OtherSecondaryApprovalStatus'],\n    '1010': ['ST', '1', 'ActualEnvironmentalConditions'],\n    '1020': ['DA', '1', 'ExpiryDate'],\n    '1040': ['ST', '1', 'EnvironmentalConditions'],\n    '2002': ['SQ', '1', 'EvaluatorSequence'],\n    '2004': ['IS', '1', 'EvaluatorNumber'],\n    '2006': ['PN', '1', 'EvaluatorName'],\n    '2008': ['IS', '1', 'EvaluationAttempt'],\n    '2012': ['SQ', '1', 'IndicationSequence'],\n    '2014': ['IS', '1', 'IndicationNumber'],\n    '2016': ['SH', '1', 'IndicationLabel'],\n    '2018': ['ST', '1', 'IndicationDescription'],\n    '201A': ['CS', '1-n', 'IndicationType'],\n    '201C': ['CS', '1', 'IndicationDisposition'],\n    '201E': ['SQ', '1', 'IndicationROISequence'],\n    '2030': ['SQ', '1', 'IndicationPhysicalPropertySequence'],\n    '2032': ['SH', '1', 'PropertyLabel'],\n    '2202': ['IS', '1', 'CoordinateSystemNumberOfAxes'],\n    '2204': ['SQ', '1', 'CoordinateSystemAxesSequence'],\n    '2206': ['ST', '1', 'CoordinateSystemAxisDescription'],\n    '2208': ['CS', '1', 'CoordinateSystemDataSetMapping'],\n    '220A': ['IS', '1', 'CoordinateSystemAxisNumber'],\n    '220C': ['CS', '1', 'CoordinateSystemAxisType'],\n    '220E': ['CS', '1', 'CoordinateSystemAxisUnits'],\n    '2210': ['OB', '1', 'CoordinateSystemAxisValues'],\n    '2220': ['SQ', '1', 'CoordinateSystemTransformSequence'],\n    '2222': ['ST', '1', 'TransformDescription'],\n    '2224': ['IS', '1', 'TransformNumberOfAxes'],\n    '2226': ['IS', '1-n', 'TransformOrderOfAxes'],\n    '2228': ['CS', '1', 'TransformedAxisUnits'],\n    '222A': ['DS', '1-n', 'CoordinateSystemTransformRotationAndScaleMatrix'],\n    '222C': ['DS', '1-n', 'CoordinateSystemTransformTranslationMatrix'],\n    '3011': ['DS', '1', 'InternalDetectorFrameTime'],\n    '3012': ['DS', '1', 'NumberOfFramesIntegrated'],\n    '3020': ['SQ', '1', 'DetectorTemperatureSequence'],\n    '3022': ['ST', '1', 'SensorName'],\n    '3024': ['DS', '1', 'HorizontalOffsetOfSensor'],\n    '3026': ['DS', '1', 'VerticalOffsetOfSensor'],\n    '3028': ['DS', '1', 'SensorTemperature'],\n    '3040': ['SQ', '1', 'DarkCurrentSequence'],\n    '3050': ['ox', '1', 'DarkCurrentCounts'],\n    '3060': ['SQ', '1', 'GainCorrectionReferenceSequence'],\n    '3070': ['ox', '1', 'AirCounts'],\n    '3071': ['DS', '1', 'KVUsedInGainCalibration'],\n    '3072': ['DS', '1', 'MAUsedInGainCalibration'],\n    '3073': ['DS', '1', 'NumberOfFramesUsedForIntegration'],\n    '3074': ['LO', '1', 'FilterMaterialUsedInGainCalibration'],\n    '3075': ['DS', '1', 'FilterThicknessUsedInGainCalibration'],\n    '3076': ['DA', '1', 'DateOfGainCalibration'],\n    '3077': ['TM', '1', 'TimeOfGainCalibration'],\n    '3080': ['OB', '1', 'BadPixelImage'],\n    '3099': ['LT', '1', 'CalibrationNotes'],\n    '3100': ['LT', '1', 'LinearityCorrectionTechnique'],\n    '3101': ['LT', '1', 'BeamHardeningCorrectionTechnique'],\n    '4002': ['SQ', '1', 'PulserEquipmentSequence'],\n    '4004': ['CS', '1', 'PulserType'],\n    '4006': ['LT', '1', 'PulserNotes'],\n    '4008': ['SQ', '1', 'ReceiverEquipmentSequence'],\n    '400A': ['CS', '1', 'AmplifierType'],\n    '400C': ['LT', '1', 'ReceiverNotes'],\n    '400E': ['SQ', '1', 'PreAmplifierEquipmentSequence'],\n    '400F': ['LT', '1', 'PreAmplifierNotes'],\n    '4010': ['SQ', '1', 'TransmitTransducerSequence'],\n    '4011': ['SQ', '1', 'ReceiveTransducerSequence'],\n    '4012': ['US', '1', 'NumberOfElements'],\n    '4013': ['CS', '1', 'ElementShape'],\n    '4014': ['DS', '1', 'ElementDimensionA'],\n    '4015': ['DS', '1', 'ElementDimensionB'],\n    '4016': ['DS', '1', 'ElementPitchA'],\n    '4017': ['DS', '1', 'MeasuredBeamDimensionA'],\n    '4018': ['DS', '1', 'MeasuredBeamDimensionB'],\n    '4019': ['DS', '1', 'LocationOfMeasuredBeamDiameter'],\n    '401A': ['DS', '1', 'NominalFrequency'],\n    '401B': ['DS', '1', 'MeasuredCenterFrequency'],\n    '401C': ['DS', '1', 'MeasuredBandwidth'],\n    '401D': ['DS', '1', 'ElementPitchB'],\n    '4020': ['SQ', '1', 'PulserSettingsSequence'],\n    '4022': ['DS', '1', 'PulseWidth'],\n    '4024': ['DS', '1', 'ExcitationFrequency'],\n    '4026': ['CS', '1', 'ModulationType'],\n    '4028': ['DS', '1', 'Damping'],\n    '4030': ['SQ', '1', 'ReceiverSettingsSequence'],\n    '4031': ['DS', '1', 'AcquiredSoundpathLength'],\n    '4032': ['CS', '1', 'AcquisitionCompressionType'],\n    '4033': ['IS', '1', 'AcquisitionSampleSize'],\n    '4034': ['DS', '1', 'RectifierSmoothing'],\n    '4035': ['SQ', '1', 'DACSequence'],\n    '4036': ['CS', '1', 'DACType'],\n    '4038': ['DS', '1-n', 'DACGainPoints'],\n    '403A': ['DS', '1-n', 'DACTimePoints'],\n    '403C': ['DS', '1-n', 'DACAmplitude'],\n    '4040': ['SQ', '1', 'PreAmplifierSettingsSequence'],\n    '4050': ['SQ', '1', 'TransmitTransducerSettingsSequence'],\n    '4051': ['SQ', '1', 'ReceiveTransducerSettingsSequence'],\n    '4052': ['DS', '1', 'IncidentAngle'],\n    '4054': ['ST', '1', 'CouplingTechnique'],\n    '4056': ['ST', '1', 'CouplingMedium'],\n    '4057': ['DS', '1', 'CouplingVelocity'],\n    '4058': ['DS', '1', 'ProbeCenterLocationX'],\n    '4059': ['DS', '1', 'ProbeCenterLocationZ'],\n    '405A': ['DS', '1', 'SoundPathLength'],\n    '405C': ['ST', '1', 'DelayLawIdentifier'],\n    '4060': ['SQ', '1', 'GateSettingsSequence'],\n    '4062': ['DS', '1', 'GateThreshold'],\n    '4064': ['DS', '1', 'VelocityOfSound'],\n    '4070': ['SQ', '1', 'CalibrationSettingsSequence'],\n    '4072': ['ST', '1', 'CalibrationProcedure'],\n    '4074': ['SH', '1', 'ProcedureVersion'],\n    '4076': ['DA', '1', 'ProcedureCreationDate'],\n    '4078': ['DA', '1', 'ProcedureExpirationDate'],\n    '407A': ['DA', '1', 'ProcedureLastModifiedDate'],\n    '407C': ['TM', '1-n', 'CalibrationTime'],\n    '407E': ['DA', '1-n', 'CalibrationDate'],\n    '4080': ['SQ', '1', 'ProbeDriveEquipmentSequence'],\n    '4081': ['CS', '1', 'DriveType'],\n    '4082': ['LT', '1', 'ProbeDriveNotes'],\n    '4083': ['SQ', '1', 'DriveProbeSequence'],\n    '4084': ['DS', '1', 'ProbeInductance'],\n    '4085': ['DS', '1', 'ProbeResistance'],\n    '4086': ['SQ', '1', 'ReceiveProbeSequence'],\n    '4087': ['SQ', '1', 'ProbeDriveSettingsSequence'],\n    '4088': ['DS', '1', 'BridgeResistors'],\n    '4089': ['DS', '1', 'ProbeOrientationAngle'],\n    '408B': ['DS', '1', 'UserSelectedGainY'],\n    '408C': ['DS', '1', 'UserSelectedPhase'],\n    '408D': ['DS', '1', 'UserSelectedOffsetX'],\n    '408E': ['DS', '1', 'UserSelectedOffsetY'],\n    '4091': ['SQ', '1', 'ChannelSettingsSequence'],\n    '4092': ['DS', '1', 'ChannelThreshold'],\n    '409A': ['SQ', '1', 'ScannerSettingsSequence'],\n    '409B': ['ST', '1', 'ScanProcedure'],\n    '409C': ['DS', '1', 'TranslationRateX'],\n    '409D': ['DS', '1', 'TranslationRateY'],\n    '409F': ['DS', '1', 'ChannelOverlap'],\n    '40A0': ['LO', '1-n', 'ImageQualityIndicatorType'],\n    '40A1': ['LO', '1-n', 'ImageQualityIndicatorMaterial'],\n    '40A2': ['LO', '1-n', 'ImageQualityIndicatorSize'],\n    '5002': ['IS', '1', 'LINACEnergy'],\n    '5004': ['IS', '1', 'LINACOutput'],\n    '5100': ['US', '1', 'ActiveAperture'],\n    '5101': ['DS', '1', 'TotalAperture'],\n    '5102': ['DS', '1', 'ApertureElevation'],\n    '5103': ['DS', '1', 'MainLobeAngle'],\n    '5104': ['DS', '1', 'MainRoofAngle'],\n    '5105': ['CS', '1', 'ConnectorType'],\n    '5106': ['SH', '1', 'WedgeModelNumber'],\n    '5107': ['DS', '1', 'WedgeAngleFloat'],\n    '5108': ['DS', '1', 'WedgeRoofAngle'],\n    '5109': ['CS', '1', 'WedgeElement1Position'],\n    '510A': ['DS', '1', 'WedgeMaterialVelocity'],\n    '510B': ['SH', '1', 'WedgeMaterial'],\n    '510C': ['DS', '1', 'WedgeOffsetZ'],\n    '510D': ['DS', '1', 'WedgeOriginOffsetX'],\n    '510E': ['DS', '1', 'WedgeTimeDelay'],\n    '510F': ['SH', '1', 'WedgeName'],\n    '5110': ['SH', '1', 'WedgeManufacturerName'],\n    '5111': ['LO', '1', 'WedgeDescription'],\n    '5112': ['DS', '1', 'NominalBeamAngle'],\n    '5113': ['DS', '1', 'WedgeOffsetX'],\n    '5114': ['DS', '1', 'WedgeOffsetY'],\n    '5115': ['DS', '1', 'WedgeTotalLength'],\n    '5116': ['DS', '1', 'WedgeInContactLength'],\n    '5117': ['DS', '1', 'WedgeFrontGap'],\n    '5118': ['DS', '1', 'WedgeTotalHeight'],\n    '5119': ['DS', '1', 'WedgeFrontHeight'],\n    '511A': ['DS', '1', 'WedgeRearHeight'],\n    '511B': ['DS', '1', 'WedgeTotalWidth'],\n    '511C': ['DS', '1', 'WedgeInContactWidth'],\n    '511D': ['DS', '1', 'WedgeChamferHeight'],\n    '511E': ['CS', '1', 'WedgeCurve'],\n    '511F': ['DS', '1', 'RadiusAlongWedge']\n  },\n  '0016': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['DS', '1', 'WhitePoint'],\n    '0002': ['DS', '3', 'PrimaryChromaticities'],\n    '0003': ['UT', '1', 'BatteryLevel'],\n    '0004': ['DS', '1', 'ExposureTimeInSeconds'],\n    '0005': ['DS', '1', 'FNumber'],\n    '0006': ['IS', '1', 'OECFRows'],\n    '0007': ['IS', '1', 'OECFColumns'],\n    '0008': ['UC', '1-n', 'OECFColumnNames'],\n    '0009': ['DS', '1-n', 'OECFValues'],\n    '000A': ['IS', '1', 'SpatialFrequencyResponseRows'],\n    '000B': ['IS', '1', 'SpatialFrequencyResponseColumns'],\n    '000C': ['UC', '1-n', 'SpatialFrequencyResponseColumnNames'],\n    '000D': ['DS', '1-n', 'SpatialFrequencyResponseValues'],\n    '000E': ['IS', '1', 'ColorFilterArrayPatternRows'],\n    '000F': ['IS', '1', 'ColorFilterArrayPatternColumns'],\n    '0010': ['DS', '1-n', 'ColorFilterArrayPatternValues'],\n    '0011': ['US', '1', 'FlashFiringStatus'],\n    '0012': ['US', '1', 'FlashReturnStatus'],\n    '0013': ['US', '1', 'FlashMode'],\n    '0014': ['US', '1', 'FlashFunctionPresent'],\n    '0015': ['US', '1', 'FlashRedEyeMode'],\n    '0016': ['US', '1', 'ExposureProgram'],\n    '0017': ['UT', '1', 'SpectralSensitivity'],\n    '0018': ['IS', '1', 'PhotographicSensitivity'],\n    '0019': ['IS', '1', 'SelfTimerMode'],\n    '001A': ['US', '1', 'SensitivityType'],\n    '001B': ['IS', '1', 'StandardOutputSensitivity'],\n    '001C': ['IS', '1', 'RecommendedExposureIndex'],\n    '001D': ['IS', '1', 'ISOSpeed'],\n    '001E': ['IS', '1', 'ISOSpeedLatitudeyyy'],\n    '001F': ['IS', '1', 'ISOSpeedLatitudezzz'],\n    '0020': ['UT', '1', 'EXIFVersion'],\n    '0021': ['DS', '1', 'ShutterSpeedValue'],\n    '0022': ['DS', '1', 'ApertureValue'],\n    '0023': ['DS', '1', 'BrightnessValue'],\n    '0024': ['DS', '1', 'ExposureBiasValue'],\n    '0025': ['DS', '1', 'MaxApertureValue'],\n    '0026': ['DS', '1', 'SubjectDistance'],\n    '0027': ['US', '1', 'MeteringMode'],\n    '0028': ['US', '1', 'LightSource'],\n    '0029': ['DS', '1', 'FocalLength'],\n    '002A': ['IS', '2-4', 'SubjectArea'],\n    '002B': ['OB', '1', 'MakerNote'],\n    '0030': ['DS', '1', 'Temperature'],\n    '0031': ['DS', '1', 'Humidity'],\n    '0032': ['DS', '1', 'Pressure'],\n    '0033': ['DS', '1', 'WaterDepth'],\n    '0034': ['DS', '1', 'Acceleration'],\n    '0035': ['DS', '1', 'CameraElevationAngle'],\n    '0036': ['DS', '1-2', 'FlashEnergy'],\n    '0037': ['IS', '2', 'SubjectLocation'],\n    '0038': ['DS', '1', 'PhotographicExposureIndex'],\n    '0039': ['US', '1', 'SensingMethod'],\n    '003A': ['US', '1', 'FileSource'],\n    '003B': ['US', '1', 'SceneType'],\n    '0041': ['US', '1', 'CustomRendered'],\n    '0042': ['US', '1', 'ExposureMode'],\n    '0043': ['US', '1', 'WhiteBalance'],\n    '0044': ['DS', '1', 'DigitalZoomRatio'],\n    '0045': ['IS', '1', 'FocalLengthIn35mmFilm'],\n    '0046': ['US', '1', 'SceneCaptureType'],\n    '0047': ['US', '1', 'GainControl'],\n    '0048': ['US', '1', 'Contrast'],\n    '0049': ['US', '1', 'Saturation'],\n    '004A': ['US', '1', 'Sharpness'],\n    '004B': ['OB', '1', 'DeviceSettingDescription'],\n    '004C': ['US', '1', 'SubjectDistanceRange'],\n    '004D': ['UT', '1', 'CameraOwnerName'],\n    '004E': ['DS', '4', 'LensSpecification'],\n    '004F': ['UT', '1', 'LensMake'],\n    '0050': ['UT', '1', 'LensModel'],\n    '0051': ['UT', '1', 'LensSerialNumber'],\n    '0061': ['CS', '1', 'InteroperabilityIndex'],\n    '0062': ['OB', '1', 'InteroperabilityVersion'],\n    '0070': ['OB', '1', 'GPSVersionID'],\n    '0071': ['CS', '1', 'GPSLatitudeRef'],\n    '0072': ['DS', '3', 'GPSLatitude'],\n    '0073': ['CS', '1', 'GPSLongitudeRef'],\n    '0074': ['DS', '3', 'GPSLongitude'],\n    '0075': ['US', '1', 'GPSAltitudeRef'],\n    '0076': ['DS', '1', 'GPSAltitude'],\n    '0077': ['DT', '1', 'GPSTimeStamp'],\n    '0078': ['UT', '1', 'GPSSatellites'],\n    '0079': ['CS', '1', 'GPSStatus'],\n    '007A': ['CS', '1', 'GPSMeasureMode'],\n    '007B': ['DS', '1', 'GPSDOP'],\n    '007C': ['CS', '1', 'GPSSpeedRef'],\n    '007D': ['DS', '1', 'GPSSpeed'],\n    '007E': ['CS', '1', 'GPSTrackRef'],\n    '007F': ['DS', '1', 'GPSTrack'],\n    '0080': ['CS', '1', 'GPSImgDirectionRef'],\n    '0081': ['DS', '1', 'GPSImgDirection'],\n    '0082': ['UT', '1', 'GPSMapDatum'],\n    '0083': ['CS', '1', 'GPSDestLatitudeRef'],\n    '0084': ['DS', '3', 'GPSDestLatitude'],\n    '0085': ['CS', '1', 'GPSDestLongitudeRef'],\n    '0086': ['DS', '3', 'GPSDestLongitude'],\n    '0087': ['CS', '1', 'GPSDestBearingRef'],\n    '0088': ['DS', '1', 'GPSDestBearing'],\n    '0089': ['CS', '1', 'GPSDestDistanceRef'],\n    '008A': ['DS', '1', 'GPSDestDistance'],\n    '008B': ['OB', '1', 'GPSProcessingMethod'],\n    '008C': ['OB', '1', 'GPSAreaInformation'],\n    '008D': ['DT', '1', 'GPSDateStamp'],\n    '008E': ['IS', '1', 'GPSDifferential'],\n    '1001': ['CS', '1', 'LightSourcePolarization'],\n    '1002': ['DS', '1', 'EmitterColorTemperature'],\n    '1003': ['CS', '1', 'ContactMethod'],\n    '1004': ['CS', '1-n', 'ImmersionMedia'],\n    '1005': ['DS', '1', 'OpticalMagnificationFactor']\n  },\n  '0018': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['LO', '1', 'ContrastBolusAgent'],\n    '0012': ['SQ', '1', 'ContrastBolusAgentSequence'],\n    '0013': ['FL', '1', 'ContrastBolusT1Relaxivity'],\n    '0014': ['SQ', '1', 'ContrastBolusAdministrationRouteSequence'],\n    '0015': ['CS', '1', 'BodyPartExamined'],\n    '0020': ['CS', '1-n', 'ScanningSequence'],\n    '0021': ['CS', '1-n', 'SequenceVariant'],\n    '0022': ['CS', '1-n', 'ScanOptions'],\n    '0023': ['CS', '1', 'MRAcquisitionType'],\n    '0024': ['SH', '1', 'SequenceName'],\n    '0025': ['CS', '1', 'AngioFlag'],\n    '0026': ['SQ', '1', 'InterventionDrugInformationSequence'],\n    '0027': ['TM', '1', 'InterventionDrugStopTime'],\n    '0028': ['DS', '1', 'InterventionDrugDose'],\n    '0029': ['SQ', '1', 'InterventionDrugCodeSequence'],\n    '002A': ['SQ', '1', 'AdditionalDrugSequence'],\n    '0030': ['LO', '1-n', 'Radionuclide'],\n    '0031': ['LO', '1', 'Radiopharmaceutical'],\n    '0032': ['DS', '1', 'EnergyWindowCenterline'],\n    '0033': ['DS', '1-n', 'EnergyWindowTotalWidth'],\n    '0034': ['LO', '1', 'InterventionDrugName'],\n    '0035': ['TM', '1', 'InterventionDrugStartTime'],\n    '0036': ['SQ', '1', 'InterventionSequence'],\n    '0037': ['CS', '1', 'TherapyType'],\n    '0038': ['CS', '1', 'InterventionStatus'],\n    '0039': ['CS', '1', 'TherapyDescription'],\n    '003A': ['ST', '1', 'InterventionDescription'],\n    '0040': ['IS', '1', 'CineRate'],\n    '0042': ['CS', '1', 'InitialCineRunState'],\n    '0050': ['DS', '1', 'SliceThickness'],\n    '0060': ['DS', '1', 'KVP'],\n    '0061': ['DS', '1', ''],\n    '0070': ['IS', '1', 'CountsAccumulated'],\n    '0071': ['CS', '1', 'AcquisitionTerminationCondition'],\n    '0072': ['DS', '1', 'EffectiveDuration'],\n    '0073': ['CS', '1', 'AcquisitionStartCondition'],\n    '0074': ['IS', '1', 'AcquisitionStartConditionData'],\n    '0075': ['IS', '1', 'AcquisitionTerminationConditionData'],\n    '0080': ['DS', '1', 'RepetitionTime'],\n    '0081': ['DS', '1', 'EchoTime'],\n    '0082': ['DS', '1', 'InversionTime'],\n    '0083': ['DS', '1', 'NumberOfAverages'],\n    '0084': ['DS', '1', 'ImagingFrequency'],\n    '0085': ['SH', '1', 'ImagedNucleus'],\n    '0086': ['IS', '1-n', 'EchoNumbers'],\n    '0087': ['DS', '1', 'MagneticFieldStrength'],\n    '0088': ['DS', '1', 'SpacingBetweenSlices'],\n    '0089': ['IS', '1', 'NumberOfPhaseEncodingSteps'],\n    '0090': ['DS', '1', 'DataCollectionDiameter'],\n    '0091': ['IS', '1', 'EchoTrainLength'],\n    '0093': ['DS', '1', 'PercentSampling'],\n    '0094': ['DS', '1', 'PercentPhaseFieldOfView'],\n    '0095': ['DS', '1', 'PixelBandwidth'],\n    '1000': ['LO', '1', 'DeviceSerialNumber'],\n    '1002': ['UI', '1', 'DeviceUID'],\n    '1003': ['LO', '1', 'DeviceID'],\n    '1004': ['LO', '1', 'PlateID'],\n    '1005': ['LO', '1', 'GeneratorID'],\n    '1006': ['LO', '1', 'GridID'],\n    '1007': ['LO', '1', 'CassetteID'],\n    '1008': ['LO', '1', 'GantryID'],\n    '1009': ['UT', '1', 'UniqueDeviceIdentifier'],\n    '100A': ['SQ', '1', 'UDISequence'],\n    '100B': ['UI', '1-n', 'ManufacturerDeviceClassUID'],\n    '1010': ['LO', '1', 'SecondaryCaptureDeviceID'],\n    '1011': ['LO', '1', 'HardcopyCreationDeviceID'],\n    '1012': ['DA', '1', 'DateOfSecondaryCapture'],\n    '1014': ['TM', '1', 'TimeOfSecondaryCapture'],\n    '1016': ['LO', '1', 'SecondaryCaptureDeviceManufacturer'],\n    '1017': ['LO', '1', 'HardcopyDeviceManufacturer'],\n    '1018': ['LO', '1', 'SecondaryCaptureDeviceManufacturerModelName'],\n    '1019': ['LO', '1-n', 'SecondaryCaptureDeviceSoftwareVersions'],\n    '101A': ['LO', '1-n', 'HardcopyDeviceSoftwareVersion'],\n    '101B': ['LO', '1', 'HardcopyDeviceManufacturerModelName'],\n    '1020': ['LO', '1-n', 'SoftwareVersions'],\n    '1022': ['SH', '1', 'VideoImageFormatAcquired'],\n    '1023': ['LO', '1', 'DigitalImageFormatAcquired'],\n    '1030': ['LO', '1', 'ProtocolName'],\n    '1040': ['LO', '1', 'ContrastBolusRoute'],\n    '1041': ['DS', '1', 'ContrastBolusVolume'],\n    '1042': ['TM', '1', 'ContrastBolusStartTime'],\n    '1043': ['TM', '1', 'ContrastBolusStopTime'],\n    '1044': ['DS', '1', 'ContrastBolusTotalDose'],\n    '1045': ['IS', '1', 'SyringeCounts'],\n    '1046': ['DS', '1-n', 'ContrastFlowRate'],\n    '1047': ['DS', '1-n', 'ContrastFlowDuration'],\n    '1048': ['CS', '1', 'ContrastBolusIngredient'],\n    '1049': ['DS', '1', 'ContrastBolusIngredientConcentration'],\n    '1050': ['DS', '1', 'SpatialResolution'],\n    '1060': ['DS', '1', 'TriggerTime'],\n    '1061': ['LO', '1', 'TriggerSourceOrType'],\n    '1062': ['IS', '1', 'NominalInterval'],\n    '1063': ['DS', '1', 'FrameTime'],\n    '1064': ['LO', '1', 'CardiacFramingType'],\n    '1065': ['DS', '1-n', 'FrameTimeVector'],\n    '1066': ['DS', '1', 'FrameDelay'],\n    '1067': ['DS', '1', 'ImageTriggerDelay'],\n    '1068': ['DS', '1', 'MultiplexGroupTimeOffset'],\n    '1069': ['DS', '1', 'TriggerTimeOffset'],\n    '106A': ['CS', '1', 'SynchronizationTrigger'],\n    '106C': ['US', '2', 'SynchronizationChannel'],\n    '106E': ['UL', '1', 'TriggerSamplePosition'],\n    '1070': ['LO', '1', 'RadiopharmaceuticalRoute'],\n    '1071': ['DS', '1', 'RadiopharmaceuticalVolume'],\n    '1072': ['TM', '1', 'RadiopharmaceuticalStartTime'],\n    '1073': ['TM', '1', 'RadiopharmaceuticalStopTime'],\n    '1074': ['DS', '1', 'RadionuclideTotalDose'],\n    '1075': ['DS', '1', 'RadionuclideHalfLife'],\n    '1076': ['DS', '1', 'RadionuclidePositronFraction'],\n    '1077': ['DS', '1', 'RadiopharmaceuticalSpecificActivity'],\n    '1078': ['DT', '1', 'RadiopharmaceuticalStartDateTime'],\n    '1079': ['DT', '1', 'RadiopharmaceuticalStopDateTime'],\n    '1080': ['CS', '1', 'BeatRejectionFlag'],\n    '1081': ['IS', '1', 'LowRRValue'],\n    '1082': ['IS', '1', 'HighRRValue'],\n    '1083': ['IS', '1', 'IntervalsAcquired'],\n    '1084': ['IS', '1', 'IntervalsRejected'],\n    '1085': ['LO', '1', 'PVCRejection'],\n    '1086': ['IS', '1', 'SkipBeats'],\n    '1088': ['IS', '1', 'HeartRate'],\n    '1090': ['IS', '1', 'CardiacNumberOfImages'],\n    '1094': ['IS', '1', 'TriggerWindow'],\n    '1100': ['DS', '1', 'ReconstructionDiameter'],\n    '1110': ['DS', '1', 'DistanceSourceToDetector'],\n    '1111': ['DS', '1', 'DistanceSourceToPatient'],\n    '1114': ['DS', '1', 'EstimatedRadiographicMagnificationFactor'],\n    '1120': ['DS', '1', 'GantryDetectorTilt'],\n    '1121': ['DS', '1', 'GantryDetectorSlew'],\n    '1130': ['DS', '1', 'TableHeight'],\n    '1131': ['DS', '1', 'TableTraverse'],\n    '1134': ['CS', '1', 'TableMotion'],\n    '1135': ['DS', '1-n', 'TableVerticalIncrement'],\n    '1136': ['DS', '1-n', 'TableLateralIncrement'],\n    '1137': ['DS', '1-n', 'TableLongitudinalIncrement'],\n    '1138': ['DS', '1', 'TableAngle'],\n    '113A': ['CS', '1', 'TableType'],\n    '1140': ['CS', '1', 'RotationDirection'],\n    '1141': ['DS', '1', 'AngularPosition'],\n    '1142': ['DS', '1-n', 'RadialPosition'],\n    '1143': ['DS', '1', 'ScanArc'],\n    '1144': ['DS', '1', 'AngularStep'],\n    '1145': ['DS', '1', 'CenterOfRotationOffset'],\n    '1146': ['DS', '1-n', 'RotationOffset'],\n    '1147': ['CS', '1', 'FieldOfViewShape'],\n    '1149': ['IS', '1-2', 'FieldOfViewDimensions'],\n    '1150': ['IS', '1', 'ExposureTime'],\n    '1151': ['IS', '1', 'XRayTubeCurrent'],\n    '1152': ['IS', '1', 'Exposure'],\n    '1153': ['IS', '1', 'ExposureInuAs'],\n    '1154': ['DS', '1', 'AveragePulseWidth'],\n    '1155': ['CS', '1', 'RadiationSetting'],\n    '1156': ['CS', '1', 'RectificationType'],\n    '115A': ['CS', '1', 'RadiationMode'],\n    '115E': ['DS', '1', 'ImageAndFluoroscopyAreaDoseProduct'],\n    '1160': ['SH', '1', 'FilterType'],\n    '1161': ['LO', '1-n', 'TypeOfFilters'],\n    '1162': ['DS', '1', 'IntensifierSize'],\n    '1164': ['DS', '2', 'ImagerPixelSpacing'],\n    '1166': ['CS', '1-n', 'Grid'],\n    '1170': ['IS', '1', 'GeneratorPower'],\n    '1180': ['SH', '1', 'CollimatorGridName'],\n    '1181': ['CS', '1', 'CollimatorType'],\n    '1182': ['IS', '1-2', 'FocalDistance'],\n    '1183': ['DS', '1-2', 'XFocusCenter'],\n    '1184': ['DS', '1-2', 'YFocusCenter'],\n    '1190': ['DS', '1-n', 'FocalSpots'],\n    '1191': ['CS', '1', 'AnodeTargetMaterial'],\n    '11A0': ['DS', '1', 'BodyPartThickness'],\n    '11A2': ['DS', '1', 'CompressionForce'],\n    '11A3': ['DS', '1', 'CompressionPressure'],\n    '11A4': ['LO', '1', 'PaddleDescription'],\n    '11A5': ['DS', '1', 'CompressionContactArea'],\n    '11B0': ['LO', '1', 'AcquisitionMode'],\n    '11B1': ['LO', '1', 'DoseModeName'],\n    '11B2': ['CS', '1', 'AcquiredSubtractionMaskFlag'],\n    '11B3': ['CS', '1', 'FluoroscopyPersistenceFlag'],\n    '11B4': ['CS', '1', 'FluoroscopyLastImageHoldPersistenceFlag'],\n    '11B5': ['IS', '1', 'UpperLimitNumberOfPersistentFluoroscopyFrames'],\n    '11B6': ['CS', '1', 'ContrastBolusAutoInjectionTriggerFlag'],\n    '11B7': ['FD', '1', 'ContrastBolusInjectionDelay'],\n    '11B8': ['SQ', '1', 'XAAcquisitionPhaseDetailsSequence'],\n    '11B9': ['FD', '1', 'XAAcquisitionFrameRate'],\n    '11BA': ['SQ', '1', 'XAPlaneDetailsSequence'],\n    '11BB': ['LO', '1', 'AcquisitionFieldOfViewLabel'],\n    '11BC': ['SQ', '1', 'XRayFilterDetailsSequence'],\n    '11BD': ['FD', '1', 'XAAcquisitionDuration'],\n    '11BE': ['CS', '1', 'ReconstructionPipelineType'],\n    '11BF': ['SQ', '1', 'ImageFilterDetailsSequence'],\n    '11C0': ['CS', '1', 'AppliedMaskSubtractionFlag'],\n    '11C1': ['SQ', '1', 'RequestedSeriesDescriptionCodeSequence'],\n    '1200': ['DA', '1-n', 'DateOfLastCalibration'],\n    '1201': ['TM', '1-n', 'TimeOfLastCalibration'],\n    '1202': ['DT', '1', 'DateTimeOfLastCalibration'],\n    '1203': ['DT', '1', 'CalibrationDateTime'],\n    '1210': ['SH', '1-n', 'ConvolutionKernel'],\n    '1240': ['IS', '1-n', 'UpperLowerPixelValues'],\n    '1242': ['IS', '1', 'ActualFrameDuration'],\n    '1243': ['IS', '1', 'CountRate'],\n    '1244': ['US', '1', 'PreferredPlaybackSequencing'],\n    '1250': ['SH', '1', 'ReceiveCoilName'],\n    '1251': ['SH', '1', 'TransmitCoilName'],\n    '1260': ['SH', '1', 'PlateType'],\n    '1261': ['LO', '1', 'PhosphorType'],\n    '1271': ['FD', '1', 'WaterEquivalentDiameter'],\n    '1272': ['SQ', '1', 'WaterEquivalentDiameterCalculationMethodCodeSequence'],\n    '1300': ['DS', '1', 'ScanVelocity'],\n    '1301': ['CS', '1-n', 'WholeBodyTechnique'],\n    '1302': ['IS', '1', 'ScanLength'],\n    '1310': ['US', '4', 'AcquisitionMatrix'],\n    '1312': ['CS', '1', 'InPlanePhaseEncodingDirection'],\n    '1314': ['DS', '1', 'FlipAngle'],\n    '1315': ['CS', '1', 'VariableFlipAngleFlag'],\n    '1316': ['DS', '1', 'SAR'],\n    '1318': ['DS', '1', 'dBdt'],\n    '1320': ['FL', '1', 'B1rms'],\n    '1400': ['LO', '1', 'AcquisitionDeviceProcessingDescription'],\n    '1401': ['LO', '1', 'AcquisitionDeviceProcessingCode'],\n    '1402': ['CS', '1', 'CassetteOrientation'],\n    '1403': ['CS', '1', 'CassetteSize'],\n    '1404': ['US', '1', 'ExposuresOnPlate'],\n    '1405': ['IS', '1', 'RelativeXRayExposure'],\n    '1411': ['DS', '1', 'ExposureIndex'],\n    '1412': ['DS', '1', 'TargetExposureIndex'],\n    '1413': ['DS', '1', 'DeviationIndex'],\n    '1450': ['DS', '1', 'ColumnAngulation'],\n    '1460': ['DS', '1', 'TomoLayerHeight'],\n    '1470': ['DS', '1', 'TomoAngle'],\n    '1480': ['DS', '1', 'TomoTime'],\n    '1490': ['CS', '1', 'TomoType'],\n    '1491': ['CS', '1', 'TomoClass'],\n    '1495': ['IS', '1', 'NumberOfTomosynthesisSourceImages'],\n    '1500': ['CS', '1', 'PositionerMotion'],\n    '1508': ['CS', '1', 'PositionerType'],\n    '1510': ['DS', '1', 'PositionerPrimaryAngle'],\n    '1511': ['DS', '1', 'PositionerSecondaryAngle'],\n    '1520': ['DS', '1-n', 'PositionerPrimaryAngleIncrement'],\n    '1521': ['DS', '1-n', 'PositionerSecondaryAngleIncrement'],\n    '1530': ['DS', '1', 'DetectorPrimaryAngle'],\n    '1531': ['DS', '1', 'DetectorSecondaryAngle'],\n    '1600': ['CS', '1-3', 'ShutterShape'],\n    '1602': ['IS', '1', 'ShutterLeftVerticalEdge'],\n    '1604': ['IS', '1', 'ShutterRightVerticalEdge'],\n    '1606': ['IS', '1', 'ShutterUpperHorizontalEdge'],\n    '1608': ['IS', '1', 'ShutterLowerHorizontalEdge'],\n    '1610': ['IS', '2', 'CenterOfCircularShutter'],\n    '1612': ['IS', '1', 'RadiusOfCircularShutter'],\n    '1620': ['IS', '2-2n', 'VerticesOfThePolygonalShutter'],\n    '1622': ['US', '1', 'ShutterPresentationValue'],\n    '1623': ['US', '1', 'ShutterOverlayGroup'],\n    '1624': ['US', '3', 'ShutterPresentationColorCIELabValue'],\n    '1630': ['CS', '1', 'OutlineShapeType'],\n    '1631': ['FD', '1', 'OutlineLeftVerticalEdge'],\n    '1632': ['FD', '1', 'OutlineRightVerticalEdge'],\n    '1633': ['FD', '1', 'OutlineUpperHorizontalEdge'],\n    '1634': ['FD', '1', 'OutlineLowerHorizontalEdge'],\n    '1635': ['FD', '2', 'CenterOfCircularOutline'],\n    '1636': ['FD', '1', 'DiameterOfCircularOutline'],\n    '1637': ['UL', '1', 'NumberOfPolygonalVertices'],\n    '1638': ['OF', '1', 'VerticesOfThePolygonalOutline'],\n    '1700': ['CS', '1-3', 'CollimatorShape'],\n    '1702': ['IS', '1', 'CollimatorLeftVerticalEdge'],\n    '1704': ['IS', '1', 'CollimatorRightVerticalEdge'],\n    '1706': ['IS', '1', 'CollimatorUpperHorizontalEdge'],\n    '1708': ['IS', '1', 'CollimatorLowerHorizontalEdge'],\n    '1710': ['IS', '2', 'CenterOfCircularCollimator'],\n    '1712': ['IS', '1', 'RadiusOfCircularCollimator'],\n    '1720': ['IS', '2-2n', 'VerticesOfThePolygonalCollimator'],\n    '1800': ['CS', '1', 'AcquisitionTimeSynchronized'],\n    '1801': ['SH', '1', 'TimeSource'],\n    '1802': ['CS', '1', 'TimeDistributionProtocol'],\n    '1803': ['LO', '1', 'NTPSourceAddress'],\n    '2001': ['IS', '1-n', 'PageNumberVector'],\n    '2002': ['SH', '1-n', 'FrameLabelVector'],\n    '2003': ['DS', '1-n', 'FramePrimaryAngleVector'],\n    '2004': ['DS', '1-n', 'FrameSecondaryAngleVector'],\n    '2005': ['DS', '1-n', 'SliceLocationVector'],\n    '2006': ['SH', '1-n', 'DisplayWindowLabelVector'],\n    '2010': ['DS', '2', 'NominalScannedPixelSpacing'],\n    '2020': ['CS', '1', 'DigitizingDeviceTransportDirection'],\n    '2030': ['DS', '1', 'RotationOfScannedFilm'],\n    '2041': ['SQ', '1', 'BiopsyTargetSequence'],\n    '2042': ['UI', '1', 'TargetUID'],\n    '2043': ['FL', '2', 'LocalizingCursorPosition'],\n    '2044': ['FL', '3', 'CalculatedTargetPosition'],\n    '2045': ['SH', '1', 'TargetLabel'],\n    '2046': ['FL', '1', 'DisplayedZValue'],\n    '3100': ['CS', '1', 'IVUSAcquisition'],\n    '3101': ['DS', '1', 'IVUSPullbackRate'],\n    '3102': ['DS', '1', 'IVUSGatedRate'],\n    '3103': ['IS', '1', 'IVUSPullbackStartFrameNumber'],\n    '3104': ['IS', '1', 'IVUSPullbackStopFrameNumber'],\n    '3105': ['IS', '1-n', 'LesionNumber'],\n    '4000': ['LT', '1', 'AcquisitionComments'],\n    '5000': ['SH', '1-n', 'OutputPower'],\n    '5010': ['LO', '1-n', 'TransducerData'],\n    '5011': ['SQ', '1', 'TransducerIdentificationSequence'],\n    '5012': ['DS', '1', 'FocusDepth'],\n    '5020': ['LO', '1', 'ProcessingFunction'],\n    '5021': ['LO', '1', 'PostprocessingFunction'],\n    '5022': ['DS', '1', 'MechanicalIndex'],\n    '5024': ['DS', '1', 'BoneThermalIndex'],\n    '5026': ['DS', '1', 'CranialThermalIndex'],\n    '5027': ['DS', '1', 'SoftTissueThermalIndex'],\n    '5028': ['DS', '1', 'SoftTissueFocusThermalIndex'],\n    '5029': ['DS', '1', 'SoftTissueSurfaceThermalIndex'],\n    '5030': ['DS', '1', 'DynamicRange'],\n    '5040': ['DS', '1', 'TotalGain'],\n    '5050': ['IS', '1', 'DepthOfScanField'],\n    '5100': ['CS', '1', 'PatientPosition'],\n    '5101': ['CS', '1', 'ViewPosition'],\n    '5104': ['SQ', '1', 'ProjectionEponymousNameCodeSequence'],\n    '5210': ['DS', '6', 'ImageTransformationMatrix'],\n    '5212': ['DS', '3', 'ImageTranslationVector'],\n    '6000': ['DS', '1', 'Sensitivity'],\n    '6011': ['SQ', '1', 'SequenceOfUltrasoundRegions'],\n    '6012': ['US', '1', 'RegionSpatialFormat'],\n    '6014': ['US', '1', 'RegionDataType'],\n    '6016': ['UL', '1', 'RegionFlags'],\n    '6018': ['UL', '1', 'RegionLocationMinX0'],\n    '601A': ['UL', '1', 'RegionLocationMinY0'],\n    '601C': ['UL', '1', 'RegionLocationMaxX1'],\n    '601E': ['UL', '1', 'RegionLocationMaxY1'],\n    '6020': ['SL', '1', 'ReferencePixelX0'],\n    '6022': ['SL', '1', 'ReferencePixelY0'],\n    '6024': ['US', '1', 'PhysicalUnitsXDirection'],\n    '6026': ['US', '1', 'PhysicalUnitsYDirection'],\n    '6028': ['FD', '1', 'ReferencePixelPhysicalValueX'],\n    '602A': ['FD', '1', 'ReferencePixelPhysicalValueY'],\n    '602C': ['FD', '1', 'PhysicalDeltaX'],\n    '602E': ['FD', '1', 'PhysicalDeltaY'],\n    '6030': ['UL', '1', 'TransducerFrequency'],\n    '6031': ['CS', '1', 'TransducerType'],\n    '6032': ['UL', '1', 'PulseRepetitionFrequency'],\n    '6034': ['FD', '1', 'DopplerCorrectionAngle'],\n    '6036': ['FD', '1', 'SteeringAngle'],\n    '6038': ['UL', '1', 'DopplerSampleVolumeXPositionRetired'],\n    '6039': ['SL', '1', 'DopplerSampleVolumeXPosition'],\n    '603A': ['UL', '1', 'DopplerSampleVolumeYPositionRetired'],\n    '603B': ['SL', '1', 'DopplerSampleVolumeYPosition'],\n    '603C': ['UL', '1', 'TMLinePositionX0Retired'],\n    '603D': ['SL', '1', 'TMLinePositionX0'],\n    '603E': ['UL', '1', 'TMLinePositionY0Retired'],\n    '603F': ['SL', '1', 'TMLinePositionY0'],\n    '6040': ['UL', '1', 'TMLinePositionX1Retired'],\n    '6041': ['SL', '1', 'TMLinePositionX1'],\n    '6042': ['UL', '1', 'TMLinePositionY1Retired'],\n    '6043': ['SL', '1', 'TMLinePositionY1'],\n    '6044': ['US', '1', 'PixelComponentOrganization'],\n    '6046': ['UL', '1', 'PixelComponentMask'],\n    '6048': ['UL', '1', 'PixelComponentRangeStart'],\n    '604A': ['UL', '1', 'PixelComponentRangeStop'],\n    '604C': ['US', '1', 'PixelComponentPhysicalUnits'],\n    '604E': ['US', '1', 'PixelComponentDataType'],\n    '6050': ['UL', '1', 'NumberOfTableBreakPoints'],\n    '6052': ['UL', '1-n', 'TableOfXBreakPoints'],\n    '6054': ['FD', '1-n', 'TableOfYBreakPoints'],\n    '6056': ['UL', '1', 'NumberOfTableEntries'],\n    '6058': ['UL', '1-n', 'TableOfPixelValues'],\n    '605A': ['FL', '1-n', 'TableOfParameterValues'],\n    '6060': ['FL', '1-n', 'RWaveTimeVector'],\n    '6070': ['US', '1', 'ActiveImageAreaOverlayGroup'],\n    '7000': ['CS', '1', 'DetectorConditionsNominalFlag'],\n    '7001': ['DS', '1', 'DetectorTemperature'],\n    '7004': ['CS', '1', 'DetectorType'],\n    '7005': ['CS', '1', 'DetectorConfiguration'],\n    '7006': ['LT', '1', 'DetectorDescription'],\n    '7008': ['LT', '1', 'DetectorMode'],\n    '700A': ['SH', '1', 'DetectorID'],\n    '700C': ['DA', '1', 'DateOfLastDetectorCalibration'],\n    '700E': ['TM', '1', 'TimeOfLastDetectorCalibration'],\n    '7010': ['IS', '1', 'ExposuresOnDetectorSinceLastCalibration'],\n    '7011': ['IS', '1', 'ExposuresOnDetectorSinceManufactured'],\n    '7012': ['DS', '1', 'DetectorTimeSinceLastExposure'],\n    '7014': ['DS', '1', 'DetectorActiveTime'],\n    '7016': ['DS', '1', 'DetectorActivationOffsetFromExposure'],\n    '701A': ['DS', '2', 'DetectorBinning'],\n    '7020': ['DS', '2', 'DetectorElementPhysicalSize'],\n    '7022': ['DS', '2', 'DetectorElementSpacing'],\n    '7024': ['CS', '1', 'DetectorActiveShape'],\n    '7026': ['DS', '1-2', 'DetectorActiveDimensions'],\n    '7028': ['DS', '2', 'DetectorActiveOrigin'],\n    '702A': ['LO', '1', 'DetectorManufacturerName'],\n    '702B': ['LO', '1', 'DetectorManufacturerModelName'],\n    '7030': ['DS', '2', 'FieldOfViewOrigin'],\n    '7032': ['DS', '1', 'FieldOfViewRotation'],\n    '7034': ['CS', '1', 'FieldOfViewHorizontalFlip'],\n    '7036': ['FL', '2', 'PixelDataAreaOriginRelativeToFOV'],\n    '7038': ['FL', '1', 'PixelDataAreaRotationAngleRelativeToFOV'],\n    '7040': ['LT', '1', 'GridAbsorbingMaterial'],\n    '7041': ['LT', '1', 'GridSpacingMaterial'],\n    '7042': ['DS', '1', 'GridThickness'],\n    '7044': ['DS', '1', 'GridPitch'],\n    '7046': ['IS', '2', 'GridAspectRatio'],\n    '7048': ['DS', '1', 'GridPeriod'],\n    '704C': ['DS', '1', 'GridFocalDistance'],\n    '7050': ['CS', '1-n', 'FilterMaterial'],\n    '7052': ['DS', '1-n', 'FilterThicknessMinimum'],\n    '7054': ['DS', '1-n', 'FilterThicknessMaximum'],\n    '7056': ['FL', '1-n', 'FilterBeamPathLengthMinimum'],\n    '7058': ['FL', '1-n', 'FilterBeamPathLengthMaximum'],\n    '7060': ['CS', '1', 'ExposureControlMode'],\n    '7062': ['LT', '1', 'ExposureControlModeDescription'],\n    '7064': ['CS', '1', 'ExposureStatus'],\n    '7065': ['DS', '1', 'PhototimerSetting'],\n    '8150': ['DS', '1', 'ExposureTimeInuS'],\n    '8151': ['DS', '1', 'XRayTubeCurrentInuA'],\n    '9004': ['CS', '1', 'ContentQualification'],\n    '9005': ['SH', '1', 'PulseSequenceName'],\n    '9006': ['SQ', '1', 'MRImagingModifierSequence'],\n    '9008': ['CS', '1', 'EchoPulseSequence'],\n    '9009': ['CS', '1', 'InversionRecovery'],\n    '9010': ['CS', '1', 'FlowCompensation'],\n    '9011': ['CS', '1', 'MultipleSpinEcho'],\n    '9012': ['CS', '1', 'MultiPlanarExcitation'],\n    '9014': ['CS', '1', 'PhaseContrast'],\n    '9015': ['CS', '1', 'TimeOfFlightContrast'],\n    '9016': ['CS', '1', 'Spoiling'],\n    '9017': ['CS', '1', 'SteadyStatePulseSequence'],\n    '9018': ['CS', '1', 'EchoPlanarPulseSequence'],\n    '9019': ['FD', '1', 'TagAngleFirstAxis'],\n    '9020': ['CS', '1', 'MagnetizationTransfer'],\n    '9021': ['CS', '1', 'T2Preparation'],\n    '9022': ['CS', '1', 'BloodSignalNulling'],\n    '9024': ['CS', '1', 'SaturationRecovery'],\n    '9025': ['CS', '1', 'SpectrallySelectedSuppression'],\n    '9026': ['CS', '1', 'SpectrallySelectedExcitation'],\n    '9027': ['CS', '1', 'SpatialPresaturation'],\n    '9028': ['CS', '1', 'Tagging'],\n    '9029': ['CS', '1', 'OversamplingPhase'],\n    '9030': ['FD', '1', 'TagSpacingFirstDimension'],\n    '9032': ['CS', '1', 'GeometryOfKSpaceTraversal'],\n    '9033': ['CS', '1', 'SegmentedKSpaceTraversal'],\n    '9034': ['CS', '1', 'RectilinearPhaseEncodeReordering'],\n    '9035': ['FD', '1', 'TagThickness'],\n    '9036': ['CS', '1', 'PartialFourierDirection'],\n    '9037': ['CS', '1', 'CardiacSynchronizationTechnique'],\n    '9041': ['LO', '1', 'ReceiveCoilManufacturerName'],\n    '9042': ['SQ', '1', 'MRReceiveCoilSequence'],\n    '9043': ['CS', '1', 'ReceiveCoilType'],\n    '9044': ['CS', '1', 'QuadratureReceiveCoil'],\n    '9045': ['SQ', '1', 'MultiCoilDefinitionSequence'],\n    '9046': ['LO', '1', 'MultiCoilConfiguration'],\n    '9047': ['SH', '1', 'MultiCoilElementName'],\n    '9048': ['CS', '1', 'MultiCoilElementUsed'],\n    '9049': ['SQ', '1', 'MRTransmitCoilSequence'],\n    '9050': ['LO', '1', 'TransmitCoilManufacturerName'],\n    '9051': ['CS', '1', 'TransmitCoilType'],\n    '9052': ['FD', '1-2', 'SpectralWidth'],\n    '9053': ['FD', '1-2', 'ChemicalShiftReference'],\n    '9054': ['CS', '1', 'VolumeLocalizationTechnique'],\n    '9058': ['US', '1', 'MRAcquisitionFrequencyEncodingSteps'],\n    '9059': ['CS', '1', 'Decoupling'],\n    '9060': ['CS', '1-2', 'DecoupledNucleus'],\n    '9061': ['FD', '1-2', 'DecouplingFrequency'],\n    '9062': ['CS', '1', 'DecouplingMethod'],\n    '9063': ['FD', '1-2', 'DecouplingChemicalShiftReference'],\n    '9064': ['CS', '1', 'KSpaceFiltering'],\n    '9065': ['CS', '1-2', 'TimeDomainFiltering'],\n    '9066': ['US', '1-2', 'NumberOfZeroFills'],\n    '9067': ['CS', '1', 'BaselineCorrection'],\n    '9069': ['FD', '1', 'ParallelReductionFactorInPlane'],\n    '9070': ['FD', '1', 'CardiacRRIntervalSpecified'],\n    '9073': ['FD', '1', 'AcquisitionDuration'],\n    '9074': ['DT', '1', 'FrameAcquisitionDateTime'],\n    '9075': ['CS', '1', 'DiffusionDirectionality'],\n    '9076': ['SQ', '1', 'DiffusionGradientDirectionSequence'],\n    '9077': ['CS', '1', 'ParallelAcquisition'],\n    '9078': ['CS', '1', 'ParallelAcquisitionTechnique'],\n    '9079': ['FD', '1-n', 'InversionTimes'],\n    '9080': ['ST', '1', 'MetaboliteMapDescription'],\n    '9081': ['CS', '1', 'PartialFourier'],\n    '9082': ['FD', '1', 'EffectiveEchoTime'],\n    '9083': ['SQ', '1', 'MetaboliteMapCodeSequence'],\n    '9084': ['SQ', '1', 'ChemicalShiftSequence'],\n    '9085': ['CS', '1', 'CardiacSignalSource'],\n    '9087': ['FD', '1', 'DiffusionBValue'],\n    '9089': ['FD', '3', 'DiffusionGradientOrientation'],\n    '9090': ['FD', '3', 'VelocityEncodingDirection'],\n    '9091': ['FD', '1', 'VelocityEncodingMinimumValue'],\n    '9092': ['SQ', '1', 'VelocityEncodingAcquisitionSequence'],\n    '9093': ['US', '1', 'NumberOfKSpaceTrajectories'],\n    '9094': ['CS', '1', 'CoverageOfKSpace'],\n    '9095': ['UL', '1', 'SpectroscopyAcquisitionPhaseRows'],\n    '9096': ['FD', '1', 'ParallelReductionFactorInPlaneRetired'],\n    '9098': ['FD', '1-2', 'TransmitterFrequency'],\n    '9100': ['CS', '1-2', 'ResonantNucleus'],\n    '9101': ['CS', '1', 'FrequencyCorrection'],\n    '9103': ['SQ', '1', 'MRSpectroscopyFOVGeometrySequence'],\n    '9104': ['FD', '1', 'SlabThickness'],\n    '9105': ['FD', '3', 'SlabOrientation'],\n    '9106': ['FD', '3', 'MidSlabPosition'],\n    '9107': ['SQ', '1', 'MRSpatialSaturationSequence'],\n    '9112': ['SQ', '1', 'MRTimingAndRelatedParametersSequence'],\n    '9114': ['SQ', '1', 'MREchoSequence'],\n    '9115': ['SQ', '1', 'MRModifierSequence'],\n    '9117': ['SQ', '1', 'MRDiffusionSequence'],\n    '9118': ['SQ', '1', 'CardiacSynchronizationSequence'],\n    '9119': ['SQ', '1', 'MRAveragesSequence'],\n    '9125': ['SQ', '1', 'MRFOVGeometrySequence'],\n    '9126': ['SQ', '1', 'VolumeLocalizationSequence'],\n    '9127': ['UL', '1', 'SpectroscopyAcquisitionDataColumns'],\n    '9147': ['CS', '1', 'DiffusionAnisotropyType'],\n    '9151': ['DT', '1', 'FrameReferenceDateTime'],\n    '9152': ['SQ', '1', 'MRMetaboliteMapSequence'],\n    '9155': ['FD', '1', 'ParallelReductionFactorOutOfPlane'],\n    '9159': ['UL', '1', 'SpectroscopyAcquisitionOutOfPlanePhaseSteps'],\n    '9166': ['CS', '1', 'BulkMotionStatus'],\n    '9168': ['FD', '1', 'ParallelReductionFactorSecondInPlane'],\n    '9169': ['CS', '1', 'CardiacBeatRejectionTechnique'],\n    '9170': ['CS', '1', 'RespiratoryMotionCompensationTechnique'],\n    '9171': ['CS', '1', 'RespiratorySignalSource'],\n    '9172': ['CS', '1', 'BulkMotionCompensationTechnique'],\n    '9173': ['CS', '1', 'BulkMotionSignalSource'],\n    '9174': ['CS', '1', 'ApplicableSafetyStandardAgency'],\n    '9175': ['LO', '1', 'ApplicableSafetyStandardDescription'],\n    '9176': ['SQ', '1', 'OperatingModeSequence'],\n    '9177': ['CS', '1', 'OperatingModeType'],\n    '9178': ['CS', '1', 'OperatingMode'],\n    '9179': ['CS', '1', 'SpecificAbsorptionRateDefinition'],\n    '9180': ['CS', '1', 'GradientOutputType'],\n    '9181': ['FD', '1', 'SpecificAbsorptionRateValue'],\n    '9182': ['FD', '1', 'GradientOutput'],\n    '9183': ['CS', '1', 'FlowCompensationDirection'],\n    '9184': ['FD', '1', 'TaggingDelay'],\n    '9185': ['ST', '1', 'RespiratoryMotionCompensationTechniqueDescription'],\n    '9186': ['SH', '1', 'RespiratorySignalSourceID'],\n    '9195': ['FD', '1', 'ChemicalShiftMinimumIntegrationLimitInHz'],\n    '9196': ['FD', '1', 'ChemicalShiftMaximumIntegrationLimitInHz'],\n    '9197': ['SQ', '1', 'MRVelocityEncodingSequence'],\n    '9198': ['CS', '1', 'FirstOrderPhaseCorrection'],\n    '9199': ['CS', '1', 'WaterReferencedPhaseCorrection'],\n    '9200': ['CS', '1', 'MRSpectroscopyAcquisitionType'],\n    '9214': ['CS', '1', 'RespiratoryCyclePosition'],\n    '9217': ['FD', '1', 'VelocityEncodingMaximumValue'],\n    '9218': ['FD', '1', 'TagSpacingSecondDimension'],\n    '9219': ['SS', '1', 'TagAngleSecondAxis'],\n    '9220': ['FD', '1', 'FrameAcquisitionDuration'],\n    '9226': ['SQ', '1', 'MRImageFrameTypeSequence'],\n    '9227': ['SQ', '1', 'MRSpectroscopyFrameTypeSequence'],\n    '9231': ['US', '1', 'MRAcquisitionPhaseEncodingStepsInPlane'],\n    '9232': ['US', '1', 'MRAcquisitionPhaseEncodingStepsOutOfPlane'],\n    '9234': ['UL', '1', 'SpectroscopyAcquisitionPhaseColumns'],\n    '9236': ['CS', '1', 'CardiacCyclePosition'],\n    '9239': ['SQ', '1', 'SpecificAbsorptionRateSequence'],\n    '9240': ['US', '1', 'RFEchoTrainLength'],\n    '9241': ['US', '1', 'GradientEchoTrainLength'],\n    '9250': ['CS', '1', 'ArterialSpinLabelingContrast'],\n    '9251': ['SQ', '1', 'MRArterialSpinLabelingSequence'],\n    '9252': ['LO', '1', 'ASLTechniqueDescription'],\n    '9253': ['US', '1', 'ASLSlabNumber'],\n    '9254': ['FD', '1', 'ASLSlabThickness'],\n    '9255': ['FD', '3', 'ASLSlabOrientation'],\n    '9256': ['FD', '3', 'ASLMidSlabPosition'],\n    '9257': ['CS', '1', 'ASLContext'],\n    '9258': ['UL', '1', 'ASLPulseTrainDuration'],\n    '9259': ['CS', '1', 'ASLCrusherFlag'],\n    '925A': ['FD', '1', 'ASLCrusherFlowLimit'],\n    '925B': ['LO', '1', 'ASLCrusherDescription'],\n    '925C': ['CS', '1', 'ASLBolusCutoffFlag'],\n    '925D': ['SQ', '1', 'ASLBolusCutoffTimingSequence'],\n    '925E': ['LO', '1', 'ASLBolusCutoffTechnique'],\n    '925F': ['UL', '1', 'ASLBolusCutoffDelayTime'],\n    '9260': ['SQ', '1', 'ASLSlabSequence'],\n    '9295': ['FD', '1', 'ChemicalShiftMinimumIntegrationLimitInppm'],\n    '9296': ['FD', '1', 'ChemicalShiftMaximumIntegrationLimitInppm'],\n    '9297': ['CS', '1', 'WaterReferenceAcquisition'],\n    '9298': ['IS', '1', 'EchoPeakPosition'],\n    '9301': ['SQ', '1', 'CTAcquisitionTypeSequence'],\n    '9302': ['CS', '1', 'AcquisitionType'],\n    '9303': ['FD', '1', 'TubeAngle'],\n    '9304': ['SQ', '1', 'CTAcquisitionDetailsSequence'],\n    '9305': ['FD', '1', 'RevolutionTime'],\n    '9306': ['FD', '1', 'SingleCollimationWidth'],\n    '9307': ['FD', '1', 'TotalCollimationWidth'],\n    '9308': ['SQ', '1', 'CTTableDynamicsSequence'],\n    '9309': ['FD', '1', 'TableSpeed'],\n    '9310': ['FD', '1', 'TableFeedPerRotation'],\n    '9311': ['FD', '1', 'SpiralPitchFactor'],\n    '9312': ['SQ', '1', 'CTGeometrySequence'],\n    '9313': ['FD', '3', 'DataCollectionCenterPatient'],\n    '9314': ['SQ', '1', 'CTReconstructionSequence'],\n    '9315': ['CS', '1', 'ReconstructionAlgorithm'],\n    '9316': ['CS', '1', 'ConvolutionKernelGroup'],\n    '9317': ['FD', '2', 'ReconstructionFieldOfView'],\n    '9318': ['FD', '3', 'ReconstructionTargetCenterPatient'],\n    '9319': ['FD', '1', 'ReconstructionAngle'],\n    '9320': ['SH', '1', 'ImageFilter'],\n    '9321': ['SQ', '1', 'CTExposureSequence'],\n    '9322': ['FD', '2', 'ReconstructionPixelSpacing'],\n    '9323': ['CS', '1-n', 'ExposureModulationType'],\n    '9324': ['FD', '1', 'EstimatedDoseSaving'],\n    '9325': ['SQ', '1', 'CTXRayDetailsSequence'],\n    '9326': ['SQ', '1', 'CTPositionSequence'],\n    '9327': ['FD', '1', 'TablePosition'],\n    '9328': ['FD', '1', 'ExposureTimeInms'],\n    '9329': ['SQ', '1', 'CTImageFrameTypeSequence'],\n    '9330': ['FD', '1', 'XRayTubeCurrentInmA'],\n    '9332': ['FD', '1', 'ExposureInmAs'],\n    '9333': ['CS', '1', 'ConstantVolumeFlag'],\n    '9334': ['CS', '1', 'FluoroscopyFlag'],\n    '9335': ['FD', '1', 'DistanceSourceToDataCollectionCenter'],\n    '9337': ['US', '1', 'ContrastBolusAgentNumber'],\n    '9338': ['SQ', '1', 'ContrastBolusIngredientCodeSequence'],\n    '9340': ['SQ', '1', 'ContrastAdministrationProfileSequence'],\n    '9341': ['SQ', '1', 'ContrastBolusUsageSequence'],\n    '9342': ['CS', '1', 'ContrastBolusAgentAdministered'],\n    '9343': ['CS', '1', 'ContrastBolusAgentDetected'],\n    '9344': ['CS', '1', 'ContrastBolusAgentPhase'],\n    '9345': ['FD', '1', 'CTDIvol'],\n    '9346': ['SQ', '1', 'CTDIPhantomTypeCodeSequence'],\n    '9351': ['FL', '1', 'CalciumScoringMassFactorPatient'],\n    '9352': ['FL', '3', 'CalciumScoringMassFactorDevice'],\n    '9353': ['FL', '1', 'EnergyWeightingFactor'],\n    '9360': ['SQ', '1', 'CTAdditionalXRaySourceSequence'],\n    '9361': ['CS', '1', 'MultienergyCTAcquisition'],\n    '9362': ['SQ', '1', 'MultienergyCTAcquisitionSequence'],\n    '9363': ['SQ', '1', 'MultienergyCTProcessingSequence'],\n    '9364': ['SQ', '1', 'MultienergyCTCharacteristicsSequence'],\n    '9365': ['SQ', '1', 'MultienergyCTXRaySourceSequence'],\n    '9366': ['US', '1', 'XRaySourceIndex'],\n    '9367': ['UC', '1', 'XRaySourceID'],\n    '9368': ['CS', '1', 'MultienergySourceTechnique'],\n    '9369': ['DT', '1', 'SourceStartDateTime'],\n    '936A': ['DT', '1', 'SourceEndDateTime'],\n    '936B': ['US', '1', 'SwitchingPhaseNumber'],\n    '936C': ['DS', '1', 'SwitchingPhaseNominalDuration'],\n    '936D': ['DS', '1', 'SwitchingPhaseTransitionDuration'],\n    '936E': ['DS', '1', 'EffectiveBinEnergy'],\n    '936F': ['SQ', '1', 'MultienergyCTXRayDetectorSequence'],\n    '9370': ['US', '1', 'XRayDetectorIndex'],\n    '9371': ['UC', '1', 'XRayDetectorID'],\n    '9372': ['CS', '1', 'MultienergyDetectorType'],\n    '9373': ['ST', '1', 'XRayDetectorLabel'],\n    '9374': ['DS', '1', 'NominalMaxEnergy'],\n    '9375': ['DS', '1', 'NominalMinEnergy'],\n    '9376': ['US', '1-n', 'ReferencedXRayDetectorIndex'],\n    '9377': ['US', '1-n', 'ReferencedXRaySourceIndex'],\n    '9378': ['US', '1-n', 'ReferencedPathIndex'],\n    '9379': ['SQ', '1', 'MultienergyCTPathSequence'],\n    '937A': ['US', '1', 'MultienergyCTPathIndex'],\n    '937B': ['UT', '1', 'MultienergyAcquisitionDescription'],\n    '937C': ['FD', '1', 'MonoenergeticEnergyEquivalent'],\n    '937D': ['SQ', '1', 'MaterialCodeSequence'],\n    '937E': ['CS', '1', 'DecompositionMethod'],\n    '937F': ['UT', '1', 'DecompositionDescription'],\n    '9380': ['SQ', '1', 'DecompositionAlgorithmIdentificationSequence'],\n    '9381': ['SQ', '1', 'DecompositionMaterialSequence'],\n    '9382': ['SQ', '1', 'MaterialAttenuationSequence'],\n    '9383': ['DS', '1', 'PhotonEnergy'],\n    '9384': ['DS', '1', 'XRayMassAttenuationCoefficient'],\n    '9401': ['SQ', '1', 'ProjectionPixelCalibrationSequence'],\n    '9402': ['FL', '1', 'DistanceSourceToIsocenter'],\n    '9403': ['FL', '1', 'DistanceObjectToTableTop'],\n    '9404': ['FL', '2', 'ObjectPixelSpacingInCenterOfBeam'],\n    '9405': ['SQ', '1', 'PositionerPositionSequence'],\n    '9406': ['SQ', '1', 'TablePositionSequence'],\n    '9407': ['SQ', '1', 'CollimatorShapeSequence'],\n    '9410': ['CS', '1', 'PlanesInAcquisition'],\n    '9412': ['SQ', '1', 'XAXRFFrameCharacteristicsSequence'],\n    '9417': ['SQ', '1', 'FrameAcquisitionSequence'],\n    '9420': ['CS', '1', 'XRayReceptorType'],\n    '9423': ['LO', '1', 'AcquisitionProtocolName'],\n    '9424': ['LT', '1', 'AcquisitionProtocolDescription'],\n    '9425': ['CS', '1', 'ContrastBolusIngredientOpaque'],\n    '9426': ['FL', '1', 'DistanceReceptorPlaneToDetectorHousing'],\n    '9427': ['CS', '1', 'IntensifierActiveShape'],\n    '9428': ['FL', '1-2', 'IntensifierActiveDimensions'],\n    '9429': ['FL', '2', 'PhysicalDetectorSize'],\n    '9430': ['FL', '2', 'PositionOfIsocenterProjection'],\n    '9432': ['SQ', '1', 'FieldOfViewSequence'],\n    '9433': ['LO', '1', 'FieldOfViewDescription'],\n    '9434': ['SQ', '1', 'ExposureControlSensingRegionsSequence'],\n    '9435': ['CS', '1', 'ExposureControlSensingRegionShape'],\n    '9436': ['SS', '1', 'ExposureControlSensingRegionLeftVerticalEdge'],\n    '9437': ['SS', '1', 'ExposureControlSensingRegionRightVerticalEdge'],\n    '9438': ['SS', '1', 'ExposureControlSensingRegionUpperHorizontalEdge'],\n    '9439': ['SS', '1', 'ExposureControlSensingRegionLowerHorizontalEdge'],\n    '9440': ['SS', '2', 'CenterOfCircularExposureControlSensingRegion'],\n    '9441': ['US', '1', 'RadiusOfCircularExposureControlSensingRegion'],\n    '9442': ['SS', '2-n', 'VerticesOfThePolygonalExposureControlSensingRegion'],\n    '9445': ['', '', ''],\n    '9447': ['FL', '1', 'ColumnAngulationPatient'],\n    '9449': ['FL', '1', 'BeamAngle'],\n    '9451': ['SQ', '1', 'FrameDetectorParametersSequence'],\n    '9452': ['FL', '1', 'CalculatedAnatomyThickness'],\n    '9455': ['SQ', '1', 'CalibrationSequence'],\n    '9456': ['SQ', '1', 'ObjectThicknessSequence'],\n    '9457': ['CS', '1', 'PlaneIdentification'],\n    '9461': ['FL', '1-2', 'FieldOfViewDimensionsInFloat'],\n    '9462': ['SQ', '1', 'IsocenterReferenceSystemSequence'],\n    '9463': ['FL', '1', 'PositionerIsocenterPrimaryAngle'],\n    '9464': ['FL', '1', 'PositionerIsocenterSecondaryAngle'],\n    '9465': ['FL', '1', 'PositionerIsocenterDetectorRotationAngle'],\n    '9466': ['FL', '1', 'TableXPositionToIsocenter'],\n    '9467': ['FL', '1', 'TableYPositionToIsocenter'],\n    '9468': ['FL', '1', 'TableZPositionToIsocenter'],\n    '9469': ['FL', '1', 'TableHorizontalRotationAngle'],\n    '9470': ['FL', '1', 'TableHeadTiltAngle'],\n    '9471': ['FL', '1', 'TableCradleTiltAngle'],\n    '9472': ['SQ', '1', 'FrameDisplayShutterSequence'],\n    '9473': ['FL', '1', 'AcquiredImageAreaDoseProduct'],\n    '9474': ['CS', '1', 'CArmPositionerTabletopRelationship'],\n    '9476': ['SQ', '1', 'XRayGeometrySequence'],\n    '9477': ['SQ', '1', 'IrradiationEventIdentificationSequence'],\n    '9504': ['SQ', '1', 'XRay3DFrameTypeSequence'],\n    '9506': ['SQ', '1', 'ContributingSourcesSequence'],\n    '9507': ['SQ', '1', 'XRay3DAcquisitionSequence'],\n    '9508': ['FL', '1', 'PrimaryPositionerScanArc'],\n    '9509': ['FL', '1', 'SecondaryPositionerScanArc'],\n    '9510': ['FL', '1', 'PrimaryPositionerScanStartAngle'],\n    '9511': ['FL', '1', 'SecondaryPositionerScanStartAngle'],\n    '9514': ['FL', '1', 'PrimaryPositionerIncrement'],\n    '9515': ['FL', '1', 'SecondaryPositionerIncrement'],\n    '9516': ['DT', '1', 'StartAcquisitionDateTime'],\n    '9517': ['DT', '1', 'EndAcquisitionDateTime'],\n    '9518': ['SS', '1', 'PrimaryPositionerIncrementSign'],\n    '9519': ['SS', '1', 'SecondaryPositionerIncrementSign'],\n    '9524': ['LO', '1', 'ApplicationName'],\n    '9525': ['LO', '1', 'ApplicationVersion'],\n    '9526': ['LO', '1', 'ApplicationManufacturer'],\n    '9527': ['CS', '1', 'AlgorithmType'],\n    '9528': ['LO', '1', 'AlgorithmDescription'],\n    '9530': ['SQ', '1', 'XRay3DReconstructionSequence'],\n    '9531': ['LO', '1', 'ReconstructionDescription'],\n    '9538': ['SQ', '1', 'PerProjectionAcquisitionSequence'],\n    '9541': ['SQ', '1', 'DetectorPositionSequence'],\n    '9542': ['SQ', '1', 'XRayAcquisitionDoseSequence'],\n    '9543': ['FD', '1', 'XRaySourceIsocenterPrimaryAngle'],\n    '9544': ['FD', '1', 'XRaySourceIsocenterSecondaryAngle'],\n    '9545': ['FD', '1', 'BreastSupportIsocenterPrimaryAngle'],\n    '9546': ['FD', '1', 'BreastSupportIsocenterSecondaryAngle'],\n    '9547': ['FD', '1', 'BreastSupportXPositionToIsocenter'],\n    '9548': ['FD', '1', 'BreastSupportYPositionToIsocenter'],\n    '9549': ['FD', '1', 'BreastSupportZPositionToIsocenter'],\n    '9550': ['FD', '1', 'DetectorIsocenterPrimaryAngle'],\n    '9551': ['FD', '1', 'DetectorIsocenterSecondaryAngle'],\n    '9552': ['FD', '1', 'DetectorXPositionToIsocenter'],\n    '9553': ['FD', '1', 'DetectorYPositionToIsocenter'],\n    '9554': ['FD', '1', 'DetectorZPositionToIsocenter'],\n    '9555': ['SQ', '1', 'XRayGridSequence'],\n    '9556': ['SQ', '1', 'XRayFilterSequence'],\n    '9557': ['FD', '3', 'DetectorActiveAreaTLHCPosition'],\n    '9558': ['FD', '6', 'DetectorActiveAreaOrientation'],\n    '9559': ['CS', '1', 'PositionerPrimaryAngleDirection'],\n    '9601': ['SQ', '1', 'DiffusionBMatrixSequence'],\n    '9602': ['FD', '1', 'DiffusionBValueXX'],\n    '9603': ['FD', '1', 'DiffusionBValueXY'],\n    '9604': ['FD', '1', 'DiffusionBValueXZ'],\n    '9605': ['FD', '1', 'DiffusionBValueYY'],\n    '9606': ['FD', '1', 'DiffusionBValueYZ'],\n    '9607': ['FD', '1', 'DiffusionBValueZZ'],\n    '9621': ['SQ', '1', 'FunctionalMRSequence'],\n    '9622': ['CS', '1', 'FunctionalSettlingPhaseFramesPresent'],\n    '9623': ['DT', '1', 'FunctionalSyncPulse'],\n    '9624': ['CS', '1', 'SettlingPhaseFrame'],\n    '9701': ['DT', '1', 'DecayCorrectionDateTime'],\n    '9715': ['FD', '1', 'StartDensityThreshold'],\n    '9716': ['FD', '1', 'StartRelativeDensityDifferenceThreshold'],\n    '9717': ['FD', '1', 'StartCardiacTriggerCountThreshold'],\n    '9718': ['FD', '1', 'StartRespiratoryTriggerCountThreshold'],\n    '9719': ['FD', '1', 'TerminationCountsThreshold'],\n    '9720': ['FD', '1', 'TerminationDensityThreshold'],\n    '9721': ['FD', '1', 'TerminationRelativeDensityThreshold'],\n    '9722': ['FD', '1', 'TerminationTimeThreshold'],\n    '9723': ['FD', '1', 'TerminationCardiacTriggerCountThreshold'],\n    '9724': ['FD', '1', 'TerminationRespiratoryTriggerCountThreshold'],\n    '9725': ['CS', '1', 'DetectorGeometry'],\n    '9726': ['FD', '1', 'TransverseDetectorSeparation'],\n    '9727': ['FD', '1', 'AxialDetectorDimension'],\n    '9729': ['US', '1', 'RadiopharmaceuticalAgentNumber'],\n    '9732': ['SQ', '1', 'PETFrameAcquisitionSequence'],\n    '9733': ['SQ', '1', 'PETDetectorMotionDetailsSequence'],\n    '9734': ['SQ', '1', 'PETTableDynamicsSequence'],\n    '9735': ['SQ', '1', 'PETPositionSequence'],\n    '9736': ['SQ', '1', 'PETFrameCorrectionFactorsSequence'],\n    '9737': ['SQ', '1', 'RadiopharmaceuticalUsageSequence'],\n    '9738': ['CS', '1', 'AttenuationCorrectionSource'],\n    '9739': ['US', '1', 'NumberOfIterations'],\n    '9740': ['US', '1', 'NumberOfSubsets'],\n    '9749': ['SQ', '1', 'PETReconstructionSequence'],\n    '9751': ['SQ', '1', 'PETFrameTypeSequence'],\n    '9755': ['CS', '1', 'TimeOfFlightInformationUsed'],\n    '9756': ['CS', '1', 'ReconstructionType'],\n    '9758': ['CS', '1', 'DecayCorrected'],\n    '9759': ['CS', '1', 'AttenuationCorrected'],\n    '9760': ['CS', '1', 'ScatterCorrected'],\n    '9761': ['CS', '1', 'DeadTimeCorrected'],\n    '9762': ['CS', '1', 'GantryMotionCorrected'],\n    '9763': ['CS', '1', 'PatientMotionCorrected'],\n    '9764': ['CS', '1', 'CountLossNormalizationCorrected'],\n    '9765': ['CS', '1', 'RandomsCorrected'],\n    '9766': ['CS', '1', 'NonUniformRadialSamplingCorrected'],\n    '9767': ['CS', '1', 'SensitivityCalibrated'],\n    '9768': ['CS', '1', 'DetectorNormalizationCorrection'],\n    '9769': ['CS', '1', 'IterativeReconstructionMethod'],\n    '9770': ['CS', '1', 'AttenuationCorrectionTemporalRelationship'],\n    '9771': ['SQ', '1', 'PatientPhysiologicalStateSequence'],\n    '9772': ['SQ', '1', 'PatientPhysiologicalStateCodeSequence'],\n    '9801': ['FD', '1-n', 'DepthsOfFocus'],\n    '9803': ['SQ', '1', 'ExcludedIntervalsSequence'],\n    '9804': ['DT', '1', 'ExclusionStartDateTime'],\n    '9805': ['FD', '1', 'ExclusionDuration'],\n    '9806': ['SQ', '1', 'USImageDescriptionSequence'],\n    '9807': ['SQ', '1', 'ImageDataTypeSequence'],\n    '9808': ['CS', '1', 'DataType'],\n    '9809': ['SQ', '1', 'TransducerScanPatternCodeSequence'],\n    '980B': ['CS', '1', 'AliasedDataType'],\n    '980C': ['CS', '1', 'PositionMeasuringDeviceUsed'],\n    '980D': ['SQ', '1', 'TransducerGeometryCodeSequence'],\n    '980E': ['SQ', '1', 'TransducerBeamSteeringCodeSequence'],\n    '980F': ['SQ', '1', 'TransducerApplicationCodeSequence'],\n    '9810': ['xs', '1', 'ZeroVelocityPixelValue'],\n    '9900': ['LO', '1', 'ReferenceLocationLabel'],\n    '9901': ['UT', '1', 'ReferenceLocationDescription'],\n    '9902': ['SQ', '1', 'ReferenceBasisCodeSequence'],\n    '9903': ['SQ', '1', 'ReferenceGeometryCodeSequence'],\n    '9904': ['DS', '1', 'OffsetDistance'],\n    '9905': ['CS', '1', 'OffsetDirection'],\n    '9906': ['SQ', '1', 'PotentialScheduledProtocolCodeSequence'],\n    '9907': ['SQ', '1', 'PotentialRequestedProcedureCodeSequence'],\n    '9908': ['UC', '1-n', 'PotentialReasonsForProcedure'],\n    '9909': ['SQ', '1', 'PotentialReasonsForProcedureCodeSequence'],\n    '990A': ['UC', '1-n', 'PotentialDiagnosticTasks'],\n    '990B': ['SQ', '1', 'ContraindicationsCodeSequence'],\n    '990C': ['SQ', '1', 'ReferencedDefinedProtocolSequence'],\n    '990D': ['SQ', '1', 'ReferencedPerformedProtocolSequence'],\n    '990E': ['SQ', '1', 'PredecessorProtocolSequence'],\n    '990F': ['UT', '1', 'ProtocolPlanningInformation'],\n    '9910': ['UT', '1', 'ProtocolDesignRationale'],\n    '9911': ['SQ', '1', 'PatientSpecificationSequence'],\n    '9912': ['SQ', '1', 'ModelSpecificationSequence'],\n    '9913': ['SQ', '1', 'ParametersSpecificationSequence'],\n    '9914': ['SQ', '1', 'InstructionSequence'],\n    '9915': ['US', '1', 'InstructionIndex'],\n    '9916': ['LO', '1', 'InstructionText'],\n    '9917': ['UT', '1', 'InstructionDescription'],\n    '9918': ['CS', '1', 'InstructionPerformedFlag'],\n    '9919': ['DT', '1', 'InstructionPerformedDateTime'],\n    '991A': ['UT', '1', 'InstructionPerformanceComment'],\n    '991B': ['SQ', '1', 'PatientPositioningInstructionSequence'],\n    '991C': ['SQ', '1', 'PositioningMethodCodeSequence'],\n    '991D': ['SQ', '1', 'PositioningLandmarkSequence'],\n    '991E': ['UI', '1', 'TargetFrameOfReferenceUID'],\n    '991F': ['SQ', '1', 'AcquisitionProtocolElementSpecificationSequence'],\n    '9920': ['SQ', '1', 'AcquisitionProtocolElementSequence'],\n    '9921': ['US', '1', 'ProtocolElementNumber'],\n    '9922': ['LO', '1', 'ProtocolElementName'],\n    '9923': ['UT', '1', 'ProtocolElementCharacteristicsSummary'],\n    '9924': ['UT', '1', 'ProtocolElementPurpose'],\n    '9930': ['CS', '1', 'AcquisitionMotion'],\n    '9931': ['SQ', '1', 'AcquisitionStartLocationSequence'],\n    '9932': ['SQ', '1', 'AcquisitionEndLocationSequence'],\n    '9933': ['SQ', '1', 'ReconstructionProtocolElementSpecificationSequence'],\n    '9934': ['SQ', '1', 'ReconstructionProtocolElementSequence'],\n    '9935': ['SQ', '1', 'StorageProtocolElementSpecificationSequence'],\n    '9936': ['SQ', '1', 'StorageProtocolElementSequence'],\n    '9937': ['LO', '1', 'RequestedSeriesDescription'],\n    '9938': ['US', '1-n', 'SourceAcquisitionProtocolElementNumber'],\n    '9939': ['US', '1-n', 'SourceAcquisitionBeamNumber'],\n    '993A': ['US', '1-n', 'SourceReconstructionProtocolElementNumber'],\n    '993B': ['SQ', '1', 'ReconstructionStartLocationSequence'],\n    '993C': ['SQ', '1', 'ReconstructionEndLocationSequence'],\n    '993D': ['SQ', '1', 'ReconstructionAlgorithmSequence'],\n    '993E': ['SQ', '1', 'ReconstructionTargetCenterLocationSequence'],\n    '9941': ['UT', '1', 'ImageFilterDescription'],\n    '9942': ['FD', '1', 'CTDIvolNotificationTrigger'],\n    '9943': ['FD', '1', 'DLPNotificationTrigger'],\n    '9944': ['CS', '1', 'AutoKVPSelectionType'],\n    '9945': ['FD', '1', 'AutoKVPUpperBound'],\n    '9946': ['FD', '1', 'AutoKVPLowerBound'],\n    '9947': ['CS', '1', 'ProtocolDefinedPatientPosition'],\n    'A001': ['SQ', '1', 'ContributingEquipmentSequence'],\n    'A002': ['DT', '1', 'ContributionDateTime'],\n    'A003': ['ST', '1', 'ContributionDescription']\n  },\n  '0020': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '000D': ['UI', '1', 'StudyInstanceUID'],\n    '000E': ['UI', '1', 'SeriesInstanceUID'],\n    '0010': ['SH', '1', 'StudyID'],\n    '0011': ['IS', '1', 'SeriesNumber'],\n    '0012': ['IS', '1', 'AcquisitionNumber'],\n    '0013': ['IS', '1', 'InstanceNumber'],\n    '0014': ['IS', '1', 'IsotopeNumber'],\n    '0015': ['IS', '1', 'PhaseNumber'],\n    '0016': ['IS', '1', 'IntervalNumber'],\n    '0017': ['IS', '1', 'TimeSlotNumber'],\n    '0018': ['IS', '1', 'AngleNumber'],\n    '0019': ['IS', '1', 'ItemNumber'],\n    '0020': ['CS', '2', 'PatientOrientation'],\n    '0022': ['IS', '1', 'OverlayNumber'],\n    '0024': ['IS', '1', 'CurveNumber'],\n    '0026': ['IS', '1', 'LUTNumber'],\n    '0030': ['DS', '3', 'ImagePosition'],\n    '0032': ['DS', '3', 'ImagePositionPatient'],\n    '0035': ['DS', '6', 'ImageOrientation'],\n    '0037': ['DS', '6', 'ImageOrientationPatient'],\n    '0050': ['DS', '1', 'Location'],\n    '0052': ['UI', '1', 'FrameOfReferenceUID'],\n    '0060': ['CS', '1', 'Laterality'],\n    '0062': ['CS', '1', 'ImageLaterality'],\n    '0070': ['LO', '1', 'ImageGeometryType'],\n    '0080': ['CS', '1-n', 'MaskingImage'],\n    '00AA': ['IS', '1', 'ReportNumber'],\n    '0100': ['IS', '1', 'TemporalPositionIdentifier'],\n    '0105': ['IS', '1', 'NumberOfTemporalPositions'],\n    '0110': ['DS', '1', 'TemporalResolution'],\n    '0200': ['UI', '1', 'SynchronizationFrameOfReferenceUID'],\n    '0242': ['UI', '1', 'SOPInstanceUIDOfConcatenationSource'],\n    '1000': ['IS', '1', 'SeriesInStudy'],\n    '1001': ['IS', '1', 'AcquisitionsInSeries'],\n    '1002': ['IS', '1', 'ImagesInAcquisition'],\n    '1003': ['IS', '1', 'ImagesInSeries'],\n    '1004': ['IS', '1', 'AcquisitionsInStudy'],\n    '1005': ['IS', '1', 'ImagesInStudy'],\n    '1020': ['LO', '1-n', 'Reference'],\n    '103F': ['LO', '1', 'TargetPositionReferenceIndicator'],\n    '1040': ['LO', '1', 'PositionReferenceIndicator'],\n    '1041': ['DS', '1', 'SliceLocation'],\n    '1070': ['IS', '1-n', 'OtherStudyNumbers'],\n    '1200': ['IS', '1', 'NumberOfPatientRelatedStudies'],\n    '1202': ['IS', '1', 'NumberOfPatientRelatedSeries'],\n    '1204': ['IS', '1', 'NumberOfPatientRelatedInstances'],\n    '1206': ['IS', '1', 'NumberOfStudyRelatedSeries'],\n    '1208': ['IS', '1', 'NumberOfStudyRelatedInstances'],\n    '1209': ['IS', '1', 'NumberOfSeriesRelatedInstances'],\n    '3100': ['CS', '1-n', 'SourceImageIDs'],\n    '3401': ['CS', '1', 'ModifyingDeviceID'],\n    '3402': ['CS', '1', 'ModifiedImageID'],\n    '3403': ['DA', '1', 'ModifiedImageDate'],\n    '3404': ['LO', '1', 'ModifyingDeviceManufacturer'],\n    '3405': ['TM', '1', 'ModifiedImageTime'],\n    '3406': ['LO', '1', 'ModifiedImageDescription'],\n    '4000': ['LT', '1', 'ImageComments'],\n    '5000': ['AT', '1-n', 'OriginalImageIdentification'],\n    '5002': ['LO', '1-n', 'OriginalImageIdentificationNomenclature'],\n    '9056': ['SH', '1', 'StackID'],\n    '9057': ['UL', '1', 'InStackPositionNumber'],\n    '9071': ['SQ', '1', 'FrameAnatomySequence'],\n    '9072': ['CS', '1', 'FrameLaterality'],\n    '9111': ['SQ', '1', 'FrameContentSequence'],\n    '9113': ['SQ', '1', 'PlanePositionSequence'],\n    '9116': ['SQ', '1', 'PlaneOrientationSequence'],\n    '9128': ['UL', '1', 'TemporalPositionIndex'],\n    '9153': ['FD', '1', 'NominalCardiacTriggerDelayTime'],\n    '9154': ['FL', '1', 'NominalCardiacTriggerTimePriorToRPeak'],\n    '9155': ['FL', '1', 'ActualCardiacTriggerTimePriorToRPeak'],\n    '9156': ['US', '1', 'FrameAcquisitionNumber'],\n    '9157': ['UL', '1-n', 'DimensionIndexValues'],\n    '9158': ['LT', '1', 'FrameComments'],\n    '9161': ['UI', '1', 'ConcatenationUID'],\n    '9162': ['US', '1', 'InConcatenationNumber'],\n    '9163': ['US', '1', 'InConcatenationTotalNumber'],\n    '9164': ['UI', '1', 'DimensionOrganizationUID'],\n    '9165': ['AT', '1', 'DimensionIndexPointer'],\n    '9167': ['AT', '1', 'FunctionalGroupPointer'],\n    '9170': ['SQ', '1', 'UnassignedSharedConvertedAttributesSequence'],\n    '9171': ['SQ', '1', 'UnassignedPerFrameConvertedAttributesSequence'],\n    '9172': ['SQ', '1', 'ConversionSourceAttributesSequence'],\n    '9213': ['LO', '1', 'DimensionIndexPrivateCreator'],\n    '9221': ['SQ', '1', 'DimensionOrganizationSequence'],\n    '9222': ['SQ', '1', 'DimensionIndexSequence'],\n    '9228': ['UL', '1', 'ConcatenationFrameOffsetNumber'],\n    '9238': ['LO', '1', 'FunctionalGroupPrivateCreator'],\n    '9241': ['FL', '1', 'NominalPercentageOfCardiacPhase'],\n    '9245': ['FL', '1', 'NominalPercentageOfRespiratoryPhase'],\n    '9246': ['FL', '1', 'StartingRespiratoryAmplitude'],\n    '9247': ['CS', '1', 'StartingRespiratoryPhase'],\n    '9248': ['FL', '1', 'EndingRespiratoryAmplitude'],\n    '9249': ['CS', '1', 'EndingRespiratoryPhase'],\n    '9250': ['CS', '1', 'RespiratoryTriggerType'],\n    '9251': ['FD', '1', 'RRIntervalTimeNominal'],\n    '9252': ['FD', '1', 'ActualCardiacTriggerDelayTime'],\n    '9253': ['SQ', '1', 'RespiratorySynchronizationSequence'],\n    '9254': ['FD', '1', 'RespiratoryIntervalTime'],\n    '9255': ['FD', '1', 'NominalRespiratoryTriggerDelayTime'],\n    '9256': ['FD', '1', 'RespiratoryTriggerDelayThreshold'],\n    '9257': ['FD', '1', 'ActualRespiratoryTriggerDelayTime'],\n    '9301': ['FD', '3', 'ImagePositionVolume'],\n    '9302': ['FD', '6', 'ImageOrientationVolume'],\n    '9307': ['CS', '1', 'UltrasoundAcquisitionGeometry'],\n    '9308': ['FD', '3', 'ApexPosition'],\n    '9309': ['FD', '16', 'VolumeToTransducerMappingMatrix'],\n    '930A': ['FD', '16', 'VolumeToTableMappingMatrix'],\n    '930B': ['CS', '1', 'VolumeToTransducerRelationship'],\n    '930C': ['CS', '1', 'PatientFrameOfReferenceSource'],\n    '930D': ['FD', '1', 'TemporalPositionTimeOffset'],\n    '930E': ['SQ', '1', 'PlanePositionVolumeSequence'],\n    '930F': ['SQ', '1', 'PlaneOrientationVolumeSequence'],\n    '9310': ['SQ', '1', 'TemporalPositionSequence'],\n    '9311': ['CS', '1', 'DimensionOrganizationType'],\n    '9312': ['UI', '1', 'VolumeFrameOfReferenceUID'],\n    '9313': ['UI', '1', 'TableFrameOfReferenceUID'],\n    '9421': ['LO', '1', 'DimensionDescriptionLabel'],\n    '9450': ['SQ', '1', 'PatientOrientationInFrameSequence'],\n    '9453': ['LO', '1', 'FrameLabel'],\n    '9518': ['US', '1-n', 'AcquisitionIndex'],\n    '9529': ['SQ', '1', 'ContributingSOPInstancesReferenceSequence'],\n    '9536': ['US', '1', 'ReconstructionIndex']\n  },\n  '0022': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['US', '1', 'LightPathFilterPassThroughWavelength'],\n    '0002': ['US', '2', 'LightPathFilterPassBand'],\n    '0003': ['US', '1', 'ImagePathFilterPassThroughWavelength'],\n    '0004': ['US', '2', 'ImagePathFilterPassBand'],\n    '0005': ['CS', '1', 'PatientEyeMovementCommanded'],\n    '0006': ['SQ', '1', 'PatientEyeMovementCommandCodeSequence'],\n    '0007': ['FL', '1', 'SphericalLensPower'],\n    '0008': ['FL', '1', 'CylinderLensPower'],\n    '0009': ['FL', '1', 'CylinderAxis'],\n    '000A': ['FL', '1', 'EmmetropicMagnification'],\n    '000B': ['FL', '1', 'IntraOcularPressure'],\n    '000C': ['FL', '1', 'HorizontalFieldOfView'],\n    '000D': ['CS', '1', 'PupilDilated'],\n    '000E': ['FL', '1', 'DegreeOfDilation'],\n    '0010': ['FL', '1', 'StereoBaselineAngle'],\n    '0011': ['FL', '1', 'StereoBaselineDisplacement'],\n    '0012': ['FL', '1', 'StereoHorizontalPixelOffset'],\n    '0013': ['FL', '1', 'StereoVerticalPixelOffset'],\n    '0014': ['FL', '1', 'StereoRotation'],\n    '0015': ['SQ', '1', 'AcquisitionDeviceTypeCodeSequence'],\n    '0016': ['SQ', '1', 'IlluminationTypeCodeSequence'],\n    '0017': ['SQ', '1', 'LightPathFilterTypeStackCodeSequence'],\n    '0018': ['SQ', '1', 'ImagePathFilterTypeStackCodeSequence'],\n    '0019': ['SQ', '1', 'LensesCodeSequence'],\n    '001A': ['SQ', '1', 'ChannelDescriptionCodeSequence'],\n    '001B': ['SQ', '1', 'RefractiveStateSequence'],\n    '001C': ['SQ', '1', 'MydriaticAgentCodeSequence'],\n    '001D': ['SQ', '1', 'RelativeImagePositionCodeSequence'],\n    '001E': ['FL', '1', 'CameraAngleOfView'],\n    '0020': ['SQ', '1', 'StereoPairsSequence'],\n    '0021': ['SQ', '1', 'LeftImageSequence'],\n    '0022': ['SQ', '1', 'RightImageSequence'],\n    '0028': ['CS', '1', 'StereoPairsPresent'],\n    '0030': ['FL', '1', 'AxialLengthOfTheEye'],\n    '0031': ['SQ', '1', 'OphthalmicFrameLocationSequence'],\n    '0032': ['FL', '2-2n', 'ReferenceCoordinates'],\n    '0035': ['FL', '1', 'DepthSpatialResolution'],\n    '0036': ['FL', '1', 'MaximumDepthDistortion'],\n    '0037': ['FL', '1', 'AlongScanSpatialResolution'],\n    '0038': ['FL', '1', 'MaximumAlongScanDistortion'],\n    '0039': ['CS', '1', 'OphthalmicImageOrientation'],\n    '0041': ['FL', '1', 'DepthOfTransverseImage'],\n    '0042': ['SQ', '1', 'MydriaticAgentConcentrationUnitsSequence'],\n    '0048': ['FL', '1', 'AcrossScanSpatialResolution'],\n    '0049': ['FL', '1', 'MaximumAcrossScanDistortion'],\n    '004E': ['DS', '1', 'MydriaticAgentConcentration'],\n    '0055': ['FL', '1', 'IlluminationWaveLength'],\n    '0056': ['FL', '1', 'IlluminationPower'],\n    '0057': ['FL', '1', 'IlluminationBandwidth'],\n    '0058': ['SQ', '1', 'MydriaticAgentSequence'],\n    '1007': ['SQ', '1', 'OphthalmicAxialMeasurementsRightEyeSequence'],\n    '1008': ['SQ', '1', 'OphthalmicAxialMeasurementsLeftEyeSequence'],\n    '1009': ['CS', '1', 'OphthalmicAxialMeasurementsDeviceType'],\n    '1010': ['CS', '1', 'OphthalmicAxialLengthMeasurementsType'],\n    '1012': ['SQ', '1', 'OphthalmicAxialLengthSequence'],\n    '1019': ['FL', '1', 'OphthalmicAxialLength'],\n    '1024': ['SQ', '1', 'LensStatusCodeSequence'],\n    '1025': ['SQ', '1', 'VitreousStatusCodeSequence'],\n    '1028': ['SQ', '1', 'IOLFormulaCodeSequence'],\n    '1029': ['LO', '1', 'IOLFormulaDetail'],\n    '1033': ['FL', '1', 'KeratometerIndex'],\n    '1035': ['SQ', '1', 'SourceOfOphthalmicAxialLengthCodeSequence'],\n    '1036': ['SQ', '1', 'SourceOfCornealSizeDataCodeSequence'],\n    '1037': ['FL', '1', 'TargetRefraction'],\n    '1039': ['CS', '1', 'RefractiveProcedureOccurred'],\n    '1040': ['SQ', '1', 'RefractiveSurgeryTypeCodeSequence'],\n    '1044': ['SQ', '1', 'OphthalmicUltrasoundMethodCodeSequence'],\n    '1045': ['SQ', '1', 'SurgicallyInducedAstigmatismSequence'],\n    '1046': ['CS', '1', 'TypeOfOpticalCorrection'],\n    '1047': ['SQ', '1', 'ToricIOLPowerSequence'],\n    '1048': ['SQ', '1', 'PredictedToricErrorSequence'],\n    '1049': ['CS', '1', 'PreSelectedForImplantation'],\n    '104A': ['SQ', '1', 'ToricIOLPowerForExactEmmetropiaSequence'],\n    '104B': ['SQ', '1', 'ToricIOLPowerForExactTargetRefractionSequence'],\n    '1050': ['SQ', '1', 'OphthalmicAxialLengthMeasurementsSequence'],\n    '1053': ['FL', '1', 'IOLPower'],\n    '1054': ['FL', '1', 'PredictedRefractiveError'],\n    '1059': ['FL', '1', 'OphthalmicAxialLengthVelocity'],\n    '1065': ['LO', '1', 'LensStatusDescription'],\n    '1066': ['LO', '1', 'VitreousStatusDescription'],\n    '1090': ['SQ', '1', 'IOLPowerSequence'],\n    '1092': ['SQ', '1', 'LensConstantSequence'],\n    '1093': ['LO', '1', 'IOLManufacturer'],\n    '1094': ['LO', '1', 'LensConstantDescription'],\n    '1095': ['LO', '1', 'ImplantName'],\n    '1096': ['SQ', '1', 'KeratometryMeasurementTypeCodeSequence'],\n    '1097': ['LO', '1', 'ImplantPartNumber'],\n    '1100': ['SQ', '1', 'ReferencedOphthalmicAxialMeasurementsSequence'],\n    '1101': ['SQ', '1', 'OphthalmicAxialLengthMeasurementsSegmentNameCodeSequence'],\n    '1103': ['SQ', '1', 'RefractiveErrorBeforeRefractiveSurgeryCodeSequence'],\n    '1121': ['FL', '1', 'IOLPowerForExactEmmetropia'],\n    '1122': ['FL', '1', 'IOLPowerForExactTargetRefraction'],\n    '1125': ['SQ', '1', 'AnteriorChamberDepthDefinitionCodeSequence'],\n    '1127': ['SQ', '1', 'LensThicknessSequence'],\n    '1128': ['SQ', '1', 'AnteriorChamberDepthSequence'],\n    '112A': ['SQ', '1', 'CalculationCommentSequence'],\n    '112B': ['CS', '1', 'CalculationCommentType'],\n    '112C': ['LT', '1', 'CalculationComment'],\n    '1130': ['FL', '1', 'LensThickness'],\n    '1131': ['FL', '1', 'AnteriorChamberDepth'],\n    '1132': ['SQ', '1', 'SourceOfLensThicknessDataCodeSequence'],\n    '1133': ['SQ', '1', 'SourceOfAnteriorChamberDepthDataCodeSequence'],\n    '1134': ['SQ', '1', 'SourceOfRefractiveMeasurementsSequence'],\n    '1135': ['SQ', '1', 'SourceOfRefractiveMeasurementsCodeSequence'],\n    '1140': ['CS', '1', 'OphthalmicAxialLengthMeasurementModified'],\n    '1150': ['SQ', '1', 'OphthalmicAxialLengthDataSourceCodeSequence'],\n    '1153': ['SQ', '1', 'OphthalmicAxialLengthAcquisitionMethodCodeSequence'],\n    '1155': ['FL', '1', 'SignalToNoiseRatio'],\n    '1159': ['LO', '1', 'OphthalmicAxialLengthDataSourceDescription'],\n    '1210': ['SQ', '1', 'OphthalmicAxialLengthMeasurementsTotalLengthSequence'],\n    '1211': ['SQ', '1', 'OphthalmicAxialLengthMeasurementsSegmentalLengthSequence'],\n    '1212': ['SQ', '1', 'OphthalmicAxialLengthMeasurementsLengthSummationSequence'],\n    '1220': ['SQ', '1', 'UltrasoundOphthalmicAxialLengthMeasurementsSequence'],\n    '1225': ['SQ', '1', 'OpticalOphthalmicAxialLengthMeasurementsSequence'],\n    '1230': ['SQ', '1', 'UltrasoundSelectedOphthalmicAxialLengthSequence'],\n    '1250': ['SQ', '1', 'OphthalmicAxialLengthSelectionMethodCodeSequence'],\n    '1255': ['SQ', '1', 'OpticalSelectedOphthalmicAxialLengthSequence'],\n    '1257': ['SQ', '1', 'SelectedSegmentalOphthalmicAxialLengthSequence'],\n    '1260': ['SQ', '1', 'SelectedTotalOphthalmicAxialLengthSequence'],\n    '1262': ['SQ', '1', 'OphthalmicAxialLengthQualityMetricSequence'],\n    '1265': ['SQ', '1', 'OphthalmicAxialLengthQualityMetricTypeCodeSequence'],\n    '1273': ['LO', '1', 'OphthalmicAxialLengthQualityMetricTypeDescription'],\n    '1300': ['SQ', '1', 'IntraocularLensCalculationsRightEyeSequence'],\n    '1310': ['SQ', '1', 'IntraocularLensCalculationsLeftEyeSequence'],\n    '1330': ['SQ', '1', 'ReferencedOphthalmicAxialLengthMeasurementQCImageSequence'],\n    '1415': ['CS', '1', 'OphthalmicMappingDeviceType'],\n    '1420': ['SQ', '1', 'AcquisitionMethodCodeSequence'],\n    '1423': ['SQ', '1', 'AcquisitionMethodAlgorithmSequence'],\n    '1436': ['SQ', '1', 'OphthalmicThicknessMapTypeCodeSequence'],\n    '1443': ['SQ', '1', 'OphthalmicThicknessMappingNormalsSequence'],\n    '1445': ['SQ', '1', 'RetinalThicknessDefinitionCodeSequence'],\n    '1450': ['SQ', '1', 'PixelValueMappingToCodedConceptSequence'],\n    '1452': ['xs', '1', 'MappedPixelValue'],\n    '1454': ['LO', '1', 'PixelValueMappingExplanation'],\n    '1458': ['SQ', '1', 'OphthalmicThicknessMapQualityThresholdSequence'],\n    '1460': ['FL', '1', 'OphthalmicThicknessMapThresholdQualityRating'],\n    '1463': ['FL', '2', 'AnatomicStructureReferencePoint'],\n    '1465': ['SQ', '1', 'RegistrationToLocalizerSequence'],\n    '1466': ['CS', '1', 'RegisteredLocalizerUnits'],\n    '1467': ['FL', '2', 'RegisteredLocalizerTopLeftHandCorner'],\n    '1468': ['FL', '2', 'RegisteredLocalizerBottomRightHandCorner'],\n    '1470': ['SQ', '1', 'OphthalmicThicknessMapQualityRatingSequence'],\n    '1472': ['SQ', '1', 'RelevantOPTAttributesSequence'],\n    '1512': ['SQ', '1', 'TransformationMethodCodeSequence'],\n    '1513': ['SQ', '1', 'TransformationAlgorithmSequence'],\n    '1515': ['CS', '1', 'OphthalmicAxialLengthMethod'],\n    '1517': ['FL', '1', 'OphthalmicFOV'],\n    '1518': ['SQ', '1', 'TwoDimensionalToThreeDimensionalMapSequence'],\n    '1525': ['SQ', '1', 'WideFieldOphthalmicPhotographyQualityRatingSequence'],\n    '1526': ['SQ', '1', 'WideFieldOphthalmicPhotographyQualityThresholdSequence'],\n    '1527': ['FL', '1', 'WideFieldOphthalmicPhotographyThresholdQualityRating'],\n    '1528': ['FL', '1', 'XCoordinatesCenterPixelViewAngle'],\n    '1529': ['FL', '1', 'YCoordinatesCenterPixelViewAngle'],\n    '1530': ['UL', '1', 'NumberOfMapPoints'],\n    '1531': ['OF', '1', 'TwoDimensionalToThreeDimensionalMapData'],\n    '1612': ['SQ', '1', 'DerivationAlgorithmSequence'],\n    '1615': ['SQ', '1', 'OphthalmicImageTypeCodeSequence'],\n    '1616': ['LO', '1', 'OphthalmicImageTypeDescription'],\n    '1618': ['SQ', '1', 'ScanPatternTypeCodeSequence'],\n    '1620': ['SQ', '1', 'ReferencedSurfaceMeshIdentificationSequence'],\n    '1622': ['CS', '1', 'OphthalmicVolumetricPropertiesFlag'],\n    '1624': ['FL', '1', 'OphthalmicAnatomicReferencePointXCoordinate'],\n    '1626': ['FL', '1', 'OphthalmicAnatomicReferencePointYCoordinate'],\n    '1628': ['SQ', '1', 'OphthalmicEnFaceImageQualityRatingSequence'],\n    '1630': ['DS', '1', 'QualityThreshold'],\n    '1640': ['SQ', '1', 'OCTBscanAnalysisAcquisitionParametersSequence'],\n    '1642': ['UL', '1', 'NumberOfBscansPerFrame'],\n    '1643': ['FL', '1', 'BscanSlabThickness'],\n    '1644': ['FL', '1', 'DistanceBetweenBscanSlabs'],\n    '1645': ['FL', '1', 'BscanCycleTime'],\n    '1646': ['FL', '1-n', 'BscanCycleTimeVector'],\n    '1649': ['FL', '1', 'AscanRate'],\n    '1650': ['FL', '1', 'BscanRate'],\n    '1658': ['UL', '1', 'SurfaceMeshZPixelOffset']\n  },\n  '0024': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['FL', '1', 'VisualFieldHorizontalExtent'],\n    '0011': ['FL', '1', 'VisualFieldVerticalExtent'],\n    '0012': ['CS', '1', 'VisualFieldShape'],\n    '0016': ['SQ', '1', 'ScreeningTestModeCodeSequence'],\n    '0018': ['FL', '1', 'MaximumStimulusLuminance'],\n    '0020': ['FL', '1', 'BackgroundLuminance'],\n    '0021': ['SQ', '1', 'StimulusColorCodeSequence'],\n    '0024': ['SQ', '1', 'BackgroundIlluminationColorCodeSequence'],\n    '0025': ['FL', '1', 'StimulusArea'],\n    '0028': ['FL', '1', 'StimulusPresentationTime'],\n    '0032': ['SQ', '1', 'FixationSequence'],\n    '0033': ['SQ', '1', 'FixationMonitoringCodeSequence'],\n    '0034': ['SQ', '1', 'VisualFieldCatchTrialSequence'],\n    '0035': ['US', '1', 'FixationCheckedQuantity'],\n    '0036': ['US', '1', 'PatientNotProperlyFixatedQuantity'],\n    '0037': ['CS', '1', 'PresentedVisualStimuliDataFlag'],\n    '0038': ['US', '1', 'NumberOfVisualStimuli'],\n    '0039': ['CS', '1', 'ExcessiveFixationLossesDataFlag'],\n    '0040': ['CS', '1', 'ExcessiveFixationLosses'],\n    '0042': ['US', '1', 'StimuliRetestingQuantity'],\n    '0044': ['LT', '1', 'CommentsOnPatientPerformanceOfVisualField'],\n    '0045': ['CS', '1', 'FalseNegativesEstimateFlag'],\n    '0046': ['FL', '1', 'FalseNegativesEstimate'],\n    '0048': ['US', '1', 'NegativeCatchTrialsQuantity'],\n    '0050': ['US', '1', 'FalseNegativesQuantity'],\n    '0051': ['CS', '1', 'ExcessiveFalseNegativesDataFlag'],\n    '0052': ['CS', '1', 'ExcessiveFalseNegatives'],\n    '0053': ['CS', '1', 'FalsePositivesEstimateFlag'],\n    '0054': ['FL', '1', 'FalsePositivesEstimate'],\n    '0055': ['CS', '1', 'CatchTrialsDataFlag'],\n    '0056': ['US', '1', 'PositiveCatchTrialsQuantity'],\n    '0057': ['CS', '1', 'TestPointNormalsDataFlag'],\n    '0058': ['SQ', '1', 'TestPointNormalsSequence'],\n    '0059': ['CS', '1', 'GlobalDeviationProbabilityNormalsFlag'],\n    '0060': ['US', '1', 'FalsePositivesQuantity'],\n    '0061': ['CS', '1', 'ExcessiveFalsePositivesDataFlag'],\n    '0062': ['CS', '1', 'ExcessiveFalsePositives'],\n    '0063': ['CS', '1', 'VisualFieldTestNormalsFlag'],\n    '0064': ['SQ', '1', 'ResultsNormalsSequence'],\n    '0065': ['SQ', '1', 'AgeCorrectedSensitivityDeviationAlgorithmSequence'],\n    '0066': ['FL', '1', 'GlobalDeviationFromNormal'],\n    '0067': ['SQ', '1', 'GeneralizedDefectSensitivityDeviationAlgorithmSequence'],\n    '0068': ['FL', '1', 'LocalizedDeviationFromNormal'],\n    '0069': ['LO', '1', 'PatientReliabilityIndicator'],\n    '0070': ['FL', '1', 'VisualFieldMeanSensitivity'],\n    '0071': ['FL', '1', 'GlobalDeviationProbability'],\n    '0072': ['CS', '1', 'LocalDeviationProbabilityNormalsFlag'],\n    '0073': ['FL', '1', 'LocalizedDeviationProbability'],\n    '0074': ['CS', '1', 'ShortTermFluctuationCalculated'],\n    '0075': ['FL', '1', 'ShortTermFluctuation'],\n    '0076': ['CS', '1', 'ShortTermFluctuationProbabilityCalculated'],\n    '0077': ['FL', '1', 'ShortTermFluctuationProbability'],\n    '0078': ['CS', '1', 'CorrectedLocalizedDeviationFromNormalCalculated'],\n    '0079': ['FL', '1', 'CorrectedLocalizedDeviationFromNormal'],\n    '0080': ['CS', '1', 'CorrectedLocalizedDeviationFromNormalProbabilityCalculated'],\n    '0081': ['FL', '1', 'CorrectedLocalizedDeviationFromNormalProbability'],\n    '0083': ['SQ', '1', 'GlobalDeviationProbabilitySequence'],\n    '0085': ['SQ', '1', 'LocalizedDeviationProbabilitySequence'],\n    '0086': ['CS', '1', 'FovealSensitivityMeasured'],\n    '0087': ['FL', '1', 'FovealSensitivity'],\n    '0088': ['FL', '1', 'VisualFieldTestDuration'],\n    '0089': ['SQ', '1', 'VisualFieldTestPointSequence'],\n    '0090': ['FL', '1', 'VisualFieldTestPointXCoordinate'],\n    '0091': ['FL', '1', 'VisualFieldTestPointYCoordinate'],\n    '0092': ['FL', '1', 'AgeCorrectedSensitivityDeviationValue'],\n    '0093': ['CS', '1', 'StimulusResults'],\n    '0094': ['FL', '1', 'SensitivityValue'],\n    '0095': ['CS', '1', 'RetestStimulusSeen'],\n    '0096': ['FL', '1', 'RetestSensitivityValue'],\n    '0097': ['SQ', '1', 'VisualFieldTestPointNormalsSequence'],\n    '0098': ['FL', '1', 'QuantifiedDefect'],\n    '0100': ['FL', '1', 'AgeCorrectedSensitivityDeviationProbabilityValue'],\n    '0102': ['CS', '1', 'GeneralizedDefectCorrectedSensitivityDeviationFlag'],\n    '0103': ['FL', '1', 'GeneralizedDefectCorrectedSensitivityDeviationValue'],\n    '0104': ['FL', '1', 'GeneralizedDefectCorrectedSensitivityDeviationProbabilityValue'],\n    '0105': ['FL', '1', 'MinimumSensitivityValue'],\n    '0106': ['CS', '1', 'BlindSpotLocalized'],\n    '0107': ['FL', '1', 'BlindSpotXCoordinate'],\n    '0108': ['FL', '1', 'BlindSpotYCoordinate'],\n    '0110': ['SQ', '1', 'VisualAcuityMeasurementSequence'],\n    '0112': ['SQ', '1', 'RefractiveParametersUsedOnPatientSequence'],\n    '0113': ['CS', '1', 'MeasurementLaterality'],\n    '0114': ['SQ', '1', 'OphthalmicPatientClinicalInformationLeftEyeSequence'],\n    '0115': ['SQ', '1', 'OphthalmicPatientClinicalInformationRightEyeSequence'],\n    '0117': ['CS', '1', 'FovealPointNormativeDataFlag'],\n    '0118': ['FL', '1', 'FovealPointProbabilityValue'],\n    '0120': ['CS', '1', 'ScreeningBaselineMeasured'],\n    '0122': ['SQ', '1', 'ScreeningBaselineMeasuredSequence'],\n    '0124': ['CS', '1', 'ScreeningBaselineType'],\n    '0126': ['FL', '1', 'ScreeningBaselineValue'],\n    '0202': ['LO', '1', 'AlgorithmSource'],\n    '0306': ['LO', '1', 'DataSetName'],\n    '0307': ['LO', '1', 'DataSetVersion'],\n    '0308': ['LO', '1', 'DataSetSource'],\n    '0309': ['LO', '1', 'DataSetDescription'],\n    '0317': ['SQ', '1', 'VisualFieldTestReliabilityGlobalIndexSequence'],\n    '0320': ['SQ', '1', 'VisualFieldGlobalResultsIndexSequence'],\n    '0325': ['SQ', '1', 'DataObservationSequence'],\n    '0338': ['CS', '1', 'IndexNormalsFlag'],\n    '0341': ['FL', '1', 'IndexProbability'],\n    '0344': ['SQ', '1', 'IndexProbabilitySequence']\n  },\n  '0028': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['US', '1', 'SamplesPerPixel'],\n    '0003': ['US', '1', 'SamplesPerPixelUsed'],\n    '0004': ['CS', '1', 'PhotometricInterpretation'],\n    '0005': ['US', '1', 'ImageDimensions'],\n    '0006': ['US', '1', 'PlanarConfiguration'],\n    '0008': ['IS', '1', 'NumberOfFrames'],\n    '0009': ['AT', '1-n', 'FrameIncrementPointer'],\n    '000A': ['AT', '1-n', 'FrameDimensionPointer'],\n    '0010': ['US', '1', 'Rows'],\n    '0011': ['US', '1', 'Columns'],\n    '0012': ['US', '1', 'Planes'],\n    '0014': ['US', '1', 'UltrasoundColorDataPresent'],\n    '0020': ['', '', ''],\n    '0030': ['DS', '2', 'PixelSpacing'],\n    '0031': ['DS', '2', 'ZoomFactor'],\n    '0032': ['DS', '2', 'ZoomCenter'],\n    '0034': ['IS', '2', 'PixelAspectRatio'],\n    '0040': ['CS', '1', 'ImageFormat'],\n    '0050': ['LO', '1-n', 'ManipulatedImage'],\n    '0051': ['CS', '1-n', 'CorrectedImage'],\n    '005F': ['LO', '1', 'CompressionRecognitionCode'],\n    '0060': ['CS', '1', 'CompressionCode'],\n    '0061': ['SH', '1', 'CompressionOriginator'],\n    '0062': ['LO', '1', 'CompressionLabel'],\n    '0063': ['SH', '1', 'CompressionDescription'],\n    '0065': ['CS', '1-n', 'CompressionSequence'],\n    '0066': ['AT', '1-n', 'CompressionStepPointers'],\n    '0068': ['US', '1', 'RepeatInterval'],\n    '0069': ['US', '1', 'BitsGrouped'],\n    '0070': ['US', '1-n', 'PerimeterTable'],\n    '0071': ['xs', '1', 'PerimeterValue'],\n    '0080': ['US', '1', 'PredictorRows'],\n    '0081': ['US', '1', 'PredictorColumns'],\n    '0082': ['US', '1-n', 'PredictorConstants'],\n    '0090': ['CS', '1', 'BlockedPixels'],\n    '0091': ['US', '1', 'BlockRows'],\n    '0092': ['US', '1', 'BlockColumns'],\n    '0093': ['US', '1', 'RowOverlap'],\n    '0094': ['US', '1', 'ColumnOverlap'],\n    '0100': ['US', '1', 'BitsAllocated'],\n    '0101': ['US', '1', 'BitsStored'],\n    '0102': ['US', '1', 'HighBit'],\n    '0103': ['US', '1', 'PixelRepresentation'],\n    '0104': ['xs', '1', 'SmallestValidPixelValue'],\n    '0105': ['xs', '1', 'LargestValidPixelValue'],\n    '0106': ['xs', '1', 'SmallestImagePixelValue'],\n    '0107': ['xs', '1', 'LargestImagePixelValue'],\n    '0108': ['xs', '1', 'SmallestPixelValueInSeries'],\n    '0109': ['xs', '1', 'LargestPixelValueInSeries'],\n    '0110': ['xs', '1', 'SmallestImagePixelValueInPlane'],\n    '0111': ['xs', '1', 'LargestImagePixelValueInPlane'],\n    '0120': ['xs', '1', 'PixelPaddingValue'],\n    '0121': ['xs', '1', 'PixelPaddingRangeLimit'],\n    '0122': ['FL', '1', 'FloatPixelPaddingValue'],\n    '0123': ['FD', '1', 'DoubleFloatPixelPaddingValue'],\n    '0124': ['FL', '1', 'FloatPixelPaddingRangeLimit'],\n    '0125': ['FD', '1', 'DoubleFloatPixelPaddingRangeLimit'],\n    '0200': ['US', '1', 'ImageLocation'],\n    '0300': ['CS', '1', 'QualityControlImage'],\n    '0301': ['CS', '1', 'BurnedInAnnotation'],\n    '0302': ['CS', '1', 'RecognizableVisualFeatures'],\n    '0303': ['CS', '1', 'LongitudinalTemporalInformationModified'],\n    '0304': ['UI', '1', 'ReferencedColorPaletteInstanceUID'],\n    '0400': ['LO', '1', 'TransformLabel'],\n    '0401': ['LO', '1', 'TransformVersionNumber'],\n    '0402': ['US', '1', 'NumberOfTransformSteps'],\n    '0403': ['LO', '1-n', 'SequenceOfCompressedData'],\n    '0404': ['AT', '1-n', 'DetailsOfCoefficients'],\n    '04x0': ['US', '1', 'RowsForNthOrderCoefficients'],\n    '04x1': ['US', '1', 'ColumnsForNthOrderCoefficients'],\n    '04x2': ['LO', '1-n', 'CoefficientCoding'],\n    '04x3': ['AT', '1-n', 'CoefficientCodingPointers'],\n    '0700': ['LO', '1', 'DCTLabel'],\n    '0701': ['CS', '1-n', 'DataBlockDescription'],\n    '0702': ['AT', '1-n', 'DataBlock'],\n    '0710': ['US', '1', 'NormalizationFactorFormat'],\n    '0720': ['US', '1', 'ZonalMapNumberFormat'],\n    '0721': ['AT', '1-n', 'ZonalMapLocation'],\n    '0722': ['US', '1', 'ZonalMapFormat'],\n    '0730': ['US', '1', 'AdaptiveMapFormat'],\n    '0740': ['US', '1', 'CodeNumberFormat'],\n    '08x0': ['CS', '1-n', 'CodeLabel'],\n    '08x2': ['US', '1', 'NumberOfTables'],\n    '08x3': ['AT', '1-n', 'CodeTableLocation'],\n    '08x4': ['US', '1', 'BitsForCodeWord'],\n    '08x8': ['AT', '1-n', 'ImageDataLocation'],\n    '0A02': ['CS', '1', 'PixelSpacingCalibrationType'],\n    '0A04': ['LO', '1', 'PixelSpacingCalibrationDescription'],\n    '1040': ['CS', '1', 'PixelIntensityRelationship'],\n    '1041': ['SS', '1', 'PixelIntensityRelationshipSign'],\n    '1050': ['DS', '1-n', 'WindowCenter'],\n    '1051': ['DS', '1-n', 'WindowWidth'],\n    '1052': ['DS', '1', 'RescaleIntercept'],\n    '1053': ['DS', '1', 'RescaleSlope'],\n    '1054': ['LO', '1', 'RescaleType'],\n    '1055': ['LO', '1-n', 'WindowCenterWidthExplanation'],\n    '1056': ['CS', '1', 'VOILUTFunction'],\n    '1080': ['CS', '1', 'GrayScale'],\n    '1090': ['CS', '1', 'RecommendedViewingMode'],\n    '1100': ['xs', '3', 'GrayLookupTableDescriptor'],\n    '1101': ['xs', '3', 'RedPaletteColorLookupTableDescriptor'],\n    '1102': ['xs', '3', 'GreenPaletteColorLookupTableDescriptor'],\n    '1103': ['xs', '3', 'BluePaletteColorLookupTableDescriptor'],\n    '1104': ['US', '3', 'AlphaPaletteColorLookupTableDescriptor'],\n    '1111': ['xs', '4', 'LargeRedPaletteColorLookupTableDescriptor'],\n    '1112': ['xs', '4', 'LargeGreenPaletteColorLookupTableDescriptor'],\n    '1113': ['xs', '4', 'LargeBluePaletteColorLookupTableDescriptor'],\n    '1199': ['UI', '1', 'PaletteColorLookupTableUID'],\n    '1200': ['xs', '1-n or 1', 'GrayLookupTableData'],\n    '1201': ['OW', '1', 'RedPaletteColorLookupTableData'],\n    '1202': ['OW', '1', 'GreenPaletteColorLookupTableData'],\n    '1203': ['OW', '1', 'BluePaletteColorLookupTableData'],\n    '1204': ['OW', '1', 'AlphaPaletteColorLookupTableData'],\n    '1211': ['OW', '1', 'LargeRedPaletteColorLookupTableData'],\n    '1212': ['OW', '1', 'LargeGreenPaletteColorLookupTableData'],\n    '1213': ['OW', '1', 'LargeBluePaletteColorLookupTableData'],\n    '1214': ['UI', '1', 'LargePaletteColorLookupTableUID'],\n    '1221': ['OW', '1', 'SegmentedRedPaletteColorLookupTableData'],\n    '1222': ['OW', '1', 'SegmentedGreenPaletteColorLookupTableData'],\n    '1223': ['OW', '1', 'SegmentedBluePaletteColorLookupTableData'],\n    '1224': ['OW', '1', 'SegmentedAlphaPaletteColorLookupTableData'],\n    '1230': ['SQ', '1', 'StoredValueColorRangeSequence'],\n    '1231': ['FD', '1', 'MinimumStoredValueMapped'],\n    '1232': ['FD', '1', 'MaximumStoredValueMapped'],\n    '1300': ['CS', '1', 'BreastImplantPresent'],\n    '1350': ['CS', '1', 'PartialView'],\n    '1351': ['ST', '1', 'PartialViewDescription'],\n    '1352': ['SQ', '1', 'PartialViewCodeSequence'],\n    '135A': ['CS', '1', 'SpatialLocationsPreserved'],\n    '1401': ['SQ', '1', 'DataFrameAssignmentSequence'],\n    '1402': ['CS', '1', 'DataPathAssignment'],\n    '1403': ['US', '1', 'BitsMappedToColorLookupTable'],\n    '1404': ['SQ', '1', 'BlendingLUT1Sequence'],\n    '1405': ['CS', '1', 'BlendingLUT1TransferFunction'],\n    '1406': ['FD', '1', 'BlendingWeightConstant'],\n    '1407': ['US', '3', 'BlendingLookupTableDescriptor'],\n    '1408': ['OW', '1', 'BlendingLookupTableData'],\n    '140B': ['SQ', '1', 'EnhancedPaletteColorLookupTableSequence'],\n    '140C': ['SQ', '1', 'BlendingLUT2Sequence'],\n    '140D': ['CS', '1', 'BlendingLUT2TransferFunction'],\n    '140E': ['CS', '1', 'DataPathID'],\n    '140F': ['CS', '1', 'RGBLUTTransferFunction'],\n    '1410': ['CS', '1', 'AlphaLUTTransferFunction'],\n    '2000': ['OB', '1', 'ICCProfile'],\n    '2002': ['CS', '1', 'ColorSpace'],\n    '2110': ['CS', '1', 'LossyImageCompression'],\n    '2112': ['DS', '1-n', 'LossyImageCompressionRatio'],\n    '2114': ['CS', '1-n', 'LossyImageCompressionMethod'],\n    '3000': ['SQ', '1', 'ModalityLUTSequence'],\n    '3002': ['xs', '3', 'LUTDescriptor'],\n    '3003': ['LO', '1', 'LUTExplanation'],\n    '3004': ['LO', '1', 'ModalityLUTType'],\n    '3006': ['xx', '1-n or 1', 'LUTData'],\n    '3010': ['SQ', '1', 'VOILUTSequence'],\n    '3110': ['SQ', '1', 'SoftcopyVOILUTSequence'],\n    '4000': ['LT', '1', 'ImagePresentationComments'],\n    '5000': ['SQ', '1', 'BiPlaneAcquisitionSequence'],\n    '6010': ['US', '1', 'RepresentativeFrameNumber'],\n    '6020': ['US', '1-n', 'FrameNumbersOfInterest'],\n    '6022': ['LO', '1-n', 'FrameOfInterestDescription'],\n    '6023': ['CS', '1-n', 'FrameOfInterestType'],\n    '6030': ['US', '1-n', 'MaskPointers'],\n    '6040': ['US', '1-n', 'RWavePointer'],\n    '6100': ['SQ', '1', 'MaskSubtractionSequence'],\n    '6101': ['CS', '1', 'MaskOperation'],\n    '6102': ['US', '2-2n', 'ApplicableFrameRange'],\n    '6110': ['US', '1-n', 'MaskFrameNumbers'],\n    '6112': ['US', '1', 'ContrastFrameAveraging'],\n    '6114': ['FL', '2', 'MaskSubPixelShift'],\n    '6120': ['SS', '1', 'TIDOffset'],\n    '6190': ['ST', '1', 'MaskOperationExplanation'],\n    '7000': ['SQ', '1', 'EquipmentAdministratorSequence'],\n    '7001': ['US', '1', 'NumberOfDisplaySubsystems'],\n    '7002': ['US', '1', 'CurrentConfigurationID'],\n    '7003': ['US', '1', 'DisplaySubsystemID'],\n    '7004': ['SH', '1', 'DisplaySubsystemName'],\n    '7005': ['LO', '1', 'DisplaySubsystemDescription'],\n    '7006': ['CS', '1', 'SystemStatus'],\n    '7007': ['LO', '1', 'SystemStatusComment'],\n    '7008': ['SQ', '1', 'TargetLuminanceCharacteristicsSequence'],\n    '7009': ['US', '1', 'LuminanceCharacteristicsID'],\n    '700A': ['SQ', '1', 'DisplaySubsystemConfigurationSequence'],\n    '700B': ['US', '1', 'ConfigurationID'],\n    '700C': ['SH', '1', 'ConfigurationName'],\n    '700D': ['LO', '1', 'ConfigurationDescription'],\n    '700E': ['US', '1', 'ReferencedTargetLuminanceCharacteristicsID'],\n    '700F': ['SQ', '1', 'QAResultsSequence'],\n    '7010': ['SQ', '1', 'DisplaySubsystemQAResultsSequence'],\n    '7011': ['SQ', '1', 'ConfigurationQAResultsSequence'],\n    '7012': ['SQ', '1', 'MeasurementEquipmentSequence'],\n    '7013': ['CS', '1-n', 'MeasurementFunctions'],\n    '7014': ['CS', '1', 'MeasurementEquipmentType'],\n    '7015': ['SQ', '1', 'VisualEvaluationResultSequence'],\n    '7016': ['SQ', '1', 'DisplayCalibrationResultSequence'],\n    '7017': ['US', '1', 'DDLValue'],\n    '7018': ['FL', '2', 'CIExyWhitePoint'],\n    '7019': ['CS', '1', 'DisplayFunctionType'],\n    '701A': ['FL', '1', 'GammaValue'],\n    '701B': ['US', '1', 'NumberOfLuminancePoints'],\n    '701C': ['SQ', '1', 'LuminanceResponseSequence'],\n    '701D': ['FL', '1', 'TargetMinimumLuminance'],\n    '701E': ['FL', '1', 'TargetMaximumLuminance'],\n    '701F': ['FL', '1', 'LuminanceValue'],\n    '7020': ['LO', '1', 'LuminanceResponseDescription'],\n    '7021': ['CS', '1', 'WhitePointFlag'],\n    '7022': ['SQ', '1', 'DisplayDeviceTypeCodeSequence'],\n    '7023': ['SQ', '1', 'DisplaySubsystemSequence'],\n    '7024': ['SQ', '1', 'LuminanceResultSequence'],\n    '7025': ['CS', '1', 'AmbientLightValueSource'],\n    '7026': ['CS', '1-n', 'MeasuredCharacteristics'],\n    '7027': ['SQ', '1', 'LuminanceUniformityResultSequence'],\n    '7028': ['SQ', '1', 'VisualEvaluationTestSequence'],\n    '7029': ['CS', '1', 'TestResult'],\n    '702A': ['LO', '1', 'TestResultComment'],\n    '702B': ['CS', '1', 'TestImageValidation'],\n    '702C': ['SQ', '1', 'TestPatternCodeSequence'],\n    '702D': ['SQ', '1', 'MeasurementPatternCodeSequence'],\n    '702E': ['SQ', '1', 'VisualEvaluationMethodCodeSequence'],\n    '7FE0': ['UR', '1', 'PixelDataProviderURL'],\n    '9001': ['UL', '1', 'DataPointRows'],\n    '9002': ['UL', '1', 'DataPointColumns'],\n    '9003': ['CS', '1', 'SignalDomainColumns'],\n    '9099': ['US', '1', 'LargestMonochromePixelValue'],\n    '9108': ['CS', '1', 'DataRepresentation'],\n    '9110': ['SQ', '1', 'PixelMeasuresSequence'],\n    '9132': ['SQ', '1', 'FrameVOILUTSequence'],\n    '9145': ['SQ', '1', 'PixelValueTransformationSequence'],\n    '9235': ['CS', '1', 'SignalDomainRows'],\n    '9411': ['FL', '1', 'DisplayFilterPercentage'],\n    '9415': ['SQ', '1', 'FramePixelShiftSequence'],\n    '9416': ['US', '1', 'SubtractionItemID'],\n    '9422': ['SQ', '1', 'PixelIntensityRelationshipLUTSequence'],\n    '9443': ['SQ', '1', 'FramePixelDataPropertiesSequence'],\n    '9444': ['CS', '1', 'GeometricalProperties'],\n    '9445': ['FL', '1', 'GeometricMaximumDistortion'],\n    '9446': ['CS', '1-n', 'ImageProcessingApplied'],\n    '9454': ['CS', '1', 'MaskSelectionMode'],\n    '9474': ['CS', '1', 'LUTFunction'],\n    '9478': ['FL', '1', 'MaskVisibilityPercentage'],\n    '9501': ['SQ', '1', 'PixelShiftSequence'],\n    '9502': ['SQ', '1', 'RegionPixelShiftSequence'],\n    '9503': ['SS', '2-2n', 'VerticesOfTheRegion'],\n    '9505': ['SQ', '1', 'MultiFramePresentationSequence'],\n    '9506': ['US', '2-2n', 'PixelShiftFrameRange'],\n    '9507': ['US', '2-2n', 'LUTFrameRange'],\n    '9520': ['DS', '16', 'ImageToEquipmentMappingMatrix'],\n    '9537': ['CS', '1', 'EquipmentCoordinateSystemIdentification']\n  },\n  '0032': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '000A': ['CS', '1', 'StudyStatusID'],\n    '000C': ['CS', '1', 'StudyPriorityID'],\n    '0012': ['LO', '1', 'StudyIDIssuer'],\n    '0032': ['DA', '1', 'StudyVerifiedDate'],\n    '0033': ['TM', '1', 'StudyVerifiedTime'],\n    '0034': ['DA', '1', 'StudyReadDate'],\n    '0035': ['TM', '1', 'StudyReadTime'],\n    '1000': ['DA', '1', 'ScheduledStudyStartDate'],\n    '1001': ['TM', '1', 'ScheduledStudyStartTime'],\n    '1010': ['DA', '1', 'ScheduledStudyStopDate'],\n    '1011': ['TM', '1', 'ScheduledStudyStopTime'],\n    '1020': ['LO', '1', 'ScheduledStudyLocation'],\n    '1021': ['AE', '1-n', 'ScheduledStudyLocationAETitle'],\n    '1030': ['LO', '1', 'ReasonForStudy'],\n    '1031': ['SQ', '1', 'RequestingPhysicianIdentificationSequence'],\n    '1032': ['PN', '1', 'RequestingPhysician'],\n    '1033': ['LO', '1', 'RequestingService'],\n    '1034': ['SQ', '1', 'RequestingServiceCodeSequence'],\n    '1040': ['DA', '1', 'StudyArrivalDate'],\n    '1041': ['TM', '1', 'StudyArrivalTime'],\n    '1050': ['DA', '1', 'StudyCompletionDate'],\n    '1051': ['TM', '1', 'StudyCompletionTime'],\n    '1055': ['CS', '1', 'StudyComponentStatusID'],\n    '1060': ['LO', '1', 'RequestedProcedureDescription'],\n    '1064': ['SQ', '1', 'RequestedProcedureCodeSequence'],\n    '1065': ['SQ', '1', 'RequestedLateralityCodeSequence'],\n    '1066': ['UT', '1', 'ReasonForVisit'],\n    '1067': ['SQ', '1', 'ReasonForVisitCodeSequence'],\n    '1070': ['LO', '1', 'RequestedContrastAgent'],\n    '4000': ['LT', '1', 'StudyComments']\n  },\n  '0034': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['SQ', '1', 'FlowIdentifierSequence'],\n    '0002': ['OB', '1', 'FlowIdentifier'],\n    '0003': ['UI', '1', 'FlowTransferSyntaxUID'],\n    '0004': ['UL', '1', 'FlowRTPSamplingRate'],\n    '0005': ['OB', '1', 'SourceIdentifier'],\n    '0007': ['OB', '1', 'FrameOriginTimestamp'],\n    '0008': ['CS', '1', 'IncludesImagingSubject'],\n    '0009': ['SQ', '1', 'FrameUsefulnessGroupSequence'],\n    '000A': ['SQ', '1', 'RealTimeBulkDataFlowSequence'],\n    '000B': ['SQ', '1', 'CameraPositionGroupSequence'],\n    '000C': ['CS', '1', 'IncludesInformation'],\n    '000D': ['SQ', '1', 'TimeOfFrameGroupSequence']\n  },\n  '0038': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0004': ['SQ', '1', 'ReferencedPatientAliasSequence'],\n    '0008': ['CS', '1', 'VisitStatusID'],\n    '0010': ['LO', '1', 'AdmissionID'],\n    '0011': ['LO', '1', 'IssuerOfAdmissionID'],\n    '0014': ['SQ', '1', 'IssuerOfAdmissionIDSequence'],\n    '0016': ['LO', '1', 'RouteOfAdmissions'],\n    '001A': ['DA', '1', 'ScheduledAdmissionDate'],\n    '001B': ['TM', '1', 'ScheduledAdmissionTime'],\n    '001C': ['DA', '1', 'ScheduledDischargeDate'],\n    '001D': ['TM', '1', 'ScheduledDischargeTime'],\n    '001E': ['LO', '1', 'ScheduledPatientInstitutionResidence'],\n    '0020': ['DA', '1', 'AdmittingDate'],\n    '0021': ['TM', '1', 'AdmittingTime'],\n    '0030': ['DA', '1', 'DischargeDate'],\n    '0032': ['TM', '1', 'DischargeTime'],\n    '0040': ['LO', '1', 'DischargeDiagnosisDescription'],\n    '0044': ['SQ', '1', 'DischargeDiagnosisCodeSequence'],\n    '0050': ['LO', '1', 'SpecialNeeds'],\n    '0060': ['LO', '1', 'ServiceEpisodeID'],\n    '0061': ['LO', '1', 'IssuerOfServiceEpisodeID'],\n    '0062': ['LO', '1', 'ServiceEpisodeDescription'],\n    '0064': ['SQ', '1', 'IssuerOfServiceEpisodeIDSequence'],\n    '0100': ['SQ', '1', 'PertinentDocumentsSequence'],\n    '0101': ['SQ', '1', 'PertinentResourcesSequence'],\n    '0102': ['LO', '1', 'ResourceDescription'],\n    '0300': ['LO', '1', 'CurrentPatientLocation'],\n    '0400': ['LO', '1', 'PatientInstitutionResidence'],\n    '0500': ['LO', '1', 'PatientState'],\n    '0502': ['SQ', '1', 'PatientClinicalTrialParticipationSequence'],\n    '4000': ['LT', '1', 'VisitComments']\n  },\n  '003A': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0004': ['CS', '1', 'WaveformOriginality'],\n    '0005': ['US', '1', 'NumberOfWaveformChannels'],\n    '0010': ['UL', '1', 'NumberOfWaveformSamples'],\n    '001A': ['DS', '1', 'SamplingFrequency'],\n    '0020': ['SH', '1', 'MultiplexGroupLabel'],\n    '0200': ['SQ', '1', 'ChannelDefinitionSequence'],\n    '0202': ['IS', '1', 'WaveformChannelNumber'],\n    '0203': ['SH', '1', 'ChannelLabel'],\n    '0205': ['CS', '1-n', 'ChannelStatus'],\n    '0208': ['SQ', '1', 'ChannelSourceSequence'],\n    '0209': ['SQ', '1', 'ChannelSourceModifiersSequence'],\n    '020A': ['SQ', '1', 'SourceWaveformSequence'],\n    '020C': ['LO', '1', 'ChannelDerivationDescription'],\n    '0210': ['DS', '1', 'ChannelSensitivity'],\n    '0211': ['SQ', '1', 'ChannelSensitivityUnitsSequence'],\n    '0212': ['DS', '1', 'ChannelSensitivityCorrectionFactor'],\n    '0213': ['DS', '1', 'ChannelBaseline'],\n    '0214': ['DS', '1', 'ChannelTimeSkew'],\n    '0215': ['DS', '1', 'ChannelSampleSkew'],\n    '0218': ['DS', '1', 'ChannelOffset'],\n    '021A': ['US', '1', 'WaveformBitsStored'],\n    '0220': ['DS', '1', 'FilterLowFrequency'],\n    '0221': ['DS', '1', 'FilterHighFrequency'],\n    '0222': ['DS', '1', 'NotchFilterFrequency'],\n    '0223': ['DS', '1', 'NotchFilterBandwidth'],\n    '0230': ['FL', '1', 'WaveformDataDisplayScale'],\n    '0231': ['US', '3', 'WaveformDisplayBackgroundCIELabValue'],\n    '0240': ['SQ', '1', 'WaveformPresentationGroupSequence'],\n    '0241': ['US', '1', 'PresentationGroupNumber'],\n    '0242': ['SQ', '1', 'ChannelDisplaySequence'],\n    '0244': ['US', '3', 'ChannelRecommendedDisplayCIELabValue'],\n    '0245': ['FL', '1', 'ChannelPosition'],\n    '0246': ['CS', '1', 'DisplayShadingFlag'],\n    '0247': ['FL', '1', 'FractionalChannelDisplayScale'],\n    '0248': ['FL', '1', 'AbsoluteChannelDisplayScale'],\n    '0300': ['SQ', '1', 'MultiplexedAudioChannelsDescriptionCodeSequence'],\n    '0301': ['IS', '1', 'ChannelIdentificationCode'],\n    '0302': ['CS', '1', 'ChannelMode'],\n    '0310': ['UI', '1', 'MultiplexGroupUID'],\n    '0311': ['DS', '1', 'PowerlineFrequency'],\n    '0312': ['SQ', '1', 'ChannelImpedanceSequence'],\n    '0313': ['DS', '1', 'ImpedanceValue'],\n    '0314': ['DT', '1', 'ImpedanceMeasurementDateTime'],\n    '0315': ['DS', '1', 'ImpedanceMeasurementFrequency'],\n    '0316': ['CS', '1', 'ImpedanceMeasurementCurrentType']\n  },\n  '0040': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['AE', '1-n', 'ScheduledStationAETitle'],\n    '0002': ['DA', '1', 'ScheduledProcedureStepStartDate'],\n    '0003': ['TM', '1', 'ScheduledProcedureStepStartTime'],\n    '0004': ['DA', '1', 'ScheduledProcedureStepEndDate'],\n    '0005': ['TM', '1', 'ScheduledProcedureStepEndTime'],\n    '0006': ['PN', '1', 'ScheduledPerformingPhysicianName'],\n    '0007': ['LO', '1', 'ScheduledProcedureStepDescription'],\n    '0008': ['SQ', '1', 'ScheduledProtocolCodeSequence'],\n    '0009': ['SH', '1', 'ScheduledProcedureStepID'],\n    '000A': ['SQ', '1', 'StageCodeSequence'],\n    '000B': ['SQ', '1', 'ScheduledPerformingPhysicianIdentificationSequence'],\n    '0010': ['SH', '1-n', 'ScheduledStationName'],\n    '0011': ['SH', '1', 'ScheduledProcedureStepLocation'],\n    '0012': ['LO', '1', 'PreMedication'],\n    '0020': ['CS', '1', 'ScheduledProcedureStepStatus'],\n    '0026': ['SQ', '1', 'OrderPlacerIdentifierSequence'],\n    '0027': ['SQ', '1', 'OrderFillerIdentifierSequence'],\n    '0031': ['UT', '1', 'LocalNamespaceEntityID'],\n    '0032': ['UT', '1', 'UniversalEntityID'],\n    '0033': ['CS', '1', 'UniversalEntityIDType'],\n    '0035': ['CS', '1', 'IdentifierTypeCode'],\n    '0036': ['SQ', '1', 'AssigningFacilitySequence'],\n    '0039': ['SQ', '1', 'AssigningJurisdictionCodeSequence'],\n    '003A': ['SQ', '1', 'AssigningAgencyOrDepartmentCodeSequence'],\n    '0100': ['SQ', '1', 'ScheduledProcedureStepSequence'],\n    '0220': ['SQ', '1', 'ReferencedNonImageCompositeSOPInstanceSequence'],\n    '0241': ['AE', '1', 'PerformedStationAETitle'],\n    '0242': ['SH', '1', 'PerformedStationName'],\n    '0243': ['SH', '1', 'PerformedLocation'],\n    '0244': ['DA', '1', 'PerformedProcedureStepStartDate'],\n    '0245': ['TM', '1', 'PerformedProcedureStepStartTime'],\n    '0250': ['DA', '1', 'PerformedProcedureStepEndDate'],\n    '0251': ['TM', '1', 'PerformedProcedureStepEndTime'],\n    '0252': ['CS', '1', 'PerformedProcedureStepStatus'],\n    '0253': ['SH', '1', 'PerformedProcedureStepID'],\n    '0254': ['LO', '1', 'PerformedProcedureStepDescription'],\n    '0255': ['LO', '1', 'PerformedProcedureTypeDescription'],\n    '0260': ['SQ', '1', 'PerformedProtocolCodeSequence'],\n    '0261': ['CS', '1', 'PerformedProtocolType'],\n    '0270': ['SQ', '1', 'ScheduledStepAttributesSequence'],\n    '0275': ['SQ', '1', 'RequestAttributesSequence'],\n    '0280': ['ST', '1', 'CommentsOnThePerformedProcedureStep'],\n    '0281': ['SQ', '1', 'PerformedProcedureStepDiscontinuationReasonCodeSequence'],\n    '0293': ['SQ', '1', 'QuantitySequence'],\n    '0294': ['DS', '1', 'Quantity'],\n    '0295': ['SQ', '1', 'MeasuringUnitsSequence'],\n    '0296': ['SQ', '1', 'BillingItemSequence'],\n    '0300': ['US', '1', 'TotalTimeOfFluoroscopy'],\n    '0301': ['US', '1', 'TotalNumberOfExposures'],\n    '0302': ['US', '1', 'EntranceDose'],\n    '0303': ['US', '1-2', 'ExposedArea'],\n    '0306': ['DS', '1', 'DistanceSourceToEntrance'],\n    '0307': ['DS', '1', 'DistanceSourceToSupport'],\n    '030E': ['SQ', '1', 'ExposureDoseSequence'],\n    '0310': ['ST', '1', 'CommentsOnRadiationDose'],\n    '0312': ['DS', '1', 'XRayOutput'],\n    '0314': ['DS', '1', 'HalfValueLayer'],\n    '0316': ['DS', '1', 'OrganDose'],\n    '0318': ['CS', '1', 'OrganExposed'],\n    '0320': ['SQ', '1', 'BillingProcedureStepSequence'],\n    '0321': ['SQ', '1', 'FilmConsumptionSequence'],\n    '0324': ['SQ', '1', 'BillingSuppliesAndDevicesSequence'],\n    '0330': ['SQ', '1', 'ReferencedProcedureStepSequence'],\n    '0340': ['SQ', '1', 'PerformedSeriesSequence'],\n    '0400': ['LT', '1', 'CommentsOnTheScheduledProcedureStep'],\n    '0440': ['SQ', '1', 'ProtocolContextSequence'],\n    '0441': ['SQ', '1', 'ContentItemModifierSequence'],\n    '0500': ['SQ', '1', 'ScheduledSpecimenSequence'],\n    '050A': ['LO', '1', 'SpecimenAccessionNumber'],\n    '0512': ['LO', '1', 'ContainerIdentifier'],\n    '0513': ['SQ', '1', 'IssuerOfTheContainerIdentifierSequence'],\n    '0515': ['SQ', '1', 'AlternateContainerIdentifierSequence'],\n    '0518': ['SQ', '1', 'ContainerTypeCodeSequence'],\n    '051A': ['LO', '1', 'ContainerDescription'],\n    '0520': ['SQ', '1', 'ContainerComponentSequence'],\n    '0550': ['SQ', '1', 'SpecimenSequence'],\n    '0551': ['LO', '1', 'SpecimenIdentifier'],\n    '0552': ['SQ', '1', 'SpecimenDescriptionSequenceTrial'],\n    '0553': ['ST', '1', 'SpecimenDescriptionTrial'],\n    '0554': ['UI', '1', 'SpecimenUID'],\n    '0555': ['SQ', '1', 'AcquisitionContextSequence'],\n    '0556': ['ST', '1', 'AcquisitionContextDescription'],\n    '0560': ['SQ', '1', 'SpecimenDescriptionSequence'],\n    '0562': ['SQ', '1', 'IssuerOfTheSpecimenIdentifierSequence'],\n    '059A': ['SQ', '1', 'SpecimenTypeCodeSequence'],\n    '0600': ['LO', '1', 'SpecimenShortDescription'],\n    '0602': ['UT', '1', 'SpecimenDetailedDescription'],\n    '0610': ['SQ', '1', 'SpecimenPreparationSequence'],\n    '0612': ['SQ', '1', 'SpecimenPreparationStepContentItemSequence'],\n    '0620': ['SQ', '1', 'SpecimenLocalizationContentItemSequence'],\n    '06FA': ['LO', '1', 'SlideIdentifier'],\n    '0710': ['SQ', '1', 'WholeSlideMicroscopyImageFrameTypeSequence'],\n    '071A': ['SQ', '1', 'ImageCenterPointCoordinatesSequence'],\n    '072A': ['DS', '1', 'XOffsetInSlideCoordinateSystem'],\n    '073A': ['DS', '1', 'YOffsetInSlideCoordinateSystem'],\n    '074A': ['DS', '1', 'ZOffsetInSlideCoordinateSystem'],\n    '08D8': ['SQ', '1', 'PixelSpacingSequence'],\n    '08DA': ['SQ', '1', 'CoordinateSystemAxisCodeSequence'],\n    '08EA': ['SQ', '1', 'MeasurementUnitsCodeSequence'],\n    '09F8': ['SQ', '1', 'VitalStainCodeSequenceTrial'],\n    '1001': ['SH', '1', 'RequestedProcedureID'],\n    '1002': ['LO', '1', 'ReasonForTheRequestedProcedure'],\n    '1003': ['SH', '1', 'RequestedProcedurePriority'],\n    '1004': ['LO', '1', 'PatientTransportArrangements'],\n    '1005': ['LO', '1', 'RequestedProcedureLocation'],\n    '1006': ['SH', '1', 'PlacerOrderNumberProcedure'],\n    '1007': ['SH', '1', 'FillerOrderNumberProcedure'],\n    '1008': ['LO', '1', 'ConfidentialityCode'],\n    '1009': ['SH', '1', 'ReportingPriority'],\n    '100A': ['SQ', '1', 'ReasonForRequestedProcedureCodeSequence'],\n    '1010': ['PN', '1-n', 'NamesOfIntendedRecipientsOfResults'],\n    '1011': ['SQ', '1', 'IntendedRecipientsOfResultsIdentificationSequence'],\n    '1012': ['SQ', '1', 'ReasonForPerformedProcedureCodeSequence'],\n    '1060': ['LO', '1', 'RequestedProcedureDescriptionTrial'],\n    '1101': ['SQ', '1', 'PersonIdentificationCodeSequence'],\n    '1102': ['ST', '1', 'PersonAddress'],\n    '1103': ['LO', '1-n', 'PersonTelephoneNumbers'],\n    '1104': ['LT', '1', 'PersonTelecomInformation'],\n    '1400': ['LT', '1', 'RequestedProcedureComments'],\n    '2001': ['LO', '1', 'ReasonForTheImagingServiceRequest'],\n    '2004': ['DA', '1', 'IssueDateOfImagingServiceRequest'],\n    '2005': ['TM', '1', 'IssueTimeOfImagingServiceRequest'],\n    '2006': ['SH', '1', 'PlacerOrderNumberImagingServiceRequestRetired'],\n    '2007': ['SH', '1', 'FillerOrderNumberImagingServiceRequestRetired'],\n    '2008': ['PN', '1', 'OrderEnteredBy'],\n    '2009': ['SH', '1', 'OrderEntererLocation'],\n    '2010': ['SH', '1', 'OrderCallbackPhoneNumber'],\n    '2011': ['LT', '1', 'OrderCallbackTelecomInformation'],\n    '2016': ['LO', '1', 'PlacerOrderNumberImagingServiceRequest'],\n    '2017': ['LO', '1', 'FillerOrderNumberImagingServiceRequest'],\n    '2400': ['LT', '1', 'ImagingServiceRequestComments'],\n    '3001': ['LO', '1', 'ConfidentialityConstraintOnPatientDataDescription'],\n    '4001': ['CS', '1', 'GeneralPurposeScheduledProcedureStepStatus'],\n    '4002': ['CS', '1', 'GeneralPurposePerformedProcedureStepStatus'],\n    '4003': ['CS', '1', 'GeneralPurposeScheduledProcedureStepPriority'],\n    '4004': ['SQ', '1', 'ScheduledProcessingApplicationsCodeSequence'],\n    '4005': ['DT', '1', 'ScheduledProcedureStepStartDateTime'],\n    '4006': ['CS', '1', 'MultipleCopiesFlag'],\n    '4007': ['SQ', '1', 'PerformedProcessingApplicationsCodeSequence'],\n    '4008': ['DT', '1', 'ScheduledProcedureStepExpirationDateTime'],\n    '4009': ['SQ', '1', 'HumanPerformerCodeSequence'],\n    '4010': ['DT', '1', 'ScheduledProcedureStepModificationDateTime'],\n    '4011': ['DT', '1', 'ExpectedCompletionDateTime'],\n    '4015': ['SQ', '1', 'ResultingGeneralPurposePerformedProcedureStepsSequence'],\n    '4016': ['SQ', '1', 'ReferencedGeneralPurposeScheduledProcedureStepSequence'],\n    '4018': ['SQ', '1', 'ScheduledWorkitemCodeSequence'],\n    '4019': ['SQ', '1', 'PerformedWorkitemCodeSequence'],\n    '4020': ['CS', '1', 'InputAvailabilityFlag'],\n    '4021': ['SQ', '1', 'InputInformationSequence'],\n    '4022': ['SQ', '1', 'RelevantInformationSequence'],\n    '4023': ['UI', '1', 'ReferencedGeneralPurposeScheduledProcedureStepTransactionUID'],\n    '4025': ['SQ', '1', 'ScheduledStationNameCodeSequence'],\n    '4026': ['SQ', '1', 'ScheduledStationClassCodeSequence'],\n    '4027': ['SQ', '1', 'ScheduledStationGeographicLocationCodeSequence'],\n    '4028': ['SQ', '1', 'PerformedStationNameCodeSequence'],\n    '4029': ['SQ', '1', 'PerformedStationClassCodeSequence'],\n    '4030': ['SQ', '1', 'PerformedStationGeographicLocationCodeSequence'],\n    '4031': ['SQ', '1', 'RequestedSubsequentWorkitemCodeSequence'],\n    '4032': ['SQ', '1', 'NonDICOMOutputCodeSequence'],\n    '4033': ['SQ', '1', 'OutputInformationSequence'],\n    '4034': ['SQ', '1', 'ScheduledHumanPerformersSequence'],\n    '4035': ['SQ', '1', 'ActualHumanPerformersSequence'],\n    '4036': ['LO', '1', 'HumanPerformerOrganization'],\n    '4037': ['PN', '1', 'HumanPerformerName'],\n    '4040': ['CS', '1', 'RawDataHandling'],\n    '4041': ['CS', '1', 'InputReadinessState'],\n    '4050': ['DT', '1', 'PerformedProcedureStepStartDateTime'],\n    '4051': ['DT', '1', 'PerformedProcedureStepEndDateTime'],\n    '4052': ['DT', '1', 'ProcedureStepCancellationDateTime'],\n    '4070': ['SQ', '1', 'OutputDestinationSequence'],\n    '4071': ['SQ', '1', 'DICOMStorageSequence'],\n    '4072': ['SQ', '1', 'STOWRSStorageSequence'],\n    '4073': ['UR', '1', 'StorageURL'],\n    '4074': ['SQ', '1', 'XDSStorageSequence'],\n    '8302': ['DS', '1', 'EntranceDoseInmGy'],\n    '8303': ['CS', '1', 'EntranceDoseDerivation'],\n    '9092': ['SQ', '1', 'ParametricMapFrameTypeSequence'],\n    '9094': ['SQ', '1', 'ReferencedImageRealWorldValueMappingSequence'],\n    '9096': ['SQ', '1', 'RealWorldValueMappingSequence'],\n    '9098': ['SQ', '1', 'PixelValueMappingCodeSequence'],\n    '9210': ['SH', '1', 'LUTLabel'],\n    '9211': ['xs', '1', 'RealWorldValueLastValueMapped'],\n    '9212': ['FD', '1-n', 'RealWorldValueLUTData'],\n    '9213': ['FD', '1', 'DoubleFloatRealWorldValueLastValueMapped'],\n    '9214': ['FD', '1', 'DoubleFloatRealWorldValueFirstValueMapped'],\n    '9216': ['xs', '1', 'RealWorldValueFirstValueMapped'],\n    '9220': ['SQ', '1', 'QuantityDefinitionSequence'],\n    '9224': ['FD', '1', 'RealWorldValueIntercept'],\n    '9225': ['FD', '1', 'RealWorldValueSlope'],\n    'A007': ['CS', '1', 'FindingsFlagTrial'],\n    'A010': ['CS', '1', 'RelationshipType'],\n    'A020': ['SQ', '1', 'FindingsSequenceTrial'],\n    'A021': ['UI', '1', 'FindingsGroupUIDTrial'],\n    'A022': ['UI', '1', 'ReferencedFindingsGroupUIDTrial'],\n    'A023': ['DA', '1', 'FindingsGroupRecordingDateTrial'],\n    'A024': ['TM', '1', 'FindingsGroupRecordingTimeTrial'],\n    'A026': ['SQ', '1', 'FindingsSourceCategoryCodeSequenceTrial'],\n    'A027': ['LO', '1', 'VerifyingOrganization'],\n    'A028': ['SQ', '1', 'DocumentingOrganizationIdentifierCodeSequenceTrial'],\n    'A030': ['DT', '1', 'VerificationDateTime'],\n    'A032': ['DT', '1', 'ObservationDateTime'],\n    'A033': ['DT', '1', 'ObservationStartDateTime'],\n    'A040': ['CS', '1', 'ValueType'],\n    'A043': ['SQ', '1', 'ConceptNameCodeSequence'],\n    'A047': ['LO', '1', 'MeasurementPrecisionDescriptionTrial'],\n    'A050': ['CS', '1', 'ContinuityOfContent'],\n    'A057': ['CS', '1-n', 'UrgencyOrPriorityAlertsTrial'],\n    'A060': ['LO', '1', 'SequencingIndicatorTrial'],\n    'A066': ['SQ', '1', 'DocumentIdentifierCodeSequenceTrial'],\n    'A067': ['PN', '1', 'DocumentAuthorTrial'],\n    'A068': ['SQ', '1', 'DocumentAuthorIdentifierCodeSequenceTrial'],\n    'A070': ['SQ', '1', 'IdentifierCodeSequenceTrial'],\n    'A073': ['SQ', '1', 'VerifyingObserverSequence'],\n    'A074': ['OB', '1', 'ObjectBinaryIdentifierTrial'],\n    'A075': ['PN', '1', 'VerifyingObserverName'],\n    'A076': ['SQ', '1', 'DocumentingObserverIdentifierCodeSequenceTrial'],\n    'A078': ['SQ', '1', 'AuthorObserverSequence'],\n    'A07A': ['SQ', '1', 'ParticipantSequence'],\n    'A07C': ['SQ', '1', 'CustodialOrganizationSequence'],\n    'A080': ['CS', '1', 'ParticipationType'],\n    'A082': ['DT', '1', 'ParticipationDateTime'],\n    'A084': ['CS', '1', 'ObserverType'],\n    'A085': ['SQ', '1', 'ProcedureIdentifierCodeSequenceTrial'],\n    'A088': ['SQ', '1', 'VerifyingObserverIdentificationCodeSequence'],\n    'A089': ['OB', '1', 'ObjectDirectoryBinaryIdentifierTrial'],\n    'A090': ['SQ', '1', 'EquivalentCDADocumentSequence'],\n    'A0B0': ['US', '2-2n', 'ReferencedWaveformChannels'],\n    'A110': ['DA', '1', 'DateOfDocumentOrVerbalTransactionTrial'],\n    'A112': ['TM', '1', 'TimeOfDocumentCreationOrVerbalTransactionTrial'],\n    'A120': ['DT', '1', 'DateTime'],\n    'A121': ['DA', '1', 'Date'],\n    'A122': ['TM', '1', 'Time'],\n    'A123': ['PN', '1', 'PersonName'],\n    'A124': ['UI', '1', 'UID'],\n    'A125': ['CS', '2', 'ReportStatusIDTrial'],\n    'A130': ['CS', '1', 'TemporalRangeType'],\n    'A132': ['UL', '1-n', 'ReferencedSamplePositions'],\n    'A136': ['US', '1-n', 'ReferencedFrameNumbers'],\n    'A138': ['DS', '1-n', 'ReferencedTimeOffsets'],\n    'A13A': ['DT', '1-n', 'ReferencedDateTime'],\n    'A160': ['UT', '1', 'TextValue'],\n    'A161': ['FD', '1-n', 'FloatingPointValue'],\n    'A162': ['SL', '1-n', 'RationalNumeratorValue'],\n    'A163': ['UL', '1-n', 'RationalDenominatorValue'],\n    'A167': ['SQ', '1', 'ObservationCategoryCodeSequenceTrial'],\n    'A168': ['SQ', '1', 'ConceptCodeSequence'],\n    'A16A': ['ST', '1', 'BibliographicCitationTrial'],\n    'A170': ['SQ', '1', 'PurposeOfReferenceCodeSequence'],\n    'A171': ['UI', '1', 'ObservationUID'],\n    'A172': ['UI', '1', 'ReferencedObservationUIDTrial'],\n    'A173': ['CS', '1', 'ReferencedObservationClassTrial'],\n    'A174': ['CS', '1', 'ReferencedObjectObservationClassTrial'],\n    'A180': ['US', '1', 'AnnotationGroupNumber'],\n    'A192': ['DA', '1', 'ObservationDateTrial'],\n    'A193': ['TM', '1', 'ObservationTimeTrial'],\n    'A194': ['CS', '1', 'MeasurementAutomationTrial'],\n    'A195': ['SQ', '1', 'ModifierCodeSequence'],\n    'A224': ['ST', '1', 'IdentificationDescriptionTrial'],\n    'A290': ['CS', '1', 'CoordinatesSetGeometricTypeTrial'],\n    'A296': ['SQ', '1', 'AlgorithmCodeSequenceTrial'],\n    'A297': ['ST', '1', 'AlgorithmDescriptionTrial'],\n    'A29A': ['SL', '2-2n', 'PixelCoordinatesSetTrial'],\n    'A300': ['SQ', '1', 'MeasuredValueSequence'],\n    'A301': ['SQ', '1', 'NumericValueQualifierCodeSequence'],\n    'A307': ['PN', '1', 'CurrentObserverTrial'],\n    'A30A': ['DS', '1-n', 'NumericValue'],\n    'A313': ['SQ', '1', 'ReferencedAccessionSequenceTrial'],\n    'A33A': ['ST', '1', 'ReportStatusCommentTrial'],\n    'A340': ['SQ', '1', 'ProcedureContextSequenceTrial'],\n    'A352': ['PN', '1', 'VerbalSourceTrial'],\n    'A353': ['ST', '1', 'AddressTrial'],\n    'A354': ['LO', '1', 'TelephoneNumberTrial'],\n    'A358': ['SQ', '1', 'VerbalSourceIdentifierCodeSequenceTrial'],\n    'A360': ['SQ', '1', 'PredecessorDocumentsSequence'],\n    'A370': ['SQ', '1', 'ReferencedRequestSequence'],\n    'A372': ['SQ', '1', 'PerformedProcedureCodeSequence'],\n    'A375': ['SQ', '1', 'CurrentRequestedProcedureEvidenceSequence'],\n    'A380': ['SQ', '1', 'ReportDetailSequenceTrial'],\n    'A385': ['SQ', '1', 'PertinentOtherEvidenceSequence'],\n    'A390': ['SQ', '1', 'HL7StructuredDocumentReferenceSequence'],\n    'A402': ['UI', '1', 'ObservationSubjectUIDTrial'],\n    'A403': ['CS', '1', 'ObservationSubjectClassTrial'],\n    'A404': ['SQ', '1', 'ObservationSubjectTypeCodeSequenceTrial'],\n    'A491': ['CS', '1', 'CompletionFlag'],\n    'A492': ['LO', '1', 'CompletionFlagDescription'],\n    'A493': ['CS', '1', 'VerificationFlag'],\n    'A494': ['CS', '1', 'ArchiveRequested'],\n    'A496': ['CS', '1', 'PreliminaryFlag'],\n    'A504': ['SQ', '1', 'ContentTemplateSequence'],\n    'A525': ['SQ', '1', 'IdenticalDocumentsSequence'],\n    'A600': ['CS', '1', 'ObservationSubjectContextFlagTrial'],\n    'A601': ['CS', '1', 'ObserverContextFlagTrial'],\n    'A603': ['CS', '1', 'ProcedureContextFlagTrial'],\n    'A730': ['SQ', '1', 'ContentSequence'],\n    'A731': ['SQ', '1', 'RelationshipSequenceTrial'],\n    'A732': ['SQ', '1', 'RelationshipTypeCodeSequenceTrial'],\n    'A744': ['SQ', '1', 'LanguageCodeSequenceTrial'],\n    'A801': ['SQ', '1', 'TabulatedValuesSequence'],\n    'A802': ['UL', '1', 'NumberOfTableRows'],\n    'A803': ['UL', '1', 'NumberOfTableColumns'],\n    'A804': ['UL', '1', 'TableRowNumber'],\n    'A805': ['UL', '1', 'TableColumnNumber'],\n    'A806': ['SQ', '1', 'TableRowDefinitionSequence'],\n    'A807': ['SQ', '1', 'TableColumnDefinitionSequence'],\n    'A808': ['SQ', '1', 'CellValuesSequence'],\n    'A992': ['ST', '1', 'UniformResourceLocatorTrial'],\n    'B020': ['SQ', '1', 'WaveformAnnotationSequence'],\n    'DB00': ['CS', '1', 'TemplateIdentifier'],\n    'DB06': ['DT', '1', 'TemplateVersion'],\n    'DB07': ['DT', '1', 'TemplateLocalVersion'],\n    'DB0B': ['CS', '1', 'TemplateExtensionFlag'],\n    'DB0C': ['UI', '1', 'TemplateExtensionOrganizationUID'],\n    'DB0D': ['UI', '1', 'TemplateExtensionCreatorUID'],\n    'DB73': ['UL', '1-n', 'ReferencedContentItemIdentifier'],\n    'E001': ['ST', '1', 'HL7InstanceIdentifier'],\n    'E004': ['DT', '1', 'HL7DocumentEffectiveTime'],\n    'E006': ['SQ', '1', 'HL7DocumentTypeCodeSequence'],\n    'E008': ['SQ', '1', 'DocumentClassCodeSequence'],\n    'E010': ['UR', '1', 'RetrieveURI'],\n    'E011': ['UI', '1', 'RetrieveLocationUID'],\n    'E020': ['CS', '1', 'TypeOfInstances'],\n    'E021': ['SQ', '1', 'DICOMRetrievalSequence'],\n    'E022': ['SQ', '1', 'DICOMMediaRetrievalSequence'],\n    'E023': ['SQ', '1', 'WADORetrievalSequence'],\n    'E024': ['SQ', '1', 'XDSRetrievalSequence'],\n    'E025': ['SQ', '1', 'WADORSRetrievalSequence'],\n    'E030': ['UI', '1', 'RepositoryUniqueID'],\n    'E031': ['UI', '1', 'HomeCommunityID']\n  },\n  '0042': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['ST', '1', 'DocumentTitle'],\n    '0011': ['OB', '1', 'EncapsulatedDocument'],\n    '0012': ['LO', '1', 'MIMETypeOfEncapsulatedDocument'],\n    '0013': ['SQ', '1', 'SourceInstanceSequence'],\n    '0014': ['LO', '1-n', 'ListOfMIMETypes'],\n    '0015': ['UL', '1', 'EncapsulatedDocumentLength']\n  },\n  '0044': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['ST', '1', 'ProductPackageIdentifier'],\n    '0002': ['CS', '1', 'SubstanceAdministrationApproval'],\n    '0003': ['LT', '1', 'ApprovalStatusFurtherDescription'],\n    '0004': ['DT', '1', 'ApprovalStatusDateTime'],\n    '0007': ['SQ', '1', 'ProductTypeCodeSequence'],\n    '0008': ['LO', '1-n', 'ProductName'],\n    '0009': ['LT', '1', 'ProductDescription'],\n    '000A': ['LO', '1', 'ProductLotIdentifier'],\n    '000B': ['DT', '1', 'ProductExpirationDateTime'],\n    '0010': ['DT', '1', 'SubstanceAdministrationDateTime'],\n    '0011': ['LO', '1', 'SubstanceAdministrationNotes'],\n    '0012': ['LO', '1', 'SubstanceAdministrationDeviceID'],\n    '0013': ['SQ', '1', 'ProductParameterSequence'],\n    '0019': ['SQ', '1', 'SubstanceAdministrationParameterSequence'],\n    '0100': ['SQ', '1', 'ApprovalSequence'],\n    '0101': ['SQ', '1', 'AssertionCodeSequence'],\n    '0102': ['UI', '1', 'AssertionUID'],\n    '0103': ['SQ', '1', 'AsserterIdentificationSequence'],\n    '0104': ['DT', '1', 'AssertionDateTime'],\n    '0105': ['DT', '1', 'AssertionExpirationDateTime'],\n    '0106': ['UT', '1', 'AssertionComments'],\n    '0107': ['SQ', '1', 'RelatedAssertionSequence'],\n    '0108': ['UI', '1', 'ReferencedAssertionUID'],\n    '0109': ['SQ', '1', 'ApprovalSubjectSequence'],\n    '010A': ['SQ', '1', 'OrganizationalRoleCodeSequence']\n  },\n  '0046': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0012': ['LO', '1', 'LensDescription'],\n    '0014': ['SQ', '1', 'RightLensSequence'],\n    '0015': ['SQ', '1', 'LeftLensSequence'],\n    '0016': ['SQ', '1', 'UnspecifiedLateralityLensSequence'],\n    '0018': ['SQ', '1', 'CylinderSequence'],\n    '0028': ['SQ', '1', 'PrismSequence'],\n    '0030': ['FD', '1', 'HorizontalPrismPower'],\n    '0032': ['CS', '1', 'HorizontalPrismBase'],\n    '0034': ['FD', '1', 'VerticalPrismPower'],\n    '0036': ['CS', '1', 'VerticalPrismBase'],\n    '0038': ['CS', '1', 'LensSegmentType'],\n    '0040': ['FD', '1', 'OpticalTransmittance'],\n    '0042': ['FD', '1', 'ChannelWidth'],\n    '0044': ['FD', '1', 'PupilSize'],\n    '0046': ['FD', '1', 'CornealSize'],\n    '0047': ['SQ', '1', 'CornealSizeSequence'],\n    '0050': ['SQ', '1', 'AutorefractionRightEyeSequence'],\n    '0052': ['SQ', '1', 'AutorefractionLeftEyeSequence'],\n    '0060': ['FD', '1', 'DistancePupillaryDistance'],\n    '0062': ['FD', '1', 'NearPupillaryDistance'],\n    '0063': ['FD', '1', 'IntermediatePupillaryDistance'],\n    '0064': ['FD', '1', 'OtherPupillaryDistance'],\n    '0070': ['SQ', '1', 'KeratometryRightEyeSequence'],\n    '0071': ['SQ', '1', 'KeratometryLeftEyeSequence'],\n    '0074': ['SQ', '1', 'SteepKeratometricAxisSequence'],\n    '0075': ['FD', '1', 'RadiusOfCurvature'],\n    '0076': ['FD', '1', 'KeratometricPower'],\n    '0077': ['FD', '1', 'KeratometricAxis'],\n    '0080': ['SQ', '1', 'FlatKeratometricAxisSequence'],\n    '0092': ['CS', '1', 'BackgroundColor'],\n    '0094': ['CS', '1', 'Optotype'],\n    '0095': ['CS', '1', 'OptotypePresentation'],\n    '0097': ['SQ', '1', 'SubjectiveRefractionRightEyeSequence'],\n    '0098': ['SQ', '1', 'SubjectiveRefractionLeftEyeSequence'],\n    '0100': ['SQ', '1', 'AddNearSequence'],\n    '0101': ['SQ', '1', 'AddIntermediateSequence'],\n    '0102': ['SQ', '1', 'AddOtherSequence'],\n    '0104': ['FD', '1', 'AddPower'],\n    '0106': ['FD', '1', 'ViewingDistance'],\n    '0110': ['SQ', '1', 'CorneaMeasurementsSequence'],\n    '0111': ['SQ', '1', 'SourceOfCorneaMeasurementDataCodeSequence'],\n    '0112': ['SQ', '1', 'SteepCornealAxisSequence'],\n    '0113': ['SQ', '1', 'FlatCornealAxisSequence'],\n    '0114': ['FD', '1', 'CornealPower'],\n    '0115': ['FD', '1', 'CornealAxis'],\n    '0116': ['SQ', '1', 'CorneaMeasurementMethodCodeSequence'],\n    '0117': ['FL', '1', 'RefractiveIndexOfCornea'],\n    '0118': ['FL', '1', 'RefractiveIndexOfAqueousHumor'],\n    '0121': ['SQ', '1', 'VisualAcuityTypeCodeSequence'],\n    '0122': ['SQ', '1', 'VisualAcuityRightEyeSequence'],\n    '0123': ['SQ', '1', 'VisualAcuityLeftEyeSequence'],\n    '0124': ['SQ', '1', 'VisualAcuityBothEyesOpenSequence'],\n    '0125': ['CS', '1', 'ViewingDistanceType'],\n    '0135': ['SS', '2', 'VisualAcuityModifiers'],\n    '0137': ['FD', '1', 'DecimalVisualAcuity'],\n    '0139': ['LO', '1', 'OptotypeDetailedDefinition'],\n    '0145': ['SQ', '1', 'ReferencedRefractiveMeasurementsSequence'],\n    '0146': ['FD', '1', 'SpherePower'],\n    '0147': ['FD', '1', 'CylinderPower'],\n    '0201': ['CS', '1', 'CornealTopographySurface'],\n    '0202': ['FL', '2', 'CornealVertexLocation'],\n    '0203': ['FL', '1', 'PupilCentroidXCoordinate'],\n    '0204': ['FL', '1', 'PupilCentroidYCoordinate'],\n    '0205': ['FL', '1', 'EquivalentPupilRadius'],\n    '0207': ['SQ', '1', 'CornealTopographyMapTypeCodeSequence'],\n    '0208': ['IS', '2-2n', 'VerticesOfTheOutlineOfPupil'],\n    '0210': ['SQ', '1', 'CornealTopographyMappingNormalsSequence'],\n    '0211': ['SQ', '1', 'MaximumCornealCurvatureSequence'],\n    '0212': ['FL', '1', 'MaximumCornealCurvature'],\n    '0213': ['FL', '2', 'MaximumCornealCurvatureLocation'],\n    '0215': ['SQ', '1', 'MinimumKeratometricSequence'],\n    '0218': ['SQ', '1', 'SimulatedKeratometricCylinderSequence'],\n    '0220': ['FL', '1', 'AverageCornealPower'],\n    '0224': ['FL', '1', 'CornealISValue'],\n    '0227': ['FL', '1', 'AnalyzedArea'],\n    '0230': ['FL', '1', 'SurfaceRegularityIndex'],\n    '0232': ['FL', '1', 'SurfaceAsymmetryIndex'],\n    '0234': ['FL', '1', 'CornealEccentricityIndex'],\n    '0236': ['FL', '1', 'KeratoconusPredictionIndex'],\n    '0238': ['FL', '1', 'DecimalPotentialVisualAcuity'],\n    '0242': ['CS', '1', 'CornealTopographyMapQualityEvaluation'],\n    '0244': ['SQ', '1', 'SourceImageCornealProcessedDataSequence'],\n    '0247': ['FL', '3', 'CornealPointLocation'],\n    '0248': ['CS', '1', 'CornealPointEstimated'],\n    '0249': ['FL', '1', 'AxialPower'],\n    '0250': ['FL', '1', 'TangentialPower'],\n    '0251': ['FL', '1', 'RefractivePower'],\n    '0252': ['FL', '1', 'RelativeElevation'],\n    '0253': ['FL', '1', 'CornealWavefront']\n  },\n  '0048': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['FL', '1', 'ImagedVolumeWidth'],\n    '0002': ['FL', '1', 'ImagedVolumeHeight'],\n    '0003': ['FL', '1', 'ImagedVolumeDepth'],\n    '0006': ['UL', '1', 'TotalPixelMatrixColumns'],\n    '0007': ['UL', '1', 'TotalPixelMatrixRows'],\n    '0008': ['SQ', '1', 'TotalPixelMatrixOriginSequence'],\n    '0010': ['CS', '1', 'SpecimenLabelInImage'],\n    '0011': ['CS', '1', 'FocusMethod'],\n    '0012': ['CS', '1', 'ExtendedDepthOfField'],\n    '0013': ['US', '1', 'NumberOfFocalPlanes'],\n    '0014': ['FL', '1', 'DistanceBetweenFocalPlanes'],\n    '0015': ['US', '3', 'RecommendedAbsentPixelCIELabValue'],\n    '0100': ['SQ', '1', 'IlluminatorTypeCodeSequence'],\n    '0102': ['DS', '6', 'ImageOrientationSlide'],\n    '0105': ['SQ', '1', 'OpticalPathSequence'],\n    '0106': ['SH', '1', 'OpticalPathIdentifier'],\n    '0107': ['ST', '1', 'OpticalPathDescription'],\n    '0108': ['SQ', '1', 'IlluminationColorCodeSequence'],\n    '0110': ['SQ', '1', 'SpecimenReferenceSequence'],\n    '0111': ['DS', '1', 'CondenserLensPower'],\n    '0112': ['DS', '1', 'ObjectiveLensPower'],\n    '0113': ['DS', '1', 'ObjectiveLensNumericalAperture'],\n    '0120': ['SQ', '1', 'PaletteColorLookupTableSequence'],\n    '0200': ['SQ', '1', 'ReferencedImageNavigationSequence'],\n    '0201': ['US', '2', 'TopLeftHandCornerOfLocalizerArea'],\n    '0202': ['US', '2', 'BottomRightHandCornerOfLocalizerArea'],\n    '0207': ['SQ', '1', 'OpticalPathIdentificationSequence'],\n    '021A': ['SQ', '1', 'PlanePositionSlideSequence'],\n    '021E': ['SL', '1', 'ColumnPositionInTotalImagePixelMatrix'],\n    '021F': ['SL', '1', 'RowPositionInTotalImagePixelMatrix'],\n    '0301': ['CS', '1', 'PixelOriginInterpretation'],\n    '0302': ['UL', '1', 'NumberOfOpticalPaths'],\n    '0303': ['UL', '1', 'TotalPixelMatrixFocalPlanes']\n  },\n  '0050': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0004': ['CS', '1', 'CalibrationImage'],\n    '0010': ['SQ', '1', 'DeviceSequence'],\n    '0012': ['SQ', '1', 'ContainerComponentTypeCodeSequence'],\n    '0013': ['FD', '1', 'ContainerComponentThickness'],\n    '0014': ['DS', '1', 'DeviceLength'],\n    '0015': ['FD', '1', 'ContainerComponentWidth'],\n    '0016': ['DS', '1', 'DeviceDiameter'],\n    '0017': ['CS', '1', 'DeviceDiameterUnits'],\n    '0018': ['DS', '1', 'DeviceVolume'],\n    '0019': ['DS', '1', 'InterMarkerDistance'],\n    '001A': ['CS', '1', 'ContainerComponentMaterial'],\n    '001B': ['LO', '1', 'ContainerComponentID'],\n    '001C': ['FD', '1', 'ContainerComponentLength'],\n    '001D': ['FD', '1', 'ContainerComponentDiameter'],\n    '001E': ['LO', '1', 'ContainerComponentDescription'],\n    '0020': ['LO', '1', 'DeviceDescription'],\n    '0021': ['ST', '1', 'LongDeviceDescription']\n  },\n  '0052': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['FL', '1', 'ContrastBolusIngredientPercentByVolume'],\n    '0002': ['FD', '1', 'OCTFocalDistance'],\n    '0003': ['FD', '1', 'BeamSpotSize'],\n    '0004': ['FD', '1', 'EffectiveRefractiveIndex'],\n    '0006': ['CS', '1', 'OCTAcquisitionDomain'],\n    '0007': ['FD', '1', 'OCTOpticalCenterWavelength'],\n    '0008': ['FD', '1', 'AxialResolution'],\n    '0009': ['FD', '1', 'RangingDepth'],\n    '0011': ['FD', '1', 'ALineRate'],\n    '0012': ['US', '1', 'ALinesPerFrame'],\n    '0013': ['FD', '1', 'CatheterRotationalRate'],\n    '0014': ['FD', '1', 'ALinePixelSpacing'],\n    '0016': ['SQ', '1', 'ModeOfPercutaneousAccessSequence'],\n    '0025': ['SQ', '1', 'IntravascularOCTFrameTypeSequence'],\n    '0026': ['CS', '1', 'OCTZOffsetApplied'],\n    '0027': ['SQ', '1', 'IntravascularFrameContentSequence'],\n    '0028': ['FD', '1', 'IntravascularLongitudinalDistance'],\n    '0029': ['SQ', '1', 'IntravascularOCTFrameContentSequence'],\n    '0030': ['SS', '1', 'OCTZOffsetCorrection'],\n    '0031': ['CS', '1', 'CatheterDirectionOfRotation'],\n    '0033': ['FD', '1', 'SeamLineLocation'],\n    '0034': ['FD', '1', 'FirstALineLocation'],\n    '0036': ['US', '1', 'SeamLineIndex'],\n    '0038': ['US', '1', 'NumberOfPaddedALines'],\n    '0039': ['CS', '1', 'InterpolationType'],\n    '003A': ['CS', '1', 'RefractiveIndexApplied']\n  },\n  '0054': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['US', '1-n', 'EnergyWindowVector'],\n    '0011': ['US', '1', 'NumberOfEnergyWindows'],\n    '0012': ['SQ', '1', 'EnergyWindowInformationSequence'],\n    '0013': ['SQ', '1', 'EnergyWindowRangeSequence'],\n    '0014': ['DS', '1', 'EnergyWindowLowerLimit'],\n    '0015': ['DS', '1', 'EnergyWindowUpperLimit'],\n    '0016': ['SQ', '1', 'RadiopharmaceuticalInformationSequence'],\n    '0017': ['IS', '1', 'ResidualSyringeCounts'],\n    '0018': ['SH', '1', 'EnergyWindowName'],\n    '0020': ['US', '1-n', 'DetectorVector'],\n    '0021': ['US', '1', 'NumberOfDetectors'],\n    '0022': ['SQ', '1', 'DetectorInformationSequence'],\n    '0030': ['US', '1-n', 'PhaseVector'],\n    '0031': ['US', '1', 'NumberOfPhases'],\n    '0032': ['SQ', '1', 'PhaseInformationSequence'],\n    '0033': ['US', '1', 'NumberOfFramesInPhase'],\n    '0036': ['IS', '1', 'PhaseDelay'],\n    '0038': ['IS', '1', 'PauseBetweenFrames'],\n    '0039': ['CS', '1', 'PhaseDescription'],\n    '0050': ['US', '1-n', 'RotationVector'],\n    '0051': ['US', '1', 'NumberOfRotations'],\n    '0052': ['SQ', '1', 'RotationInformationSequence'],\n    '0053': ['US', '1', 'NumberOfFramesInRotation'],\n    '0060': ['US', '1-n', 'RRIntervalVector'],\n    '0061': ['US', '1', 'NumberOfRRIntervals'],\n    '0062': ['SQ', '1', 'GatedInformationSequence'],\n    '0063': ['SQ', '1', 'DataInformationSequence'],\n    '0070': ['US', '1-n', 'TimeSlotVector'],\n    '0071': ['US', '1', 'NumberOfTimeSlots'],\n    '0072': ['SQ', '1', 'TimeSlotInformationSequence'],\n    '0073': ['DS', '1', 'TimeSlotTime'],\n    '0080': ['US', '1-n', 'SliceVector'],\n    '0081': ['US', '1', 'NumberOfSlices'],\n    '0090': ['US', '1-n', 'AngularViewVector'],\n    '0100': ['US', '1-n', 'TimeSliceVector'],\n    '0101': ['US', '1', 'NumberOfTimeSlices'],\n    '0200': ['DS', '1', 'StartAngle'],\n    '0202': ['CS', '1', 'TypeOfDetectorMotion'],\n    '0210': ['IS', '1-n', 'TriggerVector'],\n    '0211': ['US', '1', 'NumberOfTriggersInPhase'],\n    '0220': ['SQ', '1', 'ViewCodeSequence'],\n    '0222': ['SQ', '1', 'ViewModifierCodeSequence'],\n    '0300': ['SQ', '1', 'RadionuclideCodeSequence'],\n    '0302': ['SQ', '1', 'AdministrationRouteCodeSequence'],\n    '0304': ['SQ', '1', 'RadiopharmaceuticalCodeSequence'],\n    '0306': ['SQ', '1', 'CalibrationDataSequence'],\n    '0308': ['US', '1', 'EnergyWindowNumber'],\n    '0400': ['SH', '1', 'ImageID'],\n    '0410': ['SQ', '1', 'PatientOrientationCodeSequence'],\n    '0412': ['SQ', '1', 'PatientOrientationModifierCodeSequence'],\n    '0414': ['SQ', '1', 'PatientGantryRelationshipCodeSequence'],\n    '0500': ['CS', '1', 'SliceProgressionDirection'],\n    '0501': ['CS', '1', 'ScanProgressionDirection'],\n    '1000': ['CS', '2', 'SeriesType'],\n    '1001': ['CS', '1', 'Units'],\n    '1002': ['CS', '1', 'CountsSource'],\n    '1004': ['CS', '1', 'ReprojectionMethod'],\n    '1006': ['CS', '1', 'SUVType'],\n    '1100': ['CS', '1', 'RandomsCorrectionMethod'],\n    '1101': ['LO', '1', 'AttenuationCorrectionMethod'],\n    '1102': ['CS', '1', 'DecayCorrection'],\n    '1103': ['LO', '1', 'ReconstructionMethod'],\n    '1104': ['LO', '1', 'DetectorLinesOfResponseUsed'],\n    '1105': ['LO', '1', 'ScatterCorrectionMethod'],\n    '1200': ['DS', '1', 'AxialAcceptance'],\n    '1201': ['IS', '2', 'AxialMash'],\n    '1202': ['IS', '1', 'TransverseMash'],\n    '1203': ['DS', '2', 'DetectorElementSize'],\n    '1210': ['DS', '1', 'CoincidenceWindowWidth'],\n    '1220': ['CS', '1-n', 'SecondaryCountsType'],\n    '1300': ['DS', '1', 'FrameReferenceTime'],\n    '1310': ['IS', '1', 'PrimaryPromptsCountsAccumulated'],\n    '1311': ['IS', '1-n', 'SecondaryCountsAccumulated'],\n    '1320': ['DS', '1', 'SliceSensitivityFactor'],\n    '1321': ['DS', '1', 'DecayFactor'],\n    '1322': ['DS', '1', 'DoseCalibrationFactor'],\n    '1323': ['DS', '1', 'ScatterFractionFactor'],\n    '1324': ['DS', '1', 'DeadTimeFactor'],\n    '1330': ['US', '1', 'ImageIndex'],\n    '1400': ['CS', '1-n', 'CountsIncluded'],\n    '1401': ['CS', '1', 'DeadTimeCorrectionFlag']\n  },\n  '0060': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '3000': ['SQ', '1', 'HistogramSequence'],\n    '3002': ['US', '1', 'HistogramNumberOfBins'],\n    '3004': ['xs', '1', 'HistogramFirstBinValue'],\n    '3006': ['xs', '1', 'HistogramLastBinValue'],\n    '3008': ['US', '1', 'HistogramBinWidth'],\n    '3010': ['LO', '1', 'HistogramExplanation'],\n    '3020': ['UL', '1-n', 'HistogramData']\n  },\n  '0062': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'SegmentationType'],\n    '0002': ['SQ', '1', 'SegmentSequence'],\n    '0003': ['SQ', '1', 'SegmentedPropertyCategoryCodeSequence'],\n    '0004': ['US', '1', 'SegmentNumber'],\n    '0005': ['LO', '1', 'SegmentLabel'],\n    '0006': ['ST', '1', 'SegmentDescription'],\n    '0007': ['SQ', '1', 'SegmentationAlgorithmIdentificationSequence'],\n    '0008': ['CS', '1', 'SegmentAlgorithmType'],\n    '0009': ['LO', '1-n', 'SegmentAlgorithmName'],\n    '000A': ['SQ', '1', 'SegmentIdentificationSequence'],\n    '000B': ['US', '1-n', 'ReferencedSegmentNumber'],\n    '000C': ['US', '1', 'RecommendedDisplayGrayscaleValue'],\n    '000D': ['US', '3', 'RecommendedDisplayCIELabValue'],\n    '000E': ['US', '1', 'MaximumFractionalValue'],\n    '000F': ['SQ', '1', 'SegmentedPropertyTypeCodeSequence'],\n    '0010': ['CS', '1', 'SegmentationFractionalType'],\n    '0011': ['SQ', '1', 'SegmentedPropertyTypeModifierCodeSequence'],\n    '0012': ['SQ', '1', 'UsedSegmentsSequence'],\n    '0013': ['CS', '1', 'SegmentsOverlap'],\n    '0020': ['UT', '1', 'TrackingID'],\n    '0021': ['UI', '1', 'TrackingUID']\n  },\n  '0064': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SQ', '1', 'DeformableRegistrationSequence'],\n    '0003': ['UI', '1', 'SourceFrameOfReferenceUID'],\n    '0005': ['SQ', '1', 'DeformableRegistrationGridSequence'],\n    '0007': ['UL', '3', 'GridDimensions'],\n    '0008': ['FD', '3', 'GridResolution'],\n    '0009': ['OF', '1', 'VectorGridData'],\n    '000F': ['SQ', '1', 'PreDeformationMatrixRegistrationSequence'],\n    '0010': ['SQ', '1', 'PostDeformationMatrixRegistrationSequence']\n  },\n  '0066': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['UL', '1', 'NumberOfSurfaces'],\n    '0002': ['SQ', '1', 'SurfaceSequence'],\n    '0003': ['UL', '1', 'SurfaceNumber'],\n    '0004': ['LT', '1', 'SurfaceComments'],\n    '0009': ['CS', '1', 'SurfaceProcessing'],\n    '000A': ['FL', '1', 'SurfaceProcessingRatio'],\n    '000B': ['LO', '1', 'SurfaceProcessingDescription'],\n    '000C': ['FL', '1', 'RecommendedPresentationOpacity'],\n    '000D': ['CS', '1', 'RecommendedPresentationType'],\n    '000E': ['CS', '1', 'FiniteVolume'],\n    '0010': ['CS', '1', 'Manifold'],\n    '0011': ['SQ', '1', 'SurfacePointsSequence'],\n    '0012': ['SQ', '1', 'SurfacePointsNormalsSequence'],\n    '0013': ['SQ', '1', 'SurfaceMeshPrimitivesSequence'],\n    '0015': ['UL', '1', 'NumberOfSurfacePoints'],\n    '0016': ['OF', '1', 'PointCoordinatesData'],\n    '0017': ['FL', '3', 'PointPositionAccuracy'],\n    '0018': ['FL', '1', 'MeanPointDistance'],\n    '0019': ['FL', '1', 'MaximumPointDistance'],\n    '001A': ['FL', '6', 'PointsBoundingBoxCoordinates'],\n    '001B': ['FL', '3', 'AxisOfRotation'],\n    '001C': ['FL', '3', 'CenterOfRotation'],\n    '001E': ['UL', '1', 'NumberOfVectors'],\n    '001F': ['US', '1', 'VectorDimensionality'],\n    '0020': ['FL', '1-n', 'VectorAccuracy'],\n    '0021': ['OF', '1', 'VectorCoordinateData'],\n    '0022': ['OD', '1', 'DoublePointCoordinatesData'],\n    '0023': ['OW', '1', 'TrianglePointIndexList'],\n    '0024': ['OW', '1', 'EdgePointIndexList'],\n    '0025': ['OW', '1', 'VertexPointIndexList'],\n    '0026': ['SQ', '1', 'TriangleStripSequence'],\n    '0027': ['SQ', '1', 'TriangleFanSequence'],\n    '0028': ['SQ', '1', 'LineSequence'],\n    '0029': ['OW', '1', 'PrimitivePointIndexList'],\n    '002A': ['UL', '1', 'SurfaceCount'],\n    '002B': ['SQ', '1', 'ReferencedSurfaceSequence'],\n    '002C': ['UL', '1', 'ReferencedSurfaceNumber'],\n    '002D': ['SQ', '1', 'SegmentSurfaceGenerationAlgorithmIdentificationSequence'],\n    '002E': ['SQ', '1', 'SegmentSurfaceSourceInstanceSequence'],\n    '002F': ['SQ', '1', 'AlgorithmFamilyCodeSequence'],\n    '0030': ['SQ', '1', 'AlgorithmNameCodeSequence'],\n    '0031': ['LO', '1', 'AlgorithmVersion'],\n    '0032': ['LT', '1', 'AlgorithmParameters'],\n    '0034': ['SQ', '1', 'FacetSequence'],\n    '0035': ['SQ', '1', 'SurfaceProcessingAlgorithmIdentificationSequence'],\n    '0036': ['LO', '1', 'AlgorithmName'],\n    '0037': ['FL', '1', 'RecommendedPointRadius'],\n    '0038': ['FL', '1', 'RecommendedLineThickness'],\n    '0040': ['OL', '1', 'LongPrimitivePointIndexList'],\n    '0041': ['OL', '1', 'LongTrianglePointIndexList'],\n    '0042': ['OL', '1', 'LongEdgePointIndexList'],\n    '0043': ['OL', '1', 'LongVertexPointIndexList'],\n    '0101': ['SQ', '1', 'TrackSetSequence'],\n    '0102': ['SQ', '1', 'TrackSequence'],\n    '0103': ['OW', '1', 'RecommendedDisplayCIELabValueList'],\n    '0104': ['SQ', '1', 'TrackingAlgorithmIdentificationSequence'],\n    '0105': ['UL', '1', 'TrackSetNumber'],\n    '0106': ['LO', '1', 'TrackSetLabel'],\n    '0107': ['UT', '1', 'TrackSetDescription'],\n    '0108': ['SQ', '1', 'TrackSetAnatomicalTypeCodeSequence'],\n    '0121': ['SQ', '1', 'MeasurementsSequence'],\n    '0124': ['SQ', '1', 'TrackSetStatisticsSequence'],\n    '0125': ['OF', '1', 'FloatingPointValues'],\n    '0129': ['OL', '1', 'TrackPointIndexList'],\n    '0130': ['SQ', '1', 'TrackStatisticsSequence'],\n    '0132': ['SQ', '1', 'MeasurementValuesSequence'],\n    '0133': ['SQ', '1', 'DiffusionAcquisitionCodeSequence'],\n    '0134': ['SQ', '1', 'DiffusionModelCodeSequence']\n  },\n  '0068': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '6210': ['LO', '1', 'ImplantSize'],\n    '6221': ['LO', '1', 'ImplantTemplateVersion'],\n    '6222': ['SQ', '1', 'ReplacedImplantTemplateSequence'],\n    '6223': ['CS', '1', 'ImplantType'],\n    '6224': ['SQ', '1', 'DerivationImplantTemplateSequence'],\n    '6225': ['SQ', '1', 'OriginalImplantTemplateSequence'],\n    '6226': ['DT', '1', 'EffectiveDateTime'],\n    '6230': ['SQ', '1', 'ImplantTargetAnatomySequence'],\n    '6260': ['SQ', '1', 'InformationFromManufacturerSequence'],\n    '6265': ['SQ', '1', 'NotificationFromManufacturerSequence'],\n    '6270': ['DT', '1', 'InformationIssueDateTime'],\n    '6280': ['ST', '1', 'InformationSummary'],\n    '62A0': ['SQ', '1', 'ImplantRegulatoryDisapprovalCodeSequence'],\n    '62A5': ['FD', '1', 'OverallTemplateSpatialTolerance'],\n    '62C0': ['SQ', '1', 'HPGLDocumentSequence'],\n    '62D0': ['US', '1', 'HPGLDocumentID'],\n    '62D5': ['LO', '1', 'HPGLDocumentLabel'],\n    '62E0': ['SQ', '1', 'ViewOrientationCodeSequence'],\n    '62F0': ['SQ', '1', 'ViewOrientationModifierCodeSequence'],\n    '62F2': ['FD', '1', 'HPGLDocumentScaling'],\n    '6300': ['OB', '1', 'HPGLDocument'],\n    '6310': ['US', '1', 'HPGLContourPenNumber'],\n    '6320': ['SQ', '1', 'HPGLPenSequence'],\n    '6330': ['US', '1', 'HPGLPenNumber'],\n    '6340': ['LO', '1', 'HPGLPenLabel'],\n    '6345': ['ST', '1', 'HPGLPenDescription'],\n    '6346': ['FD', '2', 'RecommendedRotationPoint'],\n    '6347': ['FD', '4', 'BoundingRectangle'],\n    '6350': ['US', '1-n', 'ImplantTemplate3DModelSurfaceNumber'],\n    '6360': ['SQ', '1', 'SurfaceModelDescriptionSequence'],\n    '6380': ['LO', '1', 'SurfaceModelLabel'],\n    '6390': ['FD', '1', 'SurfaceModelScalingFactor'],\n    '63A0': ['SQ', '1', 'MaterialsCodeSequence'],\n    '63A4': ['SQ', '1', 'CoatingMaterialsCodeSequence'],\n    '63A8': ['SQ', '1', 'ImplantTypeCodeSequence'],\n    '63AC': ['SQ', '1', 'FixationMethodCodeSequence'],\n    '63B0': ['SQ', '1', 'MatingFeatureSetsSequence'],\n    '63C0': ['US', '1', 'MatingFeatureSetID'],\n    '63D0': ['LO', '1', 'MatingFeatureSetLabel'],\n    '63E0': ['SQ', '1', 'MatingFeatureSequence'],\n    '63F0': ['US', '1', 'MatingFeatureID'],\n    '6400': ['SQ', '1', 'MatingFeatureDegreeOfFreedomSequence'],\n    '6410': ['US', '1', 'DegreeOfFreedomID'],\n    '6420': ['CS', '1', 'DegreeOfFreedomType'],\n    '6430': ['SQ', '1', 'TwoDMatingFeatureCoordinatesSequence'],\n    '6440': ['US', '1', 'ReferencedHPGLDocumentID'],\n    '6450': ['FD', '2', 'TwoDMatingPoint'],\n    '6460': ['FD', '4', 'TwoDMatingAxes'],\n    '6470': ['SQ', '1', 'TwoDDegreeOfFreedomSequence'],\n    '6490': ['FD', '3', 'ThreeDDegreeOfFreedomAxis'],\n    '64A0': ['FD', '2', 'RangeOfFreedom'],\n    '64C0': ['FD', '3', 'ThreeDMatingPoint'],\n    '64D0': ['FD', '9', 'ThreeDMatingAxes'],\n    '64F0': ['FD', '3', 'TwoDDegreeOfFreedomAxis'],\n    '6500': ['SQ', '1', 'PlanningLandmarkPointSequence'],\n    '6510': ['SQ', '1', 'PlanningLandmarkLineSequence'],\n    '6520': ['SQ', '1', 'PlanningLandmarkPlaneSequence'],\n    '6530': ['US', '1', 'PlanningLandmarkID'],\n    '6540': ['LO', '1', 'PlanningLandmarkDescription'],\n    '6545': ['SQ', '1', 'PlanningLandmarkIdentificationCodeSequence'],\n    '6550': ['SQ', '1', 'TwoDPointCoordinatesSequence'],\n    '6560': ['FD', '2', 'TwoDPointCoordinates'],\n    '6590': ['FD', '3', 'ThreeDPointCoordinates'],\n    '65A0': ['SQ', '1', 'TwoDLineCoordinatesSequence'],\n    '65B0': ['FD', '4', 'TwoDLineCoordinates'],\n    '65D0': ['FD', '6', 'ThreeDLineCoordinates'],\n    '65E0': ['SQ', '1', 'TwoDPlaneCoordinatesSequence'],\n    '65F0': ['FD', '4', 'TwoDPlaneIntersection'],\n    '6610': ['FD', '3', 'ThreeDPlaneOrigin'],\n    '6620': ['FD', '3', 'ThreeDPlaneNormal'],\n    '7001': ['CS', '1', 'ModelModification'],\n    '7002': ['CS', '1', 'ModelMirroring'],\n    '7003': ['SQ', '1', 'ModelUsageCodeSequence'],\n    '7004': ['UI', '1', 'ModelGroupUID'],\n    '7005': ['UR', '1', 'RelativeURIReferenceWithinEncapsulatedDocument']\n  },\n  '006A': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'AnnotationCoordinateType'],\n    '0002': ['SQ', '1', 'AnnotationGroupSequence'],\n    '0003': ['UI', '1', 'AnnotationGroupUID'],\n    '0005': ['LO', '1', 'AnnotationGroupLabel'],\n    '0006': ['UT', '1', 'AnnotationGroupDescription'],\n    '0007': ['CS', '1', 'AnnotationGroupGenerationType'],\n    '0008': ['SQ', '1', 'AnnotationGroupAlgorithmIdentificationSequence'],\n    '0009': ['SQ', '1', 'AnnotationPropertyCategoryCodeSequence'],\n    '000A': ['SQ', '1', 'AnnotationPropertyTypeCodeSequence'],\n    '000B': ['SQ', '1', 'AnnotationPropertyTypeModifierCodeSequence'],\n    '000C': ['UL', '1', 'NumberOfAnnotations'],\n    '000D': ['CS', '1', 'AnnotationAppliesToAllOpticalPaths'],\n    '000E': ['SH', '1-n', 'ReferencedOpticalPathIdentifier'],\n    '000F': ['CS', '1', 'AnnotationAppliesToAllZPlanes'],\n    '0010': ['FD', '1-n', 'CommonZCoordinateValue'],\n    '0011': ['OL', '1', 'AnnotationIndexList']\n  },\n  '0070': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['SQ', '1', 'GraphicAnnotationSequence'],\n    '0002': ['CS', '1', 'GraphicLayer'],\n    '0003': ['CS', '1', 'BoundingBoxAnnotationUnits'],\n    '0004': ['CS', '1', 'AnchorPointAnnotationUnits'],\n    '0005': ['CS', '1', 'GraphicAnnotationUnits'],\n    '0006': ['ST', '1', 'UnformattedTextValue'],\n    '0008': ['SQ', '1', 'TextObjectSequence'],\n    '0009': ['SQ', '1', 'GraphicObjectSequence'],\n    '0010': ['FL', '2', 'BoundingBoxTopLeftHandCorner'],\n    '0011': ['FL', '2', 'BoundingBoxBottomRightHandCorner'],\n    '0012': ['CS', '1', 'BoundingBoxTextHorizontalJustification'],\n    '0014': ['FL', '2', 'AnchorPoint'],\n    '0015': ['CS', '1', 'AnchorPointVisibility'],\n    '0020': ['US', '1', 'GraphicDimensions'],\n    '0021': ['US', '1', 'NumberOfGraphicPoints'],\n    '0022': ['FL', '2-n', 'GraphicData'],\n    '0023': ['CS', '1', 'GraphicType'],\n    '0024': ['CS', '1', 'GraphicFilled'],\n    '0040': ['IS', '1', 'ImageRotationRetired'],\n    '0041': ['CS', '1', 'ImageHorizontalFlip'],\n    '0042': ['US', '1', 'ImageRotation'],\n    '0050': ['US', '2', 'DisplayedAreaTopLeftHandCornerTrial'],\n    '0051': ['US', '2', 'DisplayedAreaBottomRightHandCornerTrial'],\n    '0052': ['SL', '2', 'DisplayedAreaTopLeftHandCorner'],\n    '0053': ['SL', '2', 'DisplayedAreaBottomRightHandCorner'],\n    '005A': ['SQ', '1', 'DisplayedAreaSelectionSequence'],\n    '0060': ['SQ', '1', 'GraphicLayerSequence'],\n    '0062': ['IS', '1', 'GraphicLayerOrder'],\n    '0066': ['US', '1', 'GraphicLayerRecommendedDisplayGrayscaleValue'],\n    '0067': ['US', '3', 'GraphicLayerRecommendedDisplayRGBValue'],\n    '0068': ['LO', '1', 'GraphicLayerDescription'],\n    '0080': ['CS', '1', 'ContentLabel'],\n    '0081': ['LO', '1', 'ContentDescription'],\n    '0082': ['DA', '1', 'PresentationCreationDate'],\n    '0083': ['TM', '1', 'PresentationCreationTime'],\n    '0084': ['PN', '1', 'ContentCreatorName'],\n    '0086': ['SQ', '1', 'ContentCreatorIdentificationCodeSequence'],\n    '0087': ['SQ', '1', 'AlternateContentDescriptionSequence'],\n    '0100': ['CS', '1', 'PresentationSizeMode'],\n    '0101': ['DS', '2', 'PresentationPixelSpacing'],\n    '0102': ['IS', '2', 'PresentationPixelAspectRatio'],\n    '0103': ['FL', '1', 'PresentationPixelMagnificationRatio'],\n    '0207': ['LO', '1', 'GraphicGroupLabel'],\n    '0208': ['ST', '1', 'GraphicGroupDescription'],\n    '0209': ['SQ', '1', 'CompoundGraphicSequence'],\n    '0226': ['UL', '1', 'CompoundGraphicInstanceID'],\n    '0227': ['LO', '1', 'FontName'],\n    '0228': ['CS', '1', 'FontNameType'],\n    '0229': ['LO', '1', 'CSSFontName'],\n    '0230': ['FD', '1', 'RotationAngle'],\n    '0231': ['SQ', '1', 'TextStyleSequence'],\n    '0232': ['SQ', '1', 'LineStyleSequence'],\n    '0233': ['SQ', '1', 'FillStyleSequence'],\n    '0234': ['SQ', '1', 'GraphicGroupSequence'],\n    '0241': ['US', '3', 'TextColorCIELabValue'],\n    '0242': ['CS', '1', 'HorizontalAlignment'],\n    '0243': ['CS', '1', 'VerticalAlignment'],\n    '0244': ['CS', '1', 'ShadowStyle'],\n    '0245': ['FL', '1', 'ShadowOffsetX'],\n    '0246': ['FL', '1', 'ShadowOffsetY'],\n    '0247': ['US', '3', 'ShadowColorCIELabValue'],\n    '0248': ['CS', '1', 'Underlined'],\n    '0249': ['CS', '1', 'Bold'],\n    '0250': ['CS', '1', 'Italic'],\n    '0251': ['US', '3', 'PatternOnColorCIELabValue'],\n    '0252': ['US', '3', 'PatternOffColorCIELabValue'],\n    '0253': ['FL', '1', 'LineThickness'],\n    '0254': ['CS', '1', 'LineDashingStyle'],\n    '0255': ['UL', '1', 'LinePattern'],\n    '0256': ['OB', '1', 'FillPattern'],\n    '0257': ['CS', '1', 'FillMode'],\n    '0258': ['FL', '1', 'ShadowOpacity'],\n    '0261': ['FL', '1', 'GapLength'],\n    '0262': ['FL', '1', 'DiameterOfVisibility'],\n    '0273': ['FL', '2', 'RotationPoint'],\n    '0274': ['CS', '1', 'TickAlignment'],\n    '0278': ['CS', '1', 'ShowTickLabel'],\n    '0279': ['CS', '1', 'TickLabelAlignment'],\n    '0282': ['CS', '1', 'CompoundGraphicUnits'],\n    '0284': ['FL', '1', 'PatternOnOpacity'],\n    '0285': ['FL', '1', 'PatternOffOpacity'],\n    '0287': ['SQ', '1', 'MajorTicksSequence'],\n    '0288': ['FL', '1', 'TickPosition'],\n    '0289': ['SH', '1', 'TickLabel'],\n    '0294': ['CS', '1', 'CompoundGraphicType'],\n    '0295': ['UL', '1', 'GraphicGroupID'],\n    '0306': ['CS', '1', 'ShapeType'],\n    '0308': ['SQ', '1', 'RegistrationSequence'],\n    '0309': ['SQ', '1', 'MatrixRegistrationSequence'],\n    '030A': ['SQ', '1', 'MatrixSequence'],\n    '030B': ['FD', '16', 'FrameOfReferenceToDisplayedCoordinateSystemTransformationMatrix'],\n    '030C': ['CS', '1', 'FrameOfReferenceTransformationMatrixType'],\n    '030D': ['SQ', '1', 'RegistrationTypeCodeSequence'],\n    '030F': ['ST', '1', 'FiducialDescription'],\n    '0310': ['SH', '1', 'FiducialIdentifier'],\n    '0311': ['SQ', '1', 'FiducialIdentifierCodeSequence'],\n    '0312': ['FD', '1', 'ContourUncertaintyRadius'],\n    '0314': ['SQ', '1', 'UsedFiducialsSequence'],\n    '0318': ['SQ', '1', 'GraphicCoordinatesDataSequence'],\n    '031A': ['UI', '1', 'FiducialUID'],\n    '031B': ['UI', '1', 'ReferencedFiducialUID'],\n    '031C': ['SQ', '1', 'FiducialSetSequence'],\n    '031E': ['SQ', '1', 'FiducialSequence'],\n    '031F': ['SQ', '1', 'FiducialsPropertyCategoryCodeSequence'],\n    '0401': ['US', '3', 'GraphicLayerRecommendedDisplayCIELabValue'],\n    '0402': ['SQ', '1', 'BlendingSequence'],\n    '0403': ['FL', '1', 'RelativeOpacity'],\n    '0404': ['SQ', '1', 'ReferencedSpatialRegistrationSequence'],\n    '0405': ['CS', '1', 'BlendingPosition'],\n    '1101': ['UI', '1', 'PresentationDisplayCollectionUID'],\n    '1102': ['UI', '1', 'PresentationSequenceCollectionUID'],\n    '1103': ['US', '1', 'PresentationSequencePositionIndex'],\n    '1104': ['SQ', '1', 'RenderedImageReferenceSequence'],\n    '1201': ['SQ', '1', 'VolumetricPresentationStateInputSequence'],\n    '1202': ['CS', '1', 'PresentationInputType'],\n    '1203': ['US', '1', 'InputSequencePositionIndex'],\n    '1204': ['CS', '1', 'Crop'],\n    '1205': ['US', '1-n', 'CroppingSpecificationIndex'],\n    '1206': ['CS', '1', 'CompositingMethod'],\n    '1207': ['US', '1', 'VolumetricPresentationInputNumber'],\n    '1208': ['CS', '1', 'ImageVolumeGeometry'],\n    '1209': ['UI', '1', 'VolumetricPresentationInputSetUID'],\n    '120A': ['SQ', '1', 'VolumetricPresentationInputSetSequence'],\n    '120B': ['CS', '1', 'GlobalCrop'],\n    '120C': ['US', '1-n', 'GlobalCroppingSpecificationIndex'],\n    '120D': ['CS', '1', 'RenderingMethod'],\n    '1301': ['SQ', '1', 'VolumeCroppingSequence'],\n    '1302': ['CS', '1', 'VolumeCroppingMethod'],\n    '1303': ['FD', '6', 'BoundingBoxCrop'],\n    '1304': ['SQ', '1', 'ObliqueCroppingPlaneSequence'],\n    '1305': ['FD', '4', 'Plane'],\n    '1306': ['FD', '3', 'PlaneNormal'],\n    '1309': ['US', '1', 'CroppingSpecificationNumber'],\n    '1501': ['CS', '1', 'MultiPlanarReconstructionStyle'],\n    '1502': ['CS', '1', 'MPRThicknessType'],\n    '1503': ['FD', '1', 'MPRSlabThickness'],\n    '1505': ['FD', '3', 'MPRTopLeftHandCorner'],\n    '1507': ['FD', '3', 'MPRViewWidthDirection'],\n    '1508': ['FD', '1', 'MPRViewWidth'],\n    '150C': ['UL', '1', 'NumberOfVolumetricCurvePoints'],\n    '150D': ['OD', '1', 'VolumetricCurvePoints'],\n    '1511': ['FD', '3', 'MPRViewHeightDirection'],\n    '1512': ['FD', '1', 'MPRViewHeight'],\n    '1602': ['CS', '1', 'RenderProjection'],\n    '1603': ['FD', '3', 'ViewpointPosition'],\n    '1604': ['FD', '3', 'ViewpointLookAtPoint'],\n    '1605': ['FD', '3', 'ViewpointUpDirection'],\n    '1606': ['FD', '6', 'RenderFieldOfView'],\n    '1607': ['FD', '1', 'SamplingStepSize'],\n    '1701': ['CS', '1', 'ShadingStyle'],\n    '1702': ['FD', '1', 'AmbientReflectionIntensity'],\n    '1703': ['FD', '3', 'LightDirection'],\n    '1704': ['FD', '1', 'DiffuseReflectionIntensity'],\n    '1705': ['FD', '1', 'SpecularReflectionIntensity'],\n    '1706': ['FD', '1', 'Shininess'],\n    '1801': ['SQ', '1', 'PresentationStateClassificationComponentSequence'],\n    '1802': ['CS', '1', 'ComponentType'],\n    '1803': ['SQ', '1', 'ComponentInputSequence'],\n    '1804': ['US', '1', 'VolumetricPresentationInputIndex'],\n    '1805': ['SQ', '1', 'PresentationStateCompositorComponentSequence'],\n    '1806': ['SQ', '1', 'WeightingTransferFunctionSequence'],\n    '1807': ['US', '3', 'WeightingLookupTableDescriptor'],\n    '1808': ['OB', '1', 'WeightingLookupTableData'],\n    '1901': ['SQ', '1', 'VolumetricAnnotationSequence'],\n    '1903': ['SQ', '1', 'ReferencedStructuredContextSequence'],\n    '1904': ['UI', '1', 'ReferencedContentItem'],\n    '1905': ['SQ', '1', 'VolumetricPresentationInputAnnotationSequence'],\n    '1907': ['CS', '1', 'AnnotationClipping'],\n    '1A01': ['CS', '1', 'PresentationAnimationStyle'],\n    '1A03': ['FD', '1', 'RecommendedAnimationRate'],\n    '1A04': ['SQ', '1', 'AnimationCurveSequence'],\n    '1A05': ['FD', '1', 'AnimationStepSize'],\n    '1A06': ['FD', '1', 'SwivelRange'],\n    '1A07': ['OD', '1', 'VolumetricCurveUpDirections'],\n    '1A08': ['SQ', '1', 'VolumeStreamSequence'],\n    '1A09': ['LO', '1', 'RGBATransferFunctionDescription'],\n    '1B01': ['SQ', '1', 'AdvancedBlendingSequence'],\n    '1B02': ['US', '1', 'BlendingInputNumber'],\n    '1B03': ['SQ', '1', 'BlendingDisplayInputSequence'],\n    '1B04': ['SQ', '1', 'BlendingDisplaySequence'],\n    '1B06': ['CS', '1', 'BlendingMode'],\n    '1B07': ['CS', '1', 'TimeSeriesBlending'],\n    '1B08': ['CS', '1', 'GeometryForDisplay'],\n    '1B11': ['SQ', '1', 'ThresholdSequence'],\n    '1B12': ['SQ', '1', 'ThresholdValueSequence'],\n    '1B13': ['CS', '1', 'ThresholdType'],\n    '1B14': ['FD', '1', 'ThresholdValue']\n  },\n  '0072': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SH', '1', 'HangingProtocolName'],\n    '0004': ['LO', '1', 'HangingProtocolDescription'],\n    '0006': ['CS', '1', 'HangingProtocolLevel'],\n    '0008': ['LO', '1', 'HangingProtocolCreator'],\n    '000A': ['DT', '1', 'HangingProtocolCreationDateTime'],\n    '000C': ['SQ', '1', 'HangingProtocolDefinitionSequence'],\n    '000E': ['SQ', '1', 'HangingProtocolUserIdentificationCodeSequence'],\n    '0010': ['LO', '1', 'HangingProtocolUserGroupName'],\n    '0012': ['SQ', '1', 'SourceHangingProtocolSequence'],\n    '0014': ['US', '1', 'NumberOfPriorsReferenced'],\n    '0020': ['SQ', '1', 'ImageSetsSequence'],\n    '0022': ['SQ', '1', 'ImageSetSelectorSequence'],\n    '0024': ['CS', '1', 'ImageSetSelectorUsageFlag'],\n    '0026': ['AT', '1', 'SelectorAttribute'],\n    '0028': ['US', '1', 'SelectorValueNumber'],\n    '0030': ['SQ', '1', 'TimeBasedImageSetsSequence'],\n    '0032': ['US', '1', 'ImageSetNumber'],\n    '0034': ['CS', '1', 'ImageSetSelectorCategory'],\n    '0038': ['US', '2', 'RelativeTime'],\n    '003A': ['CS', '1', 'RelativeTimeUnits'],\n    '003C': ['SS', '2', 'AbstractPriorValue'],\n    '003E': ['SQ', '1', 'AbstractPriorCodeSequence'],\n    '0040': ['LO', '1', 'ImageSetLabel'],\n    '0050': ['CS', '1', 'SelectorAttributeVR'],\n    '0052': ['AT', '1-n', 'SelectorSequencePointer'],\n    '0054': ['LO', '1-n', 'SelectorSequencePointerPrivateCreator'],\n    '0056': ['LO', '1', 'SelectorAttributePrivateCreator'],\n    '005E': ['AE', '1-n', 'SelectorAEValue'],\n    '005F': ['AS', '1-n', 'SelectorASValue'],\n    '0060': ['AT', '1-n', 'SelectorATValue'],\n    '0061': ['DA', '1-n', 'SelectorDAValue'],\n    '0062': ['CS', '1-n', 'SelectorCSValue'],\n    '0063': ['DT', '1-n', 'SelectorDTValue'],\n    '0064': ['IS', '1-n', 'SelectorISValue'],\n    '0065': ['OB', '1', 'SelectorOBValue'],\n    '0066': ['LO', '1-n', 'SelectorLOValue'],\n    '0067': ['OF', '1', 'SelectorOFValue'],\n    '0068': ['LT', '1', 'SelectorLTValue'],\n    '0069': ['OW', '1', 'SelectorOWValue'],\n    '006A': ['PN', '1-n', 'SelectorPNValue'],\n    '006B': ['TM', '1-n', 'SelectorTMValue'],\n    '006C': ['SH', '1-n', 'SelectorSHValue'],\n    '006D': ['UN', '1', 'SelectorUNValue'],\n    '006E': ['ST', '1', 'SelectorSTValue'],\n    '006F': ['UC', '1-n', 'SelectorUCValue'],\n    '0070': ['UT', '1', 'SelectorUTValue'],\n    '0071': ['UR', '1', 'SelectorURValue'],\n    '0072': ['DS', '1-n', 'SelectorDSValue'],\n    '0073': ['OD', '1', 'SelectorODValue'],\n    '0074': ['FD', '1-n', 'SelectorFDValue'],\n    '0075': ['OL', '1', 'SelectorOLValue'],\n    '0076': ['FL', '1-n', 'SelectorFLValue'],\n    '0078': ['UL', '1-n', 'SelectorULValue'],\n    '007A': ['US', '1-n', 'SelectorUSValue'],\n    '007C': ['SL', '1-n', 'SelectorSLValue'],\n    '007E': ['SS', '1-n', 'SelectorSSValue'],\n    '007F': ['UI', '1-n', 'SelectorUIValue'],\n    '0080': ['SQ', '1', 'SelectorCodeSequenceValue'],\n    '0081': ['OV', '1', 'SelectorOVValue'],\n    '0082': ['SV', '1-n', 'SelectorSVValue'],\n    '0083': ['UV', '1-n', 'SelectorUVValue'],\n    '0100': ['US', '1', 'NumberOfScreens'],\n    '0102': ['SQ', '1', 'NominalScreenDefinitionSequence'],\n    '0104': ['US', '1', 'NumberOfVerticalPixels'],\n    '0106': ['US', '1', 'NumberOfHorizontalPixels'],\n    '0108': ['FD', '4', 'DisplayEnvironmentSpatialPosition'],\n    '010A': ['US', '1', 'ScreenMinimumGrayscaleBitDepth'],\n    '010C': ['US', '1', 'ScreenMinimumColorBitDepth'],\n    '010E': ['US', '1', 'ApplicationMaximumRepaintTime'],\n    '0200': ['SQ', '1', 'DisplaySetsSequence'],\n    '0202': ['US', '1', 'DisplaySetNumber'],\n    '0203': ['LO', '1', 'DisplaySetLabel'],\n    '0204': ['US', '1', 'DisplaySetPresentationGroup'],\n    '0206': ['LO', '1', 'DisplaySetPresentationGroupDescription'],\n    '0208': ['CS', '1', 'PartialDataDisplayHandling'],\n    '0210': ['SQ', '1', 'SynchronizedScrollingSequence'],\n    '0212': ['US', '2-n', 'DisplaySetScrollingGroup'],\n    '0214': ['SQ', '1', 'NavigationIndicatorSequence'],\n    '0216': ['US', '1', 'NavigationDisplaySet'],\n    '0218': ['US', '1-n', 'ReferenceDisplaySets'],\n    '0300': ['SQ', '1', 'ImageBoxesSequence'],\n    '0302': ['US', '1', 'ImageBoxNumber'],\n    '0304': ['CS', '1', 'ImageBoxLayoutType'],\n    '0306': ['US', '1', 'ImageBoxTileHorizontalDimension'],\n    '0308': ['US', '1', 'ImageBoxTileVerticalDimension'],\n    '0310': ['CS', '1', 'ImageBoxScrollDirection'],\n    '0312': ['CS', '1', 'ImageBoxSmallScrollType'],\n    '0314': ['US', '1', 'ImageBoxSmallScrollAmount'],\n    '0316': ['CS', '1', 'ImageBoxLargeScrollType'],\n    '0318': ['US', '1', 'ImageBoxLargeScrollAmount'],\n    '0320': ['US', '1', 'ImageBoxOverlapPriority'],\n    '0330': ['FD', '1', 'CineRelativeToRealTime'],\n    '0400': ['SQ', '1', 'FilterOperationsSequence'],\n    '0402': ['CS', '1', 'FilterByCategory'],\n    '0404': ['CS', '1', 'FilterByAttributePresence'],\n    '0406': ['CS', '1', 'FilterByOperator'],\n    '0420': ['US', '3', 'StructuredDisplayBackgroundCIELabValue'],\n    '0421': ['US', '3', 'EmptyImageBoxCIELabValue'],\n    '0422': ['SQ', '1', 'StructuredDisplayImageBoxSequence'],\n    '0424': ['SQ', '1', 'StructuredDisplayTextBoxSequence'],\n    '0427': ['SQ', '1', 'ReferencedFirstFrameSequence'],\n    '0430': ['SQ', '1', 'ImageBoxSynchronizationSequence'],\n    '0432': ['US', '2-n', 'SynchronizedImageBoxList'],\n    '0434': ['CS', '1', 'TypeOfSynchronization'],\n    '0500': ['CS', '1', 'BlendingOperationType'],\n    '0510': ['CS', '1', 'ReformattingOperationType'],\n    '0512': ['FD', '1', 'ReformattingThickness'],\n    '0514': ['FD', '1', 'ReformattingInterval'],\n    '0516': ['CS', '1', 'ReformattingOperationInitialViewDirection'],\n    '0520': ['CS', '1-n', 'ThreeDRenderingType'],\n    '0600': ['SQ', '1', 'SortingOperationsSequence'],\n    '0602': ['CS', '1', 'SortByCategory'],\n    '0604': ['CS', '1', 'SortingDirection'],\n    '0700': ['CS', '2', 'DisplaySetPatientOrientation'],\n    '0702': ['CS', '1', 'VOIType'],\n    '0704': ['CS', '1', 'PseudoColorType'],\n    '0705': ['SQ', '1', 'PseudoColorPaletteInstanceReferenceSequence'],\n    '0706': ['CS', '1', 'ShowGrayscaleInverted'],\n    '0710': ['CS', '1', 'ShowImageTrueSizeFlag'],\n    '0712': ['CS', '1', 'ShowGraphicAnnotationFlag'],\n    '0714': ['CS', '1', 'ShowPatientDemographicsFlag'],\n    '0716': ['CS', '1', 'ShowAcquisitionTechniquesFlag'],\n    '0717': ['CS', '1', 'DisplaySetHorizontalJustification'],\n    '0718': ['CS', '1', 'DisplaySetVerticalJustification']\n  },\n  '0074': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0120': ['FD', '1', 'ContinuationStartMeterset'],\n    '0121': ['FD', '1', 'ContinuationEndMeterset'],\n    '1000': ['CS', '1', 'ProcedureStepState'],\n    '1002': ['SQ', '1', 'ProcedureStepProgressInformationSequence'],\n    '1004': ['DS', '1', 'ProcedureStepProgress'],\n    '1006': ['ST', '1', 'ProcedureStepProgressDescription'],\n    '1007': ['SQ', '1', 'ProcedureStepProgressParametersSequence'],\n    '1008': ['SQ', '1', 'ProcedureStepCommunicationsURISequence'],\n    '100A': ['UR', '1', 'ContactURI'],\n    '100C': ['LO', '1', 'ContactDisplayName'],\n    '100E': ['SQ', '1', 'ProcedureStepDiscontinuationReasonCodeSequence'],\n    '1020': ['SQ', '1', 'BeamTaskSequence'],\n    '1022': ['CS', '1', 'BeamTaskType'],\n    '1024': ['IS', '1', 'BeamOrderIndexTrial'],\n    '1025': ['CS', '1', 'AutosequenceFlag'],\n    '1026': ['FD', '1', 'TableTopVerticalAdjustedPosition'],\n    '1027': ['FD', '1', 'TableTopLongitudinalAdjustedPosition'],\n    '1028': ['FD', '1', 'TableTopLateralAdjustedPosition'],\n    '102A': ['FD', '1', 'PatientSupportAdjustedAngle'],\n    '102B': ['FD', '1', 'TableTopEccentricAdjustedAngle'],\n    '102C': ['FD', '1', 'TableTopPitchAdjustedAngle'],\n    '102D': ['FD', '1', 'TableTopRollAdjustedAngle'],\n    '1030': ['SQ', '1', 'DeliveryVerificationImageSequence'],\n    '1032': ['CS', '1', 'VerificationImageTiming'],\n    '1034': ['CS', '1', 'DoubleExposureFlag'],\n    '1036': ['CS', '1', 'DoubleExposureOrdering'],\n    '1038': ['DS', '1', 'DoubleExposureMetersetTrial'],\n    '103A': ['DS', '4', 'DoubleExposureFieldDeltaTrial'],\n    '1040': ['SQ', '1', 'RelatedReferenceRTImageSequence'],\n    '1042': ['SQ', '1', 'GeneralMachineVerificationSequence'],\n    '1044': ['SQ', '1', 'ConventionalMachineVerificationSequence'],\n    '1046': ['SQ', '1', 'IonMachineVerificationSequence'],\n    '1048': ['SQ', '1', 'FailedAttributesSequence'],\n    '104A': ['SQ', '1', 'OverriddenAttributesSequence'],\n    '104C': ['SQ', '1', 'ConventionalControlPointVerificationSequence'],\n    '104E': ['SQ', '1', 'IonControlPointVerificationSequence'],\n    '1050': ['SQ', '1', 'AttributeOccurrenceSequence'],\n    '1052': ['AT', '1', 'AttributeOccurrencePointer'],\n    '1054': ['UL', '1', 'AttributeItemSelector'],\n    '1056': ['LO', '1', 'AttributeOccurrencePrivateCreator'],\n    '1057': ['IS', '1-n', 'SelectorSequencePointerItems'],\n    '1200': ['CS', '1', 'ScheduledProcedureStepPriority'],\n    '1202': ['LO', '1', 'WorklistLabel'],\n    '1204': ['LO', '1', 'ProcedureStepLabel'],\n    '1210': ['SQ', '1', 'ScheduledProcessingParametersSequence'],\n    '1212': ['SQ', '1', 'PerformedProcessingParametersSequence'],\n    '1216': ['SQ', '1', 'UnifiedProcedureStepPerformedProcedureSequence'],\n    '1220': ['SQ', '1', 'RelatedProcedureStepSequence'],\n    '1222': ['LO', '1', 'ProcedureStepRelationshipType'],\n    '1224': ['SQ', '1', 'ReplacedProcedureStepSequence'],\n    '1230': ['LO', '1', 'DeletionLock'],\n    '1234': ['AE', '1', 'ReceivingAE'],\n    '1236': ['AE', '1', 'RequestingAE'],\n    '1238': ['LT', '1', 'ReasonForCancellation'],\n    '1242': ['CS', '1', 'SCPStatus'],\n    '1244': ['CS', '1', 'SubscriptionListStatus'],\n    '1246': ['CS', '1', 'UnifiedProcedureStepListStatus'],\n    '1324': ['UL', '1', 'BeamOrderIndex'],\n    '1338': ['FD', '1', 'DoubleExposureMeterset'],\n    '133A': ['FD', '4', 'DoubleExposureFieldDelta'],\n    '1401': ['SQ', '1', 'BrachyTaskSequence'],\n    '1402': ['DS', '1', 'ContinuationStartTotalReferenceAirKerma'],\n    '1403': ['DS', '1', 'ContinuationEndTotalReferenceAirKerma'],\n    '1404': ['IS', '1', 'ContinuationPulseNumber'],\n    '1405': ['SQ', '1', 'ChannelDeliveryOrderSequence'],\n    '1406': ['IS', '1', 'ReferencedChannelNumber'],\n    '1407': ['DS', '1', 'StartCumulativeTimeWeight'],\n    '1408': ['DS', '1', 'EndCumulativeTimeWeight'],\n    '1409': ['SQ', '1', 'OmittedChannelSequence'],\n    '140A': ['CS', '1', 'ReasonForChannelOmission'],\n    '140B': ['LO', '1', 'ReasonForChannelOmissionDescription'],\n    '140C': ['IS', '1', 'ChannelDeliveryOrderIndex'],\n    '140D': ['SQ', '1', 'ChannelDeliveryContinuationSequence'],\n    '140E': ['SQ', '1', 'OmittedApplicationSetupSequence']\n  },\n  '0076': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['LO', '1', 'ImplantAssemblyTemplateName'],\n    '0003': ['LO', '1', 'ImplantAssemblyTemplateIssuer'],\n    '0006': ['LO', '1', 'ImplantAssemblyTemplateVersion'],\n    '0008': ['SQ', '1', 'ReplacedImplantAssemblyTemplateSequence'],\n    '000A': ['CS', '1', 'ImplantAssemblyTemplateType'],\n    '000C': ['SQ', '1', 'OriginalImplantAssemblyTemplateSequence'],\n    '000E': ['SQ', '1', 'DerivationImplantAssemblyTemplateSequence'],\n    '0010': ['SQ', '1', 'ImplantAssemblyTemplateTargetAnatomySequence'],\n    '0020': ['SQ', '1', 'ProcedureTypeCodeSequence'],\n    '0030': ['LO', '1', 'SurgicalTechnique'],\n    '0032': ['SQ', '1', 'ComponentTypesSequence'],\n    '0034': ['SQ', '1', 'ComponentTypeCodeSequence'],\n    '0036': ['CS', '1', 'ExclusiveComponentType'],\n    '0038': ['CS', '1', 'MandatoryComponentType'],\n    '0040': ['SQ', '1', 'ComponentSequence'],\n    '0055': ['US', '1', 'ComponentID'],\n    '0060': ['SQ', '1', 'ComponentAssemblySequence'],\n    '0070': ['US', '1', 'Component1ReferencedID'],\n    '0080': ['US', '1', 'Component1ReferencedMatingFeatureSetID'],\n    '0090': ['US', '1', 'Component1ReferencedMatingFeatureID'],\n    '00A0': ['US', '1', 'Component2ReferencedID'],\n    '00B0': ['US', '1', 'Component2ReferencedMatingFeatureSetID'],\n    '00C0': ['US', '1', 'Component2ReferencedMatingFeatureID']\n  },\n  '0078': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['LO', '1', 'ImplantTemplateGroupName'],\n    '0010': ['ST', '1', 'ImplantTemplateGroupDescription'],\n    '0020': ['LO', '1', 'ImplantTemplateGroupIssuer'],\n    '0024': ['LO', '1', 'ImplantTemplateGroupVersion'],\n    '0026': ['SQ', '1', 'ReplacedImplantTemplateGroupSequence'],\n    '0028': ['SQ', '1', 'ImplantTemplateGroupTargetAnatomySequence'],\n    '002A': ['SQ', '1', 'ImplantTemplateGroupMembersSequence'],\n    '002E': ['US', '1', 'ImplantTemplateGroupMemberID'],\n    '0050': ['FD', '3', 'ThreeDImplantTemplateGroupMemberMatchingPoint'],\n    '0060': ['FD', '9', 'ThreeDImplantTemplateGroupMemberMatchingAxes'],\n    '0070': ['SQ', '1', 'ImplantTemplateGroupMemberMatching2DCoordinatesSequence'],\n    '0090': ['FD', '2', 'TwoDImplantTemplateGroupMemberMatchingPoint'],\n    '00A0': ['FD', '4', 'TwoDImplantTemplateGroupMemberMatchingAxes'],\n    '00B0': ['SQ', '1', 'ImplantTemplateGroupVariationDimensionSequence'],\n    '00B2': ['LO', '1', 'ImplantTemplateGroupVariationDimensionName'],\n    '00B4': ['SQ', '1', 'ImplantTemplateGroupVariationDimensionRankSequence'],\n    '00B6': ['US', '1', 'ReferencedImplantTemplateGroupMemberID'],\n    '00B8': ['US', '1', 'ImplantTemplateGroupVariationDimensionRank']\n  },\n  '0080': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['SQ', '1', 'SurfaceScanAcquisitionTypeCodeSequence'],\n    '0002': ['SQ', '1', 'SurfaceScanModeCodeSequence'],\n    '0003': ['SQ', '1', 'RegistrationMethodCodeSequence'],\n    '0004': ['FD', '1', 'ShotDurationTime'],\n    '0005': ['FD', '1', 'ShotOffsetTime'],\n    '0006': ['US', '1-n', 'SurfacePointPresentationValueData'],\n    '0007': ['US', '3-3n', 'SurfacePointColorCIELabValueData'],\n    '0008': ['SQ', '1', 'UVMappingSequence'],\n    '0009': ['SH', '1', 'TextureLabel'],\n    '0010': ['OF', '1', 'UValueData'],\n    '0011': ['OF', '1', 'VValueData'],\n    '0012': ['SQ', '1', 'ReferencedTextureSequence'],\n    '0013': ['SQ', '1', 'ReferencedSurfaceDataSequence']\n  },\n  '0082': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'AssessmentSummary'],\n    '0003': ['UT', '1', 'AssessmentSummaryDescription'],\n    '0004': ['SQ', '1', 'AssessedSOPInstanceSequence'],\n    '0005': ['SQ', '1', 'ReferencedComparisonSOPInstanceSequence'],\n    '0006': ['UL', '1', 'NumberOfAssessmentObservations'],\n    '0007': ['SQ', '1', 'AssessmentObservationsSequence'],\n    '0008': ['CS', '1', 'ObservationSignificance'],\n    '000A': ['UT', '1', 'ObservationDescription'],\n    '000C': ['SQ', '1', 'StructuredConstraintObservationSequence'],\n    '0010': ['SQ', '1', 'AssessedAttributeValueSequence'],\n    '0016': ['LO', '1', 'AssessmentSetID'],\n    '0017': ['SQ', '1', 'AssessmentRequesterSequence'],\n    '0018': ['LO', '1', 'SelectorAttributeName'],\n    '0019': ['LO', '1', 'SelectorAttributeKeyword'],\n    '0021': ['SQ', '1', 'AssessmentTypeCodeSequence'],\n    '0022': ['SQ', '1', 'ObservationBasisCodeSequence'],\n    '0023': ['LO', '1', 'AssessmentLabel'],\n    '0032': ['CS', '1', 'ConstraintType'],\n    '0033': ['UT', '1', 'SpecificationSelectionGuidance'],\n    '0034': ['SQ', '1', 'ConstraintValueSequence'],\n    '0035': ['SQ', '1', 'RecommendedDefaultValueSequence'],\n    '0036': ['CS', '1', 'ConstraintViolationSignificance'],\n    '0037': ['UT', '1', 'ConstraintViolationCondition'],\n    '0038': ['CS', '1', 'ModifiableConstraintFlag']\n  },\n  '0088': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0130': ['SH', '1', 'StorageMediaFileSetID'],\n    '0140': ['UI', '1', 'StorageMediaFileSetUID'],\n    '0200': ['SQ', '1', 'IconImageSequence'],\n    '0904': ['LO', '1', 'TopicTitle'],\n    '0906': ['ST', '1', 'TopicSubject'],\n    '0910': ['LO', '1', 'TopicAuthor'],\n    '0912': ['LO', '1-32', 'TopicKeywords']\n  },\n  '0100': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0410': ['CS', '1', 'SOPInstanceStatus'],\n    '0420': ['DT', '1', 'SOPAuthorizationDateTime'],\n    '0424': ['LT', '1', 'SOPAuthorizationComment'],\n    '0426': ['LO', '1', 'AuthorizationEquipmentCertificationNumber']\n  },\n  '0400': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0005': ['US', '1', 'MACIDNumber'],\n    '0010': ['UI', '1', 'MACCalculationTransferSyntaxUID'],\n    '0015': ['CS', '1', 'MACAlgorithm'],\n    '0020': ['AT', '1-n', 'DataElementsSigned'],\n    '0100': ['UI', '1', 'DigitalSignatureUID'],\n    '0105': ['DT', '1', 'DigitalSignatureDateTime'],\n    '0110': ['CS', '1', 'CertificateType'],\n    '0115': ['OB', '1', 'CertificateOfSigner'],\n    '0120': ['OB', '1', 'Signature'],\n    '0305': ['CS', '1', 'CertifiedTimestampType'],\n    '0310': ['OB', '1', 'CertifiedTimestamp'],\n    '0315': ['FL', '1', ''],\n    '0401': ['SQ', '1', 'DigitalSignaturePurposeCodeSequence'],\n    '0402': ['SQ', '1', 'ReferencedDigitalSignatureSequence'],\n    '0403': ['SQ', '1', 'ReferencedSOPInstanceMACSequence'],\n    '0404': ['OB', '1', 'MAC'],\n    '0500': ['SQ', '1', 'EncryptedAttributesSequence'],\n    '0510': ['UI', '1', 'EncryptedContentTransferSyntaxUID'],\n    '0520': ['OB', '1', 'EncryptedContent'],\n    '0550': ['SQ', '1', 'ModifiedAttributesSequence'],\n    '0551': ['SQ', '1', 'NonconformingModifiedAttributesSequence'],\n    '0552': ['OB', '1', 'NonconformingDataElementValue'],\n    '0561': ['SQ', '1', 'OriginalAttributesSequence'],\n    '0562': ['DT', '1', 'AttributeModificationDateTime'],\n    '0563': ['LO', '1', 'ModifyingSystem'],\n    '0564': ['LO', '1', 'SourceOfPreviousValues'],\n    '0565': ['CS', '1', 'ReasonForTheAttributeModification'],\n    '0600': ['CS', '1', 'InstanceOriginStatus']\n  },\n  '1000': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['US', '3', 'EscapeTriplet'],\n    '0011': ['US', '3', 'RunLengthTriplet'],\n    '0012': ['US', '1', 'HuffmanTableSize'],\n    '0013': ['US', '3', 'HuffmanTableTriplet'],\n    '0014': ['US', '1', 'ShiftTableSize'],\n    '0015': ['US', '3', 'ShiftTableTriplet']\n  },\n  '1010': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0004': ['US', '1-n', 'ZonalMap']\n  },\n  '2000': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['IS', '1', 'NumberOfCopies'],\n    '001E': ['SQ', '1', 'PrinterConfigurationSequence'],\n    '0020': ['CS', '1', 'PrintPriority'],\n    '0030': ['CS', '1', 'MediumType'],\n    '0040': ['CS', '1', 'FilmDestination'],\n    '0050': ['LO', '1', 'FilmSessionLabel'],\n    '0060': ['IS', '1', 'MemoryAllocation'],\n    '0061': ['IS', '1', 'MaximumMemoryAllocation'],\n    '0062': ['CS', '1', 'ColorImagePrintingFlag'],\n    '0063': ['CS', '1', 'CollationFlag'],\n    '0065': ['CS', '1', 'AnnotationFlag'],\n    '0067': ['CS', '1', 'ImageOverlayFlag'],\n    '0069': ['CS', '1', 'PresentationLUTFlag'],\n    '006A': ['CS', '1', 'ImageBoxPresentationLUTFlag'],\n    '00A0': ['US', '1', 'MemoryBitDepth'],\n    '00A1': ['US', '1', 'PrintingBitDepth'],\n    '00A2': ['SQ', '1', 'MediaInstalledSequence'],\n    '00A4': ['SQ', '1', 'OtherMediaAvailableSequence'],\n    '00A8': ['SQ', '1', 'SupportedImageDisplayFormatsSequence'],\n    '0500': ['SQ', '1', 'ReferencedFilmBoxSequence'],\n    '0510': ['SQ', '1', 'ReferencedStoredPrintSequence']\n  },\n  '2010': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['ST', '1', 'ImageDisplayFormat'],\n    '0030': ['CS', '1', 'AnnotationDisplayFormatID'],\n    '0040': ['CS', '1', 'FilmOrientation'],\n    '0050': ['CS', '1', 'FilmSizeID'],\n    '0052': ['CS', '1', 'PrinterResolutionID'],\n    '0054': ['CS', '1', 'DefaultPrinterResolutionID'],\n    '0060': ['CS', '1', 'MagnificationType'],\n    '0080': ['CS', '1', 'SmoothingType'],\n    '00A6': ['CS', '1', 'DefaultMagnificationType'],\n    '00A7': ['CS', '1-n', 'OtherMagnificationTypesAvailable'],\n    '00A8': ['CS', '1', 'DefaultSmoothingType'],\n    '00A9': ['CS', '1-n', 'OtherSmoothingTypesAvailable'],\n    '0100': ['CS', '1', 'BorderDensity'],\n    '0110': ['CS', '1', 'EmptyImageDensity'],\n    '0120': ['US', '1', 'MinDensity'],\n    '0130': ['US', '1', 'MaxDensity'],\n    '0140': ['CS', '1', 'Trim'],\n    '0150': ['ST', '1', 'ConfigurationInformation'],\n    '0152': ['LT', '1', 'ConfigurationInformationDescription'],\n    '0154': ['IS', '1', 'MaximumCollatedFilms'],\n    '015E': ['US', '1', 'Illumination'],\n    '0160': ['US', '1', 'ReflectedAmbientLight'],\n    '0376': ['DS', '2', 'PrinterPixelSpacing'],\n    '0500': ['SQ', '1', 'ReferencedFilmSessionSequence'],\n    '0510': ['SQ', '1', 'ReferencedImageBoxSequence'],\n    '0520': ['SQ', '1', 'ReferencedBasicAnnotationBoxSequence']\n  },\n  '2020': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['US', '1', 'ImageBoxPosition'],\n    '0020': ['CS', '1', 'Polarity'],\n    '0030': ['DS', '1', 'RequestedImageSize'],\n    '0040': ['CS', '1', 'RequestedDecimateCropBehavior'],\n    '0050': ['CS', '1', 'RequestedResolutionID'],\n    '00A0': ['CS', '1', 'RequestedImageSizeFlag'],\n    '00A2': ['CS', '1', 'DecimateCropResult'],\n    '0110': ['SQ', '1', 'BasicGrayscaleImageSequence'],\n    '0111': ['SQ', '1', 'BasicColorImageSequence'],\n    '0130': ['SQ', '1', 'ReferencedImageOverlayBoxSequence'],\n    '0140': ['SQ', '1', 'ReferencedVOILUTBoxSequence']\n  },\n  '2030': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['US', '1', 'AnnotationPosition'],\n    '0020': ['LO', '1', 'TextString']\n  },\n  '2040': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['SQ', '1', 'ReferencedOverlayPlaneSequence'],\n    '0011': ['US', '1-99', 'ReferencedOverlayPlaneGroups'],\n    '0020': ['SQ', '1', 'OverlayPixelDataSequence'],\n    '0060': ['CS', '1', 'OverlayMagnificationType'],\n    '0070': ['CS', '1', 'OverlaySmoothingType'],\n    '0072': ['CS', '1', 'OverlayOrImageMagnification'],\n    '0074': ['US', '1', 'MagnifyToNumberOfColumns'],\n    '0080': ['CS', '1', 'OverlayForegroundDensity'],\n    '0082': ['CS', '1', 'OverlayBackgroundDensity'],\n    '0090': ['CS', '1', 'OverlayMode'],\n    '0100': ['CS', '1', 'ThresholdDensity'],\n    '0500': ['SQ', '1', 'ReferencedImageBoxSequenceRetired']\n  },\n  '2050': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['SQ', '1', 'PresentationLUTSequence'],\n    '0020': ['CS', '1', 'PresentationLUTShape'],\n    '0500': ['SQ', '1', 'ReferencedPresentationLUTSequence']\n  },\n  '2100': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['SH', '1', 'PrintJobID'],\n    '0020': ['CS', '1', 'ExecutionStatus'],\n    '0030': ['CS', '1', 'ExecutionStatusInfo'],\n    '0040': ['DA', '1', 'CreationDate'],\n    '0050': ['TM', '1', 'CreationTime'],\n    '0070': ['AE', '1', 'Originator'],\n    '0140': ['AE', '1', 'DestinationAE'],\n    '0160': ['SH', '1', 'OwnerID'],\n    '0170': ['IS', '1', 'NumberOfFilms'],\n    '0500': ['SQ', '1', 'ReferencedPrintJobSequencePullStoredPrint']\n  },\n  '2110': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['CS', '1', 'PrinterStatus'],\n    '0020': ['CS', '1', 'PrinterStatusInfo'],\n    '0030': ['LO', '1', 'PrinterName'],\n    '0099': ['SH', '1', 'PrintQueueID']\n  },\n  '2120': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['CS', '1', 'QueueStatus'],\n    '0050': ['SQ', '1', 'PrintJobDescriptionSequence'],\n    '0070': ['SQ', '1', 'ReferencedPrintJobSequence']\n  },\n  '2130': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['SQ', '1', 'PrintManagementCapabilitiesSequence'],\n    '0015': ['SQ', '1', 'PrinterCharacteristicsSequence'],\n    '0030': ['SQ', '1', 'FilmBoxContentSequence'],\n    '0040': ['SQ', '1', 'ImageBoxContentSequence'],\n    '0050': ['SQ', '1', 'AnnotationContentSequence'],\n    '0060': ['SQ', '1', 'ImageOverlayBoxContentSequence'],\n    '0080': ['SQ', '1', 'PresentationLUTContentSequence'],\n    '00A0': ['SQ', '1', 'ProposedStudySequence'],\n    '00C0': ['SQ', '1', 'OriginalImageSequence']\n  },\n  '2200': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'LabelUsingInformationExtractedFromInstances'],\n    '0002': ['UT', '1', 'LabelText'],\n    '0003': ['CS', '1', 'LabelStyleSelection'],\n    '0004': ['LT', '1', 'MediaDisposition'],\n    '0005': ['LT', '1', 'BarcodeValue'],\n    '0006': ['CS', '1', 'BarcodeSymbology'],\n    '0007': ['CS', '1', 'AllowMediaSplitting'],\n    '0008': ['CS', '1', 'IncludeNonDICOMObjects'],\n    '0009': ['CS', '1', 'IncludeDisplayApplication'],\n    '000A': ['CS', '1', 'PreserveCompositeInstancesAfterMediaCreation'],\n    '000B': ['US', '1', 'TotalNumberOfPiecesOfMediaCreated'],\n    '000C': ['LO', '1', 'RequestedMediaApplicationProfile'],\n    '000D': ['SQ', '1', 'ReferencedStorageMediaSequence'],\n    '000E': ['AT', '1-n', 'FailureAttributes'],\n    '000F': ['CS', '1', 'AllowLossyCompression'],\n    '0020': ['CS', '1', 'RequestPriority']\n  },\n  '3002': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SH', '1', 'RTImageLabel'],\n    '0003': ['LO', '1', 'RTImageName'],\n    '0004': ['ST', '1', 'RTImageDescription'],\n    '000A': ['CS', '1', 'ReportedValuesOrigin'],\n    '000C': ['CS', '1', 'RTImagePlane'],\n    '000D': ['DS', '3', 'XRayImageReceptorTranslation'],\n    '000E': ['DS', '1', 'XRayImageReceptorAngle'],\n    '0010': ['DS', '6', 'RTImageOrientation'],\n    '0011': ['DS', '2', 'ImagePlanePixelSpacing'],\n    '0012': ['DS', '2', 'RTImagePosition'],\n    '0020': ['SH', '1', 'RadiationMachineName'],\n    '0022': ['DS', '1', 'RadiationMachineSAD'],\n    '0024': ['DS', '1', 'RadiationMachineSSD'],\n    '0026': ['DS', '1', 'RTImageSID'],\n    '0028': ['DS', '1', 'SourceToReferenceObjectDistance'],\n    '0029': ['IS', '1', 'FractionNumber'],\n    '0030': ['SQ', '1', 'ExposureSequence'],\n    '0032': ['DS', '1', 'MetersetExposure'],\n    '0034': ['DS', '4', 'DiaphragmPosition'],\n    '0040': ['SQ', '1', 'FluenceMapSequence'],\n    '0041': ['CS', '1', 'FluenceDataSource'],\n    '0042': ['DS', '1', 'FluenceDataScale'],\n    '0050': ['SQ', '1', 'PrimaryFluenceModeSequence'],\n    '0051': ['CS', '1', 'FluenceMode'],\n    '0052': ['SH', '1', 'FluenceModeID']\n  },\n  '3004': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'DVHType'],\n    '0002': ['CS', '1', 'DoseUnits'],\n    '0004': ['CS', '1', 'DoseType'],\n    '0005': ['CS', '1', 'SpatialTransformOfDose'],\n    '0006': ['LO', '1', 'DoseComment'],\n    '0008': ['DS', '3', 'NormalizationPoint'],\n    '000A': ['CS', '1', 'DoseSummationType'],\n    '000C': ['DS', '2-n', 'GridFrameOffsetVector'],\n    '000E': ['DS', '1', 'DoseGridScaling'],\n    '0010': ['SQ', '1', 'RTDoseROISequence'],\n    '0012': ['DS', '1', 'DoseValue'],\n    '0014': ['CS', '1-3', 'TissueHeterogeneityCorrection'],\n    '0040': ['DS', '3', 'DVHNormalizationPoint'],\n    '0042': ['DS', '1', 'DVHNormalizationDoseValue'],\n    '0050': ['SQ', '1', 'DVHSequence'],\n    '0052': ['DS', '1', 'DVHDoseScaling'],\n    '0054': ['CS', '1', 'DVHVolumeUnits'],\n    '0056': ['IS', '1', 'DVHNumberOfBins'],\n    '0058': ['DS', '2-2n', 'DVHData'],\n    '0060': ['SQ', '1', 'DVHReferencedROISequence'],\n    '0062': ['CS', '1', 'DVHROIContributionType'],\n    '0070': ['DS', '1', 'DVHMinimumDose'],\n    '0072': ['DS', '1', 'DVHMaximumDose'],\n    '0074': ['DS', '1', 'DVHMeanDose']\n  },\n  '3006': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SH', '1', 'StructureSetLabel'],\n    '0004': ['LO', '1', 'StructureSetName'],\n    '0006': ['ST', '1', 'StructureSetDescription'],\n    '0008': ['DA', '1', 'StructureSetDate'],\n    '0009': ['TM', '1', 'StructureSetTime'],\n    '0010': ['SQ', '1', 'ReferencedFrameOfReferenceSequence'],\n    '0012': ['SQ', '1', 'RTReferencedStudySequence'],\n    '0014': ['SQ', '1', 'RTReferencedSeriesSequence'],\n    '0016': ['SQ', '1', 'ContourImageSequence'],\n    '0018': ['SQ', '1', 'PredecessorStructureSetSequence'],\n    '0020': ['SQ', '1', 'StructureSetROISequence'],\n    '0022': ['IS', '1', 'ROINumber'],\n    '0024': ['UI', '1', 'ReferencedFrameOfReferenceUID'],\n    '0026': ['LO', '1', 'ROIName'],\n    '0028': ['ST', '1', 'ROIDescription'],\n    '002A': ['IS', '3', 'ROIDisplayColor'],\n    '002C': ['DS', '1', 'ROIVolume'],\n    '0030': ['SQ', '1', 'RTRelatedROISequence'],\n    '0033': ['CS', '1', 'RTROIRelationship'],\n    '0036': ['CS', '1', 'ROIGenerationAlgorithm'],\n    '0037': ['SQ', '1', 'ROIDerivationAlgorithmIdentificationSequence'],\n    '0038': ['LO', '1', 'ROIGenerationDescription'],\n    '0039': ['SQ', '1', 'ROIContourSequence'],\n    '0040': ['SQ', '1', 'ContourSequence'],\n    '0042': ['CS', '1', 'ContourGeometricType'],\n    '0044': ['DS', '1', 'ContourSlabThickness'],\n    '0045': ['DS', '3', 'ContourOffsetVector'],\n    '0046': ['IS', '1', 'NumberOfContourPoints'],\n    '0048': ['IS', '1', 'ContourNumber'],\n    '0049': ['IS', '1-n', 'AttachedContours'],\n    '004A': ['SQ', '1', 'SourcePixelPlanesCharacteristicsSequence'],\n    '0050': ['DS', '3-3n', 'ContourData'],\n    '0080': ['SQ', '1', 'RTROIObservationsSequence'],\n    '0082': ['IS', '1', 'ObservationNumber'],\n    '0084': ['IS', '1', 'ReferencedROINumber'],\n    '0085': ['SH', '1', 'ROIObservationLabel'],\n    '0086': ['SQ', '1', 'RTROIIdentificationCodeSequence'],\n    '0088': ['ST', '1', 'ROIObservationDescription'],\n    '00A0': ['SQ', '1', 'RelatedRTROIObservationsSequence'],\n    '00A4': ['CS', '1', 'RTROIInterpretedType'],\n    '00A6': ['PN', '1', 'ROIInterpreter'],\n    '00B0': ['SQ', '1', 'ROIPhysicalPropertiesSequence'],\n    '00B2': ['CS', '1', 'ROIPhysicalProperty'],\n    '00B4': ['DS', '1', 'ROIPhysicalPropertyValue'],\n    '00B6': ['SQ', '1', 'ROIElementalCompositionSequence'],\n    '00B7': ['US', '1', 'ROIElementalCompositionAtomicNumber'],\n    '00B8': ['FL', '1', 'ROIElementalCompositionAtomicMassFraction'],\n    '00B9': ['SQ', '1', 'AdditionalRTROIIdentificationCodeSequence'],\n    '00C0': ['SQ', '1', 'FrameOfReferenceRelationshipSequence'],\n    '00C2': ['UI', '1', 'RelatedFrameOfReferenceUID'],\n    '00C4': ['CS', '1', 'FrameOfReferenceTransformationType'],\n    '00C6': ['DS', '16', 'FrameOfReferenceTransformationMatrix'],\n    '00C8': ['LO', '1', 'FrameOfReferenceTransformationComment'],\n    '00C9': ['SQ', '1', 'PatientLocationCoordinatesSequence'],\n    '00CA': ['SQ', '1', 'PatientLocationCoordinatesCodeSequence'],\n    '00CB': ['SQ', '1', 'PatientSupportPositionSequence']\n  },\n  '3008': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['SQ', '1', 'MeasuredDoseReferenceSequence'],\n    '0012': ['ST', '1', 'MeasuredDoseDescription'],\n    '0014': ['CS', '1', 'MeasuredDoseType'],\n    '0016': ['DS', '1', 'MeasuredDoseValue'],\n    '0020': ['SQ', '1', 'TreatmentSessionBeamSequence'],\n    '0021': ['SQ', '1', 'TreatmentSessionIonBeamSequence'],\n    '0022': ['IS', '1', 'CurrentFractionNumber'],\n    '0024': ['DA', '1', 'TreatmentControlPointDate'],\n    '0025': ['TM', '1', 'TreatmentControlPointTime'],\n    '002A': ['CS', '1', 'TreatmentTerminationStatus'],\n    '002B': ['SH', '1', 'TreatmentTerminationCode'],\n    '002C': ['CS', '1', 'TreatmentVerificationStatus'],\n    '0030': ['SQ', '1', 'ReferencedTreatmentRecordSequence'],\n    '0032': ['DS', '1', 'SpecifiedPrimaryMeterset'],\n    '0033': ['DS', '1', 'SpecifiedSecondaryMeterset'],\n    '0036': ['DS', '1', 'DeliveredPrimaryMeterset'],\n    '0037': ['DS', '1', 'DeliveredSecondaryMeterset'],\n    '003A': ['DS', '1', 'SpecifiedTreatmentTime'],\n    '003B': ['DS', '1', 'DeliveredTreatmentTime'],\n    '0040': ['SQ', '1', 'ControlPointDeliverySequence'],\n    '0041': ['SQ', '1', 'IonControlPointDeliverySequence'],\n    '0042': ['DS', '1', 'SpecifiedMeterset'],\n    '0044': ['DS', '1', 'DeliveredMeterset'],\n    '0045': ['FL', '1', 'MetersetRateSet'],\n    '0046': ['FL', '1', 'MetersetRateDelivered'],\n    '0047': ['FL', '1-n', 'ScanSpotMetersetsDelivered'],\n    '0048': ['DS', '1', 'DoseRateDelivered'],\n    '0050': ['SQ', '1', 'TreatmentSummaryCalculatedDoseReferenceSequence'],\n    '0052': ['DS', '1', 'CumulativeDoseToDoseReference'],\n    '0054': ['DA', '1', 'FirstTreatmentDate'],\n    '0056': ['DA', '1', 'MostRecentTreatmentDate'],\n    '005A': ['IS', '1', 'NumberOfFractionsDelivered'],\n    '0060': ['SQ', '1', 'OverrideSequence'],\n    '0061': ['AT', '1', 'ParameterSequencePointer'],\n    '0062': ['AT', '1', 'OverrideParameterPointer'],\n    '0063': ['IS', '1', 'ParameterItemIndex'],\n    '0064': ['IS', '1', 'MeasuredDoseReferenceNumber'],\n    '0065': ['AT', '1', 'ParameterPointer'],\n    '0066': ['ST', '1', 'OverrideReason'],\n    '0067': ['US', '1', 'ParameterValueNumber'],\n    '0068': ['SQ', '1', 'CorrectedParameterSequence'],\n    '006A': ['FL', '1', 'CorrectionValue'],\n    '0070': ['SQ', '1', 'CalculatedDoseReferenceSequence'],\n    '0072': ['IS', '1', 'CalculatedDoseReferenceNumber'],\n    '0074': ['ST', '1', 'CalculatedDoseReferenceDescription'],\n    '0076': ['DS', '1', 'CalculatedDoseReferenceDoseValue'],\n    '0078': ['DS', '1', 'StartMeterset'],\n    '007A': ['DS', '1', 'EndMeterset'],\n    '0080': ['SQ', '1', 'ReferencedMeasuredDoseReferenceSequence'],\n    '0082': ['IS', '1', 'ReferencedMeasuredDoseReferenceNumber'],\n    '0090': ['SQ', '1', 'ReferencedCalculatedDoseReferenceSequence'],\n    '0092': ['IS', '1', 'ReferencedCalculatedDoseReferenceNumber'],\n    '00A0': ['SQ', '1', 'BeamLimitingDeviceLeafPairsSequence'],\n    '00B0': ['SQ', '1', 'RecordedWedgeSequence'],\n    '00C0': ['SQ', '1', 'RecordedCompensatorSequence'],\n    '00D0': ['SQ', '1', 'RecordedBlockSequence'],\n    '00D1': ['SQ', '1', 'RecordedBlockSlabSequence'],\n    '00E0': ['SQ', '1', 'TreatmentSummaryMeasuredDoseReferenceSequence'],\n    '00F0': ['SQ', '1', 'RecordedSnoutSequence'],\n    '00F2': ['SQ', '1', 'RecordedRangeShifterSequence'],\n    '00F4': ['SQ', '1', 'RecordedLateralSpreadingDeviceSequence'],\n    '00F6': ['SQ', '1', 'RecordedRangeModulatorSequence'],\n    '0100': ['SQ', '1', 'RecordedSourceSequence'],\n    '0105': ['LO', '1', 'SourceSerialNumber'],\n    '0110': ['SQ', '1', 'TreatmentSessionApplicationSetupSequence'],\n    '0116': ['CS', '1', 'ApplicationSetupCheck'],\n    '0120': ['SQ', '1', 'RecordedBrachyAccessoryDeviceSequence'],\n    '0122': ['IS', '1', 'ReferencedBrachyAccessoryDeviceNumber'],\n    '0130': ['SQ', '1', 'RecordedChannelSequence'],\n    '0132': ['DS', '1', 'SpecifiedChannelTotalTime'],\n    '0134': ['DS', '1', 'DeliveredChannelTotalTime'],\n    '0136': ['IS', '1', 'SpecifiedNumberOfPulses'],\n    '0138': ['IS', '1', 'DeliveredNumberOfPulses'],\n    '013A': ['DS', '1', 'SpecifiedPulseRepetitionInterval'],\n    '013C': ['DS', '1', 'DeliveredPulseRepetitionInterval'],\n    '0140': ['SQ', '1', 'RecordedSourceApplicatorSequence'],\n    '0142': ['IS', '1', 'ReferencedSourceApplicatorNumber'],\n    '0150': ['SQ', '1', 'RecordedChannelShieldSequence'],\n    '0152': ['IS', '1', 'ReferencedChannelShieldNumber'],\n    '0160': ['SQ', '1', 'BrachyControlPointDeliveredSequence'],\n    '0162': ['DA', '1', 'SafePositionExitDate'],\n    '0164': ['TM', '1', 'SafePositionExitTime'],\n    '0166': ['DA', '1', 'SafePositionReturnDate'],\n    '0168': ['TM', '1', 'SafePositionReturnTime'],\n    '0171': ['SQ', '1', 'PulseSpecificBrachyControlPointDeliveredSequence'],\n    '0172': ['US', '1', 'PulseNumber'],\n    '0173': ['SQ', '1', 'BrachyPulseControlPointDeliveredSequence'],\n    '0200': ['CS', '1', 'CurrentTreatmentStatus'],\n    '0202': ['ST', '1', 'TreatmentStatusComment'],\n    '0220': ['SQ', '1', 'FractionGroupSummarySequence'],\n    '0223': ['IS', '1', 'ReferencedFractionNumber'],\n    '0224': ['CS', '1', 'FractionGroupType'],\n    '0230': ['CS', '1', 'BeamStopperPosition'],\n    '0240': ['SQ', '1', 'FractionStatusSummarySequence'],\n    '0250': ['DA', '1', 'TreatmentDate'],\n    '0251': ['TM', '1', 'TreatmentTime']\n  },\n  '300A': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SH', '1', 'RTPlanLabel'],\n    '0003': ['LO', '1', 'RTPlanName'],\n    '0004': ['ST', '1', 'RTPlanDescription'],\n    '0006': ['DA', '1', 'RTPlanDate'],\n    '0007': ['TM', '1', 'RTPlanTime'],\n    '0009': ['LO', '1-n', 'TreatmentProtocols'],\n    '000A': ['CS', '1', 'PlanIntent'],\n    '000B': ['LO', '1-n', 'TreatmentSites'],\n    '000C': ['CS', '1', 'RTPlanGeometry'],\n    '000E': ['ST', '1', 'PrescriptionDescription'],\n    '0010': ['SQ', '1', 'DoseReferenceSequence'],\n    '0012': ['IS', '1', 'DoseReferenceNumber'],\n    '0013': ['UI', '1', 'DoseReferenceUID'],\n    '0014': ['CS', '1', 'DoseReferenceStructureType'],\n    '0015': ['CS', '1', 'NominalBeamEnergyUnit'],\n    '0016': ['LO', '1', 'DoseReferenceDescription'],\n    '0018': ['DS', '3', 'DoseReferencePointCoordinates'],\n    '001A': ['DS', '1', 'NominalPriorDose'],\n    '0020': ['CS', '1', 'DoseReferenceType'],\n    '0021': ['DS', '1', 'ConstraintWeight'],\n    '0022': ['DS', '1', 'DeliveryWarningDose'],\n    '0023': ['DS', '1', 'DeliveryMaximumDose'],\n    '0025': ['DS', '1', 'TargetMinimumDose'],\n    '0026': ['DS', '1', 'TargetPrescriptionDose'],\n    '0027': ['DS', '1', 'TargetMaximumDose'],\n    '0028': ['DS', '1', 'TargetUnderdoseVolumeFraction'],\n    '002A': ['DS', '1', 'OrganAtRiskFullVolumeDose'],\n    '002B': ['DS', '1', 'OrganAtRiskLimitDose'],\n    '002C': ['DS', '1', 'OrganAtRiskMaximumDose'],\n    '002D': ['DS', '1', 'OrganAtRiskOverdoseVolumeFraction'],\n    '0040': ['SQ', '1', 'ToleranceTableSequence'],\n    '0042': ['IS', '1', 'ToleranceTableNumber'],\n    '0043': ['SH', '1', 'ToleranceTableLabel'],\n    '0044': ['DS', '1', 'GantryAngleTolerance'],\n    '0046': ['DS', '1', 'BeamLimitingDeviceAngleTolerance'],\n    '0048': ['SQ', '1', 'BeamLimitingDeviceToleranceSequence'],\n    '004A': ['DS', '1', 'BeamLimitingDevicePositionTolerance'],\n    '004B': ['FL', '1', 'SnoutPositionTolerance'],\n    '004C': ['DS', '1', 'PatientSupportAngleTolerance'],\n    '004E': ['DS', '1', 'TableTopEccentricAngleTolerance'],\n    '004F': ['FL', '1', 'TableTopPitchAngleTolerance'],\n    '0050': ['FL', '1', 'TableTopRollAngleTolerance'],\n    '0051': ['DS', '1', 'TableTopVerticalPositionTolerance'],\n    '0052': ['DS', '1', 'TableTopLongitudinalPositionTolerance'],\n    '0053': ['DS', '1', 'TableTopLateralPositionTolerance'],\n    '0055': ['CS', '1', 'RTPlanRelationship'],\n    '0070': ['SQ', '1', 'FractionGroupSequence'],\n    '0071': ['IS', '1', 'FractionGroupNumber'],\n    '0072': ['LO', '1', 'FractionGroupDescription'],\n    '0078': ['IS', '1', 'NumberOfFractionsPlanned'],\n    '0079': ['IS', '1', 'NumberOfFractionPatternDigitsPerDay'],\n    '007A': ['IS', '1', 'RepeatFractionCycleLength'],\n    '007B': ['LT', '1', 'FractionPattern'],\n    '0080': ['IS', '1', 'NumberOfBeams'],\n    '0082': ['DS', '3', 'BeamDoseSpecificationPoint'],\n    '0083': ['UI', '1', 'ReferencedDoseReferenceUID'],\n    '0084': ['DS', '1', 'BeamDose'],\n    '0086': ['DS', '1', 'BeamMeterset'],\n    '0088': ['FL', '1', 'BeamDosePointDepth'],\n    '0089': ['FL', '1', 'BeamDosePointEquivalentDepth'],\n    '008A': ['FL', '1', 'BeamDosePointSSD'],\n    '008B': ['CS', '1', 'BeamDoseMeaning'],\n    '008C': ['SQ', '1', 'BeamDoseVerificationControlPointSequence'],\n    '008D': ['FL', '1', 'AverageBeamDosePointDepth'],\n    '008E': ['FL', '1', 'AverageBeamDosePointEquivalentDepth'],\n    '008F': ['FL', '1', 'AverageBeamDosePointSSD'],\n    '0090': ['CS', '1', 'BeamDoseType'],\n    '0091': ['DS', '1', 'AlternateBeamDose'],\n    '0092': ['CS', '1', 'AlternateBeamDoseType'],\n    '0093': ['CS', '1', 'DepthValueAveragingFlag'],\n    '0094': ['DS', '1', 'BeamDosePointSourceToExternalContourDistance'],\n    '00A0': ['IS', '1', 'NumberOfBrachyApplicationSetups'],\n    '00A2': ['DS', '3', 'BrachyApplicationSetupDoseSpecificationPoint'],\n    '00A4': ['DS', '1', 'BrachyApplicationSetupDose'],\n    '00B0': ['SQ', '1', 'BeamSequence'],\n    '00B2': ['SH', '1', 'TreatmentMachineName'],\n    '00B3': ['CS', '1', 'PrimaryDosimeterUnit'],\n    '00B4': ['DS', '1', 'SourceAxisDistance'],\n    '00B6': ['SQ', '1', 'BeamLimitingDeviceSequence'],\n    '00B8': ['CS', '1', 'RTBeamLimitingDeviceType'],\n    '00BA': ['DS', '1', 'SourceToBeamLimitingDeviceDistance'],\n    '00BB': ['FL', '1', 'IsocenterToBeamLimitingDeviceDistance'],\n    '00BC': ['IS', '1', 'NumberOfLeafJawPairs'],\n    '00BE': ['DS', '3-n', 'LeafPositionBoundaries'],\n    '00C0': ['IS', '1', 'BeamNumber'],\n    '00C2': ['LO', '1', 'BeamName'],\n    '00C3': ['ST', '1', 'BeamDescription'],\n    '00C4': ['CS', '1', 'BeamType'],\n    '00C5': ['FD', '1', 'BeamDeliveryDurationLimit'],\n    '00C6': ['CS', '1', 'RadiationType'],\n    '00C7': ['CS', '1', 'HighDoseTechniqueType'],\n    '00C8': ['IS', '1', 'ReferenceImageNumber'],\n    '00CA': ['SQ', '1', 'PlannedVerificationImageSequence'],\n    '00CC': ['LO', '1-n', 'ImagingDeviceSpecificAcquisitionParameters'],\n    '00CE': ['CS', '1', 'TreatmentDeliveryType'],\n    '00D0': ['IS', '1', 'NumberOfWedges'],\n    '00D1': ['SQ', '1', 'WedgeSequence'],\n    '00D2': ['IS', '1', 'WedgeNumber'],\n    '00D3': ['CS', '1', 'WedgeType'],\n    '00D4': ['SH', '1', 'WedgeID'],\n    '00D5': ['IS', '1', 'WedgeAngle'],\n    '00D6': ['DS', '1', 'WedgeFactor'],\n    '00D7': ['FL', '1', 'TotalWedgeTrayWaterEquivalentThickness'],\n    '00D8': ['DS', '1', 'WedgeOrientation'],\n    '00D9': ['FL', '1', 'IsocenterToWedgeTrayDistance'],\n    '00DA': ['DS', '1', 'SourceToWedgeTrayDistance'],\n    '00DB': ['FL', '1', 'WedgeThinEdgePosition'],\n    '00DC': ['SH', '1', 'BolusID'],\n    '00DD': ['ST', '1', 'BolusDescription'],\n    '00DE': ['DS', '1', 'EffectiveWedgeAngle'],\n    '00E0': ['IS', '1', 'NumberOfCompensators'],\n    '00E1': ['SH', '1', 'MaterialID'],\n    '00E2': ['DS', '1', 'TotalCompensatorTrayFactor'],\n    '00E3': ['SQ', '1', 'CompensatorSequence'],\n    '00E4': ['IS', '1', 'CompensatorNumber'],\n    '00E5': ['SH', '1', 'CompensatorID'],\n    '00E6': ['DS', '1', 'SourceToCompensatorTrayDistance'],\n    '00E7': ['IS', '1', 'CompensatorRows'],\n    '00E8': ['IS', '1', 'CompensatorColumns'],\n    '00E9': ['DS', '2', 'CompensatorPixelSpacing'],\n    '00EA': ['DS', '2', 'CompensatorPosition'],\n    '00EB': ['DS', '1-n', 'CompensatorTransmissionData'],\n    '00EC': ['DS', '1-n', 'CompensatorThicknessData'],\n    '00ED': ['IS', '1', 'NumberOfBoli'],\n    '00EE': ['CS', '1', 'CompensatorType'],\n    '00EF': ['SH', '1', 'CompensatorTrayID'],\n    '00F0': ['IS', '1', 'NumberOfBlocks'],\n    '00F2': ['DS', '1', 'TotalBlockTrayFactor'],\n    '00F3': ['FL', '1', 'TotalBlockTrayWaterEquivalentThickness'],\n    '00F4': ['SQ', '1', 'BlockSequence'],\n    '00F5': ['SH', '1', 'BlockTrayID'],\n    '00F6': ['DS', '1', 'SourceToBlockTrayDistance'],\n    '00F7': ['FL', '1', 'IsocenterToBlockTrayDistance'],\n    '00F8': ['CS', '1', 'BlockType'],\n    '00F9': ['LO', '1', 'AccessoryCode'],\n    '00FA': ['CS', '1', 'BlockDivergence'],\n    '00FB': ['CS', '1', 'BlockMountingPosition'],\n    '00FC': ['IS', '1', 'BlockNumber'],\n    '00FE': ['LO', '1', 'BlockName'],\n    '0100': ['DS', '1', 'BlockThickness'],\n    '0102': ['DS', '1', 'BlockTransmission'],\n    '0104': ['IS', '1', 'BlockNumberOfPoints'],\n    '0106': ['DS', '2-2n', 'BlockData'],\n    '0107': ['SQ', '1', 'ApplicatorSequence'],\n    '0108': ['SH', '1', 'ApplicatorID'],\n    '0109': ['CS', '1', 'ApplicatorType'],\n    '010A': ['LO', '1', 'ApplicatorDescription'],\n    '010C': ['DS', '1', 'CumulativeDoseReferenceCoefficient'],\n    '010E': ['DS', '1', 'FinalCumulativeMetersetWeight'],\n    '0110': ['IS', '1', 'NumberOfControlPoints'],\n    '0111': ['SQ', '1', 'ControlPointSequence'],\n    '0112': ['IS', '1', 'ControlPointIndex'],\n    '0114': ['DS', '1', 'NominalBeamEnergy'],\n    '0115': ['DS', '1', 'DoseRateSet'],\n    '0116': ['SQ', '1', 'WedgePositionSequence'],\n    '0118': ['CS', '1', 'WedgePosition'],\n    '011A': ['SQ', '1', 'BeamLimitingDevicePositionSequence'],\n    '011C': ['DS', '2-2n', 'LeafJawPositions'],\n    '011E': ['DS', '1', 'GantryAngle'],\n    '011F': ['CS', '1', 'GantryRotationDirection'],\n    '0120': ['DS', '1', 'BeamLimitingDeviceAngle'],\n    '0121': ['CS', '1', 'BeamLimitingDeviceRotationDirection'],\n    '0122': ['DS', '1', 'PatientSupportAngle'],\n    '0123': ['CS', '1', 'PatientSupportRotationDirection'],\n    '0124': ['DS', '1', 'TableTopEccentricAxisDistance'],\n    '0125': ['DS', '1', 'TableTopEccentricAngle'],\n    '0126': ['CS', '1', 'TableTopEccentricRotationDirection'],\n    '0128': ['DS', '1', 'TableTopVerticalPosition'],\n    '0129': ['DS', '1', 'TableTopLongitudinalPosition'],\n    '012A': ['DS', '1', 'TableTopLateralPosition'],\n    '012C': ['DS', '3', 'IsocenterPosition'],\n    '012E': ['DS', '3', 'SurfaceEntryPoint'],\n    '0130': ['DS', '1', 'SourceToSurfaceDistance'],\n    '0131': ['FL', '1', 'AverageBeamDosePointSourceToExternalContourDistance'],\n    '0132': ['FL', '1', 'SourceToExternalContourDistance'],\n    '0133': ['FL', '3', 'ExternalContourEntryPoint'],\n    '0134': ['DS', '1', 'CumulativeMetersetWeight'],\n    '0140': ['FL', '1', 'TableTopPitchAngle'],\n    '0142': ['CS', '1', 'TableTopPitchRotationDirection'],\n    '0144': ['FL', '1', 'TableTopRollAngle'],\n    '0146': ['CS', '1', 'TableTopRollRotationDirection'],\n    '0148': ['FL', '1', 'HeadFixationAngle'],\n    '014A': ['FL', '1', 'GantryPitchAngle'],\n    '014C': ['CS', '1', 'GantryPitchRotationDirection'],\n    '014E': ['FL', '1', 'GantryPitchAngleTolerance'],\n    '0150': ['CS', '1', 'FixationEye'],\n    '0151': ['DS', '1', 'ChairHeadFramePosition'],\n    '0152': ['DS', '1', 'HeadFixationAngleTolerance'],\n    '0153': ['DS', '1', 'ChairHeadFramePositionTolerance'],\n    '0154': ['DS', '1', 'FixationLightAzimuthalAngleTolerance'],\n    '0155': ['DS', '1', 'FixationLightPolarAngleTolerance'],\n    '0180': ['SQ', '1', 'PatientSetupSequence'],\n    '0182': ['IS', '1', 'PatientSetupNumber'],\n    '0183': ['LO', '1', 'PatientSetupLabel'],\n    '0184': ['LO', '1', 'PatientAdditionalPosition'],\n    '0190': ['SQ', '1', 'FixationDeviceSequence'],\n    '0192': ['CS', '1', 'FixationDeviceType'],\n    '0194': ['SH', '1', 'FixationDeviceLabel'],\n    '0196': ['ST', '1', 'FixationDeviceDescription'],\n    '0198': ['SH', '1', 'FixationDevicePosition'],\n    '0199': ['FL', '1', 'FixationDevicePitchAngle'],\n    '019A': ['FL', '1', 'FixationDeviceRollAngle'],\n    '01A0': ['SQ', '1', 'ShieldingDeviceSequence'],\n    '01A2': ['CS', '1', 'ShieldingDeviceType'],\n    '01A4': ['SH', '1', 'ShieldingDeviceLabel'],\n    '01A6': ['ST', '1', 'ShieldingDeviceDescription'],\n    '01A8': ['SH', '1', 'ShieldingDevicePosition'],\n    '01B0': ['CS', '1', 'SetupTechnique'],\n    '01B2': ['ST', '1', 'SetupTechniqueDescription'],\n    '01B4': ['SQ', '1', 'SetupDeviceSequence'],\n    '01B6': ['CS', '1', 'SetupDeviceType'],\n    '01B8': ['SH', '1', 'SetupDeviceLabel'],\n    '01BA': ['ST', '1', 'SetupDeviceDescription'],\n    '01BC': ['DS', '1', 'SetupDeviceParameter'],\n    '01D0': ['ST', '1', 'SetupReferenceDescription'],\n    '01D2': ['DS', '1', 'TableTopVerticalSetupDisplacement'],\n    '01D4': ['DS', '1', 'TableTopLongitudinalSetupDisplacement'],\n    '01D6': ['DS', '1', 'TableTopLateralSetupDisplacement'],\n    '0200': ['CS', '1', 'BrachyTreatmentTechnique'],\n    '0202': ['CS', '1', 'BrachyTreatmentType'],\n    '0206': ['SQ', '1', 'TreatmentMachineSequence'],\n    '0210': ['SQ', '1', 'SourceSequence'],\n    '0212': ['IS', '1', 'SourceNumber'],\n    '0214': ['CS', '1', 'SourceType'],\n    '0216': ['LO', '1', 'SourceManufacturer'],\n    '0218': ['DS', '1', 'ActiveSourceDiameter'],\n    '021A': ['DS', '1', 'ActiveSourceLength'],\n    '021B': ['SH', '1', 'SourceModelID'],\n    '021C': ['LO', '1', 'SourceDescription'],\n    '0222': ['DS', '1', 'SourceEncapsulationNominalThickness'],\n    '0224': ['DS', '1', 'SourceEncapsulationNominalTransmission'],\n    '0226': ['LO', '1', 'SourceIsotopeName'],\n    '0228': ['DS', '1', 'SourceIsotopeHalfLife'],\n    '0229': ['CS', '1', 'SourceStrengthUnits'],\n    '022A': ['DS', '1', 'ReferenceAirKermaRate'],\n    '022B': ['DS', '1', 'SourceStrength'],\n    '022C': ['DA', '1', 'SourceStrengthReferenceDate'],\n    '022E': ['TM', '1', 'SourceStrengthReferenceTime'],\n    '0230': ['SQ', '1', 'ApplicationSetupSequence'],\n    '0232': ['CS', '1', 'ApplicationSetupType'],\n    '0234': ['IS', '1', 'ApplicationSetupNumber'],\n    '0236': ['LO', '1', 'ApplicationSetupName'],\n    '0238': ['LO', '1', 'ApplicationSetupManufacturer'],\n    '0240': ['IS', '1', 'TemplateNumber'],\n    '0242': ['SH', '1', 'TemplateType'],\n    '0244': ['LO', '1', 'TemplateName'],\n    '0250': ['DS', '1', 'TotalReferenceAirKerma'],\n    '0260': ['SQ', '1', 'BrachyAccessoryDeviceSequence'],\n    '0262': ['IS', '1', 'BrachyAccessoryDeviceNumber'],\n    '0263': ['SH', '1', 'BrachyAccessoryDeviceID'],\n    '0264': ['CS', '1', 'BrachyAccessoryDeviceType'],\n    '0266': ['LO', '1', 'BrachyAccessoryDeviceName'],\n    '026A': ['DS', '1', 'BrachyAccessoryDeviceNominalThickness'],\n    '026C': ['DS', '1', 'BrachyAccessoryDeviceNominalTransmission'],\n    '0271': ['DS', '1', 'ChannelEffectiveLength'],\n    '0272': ['DS', '1', 'ChannelInnerLength'],\n    '0273': ['SH', '1', 'AfterloaderChannelID'],\n    '0274': ['DS', '1', 'SourceApplicatorTipLength'],\n    '0280': ['SQ', '1', 'ChannelSequence'],\n    '0282': ['IS', '1', 'ChannelNumber'],\n    '0284': ['DS', '1', 'ChannelLength'],\n    '0286': ['DS', '1', 'ChannelTotalTime'],\n    '0288': ['CS', '1', 'SourceMovementType'],\n    '028A': ['IS', '1', 'NumberOfPulses'],\n    '028C': ['DS', '1', 'PulseRepetitionInterval'],\n    '0290': ['IS', '1', 'SourceApplicatorNumber'],\n    '0291': ['SH', '1', 'SourceApplicatorID'],\n    '0292': ['CS', '1', 'SourceApplicatorType'],\n    '0294': ['LO', '1', 'SourceApplicatorName'],\n    '0296': ['DS', '1', 'SourceApplicatorLength'],\n    '0298': ['LO', '1', 'SourceApplicatorManufacturer'],\n    '029C': ['DS', '1', 'SourceApplicatorWallNominalThickness'],\n    '029E': ['DS', '1', 'SourceApplicatorWallNominalTransmission'],\n    '02A0': ['DS', '1', 'SourceApplicatorStepSize'],\n    '02A1': ['IS', '1', 'ApplicatorShapeReferencedROINumber'],\n    '02A2': ['IS', '1', 'TransferTubeNumber'],\n    '02A4': ['DS', '1', 'TransferTubeLength'],\n    '02B0': ['SQ', '1', 'ChannelShieldSequence'],\n    '02B2': ['IS', '1', 'ChannelShieldNumber'],\n    '02B3': ['SH', '1', 'ChannelShieldID'],\n    '02B4': ['LO', '1', 'ChannelShieldName'],\n    '02B8': ['DS', '1', 'ChannelShieldNominalThickness'],\n    '02BA': ['DS', '1', 'ChannelShieldNominalTransmission'],\n    '02C8': ['DS', '1', 'FinalCumulativeTimeWeight'],\n    '02D0': ['SQ', '1', 'BrachyControlPointSequence'],\n    '02D2': ['DS', '1', 'ControlPointRelativePosition'],\n    '02D4': ['DS', '3', 'ControlPoint3DPosition'],\n    '02D6': ['DS', '1', 'CumulativeTimeWeight'],\n    '02E0': ['CS', '1', 'CompensatorDivergence'],\n    '02E1': ['CS', '1', 'CompensatorMountingPosition'],\n    '02E2': ['DS', '1-n', 'SourceToCompensatorDistance'],\n    '02E3': ['FL', '1', 'TotalCompensatorTrayWaterEquivalentThickness'],\n    '02E4': ['FL', '1', 'IsocenterToCompensatorTrayDistance'],\n    '02E5': ['FL', '1', 'CompensatorColumnOffset'],\n    '02E6': ['FL', '1-n', 'IsocenterToCompensatorDistances'],\n    '02E7': ['FL', '1', 'CompensatorRelativeStoppingPowerRatio'],\n    '02E8': ['FL', '1', 'CompensatorMillingToolDiameter'],\n    '02EA': ['SQ', '1', 'IonRangeCompensatorSequence'],\n    '02EB': ['LT', '1', 'CompensatorDescription'],\n    '0302': ['IS', '1', 'RadiationMassNumber'],\n    '0304': ['IS', '1', 'RadiationAtomicNumber'],\n    '0306': ['SS', '1', 'RadiationChargeState'],\n    '0308': ['CS', '1', 'ScanMode'],\n    '0309': ['CS', '1', 'ModulatedScanModeType'],\n    '030A': ['FL', '2', 'VirtualSourceAxisDistances'],\n    '030C': ['SQ', '1', 'SnoutSequence'],\n    '030D': ['FL', '1', 'SnoutPosition'],\n    '030F': ['SH', '1', 'SnoutID'],\n    '0312': ['IS', '1', 'NumberOfRangeShifters'],\n    '0314': ['SQ', '1', 'RangeShifterSequence'],\n    '0316': ['IS', '1', 'RangeShifterNumber'],\n    '0318': ['SH', '1', 'RangeShifterID'],\n    '0320': ['CS', '1', 'RangeShifterType'],\n    '0322': ['LO', '1', 'RangeShifterDescription'],\n    '0330': ['IS', '1', 'NumberOfLateralSpreadingDevices'],\n    '0332': ['SQ', '1', 'LateralSpreadingDeviceSequence'],\n    '0334': ['IS', '1', 'LateralSpreadingDeviceNumber'],\n    '0336': ['SH', '1', 'LateralSpreadingDeviceID'],\n    '0338': ['CS', '1', 'LateralSpreadingDeviceType'],\n    '033A': ['LO', '1', 'LateralSpreadingDeviceDescription'],\n    '033C': ['FL', '1', 'LateralSpreadingDeviceWaterEquivalentThickness'],\n    '0340': ['IS', '1', 'NumberOfRangeModulators'],\n    '0342': ['SQ', '1', 'RangeModulatorSequence'],\n    '0344': ['IS', '1', 'RangeModulatorNumber'],\n    '0346': ['SH', '1', 'RangeModulatorID'],\n    '0348': ['CS', '1', 'RangeModulatorType'],\n    '034A': ['LO', '1', 'RangeModulatorDescription'],\n    '034C': ['SH', '1', 'BeamCurrentModulationID'],\n    '0350': ['CS', '1', 'PatientSupportType'],\n    '0352': ['SH', '1', 'PatientSupportID'],\n    '0354': ['LO', '1', 'PatientSupportAccessoryCode'],\n    '0355': ['LO', '1', 'TrayAccessoryCode'],\n    '0356': ['FL', '1', 'FixationLightAzimuthalAngle'],\n    '0358': ['FL', '1', 'FixationLightPolarAngle'],\n    '035A': ['FL', '1', 'MetersetRate'],\n    '0360': ['SQ', '1', 'RangeShifterSettingsSequence'],\n    '0362': ['LO', '1', 'RangeShifterSetting'],\n    '0364': ['FL', '1', 'IsocenterToRangeShifterDistance'],\n    '0366': ['FL', '1', 'RangeShifterWaterEquivalentThickness'],\n    '0370': ['SQ', '1', 'LateralSpreadingDeviceSettingsSequence'],\n    '0372': ['LO', '1', 'LateralSpreadingDeviceSetting'],\n    '0374': ['FL', '1', 'IsocenterToLateralSpreadingDeviceDistance'],\n    '0380': ['SQ', '1', 'RangeModulatorSettingsSequence'],\n    '0382': ['FL', '1', 'RangeModulatorGatingStartValue'],\n    '0384': ['FL', '1', 'RangeModulatorGatingStopValue'],\n    '0386': ['FL', '1', 'RangeModulatorGatingStartWaterEquivalentThickness'],\n    '0388': ['FL', '1', 'RangeModulatorGatingStopWaterEquivalentThickness'],\n    '038A': ['FL', '1', 'IsocenterToRangeModulatorDistance'],\n    '038F': ['FL', '1-n', 'ScanSpotTimeOffset'],\n    '0390': ['SH', '1', 'ScanSpotTuneID'],\n    '0391': ['IS', '1-n', 'ScanSpotPrescribedIndices'],\n    '0392': ['IS', '1', 'NumberOfScanSpotPositions'],\n    '0393': ['CS', '1', 'ScanSpotReordered'],\n    '0394': ['FL', '1-n', 'ScanSpotPositionMap'],\n    '0395': ['CS', '1', 'ScanSpotReorderingAllowed'],\n    '0396': ['FL', '1-n', 'ScanSpotMetersetWeights'],\n    '0398': ['FL', '2', 'ScanningSpotSize'],\n    '0399': ['FL', '2-2n', 'ScanSpotSizesDelivered'],\n    '039A': ['IS', '1', 'NumberOfPaintings'],\n    '03A0': ['SQ', '1', 'IonToleranceTableSequence'],\n    '03A2': ['SQ', '1', 'IonBeamSequence'],\n    '03A4': ['SQ', '1', 'IonBeamLimitingDeviceSequence'],\n    '03A6': ['SQ', '1', 'IonBlockSequence'],\n    '03A8': ['SQ', '1', 'IonControlPointSequence'],\n    '03AA': ['SQ', '1', 'IonWedgeSequence'],\n    '03AC': ['SQ', '1', 'IonWedgePositionSequence'],\n    '0401': ['SQ', '1', 'ReferencedSetupImageSequence'],\n    '0402': ['ST', '1', 'SetupImageComment'],\n    '0410': ['SQ', '1', 'MotionSynchronizationSequence'],\n    '0412': ['FL', '3', 'ControlPointOrientation'],\n    '0420': ['SQ', '1', 'GeneralAccessorySequence'],\n    '0421': ['SH', '1', 'GeneralAccessoryID'],\n    '0422': ['ST', '1', 'GeneralAccessoryDescription'],\n    '0423': ['CS', '1', 'GeneralAccessoryType'],\n    '0424': ['IS', '1', 'GeneralAccessoryNumber'],\n    '0425': ['FL', '1', 'SourceToGeneralAccessoryDistance'],\n    '0426': ['DS', '1', 'IsocenterToGeneralAccessoryDistance'],\n    '0431': ['SQ', '1', 'ApplicatorGeometrySequence'],\n    '0432': ['CS', '1', 'ApplicatorApertureShape'],\n    '0433': ['FL', '1', 'ApplicatorOpening'],\n    '0434': ['FL', '1', 'ApplicatorOpeningX'],\n    '0435': ['FL', '1', 'ApplicatorOpeningY'],\n    '0436': ['FL', '1', 'SourceToApplicatorMountingPositionDistance'],\n    '0440': ['IS', '1', 'NumberOfBlockSlabItems'],\n    '0441': ['SQ', '1', 'BlockSlabSequence'],\n    '0442': ['DS', '1', 'BlockSlabThickness'],\n    '0443': ['US', '1', 'BlockSlabNumber'],\n    '0450': ['SQ', '1', 'DeviceMotionControlSequence'],\n    '0451': ['CS', '1', 'DeviceMotionExecutionMode'],\n    '0452': ['CS', '1', 'DeviceMotionObservationMode'],\n    '0453': ['SQ', '1', 'DeviceMotionParameterCodeSequence'],\n    '0501': ['FL', '1', 'DistalDepthFraction'],\n    '0502': ['FL', '1', 'DistalDepth'],\n    '0503': ['FL', '2', 'NominalRangeModulationFractions'],\n    '0504': ['FL', '2', 'NominalRangeModulatedRegionDepths'],\n    '0505': ['SQ', '1', 'DepthDoseParametersSequence'],\n    '0506': ['SQ', '1', 'DeliveredDepthDoseParametersSequence'],\n    '0507': ['FL', '1', 'DeliveredDistalDepthFraction'],\n    '0508': ['FL', '1', 'DeliveredDistalDepth'],\n    '0509': ['FL', '2', 'DeliveredNominalRangeModulationFractions'],\n    '0510': ['FL', '2', 'DeliveredNominalRangeModulatedRegionDepths'],\n    '0511': ['CS', '1', 'DeliveredReferenceDoseDefinition'],\n    '0512': ['CS', '1', 'ReferenceDoseDefinition'],\n    '0600': ['US', '1', 'RTControlPointIndex'],\n    '0601': ['US', '1', 'RadiationGenerationModeIndex'],\n    '0602': ['US', '1', 'ReferencedDefinedDeviceIndex'],\n    '0603': ['US', '1', 'RadiationDoseIdentificationIndex'],\n    '0604': ['US', '1', 'NumberOfRTControlPoints'],\n    '0605': ['US', '1', 'ReferencedRadiationGenerationModeIndex'],\n    '0606': ['US', '1', 'TreatmentPositionIndex'],\n    '0607': ['US', '1', 'ReferencedDeviceIndex'],\n    '0608': ['LO', '1', 'TreatmentPositionGroupLabel'],\n    '0609': ['UI', '1', 'TreatmentPositionGroupUID'],\n    '060A': ['SQ', '1', 'TreatmentPositionGroupSequence'],\n    '060B': ['US', '1', 'ReferencedTreatmentPositionIndex'],\n    '060C': ['US', '1', 'ReferencedRadiationDoseIdentificationIndex'],\n    '060D': ['FD', '1', 'RTAccessoryHolderWaterEquivalentThickness'],\n    '060E': ['US', '1', 'ReferencedRTAccessoryHolderDeviceIndex'],\n    '060F': ['CS', '1', 'RTAccessoryHolderSlotExistenceFlag'],\n    '0610': ['SQ', '1', 'RTAccessoryHolderSlotSequence'],\n    '0611': ['LO', '1', 'RTAccessoryHolderSlotID'],\n    '0612': ['FD', '1', 'RTAccessoryHolderSlotDistance'],\n    '0613': ['FD', '1', 'RTAccessorySlotDistance'],\n    '0614': ['SQ', '1', 'RTAccessoryHolderDefinitionSequence'],\n    '0615': ['LO', '1', 'RTAccessoryDeviceSlotID'],\n    '0616': ['SQ', '1', 'RTRadiationSequence'],\n    '0617': ['SQ', '1', 'RadiationDoseSequence'],\n    '0618': ['SQ', '1', 'RadiationDoseIdentificationSequence'],\n    '0619': ['LO', '1', 'RadiationDoseIdentificationLabel'],\n    '061A': ['CS', '1', 'ReferenceDoseType'],\n    '061B': ['CS', '1', 'PrimaryDoseValueIndicator'],\n    '061C': ['SQ', '1', 'DoseValuesSequence'],\n    '061D': ['CS', '1-n', 'DoseValuePurpose'],\n    '061E': ['FD', '3', 'ReferenceDosePointCoordinates'],\n    '061F': ['SQ', '1', 'RadiationDoseValuesParametersSequence'],\n    '0620': ['SQ', '1', 'MetersetToDoseMappingSequence'],\n    '0621': ['SQ', '1', 'ExpectedInVivoMeasurementValuesSequence'],\n    '0622': ['US', '1', 'ExpectedInVivoMeasurementValueIndex'],\n    '0623': ['LO', '1', 'RadiationDoseInVivoMeasurementLabel'],\n    '0624': ['FD', '2', 'RadiationDoseCentralAxisDisplacement'],\n    '0625': ['FD', '1', 'RadiationDoseValue'],\n    '0626': ['FD', '1', 'RadiationDoseSourceToSkinDistance'],\n    '0627': ['FD', '3', 'RadiationDoseMeasurementPointCoordinates'],\n    '0628': ['FD', '1', 'RadiationDoseSourceToExternalContourDistance'],\n    '0629': ['SQ', '1', 'RTToleranceSetSequence'],\n    '062A': ['LO', '1', 'RTToleranceSetLabel'],\n    '062B': ['SQ', '1', 'AttributeToleranceValuesSequence'],\n    '062C': ['FD', '1', 'ToleranceValue'],\n    '062D': ['SQ', '1', 'PatientSupportPositionToleranceSequence'],\n    '062E': ['FD', '1', 'TreatmentTimeLimit'],\n    '062F': ['SQ', '1', 'CArmPhotonElectronControlPointSequence'],\n    '0630': ['SQ', '1', 'ReferencedRTRadiationSequence'],\n    '0631': ['SQ', '1', 'ReferencedRTInstanceSequence'],\n    '0632': ['SQ', '1', 'ReferencedRTPatientSetupSequence'],\n    '0634': ['FD', '1', 'SourceToPatientSurfaceDistance'],\n    '0635': ['SQ', '1', 'TreatmentMachineSpecialModeCodeSequence'],\n    '0636': ['US', '1', 'IntendedNumberOfFractions'],\n    '0637': ['CS', '1', 'RTRadiationSetIntent'],\n    '0638': ['CS', '1', 'RTRadiationPhysicalAndGeometricContentDetailFlag'],\n    '0639': ['CS', '1', 'RTRecordFlag'],\n    '063A': ['SQ', '1', 'TreatmentDeviceIdentificationSequence'],\n    '063B': ['SQ', '1', 'ReferencedRTPhysicianIntentSequence'],\n    '063C': ['FD', '1', 'CumulativeMeterset'],\n    '063D': ['FD', '1', 'DeliveryRate'],\n    '063E': ['SQ', '1', 'DeliveryRateUnitSequence'],\n    '063F': ['SQ', '1', 'TreatmentPositionSequence'],\n    '0640': ['FD', '1', 'RadiationSourceAxisDistance'],\n    '0641': ['US', '1', 'NumberOfRTBeamLimitingDevices'],\n    '0642': ['FD', '1', 'RTBeamLimitingDeviceProximalDistance'],\n    '0643': ['FD', '1', 'RTBeamLimitingDeviceDistalDistance'],\n    '0644': ['SQ', '1', 'ParallelRTBeamDelimiterDeviceOrientationLabelCodeSequence'],\n    '0645': ['FD', '1', 'BeamModifierOrientationAngle'],\n    '0646': ['SQ', '1', 'FixedRTBeamDelimiterDeviceSequence'],\n    '0647': ['SQ', '1', 'ParallelRTBeamDelimiterDeviceSequence'],\n    '0648': ['US', '1', 'NumberOfParallelRTBeamDelimiters'],\n    '0649': ['FD', '2-n', 'ParallelRTBeamDelimiterBoundaries'],\n    '064A': ['FD', '2-n', 'ParallelRTBeamDelimiterPositions'],\n    '064B': ['FD', '2', 'RTBeamLimitingDeviceOffset'],\n    '064C': ['SQ', '1', 'RTBeamDelimiterGeometrySequence'],\n    '064D': ['SQ', '1', 'RTBeamLimitingDeviceDefinitionSequence'],\n    '064E': ['CS', '1', 'ParallelRTBeamDelimiterOpeningMode'],\n    '064F': ['CS', '1-n', 'ParallelRTBeamDelimiterLeafMountingSide'],\n    '0650': ['UI', '1', 'PatientSetupUID'],\n    '0651': ['SQ', '1', 'WedgeDefinitionSequence'],\n    '0652': ['FD', '1', 'RadiationBeamWedgeAngle'],\n    '0653': ['FD', '1', 'RadiationBeamWedgeThinEdgeDistance'],\n    '0654': ['FD', '1', 'RadiationBeamEffectiveWedgeAngle'],\n    '0655': ['US', '1', 'NumberOfWedgePositions'],\n    '0656': ['SQ', '1', 'RTBeamLimitingDeviceOpeningSequence'],\n    '0657': ['US', '1', 'NumberOfRTBeamLimitingDeviceOpenings'],\n    '0658': ['SQ', '1', 'RadiationDosimeterUnitSequence'],\n    '0659': ['SQ', '1', 'RTDeviceDistanceReferenceLocationCodeSequence'],\n    '065A': ['SQ', '1', 'RadiationDeviceConfigurationAndCommissioningKeySequence'],\n    '065B': ['SQ', '1', 'PatientSupportPositionParameterSequence'],\n    '065C': ['CS', '1', 'PatientSupportPositionSpecificationMethod'],\n    '065D': ['SQ', '1', 'PatientSupportPositionDeviceParameterSequence'],\n    '065E': ['US', '1', 'DeviceOrderIndex'],\n    '065F': ['US', '1', 'PatientSupportPositionParameterOrderIndex'],\n    '0660': ['SQ', '1', 'PatientSupportPositionDeviceToleranceSequence'],\n    '0661': ['US', '1', 'PatientSupportPositionToleranceOrderIndex'],\n    '0662': ['SQ', '1', 'CompensatorDefinitionSequence'],\n    '0663': ['CS', '1', 'CompensatorMapOrientation'],\n    '0664': ['OF', '1', 'CompensatorProximalThicknessMap'],\n    '0665': ['OF', '1', 'CompensatorDistalThicknessMap'],\n    '0666': ['FD', '1', 'CompensatorBasePlaneOffset'],\n    '0667': ['SQ', '1', 'CompensatorShapeFabricationCodeSequence'],\n    '0668': ['SQ', '1', 'CompensatorShapeSequence'],\n    '0669': ['FD', '1', 'RadiationBeamCompensatorMillingToolDiameter'],\n    '066A': ['SQ', '1', 'BlockDefinitionSequence'],\n    '066B': ['OF', '1', 'BlockEdgeData'],\n    '066C': ['CS', '1', 'BlockOrientation'],\n    '066D': ['FD', '1', 'RadiationBeamBlockThickness'],\n    '066E': ['FD', '1', 'RadiationBeamBlockSlabThickness'],\n    '066F': ['SQ', '1', 'BlockEdgeDataSequence'],\n    '0670': ['US', '1', 'NumberOfRTAccessoryHolders'],\n    '0671': ['SQ', '1', 'GeneralAccessoryDefinitionSequence'],\n    '0672': ['US', '1', 'NumberOfGeneralAccessories'],\n    '0673': ['SQ', '1', 'BolusDefinitionSequence'],\n    '0674': ['US', '1', 'NumberOfBoluses'],\n    '0675': ['UI', '1', 'EquipmentFrameOfReferenceUID'],\n    '0676': ['ST', '1', 'EquipmentFrameOfReferenceDescription'],\n    '0677': ['SQ', '1', 'EquipmentReferencePointCoordinatesSequence'],\n    '0678': ['SQ', '1', 'EquipmentReferencePointCodeSequence'],\n    '0679': ['FD', '1', 'RTBeamLimitingDeviceAngle'],\n    '067A': ['FD', '1', 'SourceRollAngle'],\n    '067B': ['SQ', '1', 'RadiationGenerationModeSequence'],\n    '067C': ['SH', '1', 'RadiationGenerationModeLabel'],\n    '067D': ['ST', '1', 'RadiationGenerationModeDescription'],\n    '067E': ['SQ', '1', 'RadiationGenerationModeMachineCodeSequence'],\n    '067F': ['SQ', '1', 'RadiationTypeCodeSequence'],\n    '0680': ['DS', '1', 'NominalEnergy'],\n    '0681': ['DS', '1', 'MinimumNominalEnergy'],\n    '0682': ['DS', '1', 'MaximumNominalEnergy'],\n    '0683': ['SQ', '1', 'RadiationFluenceModifierCodeSequence'],\n    '0684': ['SQ', '1', 'EnergyUnitCodeSequence'],\n    '0685': ['US', '1', 'NumberOfRadiationGenerationModes'],\n    '0686': ['SQ', '1', 'PatientSupportDevicesSequence'],\n    '0687': ['US', '1', 'NumberOfPatientSupportDevices'],\n    '0688': ['FD', '1', 'RTBeamModifierDefinitionDistance'],\n    '0689': ['SQ', '1', 'BeamAreaLimitSequence'],\n    '068A': ['SQ', '1', 'ReferencedRTPrescriptionSequence'],\n    '0700': ['UI', '1', 'TreatmentSessionUID'],\n    '0701': ['CS', '1', 'RTRadiationUsage'],\n    '0702': ['SQ', '1', 'ReferencedRTRadiationSetSequence'],\n    '0703': ['SQ', '1', 'ReferencedRTRadiationRecordSequence'],\n    '0704': ['US', '1', 'RTRadiationSetDeliveryNumber'],\n    '0705': ['US', '1', 'ClinicalFractionNumber'],\n    '0706': ['CS', '1', 'RTTreatmentFractionCompletionStatus'],\n    '0707': ['CS', '1', 'RTRadiationSetUsage'],\n    '0708': ['CS', '1', 'TreatmentDeliveryContinuationFlag'],\n    '0709': ['CS', '1', 'TreatmentRecordContentOrigin'],\n    '0714': ['CS', '1', 'RTTreatmentTerminationStatus'],\n    '0715': ['SQ', '1', 'RTTreatmentTerminationReasonCodeSequence'],\n    '0716': ['SQ', '1', 'MachineSpecificTreatmentTerminationCodeSequence'],\n    '0722': ['SQ', '1', 'RTRadiationSalvageRecordControlPointSequence'],\n    '0723': ['CS', '1', 'StartingMetersetValueKnownFlag'],\n    '0730': ['ST', '1', 'TreatmentTerminationDescription'],\n    '0731': ['SQ', '1', 'TreatmentToleranceViolationSequence'],\n    '0732': ['CS', '1', 'TreatmentToleranceViolationCategory'],\n    '0733': ['SQ', '1', 'TreatmentToleranceViolationAttributeSequence'],\n    '0734': ['ST', '1', 'TreatmentToleranceViolationDescription'],\n    '0735': ['ST', '1', 'TreatmentToleranceViolationIdentification'],\n    '0736': ['DT', '1', 'TreatmentToleranceViolationDateTime'],\n    '073A': ['DT', '1', 'RecordedRTControlPointDateTime'],\n    '073B': ['US', '1', 'ReferencedRadiationRTControlPointIndex'],\n    '073E': ['SQ', '1', 'AlternateValueSequence'],\n    '073F': ['SQ', '1', 'ConfirmationSequence'],\n    '0740': ['SQ', '1', 'InterlockSequence'],\n    '0741': ['DT', '1', 'InterlockDateTime'],\n    '0742': ['ST', '1', 'InterlockDescription'],\n    '0743': ['SQ', '1', 'InterlockOriginatingDeviceSequence'],\n    '0744': ['SQ', '1', 'InterlockCodeSequence'],\n    '0745': ['SQ', '1', 'InterlockResolutionCodeSequence'],\n    '0746': ['SQ', '1', 'InterlockResolutionUserSequence'],\n    '0760': ['DT', '1', 'OverrideDateTime'],\n    '0761': ['SQ', '1', 'TreatmentToleranceViolationTypeCodeSequence'],\n    '0762': ['SQ', '1', 'TreatmentToleranceViolationCauseCodeSequence'],\n    '0772': ['SQ', '1', 'MeasuredMetersetToDoseMappingSequence'],\n    '0773': ['US', '1', 'ReferencedExpectedInVivoMeasurementValueIndex'],\n    '0774': ['SQ', '1', 'DoseMeasurementDeviceCodeSequence'],\n    '0780': ['SQ', '1', 'AdditionalParameterRecordingInstanceSequence'],\n    '0782': ['US', '1', ''],\n    '0783': ['ST', '1', 'InterlockOriginDescription'],\n    '0784': ['SQ', '1', 'RTPatientPositionScopeSequence'],\n    '0785': ['UI', '1', 'ReferencedTreatmentPositionGroupUID'],\n    '0786': ['US', '1', 'RadiationOrderIndex'],\n    '0787': ['SQ', '1', 'OmittedRadiationSequence'],\n    '0788': ['SQ', '1', 'ReasonForOmissionCodeSequence'],\n    '0789': ['SQ', '1', 'RTDeliveryStartPatientPositionSequence'],\n    '078A': ['SQ', '1', 'RTTreatmentPreparationPatientPositionSequence'],\n    '078B': ['SQ', '1', 'ReferencedRTTreatmentPreparationSequence'],\n    '078C': ['SQ', '1', 'ReferencedPatientSetupPhotoSequence'],\n    '078D': ['SQ', '1', 'PatientTreatmentPreparationMethodCodeSequence'],\n    '078E': ['LT', '1', 'PatientTreatmentPreparationProcedureParameterDescription'],\n    '078F': ['SQ', '1', 'PatientTreatmentPreparationDeviceSequence'],\n    '0790': ['SQ', '1', 'PatientTreatmentPreparationProcedureSequence'],\n    '0791': ['SQ', '1', 'PatientTreatmentPreparationProcedureCodeSequence'],\n    '0792': ['LT', '1', 'PatientTreatmentPreparationMethodDescription'],\n    '0793': ['SQ', '1', 'PatientTreatmentPreparationProcedureParameterSequence'],\n    '0794': ['LT', '1', 'PatientSetupPhotoDescription'],\n    '0795': ['US', '1', 'PatientTreatmentPreparationProcedureIndex'],\n    '0796': ['US', '1', 'ReferencedPatientSetupProcedureIndex'],\n    '0797': ['SQ', '1', 'RTRadiationTaskSequence'],\n    '0798': ['SQ', '1', 'RTPatientPositionDisplacementSequence'],\n    '0799': ['SQ', '1', 'RTPatientPositionSequence'],\n    '079A': ['LO', '1', 'DisplacementReferenceLabel'],\n    '079B': ['FD', '16', 'DisplacementMatrix'],\n    '079C': ['SQ', '1', 'PatientSupportDisplacementSequence'],\n    '079D': ['SQ', '1', 'DisplacementReferenceLocationCodeSequence'],\n    '079E': ['CS', '1', 'RTRadiationSetDeliveryUsage']\n  },\n  '300C': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['SQ', '1', 'ReferencedRTPlanSequence'],\n    '0004': ['SQ', '1', 'ReferencedBeamSequence'],\n    '0006': ['IS', '1', 'ReferencedBeamNumber'],\n    '0007': ['IS', '1', 'ReferencedReferenceImageNumber'],\n    '0008': ['DS', '1', 'StartCumulativeMetersetWeight'],\n    '0009': ['DS', '1', 'EndCumulativeMetersetWeight'],\n    '000A': ['SQ', '1', 'ReferencedBrachyApplicationSetupSequence'],\n    '000C': ['IS', '1', 'ReferencedBrachyApplicationSetupNumber'],\n    '000E': ['IS', '1', 'ReferencedSourceNumber'],\n    '0020': ['SQ', '1', 'ReferencedFractionGroupSequence'],\n    '0022': ['IS', '1', 'ReferencedFractionGroupNumber'],\n    '0040': ['SQ', '1', 'ReferencedVerificationImageSequence'],\n    '0042': ['SQ', '1', 'ReferencedReferenceImageSequence'],\n    '0050': ['SQ', '1', 'ReferencedDoseReferenceSequence'],\n    '0051': ['IS', '1', 'ReferencedDoseReferenceNumber'],\n    '0055': ['SQ', '1', 'BrachyReferencedDoseReferenceSequence'],\n    '0060': ['SQ', '1', 'ReferencedStructureSetSequence'],\n    '006A': ['IS', '1', 'ReferencedPatientSetupNumber'],\n    '0080': ['SQ', '1', 'ReferencedDoseSequence'],\n    '00A0': ['IS', '1', 'ReferencedToleranceTableNumber'],\n    '00B0': ['SQ', '1', 'ReferencedBolusSequence'],\n    '00C0': ['IS', '1', 'ReferencedWedgeNumber'],\n    '00D0': ['IS', '1', 'ReferencedCompensatorNumber'],\n    '00E0': ['IS', '1', 'ReferencedBlockNumber'],\n    '00F0': ['IS', '1', 'ReferencedControlPointIndex'],\n    '00F2': ['SQ', '1', 'ReferencedControlPointSequence'],\n    '00F4': ['IS', '1', 'ReferencedStartControlPointIndex'],\n    '00F6': ['IS', '1', 'ReferencedStopControlPointIndex'],\n    '0100': ['IS', '1', 'ReferencedRangeShifterNumber'],\n    '0102': ['IS', '1', 'ReferencedLateralSpreadingDeviceNumber'],\n    '0104': ['IS', '1', 'ReferencedRangeModulatorNumber'],\n    '0111': ['SQ', '1', 'OmittedBeamTaskSequence'],\n    '0112': ['CS', '1', 'ReasonForOmission'],\n    '0113': ['LO', '1', 'ReasonForOmissionDescription'],\n    '0114': ['SQ', '1', 'PrescriptionOverviewSequence'],\n    '0115': ['FL', '1', 'TotalPrescriptionDose'],\n    '0116': ['SQ', '1', 'PlanOverviewSequence'],\n    '0117': ['US', '1', 'PlanOverviewIndex'],\n    '0118': ['US', '1', 'ReferencedPlanOverviewIndex'],\n    '0119': ['US', '1', 'NumberOfFractionsIncluded'],\n    '0120': ['SQ', '1', 'DoseCalibrationConditionsSequence'],\n    '0121': ['FD', '1', 'AbsorbedDoseToMetersetRatio'],\n    '0122': ['FD', '2', 'DelineatedRadiationFieldSize'],\n    '0123': ['CS', '1', 'DoseCalibrationConditionsVerifiedFlag'],\n    '0124': ['FD', '1', 'CalibrationReferencePointDepth'],\n    '0125': ['SQ', '1', 'GatingBeamHoldTransitionSequence'],\n    '0126': ['CS', '1', 'BeamHoldTransition'],\n    '0127': ['DT', '1', 'BeamHoldTransitionDateTime'],\n    '0128': ['SQ', '1', 'BeamHoldOriginatingDeviceSequence']\n  },\n  '300E': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0002': ['CS', '1', 'ApprovalStatus'],\n    '0004': ['DA', '1', 'ReviewDate'],\n    '0005': ['TM', '1', 'ReviewTime'],\n    '0008': ['PN', '1', 'ReviewerName']\n  },\n  '3010': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['SQ', '1', 'RadiobiologicalDoseEffectSequence'],\n    '0002': ['CS', '1', 'RadiobiologicalDoseEffectFlag'],\n    '0003': ['SQ', '1', 'EffectiveDoseCalculationMethodCategoryCodeSequence'],\n    '0004': ['SQ', '1', 'EffectiveDoseCalculationMethodCodeSequence'],\n    '0005': ['LO', '1', 'EffectiveDoseCalculationMethodDescription'],\n    '0006': ['UI', '1', 'ConceptualVolumeUID'],\n    '0007': ['SQ', '1', 'OriginatingSOPInstanceReferenceSequence'],\n    '0008': ['SQ', '1', 'ConceptualVolumeConstituentSequence'],\n    '0009': ['SQ', '1', 'EquivalentConceptualVolumeInstanceReferenceSequence'],\n    '000A': ['SQ', '1', 'EquivalentConceptualVolumesSequence'],\n    '000B': ['UI', '1', 'ReferencedConceptualVolumeUID'],\n    '000C': ['UT', '1', 'ConceptualVolumeCombinationExpression'],\n    '000D': ['US', '1', 'ConceptualVolumeConstituentIndex'],\n    '000E': ['CS', '1', 'ConceptualVolumeCombinationFlag'],\n    '000F': ['ST', '1', 'ConceptualVolumeCombinationDescription'],\n    '0010': ['CS', '1', 'ConceptualVolumeSegmentationDefinedFlag'],\n    '0011': ['SQ', '1', 'ConceptualVolumeSegmentationReferenceSequence'],\n    '0012': ['SQ', '1', 'ConceptualVolumeConstituentSegmentationReferenceSequence'],\n    '0013': ['UI', '1', 'ConstituentConceptualVolumeUID'],\n    '0014': ['SQ', '1', 'DerivationConceptualVolumeSequence'],\n    '0015': ['UI', '1', 'SourceConceptualVolumeUID'],\n    '0016': ['SQ', '1', 'ConceptualVolumeDerivationAlgorithmSequence'],\n    '0017': ['ST', '1', 'ConceptualVolumeDescription'],\n    '0018': ['SQ', '1', 'SourceConceptualVolumeSequence'],\n    '0019': ['SQ', '1', 'AuthorIdentificationSequence'],\n    '001A': ['LO', '1', 'ManufacturerModelVersion'],\n    '001B': ['UC', '1', 'DeviceAlternateIdentifier'],\n    '001C': ['CS', '1', 'DeviceAlternateIdentifierType'],\n    '001D': ['LT', '1', 'DeviceAlternateIdentifierFormat'],\n    '001E': ['LO', '1', 'SegmentationCreationTemplateLabel'],\n    '001F': ['UI', '1', 'SegmentationTemplateUID'],\n    '0020': ['US', '1', 'ReferencedSegmentReferenceIndex'],\n    '0021': ['SQ', '1', 'SegmentReferenceSequence'],\n    '0022': ['US', '1', 'SegmentReferenceIndex'],\n    '0023': ['SQ', '1', 'DirectSegmentReferenceSequence'],\n    '0024': ['SQ', '1', 'CombinationSegmentReferenceSequence'],\n    '0025': ['SQ', '1', 'ConceptualVolumeSequence'],\n    '0026': ['SQ', '1', 'SegmentedRTAccessoryDeviceSequence'],\n    '0027': ['SQ', '1', 'SegmentCharacteristicsSequence'],\n    '0028': ['SQ', '1', 'RelatedSegmentCharacteristicsSequence'],\n    '0029': ['US', '1', 'SegmentCharacteristicsPrecedence'],\n    '002A': ['SQ', '1', 'RTSegmentAnnotationSequence'],\n    '002B': ['SQ', '1', 'SegmentAnnotationCategoryCodeSequence'],\n    '002C': ['SQ', '1', 'SegmentAnnotationTypeCodeSequence'],\n    '002D': ['LO', '1', 'DeviceLabel'],\n    '002E': ['SQ', '1', 'DeviceTypeCodeSequence'],\n    '002F': ['SQ', '1', 'SegmentAnnotationTypeModifierCodeSequence'],\n    '0030': ['SQ', '1', 'PatientEquipmentRelationshipCodeSequence'],\n    '0031': ['UI', '1', 'ReferencedFiducialsUID'],\n    '0032': ['SQ', '1', 'PatientTreatmentOrientationSequence'],\n    '0033': ['SH', '1', 'UserContentLabel'],\n    '0034': ['LO', '1', 'UserContentLongLabel'],\n    '0035': ['SH', '1', 'EntityLabel'],\n    '0036': ['LO', '1', 'EntityName'],\n    '0037': ['ST', '1', 'EntityDescription'],\n    '0038': ['LO', '1', 'EntityLongLabel'],\n    '0039': ['US', '1', 'DeviceIndex'],\n    '003A': ['US', '1', 'RTTreatmentPhaseIndex'],\n    '003B': ['UI', '1', 'RTTreatmentPhaseUID'],\n    '003C': ['US', '1', 'RTPrescriptionIndex'],\n    '003D': ['US', '1', 'RTSegmentAnnotationIndex'],\n    '003E': ['US', '1', 'BasisRTTreatmentPhaseIndex'],\n    '003F': ['US', '1', 'RelatedRTTreatmentPhaseIndex'],\n    '0040': ['US', '1', 'ReferencedRTTreatmentPhaseIndex'],\n    '0041': ['US', '1', 'ReferencedRTPrescriptionIndex'],\n    '0042': ['US', '1', 'ReferencedParentRTPrescriptionIndex'],\n    '0043': ['ST', '1', 'ManufacturerDeviceIdentifier'],\n    '0044': ['SQ', '1', 'InstanceLevelReferencedPerformedProcedureStepSequence'],\n    '0045': ['CS', '1', 'RTTreatmentPhaseIntentPresenceFlag'],\n    '0046': ['CS', '1', 'RadiotherapyTreatmentType'],\n    '0047': ['CS', '1-n', 'TeletherapyRadiationType'],\n    '0048': ['CS', '1-n', 'BrachytherapySourceType'],\n    '0049': ['SQ', '1', 'ReferencedRTTreatmentPhaseSequence'],\n    '004A': ['SQ', '1', 'ReferencedDirectSegmentInstanceSequence'],\n    '004B': ['SQ', '1', 'IntendedRTTreatmentPhaseSequence'],\n    '004C': ['DA', '1', 'IntendedPhaseStartDate'],\n    '004D': ['DA', '1', 'IntendedPhaseEndDate'],\n    '004E': ['SQ', '1', 'RTTreatmentPhaseIntervalSequence'],\n    '004F': ['CS', '1', 'TemporalRelationshipIntervalAnchor'],\n    '0050': ['FD', '1', 'MinimumNumberOfIntervalDays'],\n    '0051': ['FD', '1', 'MaximumNumberOfIntervalDays'],\n    '0052': ['UI', '1-n', 'PertinentSOPClassesInStudy'],\n    '0053': ['UI', '1-n', 'PertinentSOPClassesInSeries'],\n    '0054': ['LO', '1', 'RTPrescriptionLabel'],\n    '0055': ['SQ', '1', 'RTPhysicianIntentPredecessorSequence'],\n    '0056': ['LO', '1', 'RTTreatmentApproachLabel'],\n    '0057': ['SQ', '1', 'RTPhysicianIntentSequence'],\n    '0058': ['US', '1', 'RTPhysicianIntentIndex'],\n    '0059': ['CS', '1', 'RTTreatmentIntentType'],\n    '005A': ['UT', '1', 'RTPhysicianIntentNarrative'],\n    '005B': ['SQ', '1', 'RTProtocolCodeSequence'],\n    '005C': ['ST', '1', 'ReasonForSuperseding'],\n    '005D': ['SQ', '1', 'RTDiagnosisCodeSequence'],\n    '005E': ['US', '1', 'ReferencedRTPhysicianIntentIndex'],\n    '005F': ['SQ', '1', 'RTPhysicianIntentInputInstanceSequence'],\n    '0060': ['SQ', '1', 'RTAnatomicPrescriptionSequence'],\n    '0061': ['UT', '1', 'PriorTreatmentDoseDescription'],\n    '0062': ['SQ', '1', 'PriorTreatmentReferenceSequence'],\n    '0063': ['CS', '1', 'DosimetricObjectiveEvaluationScope'],\n    '0064': ['SQ', '1', 'TherapeuticRoleCategoryCodeSequence'],\n    '0065': ['SQ', '1', 'TherapeuticRoleTypeCodeSequence'],\n    '0066': ['US', '1', 'ConceptualVolumeOptimizationPrecedence'],\n    '0067': ['SQ', '1', 'ConceptualVolumeCategoryCodeSequence'],\n    '0068': ['CS', '1', 'ConceptualVolumeBlockingConstraint'],\n    '0069': ['SQ', '1', 'ConceptualVolumeTypeCodeSequence'],\n    '006A': ['SQ', '1', 'ConceptualVolumeTypeModifierCodeSequence'],\n    '006B': ['SQ', '1', 'RTPrescriptionSequence'],\n    '006C': ['SQ', '1', 'DosimetricObjectiveSequence'],\n    '006D': ['SQ', '1', 'DosimetricObjectiveTypeCodeSequence'],\n    '006E': ['UI', '1', 'DosimetricObjectiveUID'],\n    '006F': ['UI', '1', 'ReferencedDosimetricObjectiveUID'],\n    '0070': ['SQ', '1', 'DosimetricObjectiveParameterSequence'],\n    '0071': ['SQ', '1', 'ReferencedDosimetricObjectivesSequence'],\n    '0073': ['CS', '1', 'AbsoluteDosimetricObjectiveFlag'],\n    '0074': ['FD', '1', 'DosimetricObjectiveWeight'],\n    '0075': ['CS', '1', 'DosimetricObjectivePurpose'],\n    '0076': ['SQ', '1', 'PlanningInputInformationSequence'],\n    '0077': ['LO', '1', 'TreatmentSite'],\n    '0078': ['SQ', '1', 'TreatmentSiteCodeSequence'],\n    '0079': ['SQ', '1', 'FractionPatternSequence'],\n    '007A': ['UT', '1', 'TreatmentTechniqueNotes'],\n    '007B': ['UT', '1', 'PrescriptionNotes'],\n    '007C': ['IS', '1', 'NumberOfIntervalFractions'],\n    '007D': ['US', '1', 'NumberOfFractions'],\n    '007E': ['US', '1', 'IntendedDeliveryDuration'],\n    '007F': ['UT', '1', 'FractionationNotes'],\n    '0080': ['SQ', '1', 'RTTreatmentTechniqueCodeSequence'],\n    '0081': ['SQ', '1', 'PrescriptionNotesSequence'],\n    '0082': ['SQ', '1', 'FractionBasedRelationshipSequence'],\n    '0083': ['CS', '1', 'FractionBasedRelationshipIntervalAnchor'],\n    '0084': ['FD', '1', 'MinimumHoursBetweenFractions'],\n    '0085': ['TM', '1-n', 'IntendedFractionStartTime'],\n    '0086': ['LT', '1', 'IntendedStartDayOfWeek'],\n    '0087': ['SQ', '1', 'WeekdayFractionPatternSequence'],\n    '0088': ['SQ', '1', 'DeliveryTimeStructureCodeSequence'],\n    '0089': ['SQ', '1', 'TreatmentSiteModifierCodeSequence'],\n    '0090': ['CS', '1', 'RoboticBaseLocationIndicator'],\n    '0091': ['SQ', '1', 'RoboticPathNodeSetCodeSequence'],\n    '0092': ['UL', '1', 'RoboticNodeIdentifier'],\n    '0093': ['FD', '3', 'RTTreatmentSourceCoordinates'],\n    '0094': ['FD', '1', 'RadiationSourceCoordinateSystemYawAngle'],\n    '0095': ['FD', '1', 'RadiationSourceCoordinateSystemRollAngle'],\n    '0096': ['FD', '1', 'RadiationSourceCoordinateSystemPitchAngle'],\n    '0097': ['SQ', '1', 'RoboticPathControlPointSequence'],\n    '0098': ['SQ', '1', 'TomotherapeuticControlPointSequence'],\n    '0099': ['FD', '1-n', 'TomotherapeuticLeafOpenDurations'],\n    '009A': ['FD', '1-n', 'TomotherapeuticLeafInitialClosedDurations']\n  },\n  '4000': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['LT', '1', 'Arbitrary'],\n    '4000': ['LT', '1', 'TextComments']\n  },\n  '4008': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0040': ['SH', '1', 'ResultsID'],\n    '0042': ['LO', '1', 'ResultsIDIssuer'],\n    '0050': ['SQ', '1', 'ReferencedInterpretationSequence'],\n    '00FF': ['CS', '1', 'ReportProductionStatusTrial'],\n    '0100': ['DA', '1', 'InterpretationRecordedDate'],\n    '0101': ['TM', '1', 'InterpretationRecordedTime'],\n    '0102': ['PN', '1', 'InterpretationRecorder'],\n    '0103': ['LO', '1', 'ReferenceToRecordedSound'],\n    '0108': ['DA', '1', 'InterpretationTranscriptionDate'],\n    '0109': ['TM', '1', 'InterpretationTranscriptionTime'],\n    '010A': ['PN', '1', 'InterpretationTranscriber'],\n    '010B': ['ST', '1', 'InterpretationText'],\n    '010C': ['PN', '1', 'InterpretationAuthor'],\n    '0111': ['SQ', '1', 'InterpretationApproverSequence'],\n    '0112': ['DA', '1', 'InterpretationApprovalDate'],\n    '0113': ['TM', '1', 'InterpretationApprovalTime'],\n    '0114': ['PN', '1', 'PhysicianApprovingInterpretation'],\n    '0115': ['LT', '1', 'InterpretationDiagnosisDescription'],\n    '0117': ['SQ', '1', 'InterpretationDiagnosisCodeSequence'],\n    '0118': ['SQ', '1', 'ResultsDistributionListSequence'],\n    '0119': ['PN', '1', 'DistributionName'],\n    '011A': ['LO', '1', 'DistributionAddress'],\n    '0200': ['SH', '1', 'InterpretationID'],\n    '0202': ['LO', '1', 'InterpretationIDIssuer'],\n    '0210': ['CS', '1', 'InterpretationTypeID'],\n    '0212': ['CS', '1', 'InterpretationStatusID'],\n    '0300': ['ST', '1', 'Impressions'],\n    '4000': ['ST', '1', 'ResultsComments']\n  },\n  '4010': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['CS', '1', 'LowEnergyDetectors'],\n    '0002': ['CS', '1', 'HighEnergyDetectors'],\n    '0004': ['SQ', '1', 'DetectorGeometrySequence'],\n    '1001': ['SQ', '1', 'ThreatROIVoxelSequence'],\n    '1004': ['FL', '3', 'ThreatROIBase'],\n    '1005': ['FL', '3', 'ThreatROIExtents'],\n    '1006': ['OB', '1', 'ThreatROIBitmap'],\n    '1007': ['SH', '1', 'RouteSegmentID'],\n    '1008': ['CS', '1', 'GantryType'],\n    '1009': ['CS', '1', 'OOIOwnerType'],\n    '100A': ['SQ', '1', 'RouteSegmentSequence'],\n    '1010': ['US', '1', 'PotentialThreatObjectID'],\n    '1011': ['SQ', '1', 'ThreatSequence'],\n    '1012': ['CS', '1', 'ThreatCategory'],\n    '1013': ['LT', '1', 'ThreatCategoryDescription'],\n    '1014': ['CS', '1', 'ATDAbilityAssessment'],\n    '1015': ['CS', '1', 'ATDAssessmentFlag'],\n    '1016': ['FL', '1', 'ATDAssessmentProbability'],\n    '1017': ['FL', '1', 'Mass'],\n    '1018': ['FL', '1', 'Density'],\n    '1019': ['FL', '1', 'ZEffective'],\n    '101A': ['SH', '1', 'BoardingPassID'],\n    '101B': ['FL', '3', 'CenterOfMass'],\n    '101C': ['FL', '3', 'CenterOfPTO'],\n    '101D': ['FL', '6-n', 'BoundingPolygon'],\n    '101E': ['SH', '1', 'RouteSegmentStartLocationID'],\n    '101F': ['SH', '1', 'RouteSegmentEndLocationID'],\n    '1020': ['CS', '1', 'RouteSegmentLocationIDType'],\n    '1021': ['CS', '1-n', 'AbortReason'],\n    '1023': ['FL', '1', 'VolumeOfPTO'],\n    '1024': ['CS', '1', 'AbortFlag'],\n    '1025': ['DT', '1', 'RouteSegmentStartTime'],\n    '1026': ['DT', '1', 'RouteSegmentEndTime'],\n    '1027': ['CS', '1', 'TDRType'],\n    '1028': ['CS', '1', 'InternationalRouteSegment'],\n    '1029': ['LO', '1-n', 'ThreatDetectionAlgorithmAndVersion'],\n    '102A': ['SH', '1', 'AssignedLocation'],\n    '102B': ['DT', '1', 'AlarmDecisionTime'],\n    '1031': ['CS', '1', 'AlarmDecision'],\n    '1033': ['US', '1', 'NumberOfTotalObjects'],\n    '1034': ['US', '1', 'NumberOfAlarmObjects'],\n    '1037': ['SQ', '1', 'PTORepresentationSequence'],\n    '1038': ['SQ', '1', 'ATDAssessmentSequence'],\n    '1039': ['CS', '1', 'TIPType'],\n    '103A': ['CS', '1', 'DICOSVersion'],\n    '1041': ['DT', '1', 'OOIOwnerCreationTime'],\n    '1042': ['CS', '1', 'OOIType'],\n    '1043': ['FL', '3', 'OOISize'],\n    '1044': ['CS', '1', 'AcquisitionStatus'],\n    '1045': ['SQ', '1', 'BasisMaterialsCodeSequence'],\n    '1046': ['CS', '1', 'PhantomType'],\n    '1047': ['SQ', '1', 'OOIOwnerSequence'],\n    '1048': ['CS', '1', 'ScanType'],\n    '1051': ['LO', '1', 'ItineraryID'],\n    '1052': ['SH', '1', 'ItineraryIDType'],\n    '1053': ['LO', '1', 'ItineraryIDAssigningAuthority'],\n    '1054': ['SH', '1', 'RouteID'],\n    '1055': ['SH', '1', 'RouteIDAssigningAuthority'],\n    '1056': ['CS', '1', 'InboundArrivalType'],\n    '1058': ['SH', '1', 'CarrierID'],\n    '1059': ['CS', '1', 'CarrierIDAssigningAuthority'],\n    '1060': ['FL', '3', 'SourceOrientation'],\n    '1061': ['FL', '3', 'SourcePosition'],\n    '1062': ['FL', '1', 'BeltHeight'],\n    '1064': ['SQ', '1', 'AlgorithmRoutingCodeSequence'],\n    '1067': ['CS', '1', 'TransportClassification'],\n    '1068': ['LT', '1', 'OOITypeDescriptor'],\n    '1069': ['FL', '1', 'TotalProcessingTime'],\n    '106C': ['OB', '1', 'DetectorCalibrationData'],\n    '106D': ['CS', '1', 'AdditionalScreeningPerformed'],\n    '106E': ['CS', '1', 'AdditionalInspectionSelectionCriteria'],\n    '106F': ['SQ', '1', 'AdditionalInspectionMethodSequence'],\n    '1070': ['CS', '1', 'AITDeviceType'],\n    '1071': ['SQ', '1', 'QRMeasurementsSequence'],\n    '1072': ['SQ', '1', 'TargetMaterialSequence'],\n    '1073': ['FD', '1', 'SNRThreshold'],\n    '1075': ['DS', '1', 'ImageScaleRepresentation'],\n    '1076': ['SQ', '1', 'ReferencedPTOSequence'],\n    '1077': ['SQ', '1', 'ReferencedTDRInstanceSequence'],\n    '1078': ['ST', '1', 'PTOLocationDescription'],\n    '1079': ['SQ', '1', 'AnomalyLocatorIndicatorSequence'],\n    '107A': ['FL', '3', 'AnomalyLocatorIndicator'],\n    '107B': ['SQ', '1', 'PTORegionSequence'],\n    '107C': ['CS', '1', 'InspectionSelectionCriteria'],\n    '107D': ['SQ', '1', 'SecondaryInspectionMethodSequence'],\n    '107E': ['DS', '6', 'PRCSToRCSOrientation']\n  },\n  '4FFE': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['SQ', '1', 'MACParametersSequence']\n  },\n  '5000': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0005': ['US', '1', 'CurveDimensions'],\n    '0010': ['US', '1', 'NumberOfPoints'],\n    '0020': ['CS', '1', 'TypeOfData'],\n    '0022': ['LO', '1', 'CurveDescription'],\n    '0030': ['SH', '1-n', 'AxisUnits'],\n    '0040': ['SH', '1-n', 'AxisLabels'],\n    '0103': ['US', '1', 'DataValueRepresentation'],\n    '0104': ['US', '1-n', 'MinimumCoordinateValue'],\n    '0105': ['US', '1-n', 'MaximumCoordinateValue'],\n    '0106': ['SH', '1-n', 'CurveRange'],\n    '0110': ['US', '1-n', 'CurveDataDescriptor'],\n    '0112': ['US', '1-n', 'CoordinateStartValue'],\n    '0114': ['US', '1-n', 'CoordinateStepValue'],\n    '1001': ['CS', '1', 'CurveActivationLayer'],\n    '2000': ['US', '1', 'AudioType'],\n    '2002': ['US', '1', 'AudioSampleFormat'],\n    '2004': ['US', '1', 'NumberOfChannels'],\n    '2006': ['UL', '1', 'NumberOfSamples'],\n    '2008': ['UL', '1', 'SampleRate'],\n    '200A': ['UL', '1', 'TotalTime'],\n    '200C': ['ox', '1', 'AudioSampleData'],\n    '200E': ['LT', '1', 'AudioComments'],\n    '2500': ['LO', '1', 'CurveLabel'],\n    '2600': ['SQ', '1', 'CurveReferencedOverlaySequence'],\n    '2610': ['US', '1', 'CurveReferencedOverlayGroup'],\n    '3000': ['ox', '1', 'CurveData']\n  },\n  '5200': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '9229': ['SQ', '1', 'SharedFunctionalGroupsSequence'],\n    '9230': ['SQ', '1', 'PerFrameFunctionalGroupsSequence']\n  },\n  '5400': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0100': ['SQ', '1', 'WaveformSequence'],\n    '0110': ['ox', '1', 'ChannelMinimumValue'],\n    '0112': ['ox', '1', 'ChannelMaximumValue'],\n    '1004': ['US', '1', 'WaveformBitsAllocated'],\n    '1006': ['CS', '1', 'WaveformSampleInterpretation'],\n    '100A': ['ox', '1', 'WaveformPaddingValue'],\n    '1010': ['ox', '1', 'WaveformData']\n  },\n  '5600': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['OF', '1', 'FirstOrderPhaseCorrectionAngle'],\n    '0020': ['OF', '1', 'SpectroscopyData']\n  },\n  '6000': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['US', '1', 'OverlayRows'],\n    '0011': ['US', '1', 'OverlayColumns'],\n    '0012': ['US', '1', 'OverlayPlanes'],\n    '0015': ['IS', '1', 'NumberOfFramesInOverlay'],\n    '0022': ['LO', '1', 'OverlayDescription'],\n    '0040': ['CS', '1', 'OverlayType'],\n    '0045': ['LO', '1', 'OverlaySubtype'],\n    '0050': ['SS', '2', 'OverlayOrigin'],\n    '0051': ['US', '1', 'ImageFrameOrigin'],\n    '0052': ['US', '1', 'OverlayPlaneOrigin'],\n    '0060': ['CS', '1', 'OverlayCompressionCode'],\n    '0061': ['SH', '1', 'OverlayCompressionOriginator'],\n    '0062': ['SH', '1', 'OverlayCompressionLabel'],\n    '0063': ['CS', '1', 'OverlayCompressionDescription'],\n    '0066': ['AT', '1-n', 'OverlayCompressionStepPointers'],\n    '0068': ['US', '1', 'OverlayRepeatInterval'],\n    '0069': ['US', '1', 'OverlayBitsGrouped'],\n    '0100': ['US', '1', 'OverlayBitsAllocated'],\n    '0102': ['US', '1', 'OverlayBitPosition'],\n    '0110': ['CS', '1', 'OverlayFormat'],\n    '0200': ['US', '1', 'OverlayLocation'],\n    '0800': ['CS', '1-n', 'OverlayCodeLabel'],\n    '0802': ['US', '1', 'OverlayNumberOfTables'],\n    '0803': ['AT', '1-n', 'OverlayCodeTableLocation'],\n    '0804': ['US', '1', 'OverlayBitsForCodeWord'],\n    '1001': ['CS', '1', 'OverlayActivationLayer'],\n    '1100': ['US', '1', 'OverlayDescriptorGray'],\n    '1101': ['US', '1', 'OverlayDescriptorRed'],\n    '1102': ['US', '1', 'OverlayDescriptorGreen'],\n    '1103': ['US', '1', 'OverlayDescriptorBlue'],\n    '1200': ['US', '1-n', 'OverlaysGray'],\n    '1201': ['US', '1-n', 'OverlaysRed'],\n    '1202': ['US', '1-n', 'OverlaysGreen'],\n    '1203': ['US', '1-n', 'OverlaysBlue'],\n    '1301': ['IS', '1', 'ROIArea'],\n    '1302': ['DS', '1', 'ROIMean'],\n    '1303': ['DS', '1', 'ROIStandardDeviation'],\n    '1500': ['LO', '1', 'OverlayLabel'],\n    '3000': ['ox', '1', 'OverlayData'],\n    '4000': ['LT', '1', 'OverlayComments']\n  },\n  '7F00': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0010': ['ox', '1', 'VariablePixelData'],\n    '0011': ['US', '1', 'VariableNextDataGroup'],\n    '0020': ['OW', '1', 'VariableCoefficientsSDVN'],\n    '0030': ['OW', '1', 'VariableCoefficientsSDHN'],\n    '0040': ['OW', '1', 'VariableCoefficientsSDDN']\n  },\n  '7FE0': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    '0001': ['OV', '1', 'ExtendedOffsetTable'],\n    '0002': ['OV', '1', 'ExtendedOffsetTableLengths'],\n    '0008': ['OF', '1', 'FloatPixelData'],\n    '0009': ['OD', '1', 'DoubleFloatPixelData'],\n    '0010': ['ox', '1', 'PixelData'],\n    '0020': ['OW', '1', 'CoefficientsSDVN'],\n    '0030': ['OW', '1', 'CoefficientsSDHN'],\n    '0040': ['OW', '1', 'CoefficientsSDDN']\n  },\n  'FFFA': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    'FFFA': ['SQ', '1', 'DigitalSignaturesSequence']\n  },\n  'FFFC': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    'FFFC': ['OB', '1', 'DataSetTrailingPadding']\n  },\n  'FFFE': {\n    '0000': ['UL', '1', 'GenericGroupLength'],\n    'E000': ['NONE', '1', 'Item'],\n    'E00D': ['NONE', '1', 'ItemDelimitationItem'],\n    'E0DD': ['NONE', '1', 'SequenceDelimitationItem']\n  }\n}; // Dictionary\n\n/**\n * Add tags to the dictionary.\n *\n * @param {string} group The group key.\n * @param {Object<string, string[]>} tags The tags to add as an\n *   object indexed by element key with values as:\n *   [VR, multiplicity, TagName] (all strings).\n */\nexport function addTagsToDictionary(group, tags) {\n  // TODO: add checks!\n  dictionary[group] = tags;\n}\n\n/**\n * Tag groups: key to name pairs.\n * Copied from gdcm-2.6.1\\Source\\DataDictionary\\GroupName.dic\n * -> removed duplicates (commented).\n *\n * @type {Object<string, string>}\n */\nexport const tagGroups = {\n  '0000': 'Command',\n  '0002': 'Meta Element',\n  '0004': 'File Set',\n  //'0004': 'Directory',\n  '0008': 'Identifying',\n  '0009': 'SPI Identifying',\n  '0010': 'Patient',\n  '0012': 'Clinical Trial',\n  '0018': 'Acquisition',\n  '0019': 'SPI Acquisition',\n  '0020': 'Image',\n  '0021': 'SPI Image',\n  '0022': 'Ophtalmology',\n  '0028': 'Image Presentation',\n  '0032': 'Study',\n  '0038': 'Visit',\n  '003A': 'Waveform',\n  '0040': 'Procedure',\n  //'0040': ''Modality Worklist',\n  '0042': 'Encapsulated Document',\n  '0050': 'Device Informations',\n  //'0050': 'XRay Angio Device',\n  '0054': 'Nuclear Medicine',\n  '0060': 'Histogram',\n  '0070': 'Presentation State',\n  '0072': 'Hanging Protocol',\n  '0088': 'Storage',\n  //'0088': 'Medicine',\n  '0100': 'Authorization',\n  '0400': 'Digital Signature',\n  '1000': 'Code Table',\n  '1010': 'Zonal Map',\n  '2000': 'Film Session',\n  '2010': 'Film Box',\n  '2020': 'Image Box',\n  '2030': 'Annotation',\n  '2040': 'Overlay Box',\n  '2050': 'Presentation LUT',\n  '2100': 'Print Job',\n  '2110': 'Printer',\n  '2120': 'Queue',\n  '2130': 'Print Content',\n  '2200': 'Media Creation',\n  '3002': 'RT Image',\n  '3004': 'RT Dose',\n  '3006': 'RT StructureSet',\n  '3008': 'RT Treatment',\n  '300A': 'RT Plan',\n  '300C': 'RT Relationship',\n  '300E': 'RT Approval',\n  '4000': 'Text',\n  '4008': 'Results',\n  '4FFE': 'MAC Parameters',\n  '5000': 'Curve',\n  '5002': 'Curve',\n  '5004': 'Curve',\n  '5006': 'Curve',\n  '5008': 'Curve',\n  '500A': 'Curve',\n  '500C': 'Curve',\n  '500E': 'Curve',\n  '5400': 'Waveform Data',\n  '6000': 'Overlays',\n  '6002': 'Overlays',\n  '6004': 'Overlays',\n  '6008': 'Overlays',\n  '600A': 'Overlays',\n  '600C': 'Overlays',\n  '600E': 'Overlays',\n  'FFFC': 'Generic',\n  '7FE0': 'Pixel Data',\n  'FFFF': 'Unknown'\n};\n\n/**\n * List of Value Representation (VR) with 32bit Value Length (VL).\n *\n * Added locally used 'ox'.\n * See {@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/chapter_7.html#table_7.1-1}.\n *\n * @type {Object<string, boolean>}\n */\nconst vr32bitVL = {\n  OB: true,\n  OD: true,\n  OF: true,\n  OL: true,\n  OV: true,\n  OW: true,\n  SQ: true,\n  SV: true,\n  UC: true,\n  UN: true,\n  UR: true,\n  UT: true,\n  UV: true,\n  ox: true\n};\n\n/**\n * Does the input Value Representation (VR) have a 32bit Value Length (VL).\n *\n * @param {string} vr The data Value Representation (VR).\n * @returns {boolean} True if this VR has a 32-bit VL.\n */\nexport function is32bitVLVR(vr) {\n  return typeof vr32bitVL[vr] !== 'undefined';\n}\n\n/**\n * List of string VR with extended or replaced default character repertoire defined in\n *   Specific Character Set (0008,0005).\n *\n * See {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/chapter_6.html#sect_6.1.2.2}.\n *\n * @type {Object<string, boolean>}\n */\nconst vrCharSetString = {\n  SH: true,\n  LO: true,\n  UC: true,\n  ST: true,\n  LT: true,\n  UT: true,\n  PN: true\n};\n\n/**\n * Does the input Value Representation (VR) have an special character repertoire.\n *\n * @param {string} vr The data VR.\n * @returns {boolean} True if this VR has a special char set.\n */\nexport function isCharSetStringVR(vr) {\n  return typeof vrCharSetString[vr] !== 'undefined';\n}\n\n/**\n * VR equivalent javascript types.\n *\n * See {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_6.2.html#table_6.2-1}.\n *\n * @type {Object<string, string>}\n */\nexport const vrTypes = {\n  AE: 'string',\n  AS: 'string',\n  AT: undefined,\n  CS: 'string',\n  DA: 'string',\n  DS: 'string',\n  DT: 'string',\n  FL: 'Float32',\n  FD: 'Float64',\n  IS: 'string',\n  LO: 'string',\n  LT: 'string',\n  OB: 'Uint8',\n  OD: 'Uint64',\n  OF: 'Uint32',\n  OL: 'Uint32',\n  OV: 'Uint64',\n  OW: 'Uint16',\n  PN: 'string',\n  SH: 'string',\n  SL: 'Int32',\n  SQ: undefined,\n  SS: 'Int16',\n  ST: 'string',\n  SV: 'Int64',\n  TM: 'string',\n  UC: 'string',\n  UI: 'string',\n  UL: 'Uint32',\n  UN: 'Uint8',\n  UR: 'string',\n  US: 'Uint16',\n  UT: 'string',\n  UV: 'Uint64'\n};\n\n/**\n * Transfer syntaxes.\n *\n * See {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part06/chapter_A.html#table_A-1}.\n *\n * @type {Object<string, string>}\n */\nexport const transferSyntaxes = {\n  '1.2.840.10008.1.2': 'Implicit VR Little Endian',\n  '1.2.840.10008.1.2.1': 'Explicit VR Little Endian',\n  '1.2.840.10008.1.2.1.98': 'Encapsulated Uncompressed Explicit VR Little Endian',\n  '1.2.840.10008.1.2.1.99': 'Deflated Explicit VR Little Endian',\n  '1.2.840.10008.1.2.2': 'Explicit VR Big Endian (Retired)',\n  '1.2.840.10008.1.2.4.50': 'JPEG Baseline (Process 1)',\n  '1.2.840.10008.1.2.4.51': 'JPEG Extended (Process 2 & 4)',\n  '1.2.840.10008.1.2.4.52': 'JPEG Extended (Process 3 & 5) (Retired)',\n  '1.2.840.10008.1.2.4.53': 'JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) (Retired)',\n  '1.2.840.10008.1.2.4.54': 'JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9) (Retired)',\n  '1.2.840.10008.1.2.4.55': 'JPEG Full Progression, Non-Hierarchical (Process 10 & 12) (Retired)',\n  '1.2.840.10008.1.2.4.56': 'JPEG Full Progression, Non-Hierarchical (Process 11 & 13) (Retired)',\n  '1.2.840.10008.1.2.4.57': 'JPEG Lossless, Non-Hierarchical (Process 14)',\n  '1.2.840.10008.1.2.4.58': 'JPEG Lossless, Non-Hierarchical (Process 15) (Retired)',\n  '1.2.840.10008.1.2.4.59': 'JPEG Extended, Hierarchical (Process 16 & 18) (Retired)',\n  '1.2.840.10008.1.2.4.60': 'JPEG Extended, Hierarchical (Process 17 & 19) (Retired)',\n  '1.2.840.10008.1.2.4.61': 'JPEG Spectral Selection, Hierarchical (Process 20 & 22) (Retired)',\n  '1.2.840.10008.1.2.4.62': 'JPEG Spectral Selection, Hierarchical (Process 21 & 23) (Retired)',\n  '1.2.840.10008.1.2.4.63': 'JPEG Full Progression, Hierarchical (Process 24 & 26) (Retired)',\n  '1.2.840.10008.1.2.4.64': 'JPEG Full Progression, Hierarchical (Process 25 & 27) (Retired)',\n  '1.2.840.10008.1.2.4.65': 'JPEG Lossless, Hierarchical (Process 28) (Retired)',\n  '1.2.840.10008.1.2.4.66': 'JPEG Lossless, Hierarchical (Process 29) (Retired)',\n  '1.2.840.10008.1.2.4.70': 'JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1])',\n  '1.2.840.10008.1.2.4.80': 'JPEG-LS Lossless Image Compression',\n  '1.2.840.10008.1.2.4.81': 'JPEG-LS Lossy (Near-Lossless) Image Compression',\n  '1.2.840.10008.1.2.4.90': 'JPEG 2000 Image Compression (Lossless Only)',\n  '1.2.840.10008.1.2.4.91': 'JPEG 2000 Image Compression',\n  '1.2.840.10008.1.2.4.92': 'JPEG 2000 Part 2 Multi-component Image Compression (Lossless Only)',\n  '1.2.840.10008.1.2.4.93': 'JPEG 2000 Part 2 Multi-component Image Compression',\n  '1.2.840.10008.1.2.4.94': 'JPIP Referenced',\n  '1.2.840.10008.1.2.4.95': 'JPIP Referenced Deflate',\n  '1.2.840.10008.1.2.4.100': 'MPEG2 Main Profile / Main Level',\n  '1.2.840.10008.1.2.4.101': 'MPEG2 Main Profile / High Level',\n  '1.2.840.10008.1.2.4.102': 'MPEG-4 AVC/H.264 High Profile / Level 4.1',\n  '1.2.840.10008.1.2.4.103': 'MPEG-4 AVC/H.264 BD-compatible High Profile / Level 4.1',\n  '1.2.840.10008.1.2.4.104': 'MPEG-4 AVC/H.264 High Profile / Level 4.2 For 2D Video',\n  '1.2.840.10008.1.2.4.105': 'MPEG-4 AVC/H.264 High Profile / Level 4.2 For 3D Video',\n  '1.2.840.10008.1.2.4.106': 'MPEG-4 AVC/H.264 Stereo High Profile / Level 4.2',\n  '1.2.840.10008.1.2.4.107': 'HEVC/H.265 Main Profile / Level 5.1',\n  '1.2.840.10008.1.2.4.108': 'HEVC/H.265 Main 10 Profile / Level 5.1',\n  '1.2.840.10008.1.2.5': 'RLE Lossless',\n  '1.2.840.10008.1.2.6.1': 'RFC 2557 MIME encapsulation (Retired)',\n  '1.2.840.10008.1.2.6.2': 'XML Encoding (Retired)',\n  '1.2.840.10008.1.2.7.1': 'SMPTE ST 2110-20 Uncompressed Progressive Active Video',\n  '1.2.840.10008.1.2.7.2': 'SMPTE ST 2110-20 Uncompressed Interlaced Active Video',\n  '1.2.840.10008.1.2.7.3': 'SMPTE ST 2110-30 PCM Digital Audio',\n  '1.2.840.10008.1.20': 'Papyrus 3 Implicit VR Little Endian (Retired)'\n};\n\n/**\n * Transfer syntaxes indexed by keyword.\n *\n * @type {Object<string, string>}\n */\nexport const transferSyntaxKeywords = {\n  ImplicitVRLittleEndian: '1.2.840.10008.1.2',\n  ExplicitVRLittleEndian: '1.2.840.10008.1.2.1',\n  EncapsulatedUncompressedExplicitVRLittleEndian: '1.2.840.10008.1.2.1.98',\n  DeflatedExplicitVRLittleEndian: '1.2.840.10008.1.2.1.99',\n  ExplicitVRBigEndian: '1.2.840.10008.1.2.2',\n  JPEGBaseline8Bit: '1.2.840.10008.1.2.4.50',\n  JPEGExtended12Bit: '1.2.840.10008.1.2.4.51',\n  JPEGExtended35: '1.2.840.10008.1.2.4.52',\n  JPEGSpectralSelectionNonHierarchical68: '1.2.840.10008.1.2.4.53',\n  JPEGSpectralSelectionNonHierarchical79: '1.2.840.10008.1.2.4.54',\n  JPEGFullProgressionNonHierarchical1012: '1.2.840.10008.1.2.4.55',\n  JPEGFullProgressionNonHierarchical1113: '1.2.840.10008.1.2.4.56',\n  JPEGLossless: '1.2.840.10008.1.2.4.57',\n  JPEGLosslessNonHierarchical15: '1.2.840.10008.1.2.4.58',\n  JPEGExtendedHierarchical1618: '1.2.840.10008.1.2.4.59',\n  JPEGExtendedHierarchical1719: '1.2.840.10008.1.2.4.60',\n  JPEGSpectralSelectionHierarchical2022: '1.2.840.10008.1.2.4.61',\n  JPEGSpectralSelectionHierarchical2123: '1.2.840.10008.1.2.4.62',\n  JPEGFullProgressionHierarchical2426: '1.2.840.10008.1.2.4.63',\n  JPEGFullProgressionHierarchical2527: '1.2.840.10008.1.2.4.64',\n  JPEGLosslessHierarchical28: '1.2.840.10008.1.2.4.65',\n  JPEGLosslessHierarchical29: '1.2.840.10008.1.2.4.66',\n  JPEGLosslessSV1: '1.2.840.10008.1.2.4.70',\n  JPEGLSLossless: '1.2.840.10008.1.2.4.80',\n  JPEGLSNearLossless: '1.2.840.10008.1.2.4.81',\n  JPEG2000Lossless: '1.2.840.10008.1.2.4.90',\n  JPEG2000: '1.2.840.10008.1.2.4.91',\n  JPEG2000MCLossless: '1.2.840.10008.1.2.4.92',\n  JPEG2000MC: '1.2.840.10008.1.2.4.93',\n  JPIPReferenced: '1.2.840.10008.1.2.4.94',\n  JPIPReferencedDeflate: '1.2.840.10008.1.2.4.95',\n  MPEG2MPML: '1.2.840.10008.1.2.4.100',\n  MPEG2MPHL: '1.2.840.10008.1.2.4.101',\n  MPEG4HP41: '1.2.840.10008.1.2.4.102',\n  MPEG4HP41BD: '1.2.840.10008.1.2.4.103',\n  MPEG4HP422D: '1.2.840.10008.1.2.4.104',\n  MPEG4HP423D: '1.2.840.10008.1.2.4.105',\n  MPEG4HP42STEREO: '1.2.840.10008.1.2.4.106',\n  HEVCMP51: '1.2.840.10008.1.2.4.107',\n  HEVCM10P51: '1.2.840.10008.1.2.4.108',\n  RLELossless: '1.2.840.10008.1.2.5',\n  RFC2557MIMEEncapsulation: '1.2.840.10008.1.2.6.1',\n  XMLEncoding: '1.2.840.10008.1.2.6.2',\n  SMPTEST211020UncompressedProgressiveActiveVideo: '1.2.840.10008.1.2.7.1',\n  SMPTEST211020UncompressedInterlacedActiveVideo: '1.2.840.10008.1.2.7.2',\n  SMPTEST211030PCMDigitalAudio: '1.2.840.10008.1.2.7.3',\n  Papyrus3ImplicitVRLittleEndian: '1.2.840.10008.1.20'\n};\n","import {\n  dictionary,\n  tagGroups\n} from './dictionary';\n\n/**\n * Immutable tag.\n */\nexport class Tag {\n\n  /**\n   * The tag group.\n   *\n   * @type {string}\n   */\n  #group;\n\n  /**\n   * The tag element.\n   *\n   * @type {string}\n   */\n  #element;\n\n  /**\n   * @param {string} group The tag group as '####'.\n   * @param {string} element The tag element as '####'.\n   */\n  constructor(group, element) {\n    if (!group || typeof group === 'undefined') {\n      throw new Error('Cannot create tag with no group.');\n    }\n    if (group.length !== 4) {\n      throw new Error('Cannot create tag with badly sized group: ' + group);\n    }\n    if (!element || typeof element === 'undefined') {\n      throw new Error('Cannot create tag with no element.');\n    }\n    if (element.length !== 4) {\n      throw new Error('Cannot create tag with badly sized element: ' + element);\n    }\n    this.#group = group;\n    this.#element = element;\n  }\n\n  /**\n   * Get the tag group.\n   *\n   * @returns {string} The tag group.\n   */\n  getGroup() {\n    return this.#group;\n  }\n\n  /**\n   * Get the tag element.\n   *\n   * @returns {string} The tag element.\n   */\n  getElement() {\n    return this.#element;\n  }\n\n  /**\n   * Get as string representation of the tag: 'key: name'.\n   *\n   * @returns {string} A string representing the tag.\n   */\n  toString() {\n    return this.getKey() + ': ' + this.getNameFromDictionary();\n  }\n\n  /**\n   * Check for Tag equality.\n   *\n   * @param {Tag} rhs The other tag to compare to.\n   * @returns {boolean} True if both tags are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      typeof rhs !== 'undefined' &&\n      this.#group === rhs.getGroup() &&\n      this.#element === rhs.getElement();\n  }\n\n  /**\n   * Get the group-element key used to store DICOM elements.\n   *\n   * @returns {string} The key as '########'.\n   */\n  getKey() {\n    return this.#group + this.#element;\n  }\n\n  /**\n   * Get the group name as defined in TagGroups.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return tagGroups[this.#group];\n  }\n\n  /**\n   * Does this tag have a VR.\n   * Basically not the Item, ItemDelimitationItem nor\n   *  SequenceDelimitationItem tags.\n   *\n   * @returns {boolean} True if this tag has a VR.\n   */\n  isWithVR() {\n    return !(this.#group === 'FFFE' &&\n      (this.#element === 'E000' ||\n      this.#element === 'E00D' ||\n      this.#element === 'E0DD')\n    );\n  }\n\n  /**\n   * Is the tag group a private tag group ?\n   *\n   * See: {@link http://dicom.nema.org/medical/dicom/2022a/output/html/part05.html#sect_7.8}.\n   *\n   * @returns {boolean} True if the tag group is private,\n   *   ie if its group is an odd number.\n   */\n  isPrivate() {\n    return parseInt(this.#group, 16) % 2 === 1;\n  }\n\n  /**\n   * Get the tag info from the dicom dictionary.\n   *\n   * @returns {string[]|undefined} The info as [vr, multiplicity, name].\n   */\n  #getInfoFromDictionary() {\n    let info;\n    if (typeof dictionary[this.#group] !== 'undefined' &&\n      typeof dictionary[this.#group][this.#element] !==\n        'undefined') {\n      info = dictionary[this.#group][this.#element];\n    }\n    return info;\n  }\n\n  /**\n   * Get the tag Value Representation (VR) from the dicom dictionary.\n   *\n   * @returns {string|undefined} The VR.\n   */\n  getVrFromDictionary() {\n    let vr;\n    const info = this.#getInfoFromDictionary();\n    if (typeof info !== 'undefined') {\n      vr = info[0];\n    }\n    return vr;\n  }\n\n  /**\n   * Get the tag name from the dicom dictionary.\n   *\n   * @returns {string|undefined} The VR.\n   */\n  getNameFromDictionary() {\n    let name;\n    const info = this.#getInfoFromDictionary();\n    if (typeof info !== 'undefined') {\n      name = info[2];\n    }\n    return name;\n  }\n\n} // Tag class\n\n/**\n * Tag compare function.\n *\n * @param {Tag} a The first tag.\n * @param {Tag} b The second tag.\n * @returns {number} The result of the tag comparison,\n *   positive for b before a, negative for a before b and\n *   zero to keep same order.\n */\nexport function tagCompareFunction(a, b) {\n  // first by group\n  let res = parseInt(a.getGroup(), 16) - parseInt(b.getGroup(), 16);\n  if (res === 0) {\n    // by element if same group\n    res = parseInt(a.getElement(), 16) - parseInt(b.getElement(), 16);\n  }\n  return res;\n}\n\n/**\n * Split a group-element key used to store DICOM elements.\n *\n * @param {string} key The key in form \"00280102\" as generated by tag::getKey.\n * @returns {Tag} The DICOM tag.\n */\nexport function getTagFromKey(key) {\n  if (!key || typeof key === 'undefined') {\n    throw new Error('Cannot create tag with no key.');\n  }\n  if (key.length !== 8) {\n    throw new Error('Cannot create tag with badly sized key: ' + key);\n  }\n  return new Tag(key.substring(0, 4), key.substring(4, 8));\n}\n\n/**\n * Get the TransferSyntaxUID Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getTransferSyntaxUIDTag() {\n  return new Tag('0002', '0010');\n}\n\n/**\n * Get the FileMetaInformationGroupLength Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getFileMetaInformationGroupLengthTag() {\n  return new Tag('0002', '0000');\n}\n\n/**\n * Is the input tag the FileMetaInformationGroupLength Tag.\n *\n * @param {Tag} tag The tag to test.\n * @returns {boolean} True if the asked tag.\n */\nexport function isFileMetaInformationGroupLengthTag(tag) {\n  return tag.equals(getFileMetaInformationGroupLengthTag());\n}\n\n/**\n * Get the Item Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getItemTag() {\n  return new Tag('FFFE', 'E000');\n}\n\n/**\n * Is the input tag the Item Tag.\n *\n * @param {Tag} tag The tag to test.\n * @returns {boolean} True if the asked tag.\n */\nexport function isItemTag(tag) {\n  // faster than tag.equals(getItemTag());\n  return tag.getKey() === 'FFFEE000';\n}\n\n/**\n * Get the ItemDelimitationItem Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getItemDelimitationItemTag() {\n  return new Tag('FFFE', 'E00D');\n}\n\n/**\n * Is the input tag the ItemDelimitationItem Tag.\n *\n * @param {Tag} tag The tag to test.\n * @returns {boolean} True if the asked tag.\n */\nexport function isItemDelimitationItemTag(tag) {\n  // faster than tag.equals(getItemDelimitationItemTag());\n  return tag.getKey() === 'FFFEE00D';\n}\n\n/**\n * Get the SequenceDelimitationItem Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getSequenceDelimitationItemTag() {\n  return new Tag('FFFE', 'E0DD');\n}\n\n/**\n * Is the input tag the SequenceDelimitationItem Tag.\n *\n * @param {Tag} tag The tag to test.\n * @returns {boolean} True if the asked tag.\n */\nexport function isSequenceDelimitationItemTag(tag) {\n  // faster than tag.equals(getSequenceDelimitationItemTag());\n  return tag.getKey() === 'FFFEE0DD';\n}\n\n/**\n * Get the PixelData Tag.\n *\n * @returns {Tag} The tag.\n */\nexport function getPixelDataTag() {\n  return new Tag('7FE0', '0010');\n}\n\n/**\n * Is the input tag the PixelData Tag.\n *\n * @param {Tag} tag The tag to test.\n * @returns {boolean} True if the asked tag.\n */\nexport function isPixelDataTag(tag) {\n  // faster than tag.equals(getPixelDataTag());\n  return tag.getKey() === '7FE00010';\n}\n\n/**\n * Get a tag from the dictionary using a tag string name.\n *\n * @param {string} tagName The tag string name.\n * @returns {Tag|undefined} The tag object or null if not found.\n */\nexport function getTagFromDictionary(tagName) {\n  if (typeof tagName === 'undefined' || tagName === null) {\n    return null;\n  }\n  let group = null;\n  let element = null;\n  const dict = dictionary;\n  const keys0 = Object.keys(dict);\n  let keys1 = null;\n  let foundTag = false;\n  // search through dictionary\n  for (let k0 = 0, lenK0 = keys0.length; k0 < lenK0; ++k0) {\n    group = keys0[k0];\n    keys1 = Object.keys(dict[group]);\n    for (let k1 = 0, lenK1 = keys1.length; k1 < lenK1; ++k1) {\n      element = keys1[k1];\n      if (dict[group][element][2] === tagName) {\n        foundTag = true;\n        break;\n      }\n    }\n    if (foundTag) {\n      break;\n    }\n  }\n  let tag;\n  if (foundTag) {\n    tag = new Tag(group, element);\n  }\n  return tag;\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {Tag} from './dicomTag';\n/* eslint-enable no-unused-vars */\n\n/**\n * DICOM data element.\n */\nexport class DataElement {\n  /**\n   * The element Value Representation.\n   *\n   * @type {string}\n   */\n  vr;\n  /**\n   * The element value.\n   *\n   * @type {Array}\n   */\n  value;\n\n  // [start] internal values\n  // only present during parsing or writing otherwise not set\n\n  /**\n   * The element dicom tag.\n   *\n   * @type {Tag}\n   */\n  tag;\n\n  /**\n   * The element Value Length.\n   *\n   * @type {number}\n   */\n  vl;\n\n  /**\n   * Flag to know if defined or undefined sequence length.\n   *\n   * @type {boolean}\n   */\n  undefinedLength;\n\n  /**\n   * The element start offset.\n   *\n   * @type {number}\n   */\n  startOffset;\n\n  /**\n   * The element end offset.\n   *\n   * @type {number}\n   */\n  endOffset;\n\n  /**\n   * The sequence items.\n   *\n   * @type {Array}\n   */\n  items;\n\n  // [end] internal values\n\n  /**\n   * @param {string} vr The element VR (Value Representation).\n   */\n  constructor(vr) {\n    this.vr = vr;\n  }\n}\n\n/**\n * Safely get an elements' first value from a list of elements.\n *\n * @param {Object<string, DataElement>} tags The list of tags.\n * @param {string} key The tag key as for example '00100020'.\n * @returns {any|undefined} The elements' value or undefined.\n */\nexport function safeGet(tags, key) {\n  let res;\n  if (typeof tags[key] !== 'undefined') {\n    res = tags[key].value[0];\n  }\n  return res;\n};\n","/**\n * Is the Native endianness Little Endian.\n *\n * @returns {boolean} True if little endian.\n */\nexport function isNativeLittleEndian() {\n  return new Int8Array(new Int16Array([1]).buffer)[0] > 0;\n}\n\n/**\n * Flip an array's endianness.\n * Inspired from [DataStream.js]{@link https://github.com/kig/DataStream.js}.\n *\n * @param {object} array The array to flip (modified).\n */\nfunction flipArrayEndianness(array) {\n  const blen = array.byteLength;\n  const u8 = new Uint8Array(array.buffer, array.byteOffset, blen);\n  const bpe = array.BYTES_PER_ELEMENT;\n  let tmp;\n  for (let i = 0; i < blen; i += bpe) {\n    for (let j = i + bpe - 1, k = i; j > k; j--, k++) {\n      tmp = u8[k];\n      u8[k] = u8[j];\n      u8[j] = tmp;\n    }\n  }\n}\n\n/**\n * Data reader.\n */\nexport class DataReader {\n\n  /**\n   * The input buffer.\n   *\n   * @type {ArrayBuffer}\n   */\n  #buffer;\n\n  /**\n   * Is the endianness Little Endian.\n   *\n   * @type {boolean}\n   */\n  #isLittleEndian = true;\n\n  /**\n   * Is the Native endianness Little Endian.\n   *\n   * @type {boolean}\n   */\n  #isNativeLittleEndian = isNativeLittleEndian();\n\n  /**\n   * Flag to know if the TypedArray data needs flipping.\n   *\n   * @type {boolean}\n   */\n  #needFlip;\n\n  /**\n   * The main data view.\n   *\n   * @type {DataView}\n   */\n  #view;\n\n  /**\n   * @param {ArrayBuffer} buffer The input array buffer.\n   * @param {boolean} [isLittleEndian] Flag to tell if the data is little\n   *   or big endian (default: true).\n   */\n  constructor(buffer, isLittleEndian) {\n    this.#buffer = buffer;\n    // Set endian flag if not defined.\n    if (typeof isLittleEndian !== 'undefined') {\n      this.#isLittleEndian = isLittleEndian;\n    }\n    this.#needFlip = (this.#isLittleEndian !== this.#isNativeLittleEndian);\n    this.#view = new DataView(buffer);\n  }\n\n  /**\n   * Read Uint16 (2 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readUint16(byteOffset) {\n    return this.#view.getUint16(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read Int16 (2 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readInt16(byteOffset) {\n    return this.#view.getInt16(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read Uint32 (4 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readUint32(byteOffset) {\n    return this.#view.getUint32(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read BigUint64 (8 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {bigint} The read data.\n   */\n  readBigUint64(byteOffset) {\n    return this.#view.getBigUint64(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read Int32 (4 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readInt32(byteOffset) {\n    return this.#view.getInt32(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read BigInt64 (8 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {bigint} The read data.\n   */\n  readBigInt64(byteOffset) {\n    return this.#view.getBigInt64(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read Float32 (4 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readFloat32(byteOffset) {\n    return this.#view.getFloat32(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read Float64 (8 bytes) data.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {number} The read data.\n   */\n  readFloat64(byteOffset) {\n    return this.#view.getFloat64(byteOffset, this.#isLittleEndian);\n  }\n\n  /**\n   * Read binary (0/1) array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Uint8Array} The read data.\n   */\n  readBinaryArray(byteOffset, size) {\n    // input\n    const bitArray = new Uint8Array(this.#buffer, byteOffset, size);\n    // result\n    const byteArrayLength = 8 * bitArray.length;\n    const data = new Uint8Array(byteArrayLength);\n    let bitNumber = 0;\n    let bitIndex = 0;\n    for (let i = 0; i < byteArrayLength; ++i) {\n      bitNumber = i % 8;\n      bitIndex = Math.floor(i / 8);\n      // see https://stackoverflow.com/questions/4854207/get-a-specific-bit-from-byte/4854257\n      // @ts-ignore\n      data[i] = 255 * ((bitArray[bitIndex] & (1 << bitNumber)) !== 0);\n    }\n    return data;\n  }\n\n  /**\n   * Read Uint8 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Uint8Array} The read data.\n   */\n  readUint8Array(byteOffset, size) {\n    return new Uint8Array(this.#buffer, byteOffset, size);\n  }\n\n  /**\n   * Read Int8 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Int8Array} The read data.\n   */\n  readInt8Array(byteOffset, size) {\n    return new Int8Array(this.#buffer, byteOffset, size);\n  }\n\n  /**\n   * Read Uint16 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Uint16Array} The read data.\n   */\n  readUint16Array(byteOffset, size) {\n    const bpe = Uint16Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Uint16Array.BYTES_PER_ELEMENT (=2)\n    if (byteOffset % bpe === 0) {\n      data = new Uint16Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Uint16Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readUint16(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Int16 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Int16Array} The read data.\n   */\n  readInt16Array(byteOffset, size) {\n    const bpe = Int16Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Int16Array.BYTES_PER_ELEMENT (=2)\n    if (byteOffset % bpe === 0) {\n      data = new Int16Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Int16Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readInt16(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Uint32 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Uint32Array} The read data.\n   */\n  readUint32Array(byteOffset, size) {\n    const bpe = Uint32Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Uint32Array.BYTES_PER_ELEMENT (=4)\n    if (byteOffset % bpe === 0) {\n      data = new Uint32Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Uint32Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readUint32(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Uint64 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {BigUint64Array} The read data.\n   */\n  readUint64Array(byteOffset, size) {\n    const bpe = BigUint64Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of BigUint64Array.BYTES_PER_ELEMENT (=8)\n    if (byteOffset % bpe === 0) {\n      data = new BigUint64Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new BigUint64Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readBigUint64(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Int32 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Int32Array} The read data.\n   */\n  readInt32Array(byteOffset, size) {\n    const bpe = Int32Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Int32Array.BYTES_PER_ELEMENT (=4)\n    if (byteOffset % bpe === 0) {\n      data = new Int32Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Int32Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readInt32(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Int64 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {BigInt64Array} The read data.\n   */\n  readInt64Array(byteOffset, size) {\n    const bpe = BigInt64Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of BigInt64Array.BYTES_PER_ELEMENT (=8)\n    if (byteOffset % bpe === 0) {\n      data = new BigInt64Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new BigInt64Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readBigInt64(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Float32 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Float32Array} The read data.\n   */\n  readFloat32Array(byteOffset, size) {\n    const bpe = Float32Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Float32Array.BYTES_PER_ELEMENT (=4)\n    if (byteOffset % bpe === 0) {\n      data = new Float32Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Float32Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readFloat32(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read Float64 array.\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @param {number} size The size of the array.\n   * @returns {Float64Array} The read data.\n   */\n  readFloat64Array(byteOffset, size) {\n    const bpe = Float64Array.BYTES_PER_ELEMENT;\n    const arraySize = size / bpe;\n    let data = null;\n    // byteOffset should be a multiple of Float64Array.BYTES_PER_ELEMENT (=8)\n    if (byteOffset % bpe === 0) {\n      data = new Float64Array(this.#buffer, byteOffset, arraySize);\n      if (this.#needFlip) {\n        flipArrayEndianness(data);\n      }\n    } else {\n      data = new Float64Array(arraySize);\n      let index = byteOffset;\n      for (let i = 0; i < arraySize; ++i) {\n        data[i] = this.readFloat64(index);\n        index += bpe;\n      }\n    }\n    return data;\n  }\n\n  /**\n   * Read data as an hexadecimal string of length 4 (no '0x' prefix).\n   *\n   * @param {number} byteOffset The offset to start reading from.\n   * @returns {string} The read data ('####').\n   */\n  readHex(byteOffset) {\n    // read and convert to hex string\n    const str = this.readUint16(byteOffset).toString(16);\n    // return padded\n    return '0000'.substring(0, 4 - str.length) + str.toUpperCase();\n  }\n\n} // class DataReader\n","import {\n  Tag,\n  getTransferSyntaxUIDTag,\n  isSequenceDelimitationItemTag,\n  isItemDelimitationItemTag,\n  isPixelDataTag\n} from './dicomTag';\nimport {\n  is32bitVLVR,\n  isCharSetStringVR,\n  transferSyntaxes,\n  transferSyntaxKeywords,\n  vrTypes,\n} from './dictionary';\nimport {\n  safeGet,\n  DataElement\n} from './dataElement';\nimport {DataReader} from './dataReader';\nimport {logger} from '../utils/logger';\n\n/**\n * List of DICOM data elements indexed via a 8 character string formed from\n * the group and element numbers.\n *\n * @typedef {Object<string, DataElement>} DataElements\n */\n\n/**\n * Get the version of the library.\n *\n * @returns {string} The version of the library.\n */\nexport function getDwvVersion() {\n  return '0.35.0-beta.11';\n}\n\n/**\n * Check that an input buffer includes the DICOM prefix 'DICM'\n *   after the 128 bytes preamble.\n *\n * Ref: [DICOM File Meta]{@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part10/chapter_7.html#sect_7.1}.\n *\n * @param {ArrayBuffer} buffer The buffer to check.\n * @returns {boolean} True if the buffer includes the prefix.\n */\nexport function hasDicomPrefix(buffer) {\n  // check size: typed array constructor will throw RangeError if\n  // byteOffset + length * TypedArray.BYTES_PER_ELEMENT > buffer.byteLength\n  if (buffer.byteLength < 132) {\n    return false;\n  }\n  const prefixArray = new Uint8Array(buffer, 128, 4);\n  const stringReducer = function (previous, current) {\n    return previous += String.fromCharCode(current);\n  };\n  return prefixArray.reduce(stringReducer, '') === 'DICM';\n}\n\n// Zero-width space (u200B)\n// @ts-ignore\nconst ZWS = String.fromCharCode('u200B');\n\n/**\n * Clean string: remove zero-width space ending and trim.\n * Warning: no tests are done on the input, will fail if\n *   null or undefined or not string.\n * Exported for tests only.\n *\n * @param {string} inputStr The string to clean.\n * @returns {string} The cleaned string.\n */\nexport function cleanString(inputStr) {\n  let res = inputStr;\n  // get rid of ending zero-width space\n  const lastIndex = inputStr.length - 1;\n  if (inputStr[lastIndex] === ZWS) {\n    res = inputStr.substring(0, lastIndex);\n  }\n  // trim spaces\n  res = res.trim();\n  // return\n  return res;\n}\n\n/**\n * Get the utfLabel (used by the TextDecoder) from a character set term.\n *\n * References:\n * - DICOM [Value Encoding]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/chapter_6.html},\n * - DICOM [Specific Character Set]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.12.html#sect_C.12.1.1.2},\n * - [TextDecoder#Parameters]{@link https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder/TextDecoder#Parameters}.\n *\n * @param {string} charSetTerm The DICOM character set.\n * @returns {string} The corresponding UTF label.\n */\nfunction getUtfLabel(charSetTerm) {\n  let label = 'utf-8';\n  if (charSetTerm === 'ISO_IR 100') {\n    label = 'iso-8859-1';\n  } else if (charSetTerm === 'ISO_IR 101') {\n    label = 'iso-8859-2';\n  } else if (charSetTerm === 'ISO_IR 109') {\n    label = 'iso-8859-3';\n  } else if (charSetTerm === 'ISO_IR 110') {\n    label = 'iso-8859-4';\n  } else if (charSetTerm === 'ISO_IR 144') {\n    label = 'iso-8859-5';\n  } else if (charSetTerm === 'ISO_IR 127') {\n    label = 'iso-8859-6';\n  } else if (charSetTerm === 'ISO_IR 126') {\n    label = 'iso-8859-7';\n  } else if (charSetTerm === 'ISO_IR 138') {\n    label = 'iso-8859-8';\n  } else if (charSetTerm === 'ISO_IR 148') {\n    label = 'iso-8859-9';\n  } else if (charSetTerm === 'ISO_IR 13') {\n    label = 'shift-jis';\n  } else if (charSetTerm === 'ISO_IR 166') {\n    label = 'iso-8859-11';\n  } else if (charSetTerm === 'ISO 2022 IR 87') {\n    label = 'iso-2022-jp';\n  } else if (charSetTerm === 'ISO 2022 IR 149') {\n    // not supported by TextDecoder when it says it should...\n    //label = \"iso-2022-kr\";\n  } else if (charSetTerm === 'ISO 2022 IR 58') {\n    // not supported by TextDecoder...\n    //label = \"iso-2022-cn\";\n  } else if (charSetTerm === 'ISO_IR 192') {\n    label = 'utf-8';\n  } else if (charSetTerm === 'GB18030') {\n    label = 'gb18030';\n  } else if (charSetTerm === 'GB2312') {\n    label = 'gb2312';\n  } else if (charSetTerm === 'GBK') {\n    label = 'chinese';\n  }\n  return label;\n}\n\n/**\n * Default text decoder.\n */\nclass DefaultTextDecoder {\n  /**\n   * Decode an input string buffer.\n   *\n   * @param {Uint8Array} buffer The buffer to decode.\n   * @returns {string} The decoded string.\n   */\n  decode(buffer) {\n    let result = '';\n    for (let i = 0, leni = buffer.length; i < leni; ++i) {\n      result += String.fromCharCode(buffer[i]);\n    }\n    return result;\n  }\n}\n\n/**\n * Get patient orientation label in the reverse direction.\n *\n * @param {string} ori Patient Orientation value.\n * @returns {string} Reverse Orientation Label.\n */\nexport function getReverseOrientation(ori) {\n  if (!ori) {\n    return null;\n  }\n  // reverse labels\n  const rlabels = {\n    L: 'R',\n    R: 'L',\n    A: 'P',\n    P: 'A',\n    H: 'F',\n    F: 'H'\n  };\n\n  let rori = '';\n  for (let n = 0; n < ori.length; n++) {\n    const o = ori.substring(n, n + 1);\n    const r = rlabels[o];\n    if (r) {\n      rori += r;\n    }\n  }\n  // return\n  return rori;\n}\n\n/**\n * Tell if a given syntax is an implicit one (element with no VR).\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if an implicit syntax.\n */\nexport function isImplicitTransferSyntax(syntax) {\n  return syntax === transferSyntaxKeywords.ImplicitVRLittleEndian;\n}\n\n/**\n * Tell if a given syntax is a big endian syntax.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a big endian syntax.\n */\nexport function isBigEndianTransferSyntax(syntax) {\n  return syntax === transferSyntaxKeywords.ExplicitVRBigEndian;\n}\n\n/**\n * Tell if a given syntax is a JPEG baseline one.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a jpeg baseline syntax.\n */\nexport function isJpegBaselineTransferSyntax(syntax) {\n  return syntax === transferSyntaxKeywords.JPEGBaseline8Bit ||\n    syntax === transferSyntaxKeywords.JPEGExtended12Bit;\n}\n\n/**\n * Tell if a given syntax is a JPEG Lossless one.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a jpeg lossless syntax.\n */\nexport function isJpegLosslessTransferSyntax(syntax) {\n  return syntax === transferSyntaxKeywords.JPEGLossless ||\n    syntax === transferSyntaxKeywords.JPEGLosslessSV1;\n}\n\n/**\n * Tell if a given syntax is a JPEG 2000 one.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a jpeg 2000 syntax.\n */\nexport function isJpeg2000TransferSyntax(syntax) {\n  return syntax.match(/1.2.840.10008.1.2.4.9/) !== null;\n}\n\n/**\n * Tell if a given syntax is a RLE (Run-length encoding) one.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a RLE syntax.\n */\nfunction isRleTransferSyntax(syntax) {\n  return syntax === transferSyntaxKeywords.RLELossless;\n}\n\n/**\n * Tell if a given syntax needs decompression.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {string|undefined} The name of the decompression algorithm.\n */\nexport function getSyntaxDecompressionName(syntax) {\n  let algo;\n  if (isJpeg2000TransferSyntax(syntax)) {\n    algo = 'jpeg2000';\n  } else if (isJpegBaselineTransferSyntax(syntax)) {\n    algo = 'jpeg-baseline';\n  } else if (isJpegLosslessTransferSyntax(syntax)) {\n    algo = 'jpeg-lossless';\n  } else if (isRleTransferSyntax(syntax)) {\n    algo = 'rle';\n  }\n  return algo;\n}\n\n/**\n * Tell if a given syntax is supported for reading.\n *\n * @param {string} syntax The transfer syntax to test.\n * @returns {boolean} True if a supported syntax.\n */\nfunction isReadSupportedTransferSyntax(syntax) {\n  return (syntax === transferSyntaxKeywords.ImplicitVRLittleEndian ||\n    syntax === transferSyntaxKeywords.ExplicitVRLittleEndian ||\n    syntax === transferSyntaxKeywords.ExplicitVRBigEndian ||\n    isJpegBaselineTransferSyntax(syntax) ||\n    isJpegLosslessTransferSyntax(syntax) ||\n    isJpeg2000TransferSyntax(syntax) ||\n    isRleTransferSyntax(syntax));\n}\n\n/**\n * Get a transfer syntax name from its UID.\n *\n * @param {string} syntax The transfer syntax UID value.\n * @returns {string} The transfer syntax name.\n */\nexport function getTransferSyntaxName(syntax) {\n  let name = 'Unknown';\n  if (typeof transferSyntaxes[syntax] !== 'undefined') {\n    name = transferSyntaxes[syntax];\n  }\n  return name;\n}\n\n/**\n * Guess the transfer syntax from the first data element.\n *\n * See {@link https://github.com/ivmartel/dwv/issues/188}\n *   (Allow to load DICOM with no DICM preamble) for more details.\n *\n * @param {DataElement} firstDataElement The first data element\n *   of the DICOM header.\n * @returns {DataElement} The transfer syntax data element.\n */\nfunction guessTransferSyntax(firstDataElement) {\n  const oEightGroupBigEndian = '0800';\n  const oEightGroupLittleEndian = '0008';\n  // check that group is 0008\n  const group = firstDataElement.tag.getGroup();\n  if (group !== oEightGroupBigEndian &&\n    group !== oEightGroupLittleEndian) {\n    throw new Error(\n      'Not a valid DICOM file (no magic DICM word found' +\n        ' and first element not in 0008 group)'\n    );\n  }\n  // reasonable assumption: 2 uppercase characters => explicit vr\n  const vr = firstDataElement.vr;\n  const vr0 = vr.charCodeAt(0);\n  const vr1 = vr.charCodeAt(1);\n  const implicit = (vr0 >= 65 && vr0 <= 90 && vr1 >= 65 && vr1 <= 90)\n    ? false : true;\n  // guess transfer syntax\n  let syntax = null;\n  if (group === oEightGroupLittleEndian) {\n    if (implicit) {\n      syntax = transferSyntaxKeywords.ImplicitVRLittleEndian;\n    } else {\n      syntax = transferSyntaxKeywords.ExplicitVRLittleEndian;\n    }\n  } else {\n    if (implicit) {\n      // ImplicitVRBigEndian: impossible\n      throw new Error(\n        'Not a valid DICOM file (no magic DICM word found' +\n        'and implicit VR big endian detected)'\n      );\n    } else {\n      syntax = transferSyntaxKeywords.ExplicitVRBigEndian;\n    }\n  }\n  // set transfer syntax data element\n  const dataElement = new DataElement('UI');\n  dataElement.tag = getTransferSyntaxUIDTag();\n  dataElement.value = [syntax];\n  dataElement.vl = dataElement.value[0].length;\n  dataElement.startOffset = firstDataElement.startOffset;\n  dataElement.endOffset = dataElement.startOffset + dataElement.vl;\n\n  return dataElement;\n}\n\n/**\n * Get the appropriate TypedArray in function of arguments.\n *\n * @param {number} bitsAllocated The number of bites used to store\n *   the data: [8, 16, 32].\n * @param {number} pixelRepresentation The pixel representation,\n *   0:unsigned;1:signed.\n * @param {number} size The size of the new array.\n * @returns {Uint8Array|Int8Array|Uint16Array|Int16Array|Uint32Array|Int32Array}\n *   The good typed array.\n */\nexport function getTypedArray(bitsAllocated, pixelRepresentation, size) {\n  let res = null;\n  try {\n    if (bitsAllocated === 1 || bitsAllocated === 8) {\n      if (pixelRepresentation === 0) {\n        res = new Uint8Array(size);\n      } else {\n        res = new Int8Array(size);\n      }\n    } else if (bitsAllocated === 16) {\n      if (pixelRepresentation === 0) {\n        res = new Uint16Array(size);\n      } else {\n        res = new Int16Array(size);\n      }\n    } else if (bitsAllocated === 32) {\n      if (pixelRepresentation === 0) {\n        res = new Uint32Array(size);\n      } else {\n        res = new Int32Array(size);\n      }\n    }\n  } catch (error) {\n    if (error instanceof RangeError) {\n      const powerOf2 = Math.floor(Math.log(size) / Math.log(2));\n      logger.error('Cannot allocate array of size: ' +\n        size + ' (>2^' + powerOf2 + ').');\n    }\n  }\n  return res;\n}\n\n/**\n * Get the number of bytes occupied by a data element prefix,\n *   (without its value).\n *\n * WARNING: this is valid for tags with a VR, if not sure use\n *   the 'isTagWithVR' function first.\n *\n * Reference:\n * - [Data Element explicit]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/chapter_7.html#table_7.1-1},\n * - [Data Element implicit]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_7.5.2.html#table_7.5-1}.\n *\n * ```\n * | Tag | VR  | VL | Value |\n * | 4   | 2   | 2  | X     | -> regular explicit: 8 + X\n * | 4   | 2+2 | 4  | X     | -> 32bit VL: 12 + X\n *\n * | Tag | VL | Value |\n * | 4   | 4  | X     | -> implicit (32bit VL): 8 + X\n *\n * | Tag | Len | Value |\n * | 4   | 4   | X     | -> item: 8 + X\n * ```\n *\n * @param {string} vr The Value Representation of the element.\n * @param {boolean} isImplicit Does the data use implicit VR?\n * @returns {number} The size of the element prefix.\n */\nexport function getDataElementPrefixByteSize(vr, isImplicit) {\n  return isImplicit ? 8 : is32bitVLVR(vr) ? 12 : 8;\n}\n\n/**\n * Is the input VR a known VR.\n *\n * @param {string} vr The vr to test.\n * @returns {boolean} True if known.\n */\nfunction isKnownVR(vr) {\n  const extraVrTypes = ['NONE', 'ox', 'xx', 'xs'];\n  const knownTypes = Object.keys(vrTypes).concat(extraVrTypes);\n  return knownTypes.includes(vr);\n}\n\n/**\n * Small list of used tag keys.\n */\nconst TagKeys = {\n  TransferSyntax: '00020010',\n  SpecificCharacterSet: '00080005',\n  NumberOfFrames: '00280008',\n  BitsAllocated: '00280100',\n  PixelRepresentation: '00280103',\n  PixelData: '7FE00010'\n};\n\n/**\n * DicomParser class.\n *\n * @example\n * // XMLHttpRequest onload callback\n * const onload = function (event) {\n *   // setup the dicom parser\n *   const dicomParser = new dwv.DicomParser();\n *   // parse the buffer\n *   dicomParser.parse(event.target.response);\n *   // get the dicom tags\n *   const tags = dicomParser.getDicomElements();\n *   // display the modality\n *   const div = document.getElementById('dwv');\n *   div.appendChild(document.createTextNode(\n *     'Modality: ' + tags['00080060'].value[0]\n *   ));\n * };\n * // DICOM file request\n * const request = new XMLHttpRequest();\n * const url = 'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm';\n * request.open('GET', url);\n * request.responseType = 'arraybuffer';\n * request.onload = onload;\n * request.send();\n */\nexport class DicomParser {\n\n  /**\n   * The list of DICOM elements.\n   *\n   * @type {DataElements}\n   */\n  #dataElements = {};\n\n  /**\n   * Default character set (optional).\n   *\n   * @type {string}\n   */\n  #defaultCharacterSet;\n\n  /**\n   * Default text decoder.\n   *\n   * @type {DefaultTextDecoder}\n   */\n  #defaultTextDecoder = new DefaultTextDecoder();\n\n  /**\n   * Special text decoder.\n   *\n   * @type {DefaultTextDecoder|TextDecoder}\n   */\n  #textDecoder = this.#defaultTextDecoder;\n\n  /**\n   * Decode an input string buffer using the default text decoder.\n   *\n   * @param {Uint8Array} buffer The buffer to decode.\n   * @returns {string} The decoded string.\n   */\n  #decodeString(buffer) {\n    return this.#defaultTextDecoder.decode(buffer);\n  }\n\n  /**\n   * Decode an input string buffer using the 'special' text decoder.\n   *\n   * @param {Uint8Array} buffer The buffer to decode.\n   * @returns {string} The decoded string.\n   */\n  #decodeSpecialString(buffer) {\n    return this.#textDecoder.decode(buffer);\n  }\n\n  /**\n   * Get the default character set.\n   *\n   * @returns {string} The default character set.\n   */\n  getDefaultCharacterSet() {\n    return this.#defaultCharacterSet;\n  }\n\n  /**\n   * Set the default character set.\n   *\n   * @param {string} characterSet The input character set.\n   */\n  setDefaultCharacterSet(characterSet) {\n    this.#defaultCharacterSet = characterSet;\n  }\n\n  /**\n   * Set the text decoder character set.\n   *\n   * @param {string} characterSet The input character set.\n   */\n  setDecoderCharacterSet(characterSet) {\n    /**\n     * The text decoder.\n     *\n     * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder}.\n     *\n     * @external TextDecoder\n     */\n    this.#textDecoder = new TextDecoder(characterSet);\n  }\n\n  // not using type DataElements since the typedef is not exported with the API\n\n  /**\n   * Get the DICOM data elements.\n   *\n   * @returns {Object<string, DataElement>} The data elements.\n   */\n  getDicomElements() {\n    return this.#dataElements;\n  }\n\n  /**\n   * Safely get an elements' first value from the parsed elements.\n   *\n   * @param {string} key The tag key as for example '00100020'.\n   * @returns {any|undefined} The elements' value or undefined.\n   */\n  safeGet(key) {\n    return safeGet(this.#dataElements, key);\n  }\n\n  /**\n   * Read a DICOM tag.\n   *\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} offset The offset where to start to read.\n   * @returns {object} An object containing the tag and the end offset.\n   */\n  #readTag(reader, offset) {\n    // group\n    const group = reader.readHex(offset);\n    offset += Uint16Array.BYTES_PER_ELEMENT;\n    // element\n    const element = reader.readHex(offset);\n    offset += Uint16Array.BYTES_PER_ELEMENT;\n    // return\n    return {\n      tag: new Tag(group, element),\n      endOffset: offset\n    };\n  }\n\n  /**\n   * Read an item data element.\n   *\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} offset The offset where to start to read.\n   * @param {boolean} implicit Is the DICOM VR implicit?\n   * @returns {object} The item data as a list of data elements.\n   */\n  #readItemDataElement(reader, offset, implicit) {\n    const itemData = {};\n\n    // read the first item\n    let item = this.#readDataElement(reader, offset, implicit);\n    offset = item.endOffset;\n\n    // exit if it is a sequence delimitation item\n    if (isSequenceDelimitationItemTag(item.tag)) {\n      return {\n        data: itemData,\n        endOffset: item.endOffset,\n        isSeqDelim: true\n      };\n    }\n\n    // store item (mainly to keep vl)\n    itemData[item.tag.getKey()] = {\n      tag: item.tag,\n      vr: 'NONE',\n      vl: item.vl,\n      undefinedLength: item.undefinedLength\n    };\n\n    if (!item.undefinedLength) {\n      // explicit VR item: read until the end offset\n      const endOffset = offset;\n      offset -= item.vl;\n      while (offset < endOffset) {\n        item = this.#readDataElement(reader, offset, implicit);\n        offset = item.endOffset;\n        itemData[item.tag.getKey()] = item;\n      }\n    } else {\n      // implicit VR item: read until the item delimitation item\n      let isItemDelim = false;\n      while (!isItemDelim) {\n        item = this.#readDataElement(reader, offset, implicit);\n        offset = item.endOffset;\n        isItemDelim = isItemDelimitationItemTag(item.tag);\n        if (!isItemDelim) {\n          itemData[item.tag.getKey()] = item;\n        }\n      }\n    }\n\n    return {\n      data: itemData,\n      endOffset: offset,\n      isSeqDelim: false\n    };\n  }\n\n  /**\n   * Read the pixel item data element.\n   * Ref: [Single frame fragments]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_A.4.html#table_A.4-1}.\n   *\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} offset The offset where to start to read.\n   * @param {boolean} implicit Is the DICOM VR implicit?\n   * @returns {object} The item data as an array of data elements.\n   */\n  #readPixelItemDataElement(\n    reader, offset, implicit) {\n    const itemData = [];\n\n    // first item: basic offset table\n    let item = this.#readDataElement(reader, offset, implicit);\n    const offsetTableVl = item.vl;\n    offset = item.endOffset;\n\n    // read until the sequence delimitation item\n    let isSeqDelim = false;\n    while (!isSeqDelim) {\n      item = this.#readDataElement(reader, offset, implicit);\n      offset = item.endOffset;\n      isSeqDelim = isSequenceDelimitationItemTag(item.tag);\n      if (!isSeqDelim) {\n        // force pixel item vr to OB\n        item.vr = 'OB';\n        itemData.push(item);\n      }\n    }\n\n    return {\n      data: itemData,\n      endOffset: offset,\n      offsetTableVl: offsetTableVl\n    };\n  }\n\n  /**\n   * Read a DICOM data element.\n   *\n   * Reference: [DICOM VRs]{@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_6.2.html#table_6.2-1}.\n   *\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} offset The offset where to start to read.\n   * @param {boolean} implicit Is the DICOM VR implicit?\n   * @param {Tag} [untilTag] Optional tag to stop the reading once reached,\n   *   the returned element will only contain the tag.\n   * @returns {DataElement} The data element.\n   */\n  #readDataElement(reader, offset, implicit, untilTag) {\n    // Tag: group, element\n    const readTagRes = this.#readTag(reader, offset);\n    const tag = readTagRes.tag;\n\n    if (typeof untilTag !== 'undefined' &&\n      tag.equals(untilTag)) {\n      const element = new DataElement('');\n      element.tag = tag;\n      return element;\n    }\n\n    offset = readTagRes.endOffset;\n\n    // Value Representation (VR)\n    let vr = null;\n    let is32bitVL = false;\n    if (tag.isWithVR()) {\n      // implicit VR\n      if (implicit) {\n        vr = tag.getVrFromDictionary();\n        if (typeof vr === 'undefined') {\n          vr = 'UN';\n        }\n        is32bitVL = true;\n      } else {\n        vr = this.#decodeString(reader.readUint8Array(offset, 2));\n        offset += 2 * Uint8Array.BYTES_PER_ELEMENT;\n        is32bitVL = is32bitVLVR(vr);\n        // reserved 2 bytes\n        if (is32bitVL) {\n          offset += 2 * Uint8Array.BYTES_PER_ELEMENT;\n        }\n      }\n    } else {\n      vr = 'NONE';\n      is32bitVL = true;\n    }\n\n    // check vr\n    if (!isKnownVR(vr)) {\n      logger.warn('Unknown VR: ' + vr +\n        ' (for tag ' + tag.getKey() + '), treating as \\'UN\\'');\n      vr = 'UN';\n    }\n\n    // Value Length (VL)\n    let vl = 0;\n    if (is32bitVL) {\n      vl = reader.readUint32(offset);\n      offset += Uint32Array.BYTES_PER_ELEMENT;\n    } else {\n      vl = reader.readUint16(offset);\n      offset += Uint16Array.BYTES_PER_ELEMENT;\n    }\n\n    // check the value of VL\n    let undefinedLength = false;\n    if (vl === 0xffffffff) {\n      undefinedLength = true;\n      vl = 0;\n    }\n\n    // treat private tag with unknown VR and zero VL as a sequence (see #799)\n    if (tag.isPrivate() && vr === 'UN' && vl === 0) {\n      vr = 'SQ';\n    }\n\n    let startOffset = offset;\n    let endOffset = startOffset + vl;\n\n    // read sequence elements\n    let data;\n    if (isPixelDataTag(tag) && undefinedLength) {\n      // pixel data sequence (implicit)\n      const pixItemData =\n        this.#readPixelItemDataElement(reader, offset, implicit);\n      offset = pixItemData.endOffset;\n      startOffset += pixItemData.offsetTableVl;\n      data = pixItemData.data;\n      endOffset = offset;\n      vl = offset - startOffset;\n    } else if (vr === 'SQ') {\n      // sequence\n      data = [];\n      let itemData;\n      if (!undefinedLength) {\n        if (vl !== 0) {\n          // explicit VR sequence: read until the end offset\n          const sqEndOffset = offset + vl;\n          while (offset < sqEndOffset) {\n            itemData = this.#readItemDataElement(reader, offset, implicit);\n            data.push(itemData.data);\n            offset = itemData.endOffset;\n          }\n          endOffset = offset;\n          vl = offset - startOffset;\n        }\n      } else {\n        // implicit VR sequence: read until the sequence delimitation item\n        let isSeqDelim = false;\n        while (!isSeqDelim) {\n          itemData = this.#readItemDataElement(reader, offset, implicit);\n          isSeqDelim = itemData.isSeqDelim;\n          offset = itemData.endOffset;\n          // do not store the delimitation item\n          if (!isSeqDelim) {\n            data.push(itemData.data);\n          }\n        }\n        endOffset = offset;\n        vl = offset - startOffset;\n      }\n    }\n\n    // return\n    const element = new DataElement(vr);\n    element.tag = tag;\n    element.vl = vl;\n    element.startOffset = startOffset;\n    element.endOffset = endOffset;\n    // only set if true (only for sequences and items)\n    if (undefinedLength) {\n      element.undefinedLength = undefinedLength;\n    }\n    if (data) {\n      element.items = data;\n    }\n    return element;\n  }\n\n  /**\n   * Interpret the data of an element.\n   *\n   * @param {DataElement} element The data element.\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} [pixelRepresentation] PixelRepresentation 0->unsigned,\n   *   1->signed (needed for pixel data or VR=xs).\n   * @param {number} [bitsAllocated] Bits allocated (needed for pixel data).\n   * @returns {object} The interpreted data.\n   */\n  #interpretElement(\n    element, reader, pixelRepresentation, bitsAllocated) {\n\n    const tag = element.tag;\n    const vl = element.vl;\n    const vr = element.vr;\n    const offset = element.startOffset;\n\n    // data\n    let data = null;\n    const vrType = vrTypes[vr];\n    if (isPixelDataTag(tag)) {\n      if (element.undefinedLength) {\n        // implicit pixel data sequence\n        data = [];\n        for (let j = 0; j < element.items.length; ++j) {\n          data.push(this.#interpretElement(\n            element.items[j], reader,\n            pixelRepresentation, bitsAllocated));\n        }\n        // remove non parsed items\n        delete element.items;\n      } else {\n        // check bits allocated and VR\n        // https://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_A.2.html\n        if (bitsAllocated > 8 && vr === 'OB') {\n          logger.warn(\n            'Reading DICOM pixel data with bitsAllocated>8 and OB VR' +\n            ', treating as OW'\n          );\n          element.vr = 'OW';\n        }\n        // read\n        data = [];\n        if (bitsAllocated === 1) {\n          data.push(reader.readBinaryArray(offset, vl));\n        } else if (bitsAllocated === 8) {\n          if (pixelRepresentation === 0) {\n            data.push(reader.readUint8Array(offset, vl));\n          } else {\n            data.push(reader.readInt8Array(offset, vl));\n          }\n        } else if (bitsAllocated === 16) {\n          if (pixelRepresentation === 0) {\n            data.push(reader.readUint16Array(offset, vl));\n          } else {\n            data.push(reader.readInt16Array(offset, vl));\n          }\n        } else {\n          throw new Error('Unsupported bits allocated: ' + bitsAllocated);\n        }\n      }\n    } else if (typeof vrType !== 'undefined') {\n      if (vrType === 'Uint8') {\n        data = reader.readUint8Array(offset, vl);\n      } else if (vrType === 'Uint16') {\n        data = reader.readUint16Array(offset, vl);\n        // keep as binary for 'O*' VR\n        if (vr[0] !== 'O') {\n          data = Array.from(data);\n        }\n      } else if (vrType === 'Uint32') {\n        data = reader.readUint32Array(offset, vl);\n        // keep as binary for 'O*' VR\n        if (vr[0] !== 'O') {\n          data = Array.from(data);\n        }\n      } else if (vrType === 'Uint64') {\n        data = reader.readUint64Array(offset, vl);\n      } else if (vrType === 'Int16') {\n        data = Array.from(reader.readInt16Array(offset, vl));\n      } else if (vrType === 'Int32') {\n        data = Array.from(reader.readInt32Array(offset, vl));\n      } else if (vrType === 'Int64') {\n        data = reader.readInt64Array(offset, vl);\n      } else if (vrType === 'Float32') {\n        data = Array.from(reader.readFloat32Array(offset, vl));\n      } else if (vrType === 'Float64') {\n        data = Array.from(reader.readFloat64Array(offset, vl));\n      } else if (vrType === 'string') {\n        const stream = reader.readUint8Array(offset, vl);\n        if (isCharSetStringVR(vr)) {\n          data = this.#decodeSpecialString(stream);\n        } else {\n          data = this.#decodeString(stream);\n        }\n        data = cleanString(data).split('\\\\');\n      } else {\n        throw new Error('Unknown VR type: ' + vrType);\n      }\n    } else if (vr === 'xx') {\n      // US or OW\n      data = Array.from(reader.readUint16Array(offset, vl));\n    } else if (vr === 'ox') {\n      // OB or OW\n      if (bitsAllocated === 8) {\n        if (pixelRepresentation === 0) {\n          data = Array.from(reader.readUint8Array(offset, vl));\n        } else {\n          data = Array.from(reader.readInt8Array(offset, vl));\n        }\n      } else {\n        if (pixelRepresentation === 0) {\n          data = Array.from(reader.readUint16Array(offset, vl));\n        } else {\n          data = Array.from(reader.readInt16Array(offset, vl));\n        }\n      }\n    } else if (vr === 'xs') {\n      // (US or SS) or (US or SS or OW)\n      if (pixelRepresentation === 0) {\n        data = Array.from(reader.readUint16Array(offset, vl));\n      } else {\n        data = Array.from(reader.readInt16Array(offset, vl));\n      }\n    } else if (vr === 'AT') {\n      // attribute\n      const raw = reader.readUint16Array(offset, vl);\n      data = [];\n      for (let i = 0, leni = raw.length; i < leni; i += 2) {\n        const stri = raw[i].toString(16);\n        const stri1 = raw[i + 1].toString(16);\n        let str = '(';\n        str += '0000'.substring(0, 4 - stri.length) + stri.toUpperCase();\n        str += ',';\n        str += '0000'.substring(0, 4 - stri1.length) + stri1.toUpperCase();\n        str += ')';\n        data.push(str);\n      }\n    } else if (vr === 'SQ') {\n      // sequence\n      data = [];\n      for (let k = 0; k < element.items.length; ++k) {\n        const item = element.items[k];\n        const itemData = {};\n        const keys = Object.keys(item);\n        let sqBitsAllocated = bitsAllocated;\n        let sqPixelRepresentation = pixelRepresentation;\n        for (let l = 0; l < keys.length; ++l) {\n          // check if local bitsAllocated\n          // (inside item loop to get interpreted value)\n          let dataElement = item[TagKeys.BitsAllocated];\n          if (typeof dataElement !== 'undefined' &&\n            typeof dataElement.value !== 'undefined') {\n            sqBitsAllocated = dataElement.value[0];\n          }\n          // check if local pixelRepresentation\n          // (inside item loop to get interpreted value)\n          dataElement = item[TagKeys.PixelRepresentation];\n          if (typeof dataElement !== 'undefined' &&\n            typeof dataElement.value !== 'undefined') {\n            sqPixelRepresentation = dataElement.value[0];\n          }\n          const subElement = item[keys[l]];\n          subElement.value = this.#interpretElement(\n            subElement, reader,\n            sqPixelRepresentation, sqBitsAllocated);\n          delete subElement.tag;\n          delete subElement.vl;\n          delete subElement.startOffset;\n          delete subElement.endOffset;\n          itemData[keys[l]] = subElement;\n        }\n        data.push(itemData);\n      }\n      // remove non parsed elements\n      delete element.items;\n    } else if (vr === 'NONE') {\n      // no VR -> no data\n      data = [];\n    } else {\n      logger.warn('Unknown VR: ' + vr +\n        ' (for tag ' + element.tag.getKey() + ')');\n      // empty data...\n      data = [];\n    }\n\n    return data;\n  }\n\n  /**\n   * Interpret the data of a list of elements.\n   *\n   * @param {DataElements} elements A list of data elements.\n   * @param {DataReader} reader The raw data reader.\n   * @param {number} pixelRepresentation PixelRepresentation 0->unsigned,\n   *   1->signed.\n   * @param {number} bitsAllocated Bits allocated.\n   */\n  #interpret(\n    elements, reader,\n    pixelRepresentation, bitsAllocated) {\n\n    const keys = Object.keys(elements);\n    for (let i = 0; i < keys.length; ++i) {\n      const element = elements[keys[i]];\n      if (typeof element.value === 'undefined') {\n        element.value = this.#interpretElement(\n          element, reader, pixelRepresentation, bitsAllocated);\n      }\n      // delete interpretation specific properties\n      delete element.tag;\n      delete element.vl;\n      delete element.startOffset;\n      delete element.endOffset;\n    }\n  }\n\n  /**\n   * Parse a DICOM buffer.\n   * Fills in the member object 'dataElements'.\n   *\n   * @param {ArrayBuffer} buffer The input array buffer.\n   * @param {Tag} [untilTag] Optional tag to stop the parsing once reached.\n   */\n  parse(buffer, untilTag) {\n    let offset = 0;\n    let syntax = '';\n    let dataElement = null;\n    // default readers\n    const metaReader = new DataReader(buffer);\n    let dataReader = new DataReader(buffer);\n\n    // 128 -> 132: magic word\n    offset = 128;\n    const magicword = this.#decodeString(metaReader.readUint8Array(offset, 4));\n    offset += 4 * Uint8Array.BYTES_PER_ELEMENT;\n    if (magicword === 'DICM') {\n      // 0002, 0000: FileMetaInformationGroupLength (vr='UL')\n      dataElement = this.#readDataElement(metaReader, offset, false);\n      dataElement.value = this.#interpretElement(dataElement, metaReader);\n      // increment offset\n      offset = dataElement.endOffset;\n      // store the data element\n      this.#dataElements[dataElement.tag.getKey()] = dataElement;\n      // get meta length\n      const metaLength = dataElement.value[0];\n\n      // meta elements\n      const metaEnd = offset + metaLength;\n      while (offset < metaEnd) {\n        // get the data element\n        dataElement = this.#readDataElement(metaReader, offset, false);\n        offset = dataElement.endOffset;\n        // store the data element\n        this.#dataElements[dataElement.tag.getKey()] = dataElement;\n      }\n\n      // check the TransferSyntaxUID (has to be there!)\n      dataElement = this.#dataElements[TagKeys.TransferSyntax];\n      if (typeof dataElement === 'undefined') {\n        throw new Error('Not a valid DICOM file (no TransferSyntaxUID found)');\n      }\n      dataElement.value = this.#interpretElement(dataElement, metaReader);\n      syntax = dataElement.value[0];\n\n    } else {\n      logger.warn('No DICM prefix, trying to guess tansfer syntax.');\n      // read first element\n      dataElement = this.#readDataElement(dataReader, 0, false);\n      // guess transfer syntax\n      const tsElement = guessTransferSyntax(dataElement);\n      // store\n      this.#dataElements[tsElement.tag.getKey()] = tsElement;\n      syntax = tsElement.value[0];\n      // reset offset\n      offset = 0;\n    }\n\n    // check transfer syntax support\n    if (!isReadSupportedTransferSyntax(syntax)) {\n      throw new Error('Unsupported DICOM transfer syntax: \\'' + syntax +\n        '\\' (' + getTransferSyntaxName(syntax) + ')');\n    }\n\n    // set implicit flag\n    let implicit = false;\n    if (isImplicitTransferSyntax(syntax)) {\n      implicit = true;\n    }\n\n    // Big Endian\n    if (isBigEndianTransferSyntax(syntax)) {\n      dataReader = new DataReader(buffer, false);\n    }\n\n    let reachedUntilTag = false;\n\n    // DICOM data elements\n    while (offset < buffer.byteLength) {\n      // get the data element\n      dataElement = this.#readDataElement(\n        dataReader, offset, implicit, untilTag);\n      // until tag\n      if (typeof untilTag !== 'undefined' &&\n        dataElement.tag.equals(untilTag)) {\n        reachedUntilTag = true;\n        break;\n      }\n      // increment offset\n      offset = dataElement.endOffset;\n      // store the data element\n      const key = dataElement.tag.getKey();\n      if (typeof this.#dataElements[key] === 'undefined') {\n        this.#dataElements[key] = dataElement;\n      } else {\n        logger.warn('Not saving duplicate tag: ' + key);\n      }\n    }\n\n    // safety checks...\n    if (isNaN(offset)) {\n      throw new Error('Problem while parsing, bad offset');\n    }\n    if (!reachedUntilTag && buffer.byteLength !== offset) {\n      logger.warn('Did not reach the end of the buffer: ' +\n        offset + ' != ' + buffer.byteLength);\n    }\n\n    //-------------------------------------------------\n    // values needed for data interpretation\n\n    // pixel specific\n    let pixelRepresentation = 0;\n    let bitsAllocated = 16;\n    if (typeof this.#dataElements[TagKeys.PixelData] !== 'undefined') {\n      // PixelRepresentation 0->unsigned, 1->signed\n      dataElement = this.#dataElements[TagKeys.PixelRepresentation];\n      if (typeof dataElement !== 'undefined') {\n        dataElement.value = this.#interpretElement(dataElement, dataReader);\n        pixelRepresentation = dataElement.value[0];\n      } else {\n        logger.warn(\n          'Reading DICOM pixel data with default pixelRepresentation.');\n      }\n\n      // BitsAllocated\n      dataElement = this.#dataElements[TagKeys.BitsAllocated];\n      if (typeof dataElement !== 'undefined') {\n        dataElement.value = this.#interpretElement(dataElement, dataReader);\n        bitsAllocated = dataElement.value[0];\n      } else {\n        logger.warn('Reading DICOM pixel data with default bitsAllocated.');\n      }\n    }\n\n    // default character set\n    if (typeof this.#defaultCharacterSet !== 'undefined') {\n      this.setDecoderCharacterSet(this.#defaultCharacterSet);\n    }\n\n    // SpecificCharacterSet\n    dataElement = this.#dataElements[TagKeys.SpecificCharacterSet];\n    if (typeof dataElement !== 'undefined') {\n      dataElement.value = this.#interpretElement(dataElement, dataReader);\n      let charSetTerm;\n      if (dataElement.value.length === 1) {\n        charSetTerm = dataElement.value[0];\n      } else {\n        charSetTerm = dataElement.value[1];\n        logger.warn('Unsupported character set with code extensions: \\'' +\n          charSetTerm + '\\'.');\n      }\n      this.setDecoderCharacterSet(getUtfLabel(charSetTerm));\n    }\n\n    // interpret the dicom elements\n    this.#interpret(\n      this.#dataElements, dataReader,\n      pixelRepresentation, bitsAllocated\n    );\n\n    // handle fragmented pixel buffer\n    // Reference: http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_8.2.html\n    // (third note, \"Depending on the transfer syntax...\")\n    dataElement = this.#dataElements[TagKeys.PixelData];\n    if (typeof dataElement !== 'undefined') {\n      if (dataElement.undefinedLength) {\n        let numberOfFrames = 1;\n        if (typeof this.#dataElements[TagKeys.NumberOfFrames] !== 'undefined') {\n          numberOfFrames = Number(\n            this.#dataElements[TagKeys.NumberOfFrames].value[0]\n          );\n        }\n        const pixItems = dataElement.value;\n        if (pixItems.length > 1 && pixItems.length > numberOfFrames) {\n          // concatenate pixel data items\n          // concat does not work on typed arrays\n          //this.pixelBuffer = this.pixelBuffer.concat( dataElement.data );\n          // manual concat...\n          const nItemPerFrame = pixItems.length / numberOfFrames;\n          const newPixItems = [];\n          let index = 0;\n          for (let f = 0; f < numberOfFrames; ++f) {\n            index = f * nItemPerFrame;\n            // calculate the size of a frame\n            let size = 0;\n            for (let i = 0; i < nItemPerFrame; ++i) {\n              size += pixItems[index + i].length;\n            }\n            // create new buffer\n            const newBuffer = new pixItems[0].constructor(size);\n            // fill new buffer\n            let fragOffset = 0;\n            for (let j = 0; j < nItemPerFrame; ++j) {\n              newBuffer.set(pixItems[index + j], fragOffset);\n              fragOffset += pixItems[index + j].length;\n            }\n            newPixItems[f] = newBuffer;\n          }\n          // store as pixel data\n          dataElement.value = newPixItems;\n        }\n      }\n    }\n  }\n\n} // class DicomParser\n","import {logger} from './logger';\n\n/**\n * ListenerHandler class: handles add/removing and firing listeners.\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget#example}.\n */\nexport class ListenerHandler {\n  /**\n   * Listeners.\n   *\n   * @type {object}\n   */\n  #listeners = {};\n\n  /**\n   * Add an event listener.\n   *\n   * @param {string} type The event type.\n   * @param {object} callback The method associated with the provided\n   *    event type, will be called with the fired event.\n   */\n  add(type, callback) {\n    // create array if not present\n    if (typeof this.#listeners[type] === 'undefined') {\n      this.#listeners[type] = [];\n    }\n    // add callback to listeners array\n    this.#listeners[type].push(callback);\n  }\n\n  /**\n   * Remove an event listener.\n   *\n   * @param {string} type The event type.\n   * @param {object} callback The method associated with the provided\n   *   event type.\n   */\n  remove(type, callback) {\n    // check if the type is present\n    if (typeof this.#listeners[type] === 'undefined') {\n      return;\n    }\n    // remove from listeners array\n    let nFound = 0;\n    for (let i = 0; i < this.#listeners[type].length; ++i) {\n      if (this.#listeners[type][i] === callback) {\n        ++nFound;\n        this.#listeners[type].splice(i, 1);\n      }\n    }\n    if (nFound === 0) {\n      logger.debug('No callback found on remove listener for type ' + type);\n    }\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  fireEvent = (event) => {\n    // check if they are listeners for the event type\n    if (typeof this.#listeners[event.type] === 'undefined') {\n      return;\n    }\n    // fire events from a copy of the listeners array\n    // to avoid interference from possible add/remove\n    const stack = this.#listeners[event.type].slice();\n    for (let i = 0; i < stack.length; ++i) {\n      stack[i](event);\n    }\n  };\n}\n","import {Index} from '../math/index';\nimport {Point2D} from '../math/point';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {Matrix33} from '../math/matrix';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get an simple iterator for a given range for a one component data.\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols}.\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start The start of the range (included).\n * @param {number} end The end of the range (excluded).\n * @param {number} [increment] The increment between indicies (default=1).\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function simpleRange(dataAccessor, start, end, increment) {\n  if (typeof increment === 'undefined') {\n    increment = 1;\n  }\n  let nextIndex = start;\n  // result\n  return {\n    next: function () {\n      if (nextIndex < end) {\n        const result = {\n          value: dataAccessor(nextIndex),\n          done: false,\n          index: nextIndex\n        };\n        nextIndex += increment;\n        return result;\n      }\n      return {\n        done: true,\n        index: end\n      };\n    }\n  };\n}\n\n/**\n * Get an iterator for a given range for a one component data.\n *\n * Using 'maxIter' and not an 'end' index since it fails in some edge cases\n * (for ex coronal2, ie zxy).\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start Zero-based index at which to start the iteration.\n * @param {number} maxIter The maximum number of iterations.\n * @param {number} increment Increment between indicies.\n * @param {number} blockMaxIter Number of applied increment after which\n *   blockIncrement is applied.\n * @param {number} blockIncrement Increment after blockMaxIter is reached,\n *   the value is from block start to the next block start.\n * @param {boolean} reverse1 If true, loop from end to start.\n *   WARN: don't forget to set the value of start as the last index!\n * @param {boolean} reverse2 If true, loop from block end to block start.\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function range(dataAccessor, start, maxIter, increment,\n  blockMaxIter, blockIncrement, reverse1, reverse2) {\n  if (typeof reverse1 === 'undefined') {\n    reverse1 = false;\n  }\n  if (typeof reverse2 === 'undefined') {\n    reverse2 = false;\n  }\n\n  // first index of the iteration\n  let nextIndex = start;\n  // adapt first index and increments to reverse values\n  if (reverse1) {\n    blockIncrement *= -1;\n    if (reverse2) {\n      // start at end of line\n      nextIndex -= (blockMaxIter - 1) * increment;\n    } else {\n      increment *= -1;\n    }\n  } else {\n    if (reverse2) {\n      // start at end of line\n      nextIndex += (blockMaxIter - 1) * increment;\n      increment *= -1;\n    }\n  }\n  const finalBlockIncrement = blockIncrement - blockMaxIter * increment;\n\n  // counters\n  let mainCount = 0;\n  let blockCount = 0;\n  // result\n  return {\n    next: function () {\n      if (mainCount < maxIter) {\n        const result = {\n          value: dataAccessor(nextIndex),\n          done: false,\n          index: nextIndex\n        };\n        nextIndex += increment;\n        ++mainCount;\n        ++blockCount;\n        if (blockCount === blockMaxIter) {\n          blockCount = 0;\n          nextIndex += finalBlockIncrement;\n        }\n        return result;\n      }\n      return {\n        done: true,\n        index: nextIndex\n      };\n    }\n  };\n}\n\n/**\n * Get an iterator for a given range with bounds (for a one component data).\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols}.\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start The start of the range (included).\n * @param {number} end The end of the range (excluded).\n * @param {number} increment The increment between indicies.\n * @param {number} regionSize The size of the region to iterate through.\n * @param {number} regionOffset The offset between regions.\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function rangeRegion(\n  dataAccessor, start, end, increment, regionSize, regionOffset) {\n  let nextIndex = start;\n  let regionElementCount = 0;\n  // result\n  return {\n    next: function () {\n      if (nextIndex < end) {\n        const result = {\n          value: dataAccessor(nextIndex),\n          done: false,\n          index: nextIndex\n        };\n        regionElementCount += 1;\n        nextIndex += increment;\n        if (regionElementCount === regionSize) {\n          regionElementCount = 0;\n          nextIndex += regionOffset;\n        }\n        return result;\n      }\n      return {\n        done: true,\n        index: end\n      };\n    }\n  };\n}\n\n/**\n * Get an iterator for a given range with bounds (for a one component data).\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols}.\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start The start of the range (included).\n * @param {number} end The end of the range (excluded).\n * @param {number} increment The increment between indicies.\n * @param {number[][]} regions An array of regions: [off0, size, off1].\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function rangeRegions(\n  dataAccessor, start, end, increment, regions) {\n  let nextIndex = start;\n  let regionCount = 0;\n  let regionElementCount = 0;\n  // result\n  return {\n    next: function () {\n      if (nextIndex < end) {\n        const result = {\n          value: dataAccessor(nextIndex),\n          done: false,\n          index: nextIndex\n        };\n        regionElementCount += 1;\n        nextIndex += increment;\n        if (regionElementCount === regions[regionCount][1]) {\n          regionElementCount = 0;\n          // off1 of current group\n          nextIndex += regions[regionCount][2];\n          regionCount += 1;\n          // off0 of next group\n          if (regionCount < regions.length) {\n            nextIndex += regions[regionCount][0];\n          }\n        }\n        return result;\n      }\n      return {\n        done: true,\n        index: end\n      };\n    }\n  };\n}\n\n/**\n * Get an iterator for a given range for a 3 components data.\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols}.\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start The start of the range (included).\n * @param {number} end The end of the range (excluded).\n *   (end - start) needs to be a multiple of 3...\n * @param {number} increment The increment between indicies (default=1).\n * @param {boolean} isPlanar A flag to know if the data is planar\n *   (RRRR...GGGG...BBBB...) or not (RGBRGBRGBRGB...), defaults to false.\n * @returns {object} A 3 components iterator folowing the iterator and iterable\n *   protocol, the value is an array of size 3 with each component.\n */\nexport function simpleRange3d(\n  dataAccessor, start, end, increment, isPlanar) {\n  if (typeof increment === 'undefined') {\n    increment = 1;\n  }\n  if (typeof isPlanar === 'undefined') {\n    isPlanar = false;\n  }\n  let nextIndex = start;\n  let componentIncrement = 1;\n  if (isPlanar) {\n    componentIncrement = (end - start) / 3;\n  } else {\n    increment *= 3;\n  }\n  let nextIndex1 = nextIndex + componentIncrement;\n  let nextIndex2 = nextIndex + 2 * componentIncrement;\n\n  // result\n  return {\n    next: function () {\n      if (nextIndex < end) {\n        const result = {\n          value: [\n            dataAccessor(nextIndex),\n            dataAccessor(nextIndex1),\n            dataAccessor(nextIndex2)\n          ],\n          done: false,\n          index: [nextIndex, nextIndex1, nextIndex2]\n        };\n        nextIndex += increment;\n        nextIndex1 += increment;\n        nextIndex2 += increment;\n        return result;\n      }\n      return {\n        done: true,\n        index: [end]\n      };\n    }\n  };\n}\n\n/**\n * Get an iterator for a given range for a 3 components data.\n *\n * Using 'maxIter' and not an 'end' index since it fails in some edge cases\n * (for ex coronal2, ie zxy).\n *\n * @param {Function} dataAccessor Function to access data.\n * @param {number} start Zero-based index at which to start the iteration.\n * @param {number} maxIter The maximum number of iterations.\n * @param {number} increment Increment between indicies.\n * @param {number} blockMaxIter Number of applied increment after which\n *   blockIncrement is applied.\n * @param {number} blockIncrement Increment after blockMaxIter is reached,\n *   the value is from block start to the next block start.\n * @param {boolean} reverse1 If true, loop from end to start.\n *   WARN: don't forget to set the value of start as the last index!\n * @param {boolean} reverse2 If true, loop from block end to block start.\n * @param {boolean} isPlanar A flag to know if the data is planar\n *   (RRRR...GGGG...BBBB...) or not (RGBRGBRGBRGB...), defaults to false.\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function range3d(dataAccessor, start, maxIter, increment,\n  blockMaxIter, blockIncrement, reverse1, reverse2, isPlanar) {\n  const iters = [];\n  if (isPlanar) {\n    iters.push(range(\n      dataAccessor, start, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n    iters.push(range(\n      dataAccessor, start + maxIter * increment, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n    iters.push(range(\n      dataAccessor, start + 2 * maxIter * increment, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n  } else {\n    increment *= 3;\n    blockIncrement *= 3;\n    iters.push(range(\n      dataAccessor, start, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n    iters.push(range(\n      dataAccessor, start + 1, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n    iters.push(range(\n      dataAccessor, start + 2, maxIter, increment,\n      blockMaxIter, blockIncrement, reverse1, reverse2\n    ));\n  }\n\n  // result\n  return {\n    next: function () {\n      const r0 = iters[0].next();\n      const r1 = iters[1].next();\n      const r2 = iters[2].next();\n      if (!r0.done) {\n        return {\n          value: [\n            r0.value,\n            r1.value,\n            r2.value\n          ],\n          done: false,\n          index: [\n            r0.index,\n            r1.index,\n            r2.index\n          ]\n        };\n      }\n      return {\n        done: true,\n        index: r2.index\n      };\n    }\n  };\n}\n\n/**\n * Get a list of values for a given iterator.\n *\n * @param {object} iterator The iterator to use to loop through data.\n * @returns {Array} The list of values.\n */\nexport function getIteratorValues(iterator) {\n  const values = [];\n  let ival = iterator.next();\n  while (!ival.done) {\n    values.push(ival.value);\n    ival = iterator.next();\n  }\n  return values;\n}\n\n/**\n * Get a slice index iterator.\n *\n * @param {Image} image The image to parse.\n * @param {Index} index The current index.\n * @param {boolean} isRescaled Flag for rescaled values (default false).\n * @param {Matrix33} viewOrientation The view orientation.\n * @returns {object} The slice iterator.\n */\nexport function getSliceIterator(\n  image, index, isRescaled, viewOrientation) {\n  const size = image.getGeometry().getSize();\n  // zero-ify non direction index\n  let dirMax2Index = 2;\n  if (viewOrientation && typeof viewOrientation !== 'undefined') {\n    dirMax2Index = viewOrientation.getColAbsMax(2).index;\n  }\n  const posValues = index.getValues();\n  // keep the main direction and any other than 3D\n  const indexFilter = function (element, i) {\n    return (i === dirMax2Index || i > 2) ? element : 0;\n  };\n  const posStart = new Index(posValues.map(indexFilter));\n  let start = size.indexToOffset(posStart);\n\n  // default to non rescaled data\n  if (typeof isRescaled === 'undefined') {\n    isRescaled = false;\n  }\n  let dataAccessor = null;\n  if (isRescaled) {\n    dataAccessor = function (offset) {\n      return image.getRescaledValueAtOffset(offset);\n    };\n  } else {\n    dataAccessor = function (offset) {\n      return image.getValueAtOffset(offset);\n    };\n  }\n\n  const ncols = size.get(0);\n  const nrows = size.get(1);\n  const nslices = size.get(2);\n  let sliceSize = size.getDimSize(2);\n\n  const ncomp = image.getNumberOfComponents();\n  const isPlanar = image.getPlanarConfiguration() === 1;\n  const getRange = function (\n    dataAccessor, start, maxIter, increment,\n    blockMaxIter, blockIncrement, reverse1, reverse2) {\n    if (ncomp === 1) {\n      return range(dataAccessor, start, maxIter, increment,\n        blockMaxIter, blockIncrement, reverse1, reverse2);\n    } else if (ncomp === 3) {\n      return range3d(dataAccessor, 3 * start, maxIter, increment,\n        blockMaxIter, blockIncrement, reverse1, reverse2, isPlanar);\n    }\n  };\n\n  let rangeObj = null;\n  if (viewOrientation && typeof viewOrientation !== 'undefined') {\n    const dirMax0 = viewOrientation.getColAbsMax(0);\n    const dirMax2 = viewOrientation.getColAbsMax(2);\n\n    // default reverse\n    const reverse1 = false;\n    const reverse2 = false;\n\n    let maxIter = null;\n    if (dirMax2.index === 2) {\n      // axial\n      maxIter = ncols * nrows;\n      if (dirMax0.index === 0) {\n        // xyz\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, 1, ncols, ncols, reverse1, reverse2);\n      } else {\n        // yxz\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, ncols, nrows, 1, reverse1, reverse2);\n      }\n    } else if (dirMax2.index === 0) {\n      // sagittal\n      maxIter = nslices * nrows;\n      if (dirMax0.index === 1) {\n        // yzx\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, ncols, nrows, sliceSize, reverse1, reverse2);\n      } else {\n        // zyx\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, sliceSize, nslices, ncols, reverse1, reverse2);\n      }\n    } else if (dirMax2.index === 1) {\n      // coronal\n      maxIter = nslices * ncols;\n      if (dirMax0.index === 0) {\n        // xzy\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, 1, ncols, sliceSize, reverse1, reverse2);\n      } else {\n        // zxy\n        rangeObj = getRange(dataAccessor,\n          start, maxIter, sliceSize, nslices, 1, reverse1, reverse2);\n      }\n    } else {\n      throw new Error('Unknown direction: ' + dirMax2.index);\n    }\n  } else {\n    if (image.getNumberOfComponents() === 1) {\n      rangeObj = simpleRange(dataAccessor, start, start + sliceSize);\n    } else if (image.getNumberOfComponents() === 3) {\n      // 3 times bigger...\n      start *= 3;\n      sliceSize *= 3;\n      rangeObj = simpleRange3d(\n        dataAccessor, start, start + sliceSize, 1, isPlanar);\n    } else {\n      throw new Error('Unsupported number of components: ' +\n        image.getNumberOfComponents());\n    }\n  }\n\n  return rangeObj;\n}\n\n/**\n * Get a slice index iterator for a rectangular region.\n *\n * @param {Image} image The image to parse.\n * @param {Index} index The current index.\n * @param {boolean} isRescaled Flag for rescaled values (default false).\n * @param {Point2D} min The minimum position (optional).\n * @param {Point2D} max The maximum position (optional).\n * @returns {object} The slice iterator.\n */\nexport function getRegionSliceIterator(\n  image, index, isRescaled, min, max) {\n  if (image.getNumberOfComponents() !== 1) {\n    throw new Error('Unsupported number of components for region iterator: ' +\n      image.getNumberOfComponents());\n  }\n\n  // default to non rescaled data\n  if (typeof isRescaled === 'undefined') {\n    isRescaled = false;\n  }\n  let dataAccessor = null;\n  if (isRescaled) {\n    dataAccessor = function (offset) {\n      return image.getRescaledValueAtOffset(offset);\n    };\n  } else {\n    dataAccessor = function (offset) {\n      return image.getValueAtOffset(offset);\n    };\n  }\n\n  const size = image.getGeometry().getSize();\n  if (typeof min === 'undefined') {\n    min = new Point2D(0, 0);\n  }\n  if (typeof max === 'undefined') {\n    max = new Point2D(\n      size.get(0) - 1,\n      size.get(1)\n    );\n  }\n  // position to pixel for max: extra X is ok, remove extra Y\n  const startOffset = size.indexToOffset(index.getWithNew2D(\n    min.getX(), min.getY()\n  ));\n  const endOffset = size.indexToOffset(index.getWithNew2D(\n    max.getX(), max.getY() - 1\n  ));\n\n  // minimum 1 column\n  const rangeNumberOfColumns = Math.max(1, max.getX() - min.getX());\n  const rowIncrement = size.get(0) - rangeNumberOfColumns;\n\n  return rangeRegion(\n    dataAccessor, startOffset, endOffset + 1,\n    1, rangeNumberOfColumns, rowIncrement);\n}\n\n/**\n * Get a slice index iterator for a rectangular region.\n *\n * @param {Image} image The image to parse.\n * @param {Index} index The current index.\n * @param {boolean} isRescaled Flag for rescaled values (default false).\n * @param {number[][][]} regions An array of [x, y] pairs (min, max).\n * @returns {object|undefined} The slice iterator.\n */\nexport function getVariableRegionSliceIterator(\n  image, index, isRescaled, regions) {\n  if (image.getNumberOfComponents() !== 1) {\n    throw new Error('Unsupported number of components for region iterator: ' +\n      image.getNumberOfComponents());\n  }\n\n  // default to non rescaled data\n  if (typeof isRescaled === 'undefined') {\n    isRescaled = false;\n  }\n  let dataAccessor = null;\n  if (isRescaled) {\n    dataAccessor = function (offset) {\n      return image.getRescaledValueAtOffset(offset);\n    };\n  } else {\n    dataAccessor = function (offset) {\n      return image.getValueAtOffset(offset);\n    };\n  }\n\n  const size = image.getGeometry().getSize();\n\n  const offsetRegions = [];\n  let region;\n  let min = null;\n  let max = null;\n  let regionIndex = null;\n  for (let i = 0; i < regions.length; ++i) {\n    region = regions[i];\n    const width = region[1][0] - region[0][0];\n    if (width !== 0) {\n      regionIndex = i;\n      if (!min) {\n        min = region[0];\n      }\n      offsetRegions.push([\n        region[0][0],\n        width,\n        size.get(0) - region[1][0]\n      ]);\n    }\n  }\n  if (regionIndex !== null) {\n    max = regions[regionIndex][1];\n  }\n\n  // exit if no offsets\n  if (offsetRegions.length === 0) {\n    return undefined;\n  }\n\n  const startOffset = size.indexToOffset(index.getWithNew2D(\n    min[0], min[1]\n  ));\n  const endOffset = size.indexToOffset(index.getWithNew2D(\n    max[0], max[1]\n  ));\n\n  return rangeRegions(\n    dataAccessor, startOffset, endOffset + 1,\n    1, offsetRegions);\n}\n\n/**\n * Get a multiple value iterator. The input array defines the values and\n * their start index.\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols}.\n *\n * @param {Array} values An array of {index, value} pairs.\n * @param {number} end The end of the range (excluded).\n * @returns {object} An iterator folowing the iterator and iterable protocol.\n */\nexport function valueRange(values, end) {\n  let nextIndex = 0;\n  let nextValueIndex = 0;\n  // result\n  return {\n    next: function () {\n      if (nextIndex < end) {\n        if (nextValueIndex + 1 < values.length &&\n          nextIndex >= values[nextValueIndex + 1].index) {\n          ++nextValueIndex;\n        }\n        const result = {\n          value: values[nextValueIndex].value,\n          done: false,\n          index: nextIndex\n        };\n        ++nextIndex;\n        return result;\n      }\n      return {\n        done: true,\n        index: end\n      };\n    }\n  };\n}\n","/**\n * Rescale Slope and Intercept.\n */\nexport class RescaleSlopeAndIntercept {\n\n  /**\n   * The slope.\n   *\n   * @type {number}\n   */\n  #slope;\n\n  /**\n   * The intercept.\n   *\n   * @type {number}\n   */\n  #intercept;\n\n  /**\n   * @param {number} slope The slope of the RSI.\n   * @param {number} intercept The intercept of the RSI.\n   */\n  constructor(slope, intercept) {\n    /*// Check the rescale slope.\n      if(typeof(slope) === 'undefined') {\n          slope = 1;\n      }\n      // Check the rescale intercept.\n      if(typeof(intercept) === 'undefined') {\n          intercept = 0;\n      }*/\n    this.#slope = slope;\n    this.#intercept = intercept;\n  }\n\n  /**\n   * Get the slope of the RSI.\n   *\n   * @returns {number} The slope of the RSI.\n   */\n  getSlope() {\n    return this.#slope;\n  }\n\n  /**\n   * Get the intercept of the RSI.\n   *\n   * @returns {number} The intercept of the RSI.\n   */\n  getIntercept() {\n    return this.#intercept;\n  }\n\n  /**\n   * Apply the RSI on an input value.\n   *\n   * @param {number} value The input value.\n   * @returns {number} The value to rescale.\n   */\n  apply(value) {\n    return value * this.#slope + this.#intercept;\n  }\n\n  /**\n   * Check for RSI equality.\n   *\n   * @param {RescaleSlopeAndIntercept} rhs The other RSI to compare to.\n   * @returns {boolean} True if both RSI are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      typeof rhs !== 'undefined' &&\n      this.getSlope() === rhs.getSlope() &&\n      this.getIntercept() === rhs.getIntercept();\n  }\n\n  /**\n   * Is this RSI an ID RSI.\n   *\n   * @returns {boolean} True if the RSI has a slope of 1 and no intercept.\n   */\n  isID() {\n    return (this.getSlope() === 1 && this.getIntercept() === 0);\n  }\n\n} // class RescaleSlopeAndIntercept\n","import {Index} from '../math/index';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Matrix33} from '../math/matrix';\nimport {Scalar2D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Immutable Size class.\n * Warning: the input array is NOT cloned, modifying it will\n *  modify the index values.\n */\nexport class Size {\n\n  /**\n   * The size values.\n   *\n   * @type {number[]}\n   */\n  #values;\n\n  /**\n   * @param {number[]} values The size values.\n   */\n  constructor(values) {\n    if (!values || typeof values === 'undefined') {\n      throw new Error('Cannot create size with no values.');\n    }\n    if (values.length === 0) {\n      throw new Error('Cannot create size with empty values.');\n    }\n    const valueCheck = function (val) {\n      return !isNaN(val) && val !== 0;\n    };\n    if (!values.every(valueCheck)) {\n      throw new Error('Cannot create size with non number or zero values.');\n    }\n    this.#values = values;\n  }\n\n  /**\n   * Get the size value at the given array index.\n   *\n   * @param {number} i The index to get.\n   * @returns {number} The value.\n   */\n  get(i) {\n    return this.#values[i];\n  }\n\n  /**\n   * Get the length of the index.\n   *\n   * @returns {number} The length.\n   */\n  length() {\n    return this.#values.length;\n  }\n\n  /**\n   * Get a string representation of the size.\n   *\n   * @returns {string} The Size as a string.\n   */\n  toString() {\n    return '(' + this.#values.toString() + ')';\n  }\n\n  /**\n   * Get the values of this index.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return this.#values.slice();\n  }\n\n  /**\n   * Check if a dimension exists and has more than one element.\n   *\n   * @param {number} dimension The dimension to check.\n   * @returns {boolean} True if the size is more than one.\n   */\n  moreThanOne(dimension) {\n    return this.length() >= dimension + 1 && this.get(dimension) !== 1;\n  }\n\n  /**\n   * Check if the associated data is scrollable in 3D.\n   *\n   * @param {Matrix33} [viewOrientation] The orientation matrix.\n   * @returns {boolean} True if scrollable.\n   */\n  canScroll3D(viewOrientation) {\n    let dimension = 2;\n    if (typeof viewOrientation !== 'undefined') {\n      dimension = viewOrientation.getThirdColMajorDirection();\n    }\n    return this.moreThanOne(dimension);\n  }\n\n  /**\n   * Check if the associated data is scrollable: either in 3D or\n   * in other directions.\n   *\n   * @param {Matrix33} viewOrientation The orientation matrix.\n   * @returns {boolean} True if scrollable.\n   */\n  canScroll(viewOrientation) {\n    let canScroll = this.canScroll3D(viewOrientation);\n    // check possible other dimensions\n    for (let i = 3; i < this.length(); ++i) {\n      canScroll = canScroll || this.moreThanOne(i);\n    }\n    return canScroll;\n  }\n\n  /**\n   * Get the size of a given dimension.\n   *\n   * @param {number} dimension The dimension.\n   * @param {number} [start] Optional start dimension to start counting from.\n   * @returns {number} The size.\n   */\n  getDimSize(dimension, start) {\n    if (dimension > this.length()) {\n      return null;\n    }\n    if (typeof start === 'undefined') {\n      start = 0;\n    } else {\n      if (start < 0 || start > dimension) {\n        throw new Error('Invalid start value for getDimSize');\n      }\n    }\n    let size = 1;\n    for (let i = start; i < dimension; ++i) {\n      size *= this.get(i);\n    }\n    return size;\n  }\n\n  /**\n   * Get the total size.\n   *\n   * @param {number} [start] Optional start dimension to base the offset on.\n   * @returns {number} The total size.\n   */\n  getTotalSize(start) {\n    return this.getDimSize(this.length(), start);\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Size} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    // check input\n    if (!rhs) {\n      return false;\n    }\n    // check length\n    const length = this.length();\n    if (length !== rhs.length()) {\n      return false;\n    }\n    // check values\n    for (let i = 0; i < length; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        return false;\n      }\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Check that an index is within bounds.\n   *\n   * @param {Index} index The index to check.\n   * @param {number[]} dirs Optional list of directions to check.\n   * @returns {boolean} True if the given coordinates are within bounds.\n   */\n  isInBounds(index, dirs) {\n    // check input\n    if (!index) {\n      return false;\n    }\n    // check length\n    const length = this.length();\n    if (length !== index.length()) {\n      return false;\n    }\n    // create dirs if not there\n    if (typeof dirs === 'undefined') {\n      dirs = [];\n      for (let j = 0; j < length; ++j) {\n        dirs.push(j);\n      }\n    } else {\n      for (let k = 0; k < length; ++k) {\n        if (dirs[k] > length - 1) {\n          throw new Error('Wrong input dir value: ' + dirs[k]);\n        }\n      }\n    }\n    // check values is 0 <= v < size\n    const inBound = function (value, size) {\n      return value >= 0 && value < size;\n    };\n    // check\n    for (let i = 0; i < dirs.length; ++i) {\n      if (!inBound(index.get(dirs[i]), this.get(dirs[i]))) {\n        return false;\n      }\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Convert an index to an offset in memory.\n   *\n   * @param {Index} index The index to convert.\n   * @param {number} [start] Optional start dimension to base the offset on.\n   * @returns {number} The offset.\n   */\n  indexToOffset(index, start) {\n    // TODO check for equality\n    if (index.length() < this.length()) {\n      throw new Error('Incompatible index and size length');\n    }\n    if (typeof start === 'undefined') {\n      start = 0;\n    } else {\n      if (start < 0 || start > this.length() - 1) {\n        throw new Error('Invalid start value for indexToOffset');\n      }\n    }\n    let offset = 0;\n    for (let i = start; i < this.length(); ++i) {\n      offset += index.get(i) * this.getDimSize(i, start);\n    }\n    return offset;\n  }\n\n  /**\n   * Convert an offset in memory to an index.\n   *\n   * @param {number} offset The offset to convert.\n   * @returns {Index} The index.\n   */\n  offsetToIndex(offset) {\n    const values = new Array(this.length());\n    let off = offset;\n    let dimSize = 0;\n    for (let i = this.length() - 1; i > 0; --i) {\n      dimSize = this.getDimSize(i);\n      values[i] = Math.floor(off / dimSize);\n      off = off - values[i] * dimSize;\n    }\n    values[0] = off;\n    return new Index(values);\n  }\n\n  /**\n   * Get the 2D base of this size.\n   *\n   * @returns {Scalar2D} The 2D base [0,1] as {x,y}.\n   */\n  get2D() {\n    return {\n      x: this.get(0),\n      y: this.get(1)\n    };\n  }\n\n} // Size class\n","/**\n * Statistics storage class.\n * 'simple' statistics do not include median, p25 nor p75.\n */\nexport class Statistics {\n  /**\n   * Minimum.\n   *\n   * @type {number}\n   */\n  min;\n  /**\n   * Maximum.\n   *\n   * @type {number}\n   */\n  max;\n  /**\n   * Mean.\n   *\n   * @type {number}\n   */\n  mean;\n  /**\n   * Standard deviation.\n   *\n   * @type {number}\n   */\n  stdDev;\n  /**\n   * Median.\n   *\n   * @type {number|undefined}\n   */\n  median;\n  /**\n   * 25th percentile.\n   *\n   * @type {number|undefined}\n   */\n  p25;\n  /**\n   * 75th percentile.\n   *\n   * @type {number|undefined}\n   */\n  p75;\n\n  /**\n   * @param {number} min The minimum.\n   * @param {number} max The maxnimum.\n   * @param {number} mean The mean.\n   * @param {number} stdDev The standard deviation.\n   */\n  constructor(min, max, mean, stdDev) {\n    this.min = min;\n    this.max = max;\n    this.mean = mean;\n    this.stdDev = stdDev;\n  }\n}\n\n/**\n * Get statistics on an input array of number.\n * Note: could use {@link https://github.com/tmcw/simple-statistics}.\n *\n * @param {number[]} values The array of values to extract stats from.\n * @param {string[]} flags A list of stat value names to calculate.\n * @returns {Statistics} A statistics object.\n */\nexport function getStats(values, flags) {\n  if (includesFullStatsFlags(flags)) {\n    return getFullStats(values);\n  } else {\n    return getBasicStats(values);\n  }\n}\n\n/**\n * Does the input flag list contain a full stat element?\n *\n * @param {string[]} flags A list of stat values to calculate.\n * @returns {boolean} True if one of the flags is a full stat flag.\n */\nfunction includesFullStatsFlags(flags) {\n  return typeof flags !== 'undefined' &&\n    flags !== null &&\n    (flags.includes('median') ||\n    flags.includes('p25') ||\n    flags.includes('p75'));\n}\n\n/**\n * Get simple stats: minimum, maximum, mean and standard deviation\n * of an array of values.\n *\n * @param {number[]} values The array of values to extract stats from.\n * @returns {Statistics} Simple statistics (no median, p25 nor p75).\n */\nexport function getBasicStats(values) {\n  let min = values[0];\n  let max = min;\n  let sum = 0;\n  let sumSqr = 0;\n  let val = 0;\n  const length = values.length;\n  for (let i = 0; i < length; ++i) {\n    val = values[i];\n    if (val < min) {\n      min = val;\n    } else if (val > max) {\n      max = val;\n    }\n    sum += val;\n    sumSqr += val * val;\n  }\n\n  const mean = sum / length;\n  // see http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance\n  let variance = sumSqr / length - mean * mean;\n  if (variance < 0) {\n    variance = 0;\n  }\n  const stdDev = Math.sqrt(variance);\n\n  return new Statistics(min, max, mean, stdDev);\n}\n\n/**\n * Get full stats: minimum, maximum, mean, standard deviation, median, 25%\n * and 75% percentile of an array of values.\n *\n * @param {number[]} values The array of values to extract stats from.\n * @returns {Statistics} Complete statistics (includes median, p25 and p75).\n */\nfunction getFullStats(values) {\n  // get basic stats\n  const stats = getBasicStats(values);\n\n  // sort array... can get slow...\n  values.sort(function (a, b) {\n    return a - b;\n  });\n\n  stats.median = getPercentile(values, 0.5);\n  stats.p25 = getPercentile(values, 0.25);\n  stats.p75 = getPercentile(values, 0.75);\n\n  return stats;\n}\n\n/**\n * Get an arrays' percentile. Uses linear interpolation for percentiles\n *   that lie between data points.\n * See: {@link https://en.wikipedia.org/wiki/Percentile} (second variant interpolation).\n *\n * @param {number[]} values The sorted array of values.\n * @param {number} ratio The percentile ratio [0-1].\n * @returns {number} The percentile.\n */\nfunction getPercentile(values, ratio) {\n  // check input\n  if (values.length === 0) {\n    throw new Error('Empty array provided for percentile calculation.');\n  }\n  if (ratio < 0 || ratio > 1) {\n    throw new Error(\n      'Invalid ratio provided for percentile calculation: ' + ratio);\n  }\n  // return min for ratio=0 amd max for ratio=1\n  if (ratio === 0) {\n    return values[0];\n  } else if (ratio === 1) {\n    return values[values.length - 1];\n  }\n  // general case: interpolate between indices if needed\n  const i = (values.length - 1) * ratio;\n  const i0 = Math.floor(i);\n  const v0 = values[i0];\n  const v1 = values[i0 + 1];\n  return v0 + (v1 - v0) * (i - i0);\n}\n\n/**\n * Unique ID generator.\n *\n * See {@link http://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript}\n *   and this {@link http://stackoverflow.com/a/13403498 answer}.\n *\n * @returns {string} A unique ID.\n */\nexport function guid() {\n  return Math.random().toString(36).substring(2, 15);\n}\n\n/**\n * Number range.\n */\nexport class NumberRange {\n  /**\n   * @type {number}\n   */\n  min;\n  /**\n   * @type {number}\n   */\n  max;\n  /**\n   * @param {number} min The minimum.\n   * @param {number} max The maximum.\n   */\n  constructor(min, max) {\n    this.min = min;\n    this.max = max;\n  }\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {Scalar2D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Immutable Spacing class.\n * Warning: the input array is NOT cloned, modifying it will\n *  modify the index values.\n */\nexport class Spacing {\n\n  /**\n   * The spacing values.\n   *\n   * @type {number[]}\n   */\n  #values;\n\n  /**\n   * @param {number[]} values The spacing values.\n   */\n  constructor(values) {\n    if (!values || typeof values === 'undefined') {\n      throw new Error('Cannot create spacing with no values.');\n    }\n    if (values.length === 0) {\n      throw new Error('Cannot create spacing with empty values.');\n    }\n    const valueCheck = function (val) {\n      return !isNaN(val) && val !== 0;\n    };\n    if (!values.every(valueCheck)) {\n      throw new Error('Cannot create spacing with non number or zero values.');\n    }\n    this.#values = values;\n  }\n\n  /**\n   * Get the spacing value at the given array index.\n   *\n   * @param {number} i The index to get.\n   * @returns {number} The value.\n   */\n  get(i) {\n    return this.#values[i];\n  }\n\n  /**\n   * Get the length of the spacing.\n   *\n   * @returns {number} The length.\n   */\n  length() {\n    return this.#values.length;\n  }\n\n  /**\n   * Get a string representation of the spacing.\n   *\n   * @returns {string} The spacing as a string.\n   */\n  toString() {\n    return '(' + this.#values.toString() + ')';\n  }\n\n  /**\n   * Get the values of this spacing.\n   *\n   * @returns {number[]} The array of values.\n   */\n  getValues() {\n    return this.#values.slice();\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Spacing} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    // check input\n    if (!rhs) {\n      return false;\n    }\n    // check length\n    const length = this.length();\n    if (length !== rhs.length()) {\n      return false;\n    }\n    // check values\n    for (let i = 0; i < length; ++i) {\n      if (this.get(i) !== rhs.get(i)) {\n        return false;\n      }\n    }\n    // seems ok!\n    return true;\n  }\n\n  /**\n   * Get the 2D base of this size.\n   *\n   * @returns {Scalar2D} The 2D base [col,row] as {x,y}.\n   */\n  get2D() {\n    return {\n      x: this.get(0),\n      y: this.get(1)\n    };\n  }\n\n} // Spacing class\n","import {\n  getIdentityMat33,\n  REAL_WORLD_EPSILON\n} from '../math/matrix';\nimport {Point3D, Point} from '../math/point';\nimport {Vector3D} from '../math/vector';\nimport {Index} from '../math/index';\nimport {getBasicStats} from '../math/stats';\nimport {precisionRound} from '../utils/string';\nimport {logger} from '../utils/logger';\nimport {Size} from './size';\nimport {Spacing} from './spacing';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Matrix33} from '../math/matrix';\n/* eslint-enable no-unused-vars */\n\n/**\n * 2D/3D Geometry class.\n */\nexport class Geometry {\n\n  /**\n   * Array of origins.\n   *\n   * @type {Point3D[]}\n   */\n  #origins;\n\n  /**\n   * Data size.\n   *\n   * @type {Size}\n   */\n  #size;\n\n  /**\n   * Data spacing.\n   *\n   * @type {Spacing}\n   */\n  #spacing;\n\n  /**\n   * Local helper object for time points.\n   *\n   * @type {Object<string, Point3D[]>}\n   */\n  #timeOrigins = {};\n\n  /**\n   * Initial time index.\n   *\n   * @type {number}\n   */\n  #initialTime;\n\n  /**\n   * Data orientation.\n   *\n   * @type {Matrix33}\n   */\n  #orientation = getIdentityMat33();\n\n  /**\n   * Flag to know if new origins were added.\n   *\n   * @type {boolean}\n   */\n  #newOrigins = false;\n\n  /**\n   * @param {Point3D[]} origins The object origins.\n   * @param {Size} size The object size.\n   * @param {Spacing} spacing The object spacing.\n   * @param {Matrix33} [orientation] The object orientation (3*3 matrix,\n   *   default to 3*3 identity).\n   * @param {number} [time] Optional time index.\n   */\n  constructor(origins, size, spacing, orientation, time) {\n    this.#origins = origins;\n    this.#size = size;\n    this.#spacing = spacing;\n    if (typeof time !== 'undefined') {\n      this.#initialTime = time;\n      this.#timeOrigins[time] = origins;\n    }\n    // check input orientation\n    if (typeof orientation !== 'undefined') {\n      this.#orientation = orientation;\n    }\n  }\n\n  /**\n   * Get the time value that was passed at construction.\n   *\n   * @returns {number} The time value.\n   */\n  getInitialTime() {\n    return this.#initialTime;\n  }\n\n  /**\n   * Get the total number of slices.\n   * Can be different from what is stored in the size object\n   *  during a volume with time points creation process.\n   *\n   * @returns {number} The total count.\n   */\n  getCurrentTotalNumberOfSlices() {\n    const keys = Object.keys(this.#timeOrigins);\n    if (keys.length === 0) {\n      return this.#origins.length;\n    }\n    let count = 0;\n    for (let i = 0; i < keys.length; ++i) {\n      count += this.#timeOrigins[keys[i]].length;\n    }\n    return count;\n  }\n\n  /**\n   * Check if a time point has associated slices.\n   *\n   * @param {number} time The time point to check.\n   * @returns {boolean} True if slices are present.\n   */\n  hasSlicesAtTime(time) {\n    return typeof this.#timeOrigins[time] !== 'undefined';\n  }\n\n  /**\n   * Get the number of slices stored for time points preceding\n   * the input one.\n   *\n   * @param {number} time The time point to check.\n   * @returns {number|undefined} The count.\n   */\n  getCurrentNumberOfSlicesBeforeTime(time) {\n    const keys = Object.keys(this.#timeOrigins);\n    if (keys.length === 0) {\n      return undefined;\n    }\n    let count = 0;\n    for (let i = 0; i < keys.length; ++i) {\n      const key = keys[i];\n      if (parseInt(key, 10) === time) {\n        break;\n      }\n      count += this.#timeOrigins[key].length;\n    }\n    return count;\n  }\n\n  /**\n   * Get the object origin.\n   * This should be the lowest origin to ease calculations (?).\n   *\n   * @returns {Point3D} The object origin.\n   */\n  getOrigin() {\n    return this.#origins[0];\n  }\n\n  /**\n   * Get the object origins.\n   *\n   * @returns {Point3D[]} The object origins.\n   */\n  getOrigins() {\n    return this.#origins;\n  }\n\n  /**\n   * Check if a point is in the origin list.\n   *\n   * @param {Point3D} point3D The point to check.\n   * @param {number} tol The comparison tolerance\n   *   default to Number.EPSILON.\n   * @returns {boolean} True if in list.\n   */\n  includesOrigin(point3D, tol) {\n    for (let i = 0; i < this.#origins.length; ++i) {\n      if (this.#origins[i].isSimilar(point3D, tol)) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Get the object size.\n   * Warning: the size comes as stored in DICOM, meaning that it could\n   * be oriented.\n   *\n   * @param {Matrix33} [viewOrientation] The view orientation (optional).\n   * @returns {Size} The object size.\n   */\n  getSize(viewOrientation) {\n    let res = this.#size;\n    if (viewOrientation && typeof viewOrientation !== 'undefined') {\n      let values = getOrientedArray3D(\n        [\n          this.#size.get(0),\n          this.#size.get(1),\n          this.#size.get(2)\n        ],\n        viewOrientation);\n      values = values.map(Math.abs);\n      res = new Size(values.concat(this.#size.getValues().slice(3)));\n    }\n    return res;\n  }\n\n  /**\n   * Calculate slice spacing from origins and replace current\n   *   if needed.\n   */\n  #updateSliceSpacing() {\n    const geoSliceSpacing = getSliceGeometrySpacing(this.#origins);\n    // update local if needed\n    if (typeof geoSliceSpacing !== 'undefined' &&\n      this.#spacing.get(2) !== geoSliceSpacing) {\n      logger.trace('Using geometric spacing ' + geoSliceSpacing +\n        ' instead of tag spacing ' + this.#spacing.get(2));\n      const values = this.#spacing.getValues();\n      values[2] = geoSliceSpacing;\n      this.#spacing = new Spacing(values);\n    }\n  }\n\n  /**\n   * Get the object spacing.\n   * Warning: the spacing comes as stored in DICOM, meaning that it could\n   * be oriented.\n   *\n   * @param {Matrix33} [viewOrientation] The view orientation (optional).\n   * @returns {Spacing} The object spacing.\n   */\n  getSpacing(viewOrientation) {\n    // update slice spacing after appendSlice\n    if (this.#newOrigins) {\n      this.#updateSliceSpacing();\n      this.#newOrigins = false;\n    }\n    let res = this.#spacing;\n    if (viewOrientation && typeof viewOrientation !== 'undefined') {\n      let orientedValues = getOrientedArray3D(\n        [\n          this.#spacing.get(0),\n          this.#spacing.get(1),\n          this.#spacing.get(2)\n        ],\n        viewOrientation);\n      orientedValues = orientedValues.map(Math.abs);\n      res = new Spacing(orientedValues);\n    }\n    return res;\n  }\n\n  /**\n   * Get the image spacing in real world.\n   *\n   * @returns {Spacing} The object spacing.\n   */\n  getRealSpacing() {\n    // asOneAndZeros to not change spacing values...\n    return this.getSpacing(\n      this.#orientation.getInverse().asOneAndZeros()\n    );\n  }\n\n  /**\n   * Get the object orientation.\n   *\n   * @returns {Matrix33} The object orientation.\n   */\n  getOrientation() {\n    return this.#orientation;\n  }\n\n  /**\n   * Get the slice position of a point in the current slice layout.\n   * Slice indices increase with decreasing origins (high index -> low origin),\n   * this simplified the handling of reconstruction since it means\n   * the displayed data is in the same 'direction' as the extracted data.\n   * As seen in the getOrigin method, the main origin is the lowest one.\n   * This implies that the index to world and reverse method do some flipping\n   * magic...\n   *\n   * @param {Point3D} point The point to evaluate.\n   * @param {number} time Optional time index.\n   * @returns {number} The slice index.\n   */\n  getSliceIndex(point, time) {\n    // cannot use this.worldToIndex(point).getK() since\n    // we cannot guaranty consecutive slices...\n\n    let localOrigins = this.#origins;\n    if (typeof time !== 'undefined') {\n      localOrigins = this.#timeOrigins[time];\n    }\n\n    // find the closest origin\n    const closestOriginIndex = point.getClosest(localOrigins);\n    const closestOrigin = localOrigins[closestOriginIndex];\n\n    // direction between the input point and the closest origin\n    const pointDir = point.minus(closestOrigin);\n\n    // use third orientation matrix column as plane normal vector\n    const normal = new Vector3D(\n      this.#orientation.get(0, 2),\n      this.#orientation.get(1, 2),\n      this.#orientation.get(2, 2)\n    );\n\n    // codirectional vectors: above slice index\n    // oposite vectors: below slice index\n    const isCodirectional = normal.isCodirectional(pointDir);\n    const sliceIndex = isCodirectional\n      ? closestOriginIndex + 1 : closestOriginIndex;\n\n    return sliceIndex;\n  }\n\n  /**\n   * Append an origin to the geometry.\n   *\n   * @param {Point3D} origin The origin to append.\n   * @param {number} index The index at which to append.\n   * @param {number} [time] Optional time index.\n   */\n  appendOrigin(origin, index, time) {\n    // equal callback\n    const equalToOrigin = function (element) {\n      return element.equals(origin);\n    };\n    if (typeof time !== 'undefined') {\n      // check if not already in list\n      const found = this.#timeOrigins[time].find(equalToOrigin);\n      if (typeof found !== 'undefined') {\n        throw new Error('Cannot append same time origin twice');\n      }\n      // add in origin array\n      this.#timeOrigins[time].splice(index, 0, origin);\n    }\n    if (typeof time === 'undefined' || time === this.#initialTime) {\n      // check if not already in list\n      const found = this.#origins.find(equalToOrigin);\n      if (typeof found !== 'undefined') {\n        throw new Error('Cannot append same origin twice');\n      }\n      // update flag\n      this.#newOrigins = true;\n      // add in origin array\n      this.#origins.splice(index, 0, origin);\n      // increment second dimension\n      const values = this.#size.getValues();\n      values[2] += 1;\n      this.#size = new Size(values);\n    }\n  }\n\n  /**\n   * Append a frame to the geometry.\n   *\n   * @param {Point3D} origin The origin to append.\n   * @param {number} time Optional time index.\n   */\n  appendFrame(origin, time) {\n    // add origin to list\n    this.#timeOrigins[time] = [origin];\n    // increment third dimension\n    const sizeValues = this.#size.getValues();\n    const spacingValues = this.#spacing.getValues();\n    if (sizeValues.length === 4) {\n      sizeValues[3] += 1;\n    } else {\n      sizeValues.push(2);\n      spacingValues.push(1);\n    }\n    this.#size = new Size(sizeValues);\n    this.#spacing = new Spacing(spacingValues);\n  }\n\n  /**\n   * Get a string representation of the geometry.\n   *\n   * @returns {string} The geometry as a string.\n   */\n  toString() {\n    return 'Origin: ' + this.getOrigin() +\n      ', Size: ' + this.getSize() +\n      ', Spacing: ' + this.getSpacing() +\n      ', Orientation: ' + this.getOrientation();\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Geometry} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.getOrigin().equals(rhs.getOrigin()) &&\n      this.getSize().equals(rhs.getSize()) &&\n      this.getSpacing().equals(rhs.getSpacing());\n  }\n\n  /**\n   * Check that a point is within bounds.\n   *\n   * @param {Point} point The point to check.\n   * @returns {boolean} True if the given coordinates are within bounds.\n   */\n  isInBounds(point) {\n    return this.isIndexInBounds(this.worldToIndex(point));\n  }\n\n  /**\n   * Check that a index is within bounds.\n   *\n   * @param {Index} index The index to check.\n   * @param {number[]} [dirs] Optional list of directions to check.\n   * @returns {boolean} True if the given coordinates are within bounds.\n   */\n  isIndexInBounds(index, dirs) {\n    return this.getSize().isInBounds(index, dirs);\n  }\n\n  /**\n   * Get the geometrical range, ie the minimum and maximum\n   *   positions.\n   *\n   * @returns {Point[]} The min and max positions.\n   */\n  getRange() {\n    const nDims = this.getSize().length();\n    const minValues = new Array(nDims);\n    minValues.fill(0);\n    const minIndex = new Index(minValues);\n    const maxIndex = new Index(this.getSize().getValues());\n    return [\n      this.indexToWorld(minIndex),\n      this.indexToWorld(maxIndex)\n    ];\n  }\n\n  /**\n   * Convert an index into world coordinates.\n   *\n   * @param {Index} index The index to convert.\n   * @returns {Point} The corresponding point.\n   */\n  indexToWorld(index) {\n    // apply spacing\n    // (spacing is oriented, apply before orientation)\n    const spacing = this.getSpacing();\n    const orientedPoint3D = new Point3D(\n      index.get(0) * spacing.get(0),\n      index.get(1) * spacing.get(1),\n      index.get(2) * spacing.get(2)\n    );\n    // de-orient\n    const point3D = this.getOrientation().multiplyPoint3D(orientedPoint3D);\n    // keep >3d values\n    const values = index.getValues();\n    const origin = this.getOrigin();\n    values[0] = origin.getX() + point3D.getX();\n    values[1] = origin.getY() + point3D.getY();\n    values[2] = origin.getZ() + point3D.getZ();\n    // return point\n    return new Point(values);\n  }\n\n  /**\n   * Convert a 3D point into world coordinates.\n   *\n   * @param {Point3D} point The 3D point to convert.\n   * @returns {Point3D} The corresponding world 3D point.\n   */\n  pointToWorld(point) {\n    // apply spacing\n    // (spacing is oriented, apply before orientation)\n    const spacing = this.getSpacing();\n    const orientedPoint3D = new Point3D(\n      point.getX() * spacing.get(0),\n      point.getY() * spacing.get(1),\n      point.getZ() * spacing.get(2)\n    );\n    // de-orient\n    const point3D = this.getOrientation().multiplyPoint3D(orientedPoint3D);\n    // return point3D\n    const origin = this.getOrigin();\n    return new Point3D(\n      origin.getX() + point3D.getX(),\n      origin.getY() + point3D.getY(),\n      origin.getZ() + point3D.getZ()\n    );\n  }\n\n  /**\n   * Convert world coordinates into an index.\n   *\n   * @param {Point} point The point to convert.\n   * @returns {Index} The corresponding index.\n   */\n  worldToIndex(point) {\n    // compensate for origin\n    // (origin is not oriented, compensate before orientation)\n    // TODO: use slice origin...\n    const origin = this.getOrigin();\n    const point3D = new Point3D(\n      point.get(0) - origin.getX(),\n      point.get(1) - origin.getY(),\n      point.get(2) - origin.getZ()\n    );\n    // orient\n    const orientedPoint3D =\n      this.getOrientation().getInverse().multiplyPoint3D(point3D);\n    // keep >3d values\n    const values = point.getValues();\n    // apply spacing and round\n    const spacing = this.getSpacing();\n    values[0] = Math.round(orientedPoint3D.getX() / spacing.get(0));\n    values[1] = Math.round(orientedPoint3D.getY() / spacing.get(1));\n    values[2] = Math.round(orientedPoint3D.getZ() / spacing.get(2));\n\n    // return index\n    return new Index(values);\n  }\n\n  /**\n   * Convert world coordinates into an point.\n   *\n   * @param {Point} point The world point to convert.\n   * @returns {Point3D} The corresponding point.\n   */\n  worldToPoint(point) {\n    // compensate for origin\n    // (origin is not oriented, compensate before orientation)\n    const origin = this.getOrigin();\n    const point3D = new Point3D(\n      point.get(0) - origin.getX(),\n      point.get(1) - origin.getY(),\n      point.get(2) - origin.getZ()\n    );\n    // orient\n    const orientedPoint3D =\n      this.getOrientation().getInverse().multiplyPoint3D(point3D);\n    // keep >3d values\n    const values = point.getValues();\n    // apply spacing and round\n    const spacing = this.getSpacing();\n    values[0] = orientedPoint3D.getX() / spacing.get(0);\n    values[1] = orientedPoint3D.getY() / spacing.get(1);\n    values[2] = orientedPoint3D.getZ() / spacing.get(2);\n\n    // return index\n    return new Point3D(values[0], values[1], values[2]);\n  }\n\n} // class Geometry\n\n/**\n * Get the oriented values of an input 3D array.\n *\n * @param {number[]} array3D The 3D array.\n * @param {Matrix33} orientation The orientation 3D matrix.\n * @returns {number[]} The values reordered according to the orientation.\n */\nexport function getOrientedArray3D(array3D, orientation) {\n  // values = orientation * orientedValues\n  // -> inv(orientation) * values = orientedValues\n  return orientation.getInverse().multiplyArray3D(array3D);\n}\n\n/**\n * Get the raw values of an oriented input 3D array.\n *\n * @param {number[]} array3D The 3D array.\n * @param {Matrix33} orientation The orientation 3D matrix.\n * @returns {number[]} The values reordered to compensate the orientation.\n */\nexport function getDeOrientedArray3D(array3D, orientation) {\n  // values = orientation * orientedValues\n  return orientation.multiplyArray3D(array3D);\n}\n\n/**\n * Get the slice spacing from the difference in the Z directions\n * of input origins.\n *\n * @param {Point3D[]} origins An array of Point3D.\n * @returns {number|undefined} The spacing.\n */\nexport function getSliceGeometrySpacing(origins) {\n  // check origins\n  if (origins.length <= 1) {\n    return;\n  }\n\n  const spacings = [];\n  for (let i = 0; i < origins.length - 1; ++i) {\n    const origin1 = origins[i];\n    const origin2 = origins[i + 1];\n    const sliceSpacing = origin1.getDistance(origin2);\n    if (sliceSpacing === 0) {\n      throw new Error('Zero slice spacing ' +\n        origin1.toString() + ' ' + origin2.toString());\n    }\n    spacings.push(sliceSpacing);\n  }\n\n  // use rounded mean value as spacing\n  const stats = getBasicStats(spacings);\n  const spacing = precisionRound(stats.mean, 4);\n\n  // warn if non constant\n  if (stats.stdDev > REAL_WORLD_EPSILON) {\n    logger.warn('Varying slice spacing, value: ' + spacing +\n      ' (mean: ' + stats.mean +\n      ', min: ' + stats.min +\n      ', max: ' + stats.max +\n      ', stdDev: ' + stats.stdDev + ')');\n  }\n\n  return spacing;\n}\n\n/**\n * Merge two geometries into one using the largest size and\n *   smallest resolution.\n *\n * @param {Geometry} geometry1 The first geometry.\n * @param {Geometry} geometry2 The second geometry.\n * @returns {Geometry} The merged geometry.\n */\nexport function mergeGeometries(geometry1, geometry2) {\n  const minByIndex = function (array1, array2) {\n    return array1.map((v, i) => Math.min(v, array2[i]));\n  };\n  const maxByIndex = function (array1, array2) {\n    return array1.map((v, i) => Math.max(v, array2[i]));\n  };\n\n  const newSize = new Size(maxByIndex(\n    geometry1.getSize().getValues(),\n    geometry2.getSize().getValues()\n  ));\n  const newSpacing = new Spacing(minByIndex(\n    geometry1.getSpacing().getValues(),\n    geometry2.getSpacing().getValues()\n  ));\n\n  const range1 = geometry1.getRange();\n  const range2 = geometry2.getRange();\n  const minValues = minByIndex(\n    range1[0].getValues(),\n    range2[0].getValues()\n  );\n  const newOrigins = [];\n  for (let i = 0; i < newSize.get(2); ++i) {\n    const values = minValues.slice();\n    values[2] = minValues[2] + i * newSpacing.get(2);\n    newOrigins.push(new Point3D(\n      values[0], values[1], values[2]\n    ));\n  }\n\n  return new Geometry(\n    newOrigins,\n    newSize,\n    newSpacing,\n    geometry1.getOrientation()\n  );\n}\n","import {DataElement} from './dataElement';\n\n/**\n * Pad an input string with a '0' to form a 2 digit one.\n *\n * @param {string} str The string to pad.\n * @returns {string} The padded string.\n */\nfunction padZeroTwoDigit(str) {\n  return ('0' + str).slice(-2);\n}\n\n/**\n * Get a 'date' object with {year, monthIndex, day} ready for the\n *   Date constructor from a DICOM element with vr=DA.\n *\n * @param {DataElement} element The DICOM element with date information.\n * @returns {{year, monthIndex, day}|undefined} The 'date' object.\n */\nexport function getDate(element) {\n  if (typeof element === 'undefined') {\n    return undefined;\n  }\n  if (element.value.length !== 1) {\n    return undefined;\n  }\n  const daValue = element.value[0];\n  // Two possible formats:\n  // - standard 'YYYYMMDD'\n  // - non-standard 'YYYY.MM.DD' (previous ACR-NEMA)\n  let monthBeginIndex = 4;\n  let dayBeginIndex = 6;\n  if (daValue.length === 10) {\n    monthBeginIndex = 5;\n    dayBeginIndex = 8;\n  }\n  const daYears = parseInt(daValue.substring(0, 4), 10);\n  // 0-11 range\n  const daMonthIndex = daValue.length >= monthBeginIndex + 2\n    ? parseInt(daValue.substring(\n      monthBeginIndex, monthBeginIndex + 2), 10) - 1 : 0;\n  const daDay = daValue.length === dayBeginIndex + 2\n    ? parseInt(daValue.substring(\n      dayBeginIndex, dayBeginIndex + 2), 10) : 0;\n  return {\n    year: daYears,\n    monthIndex: daMonthIndex,\n    day: daDay\n  };\n}\n\n/**\n * Get a time object with {hours, minutes, seconds} ready for the\n *   Date constructor from a DICOM element with vr=TM.\n *\n * @param {DataElement} element The DICOM element with date information.\n * @returns {{hours, minutes, seconds, milliseconds}|undefined} The time object.\n */\nexport function getTime(element) {\n  if (typeof element === 'undefined') {\n    return undefined;\n  }\n  if (element.value.length !== 1) {\n    return undefined;\n  }\n  // format: HH[MMSS.FFFFFF]\n  const tmValue = element.value[0];\n  const tmHours = parseInt(tmValue.substring(0, 2), 10);\n  const tmMinutes = tmValue.length >= 4\n    ? parseInt(tmValue.substring(2, 4), 10) : 0;\n  const tmSeconds = tmValue.length >= 6\n    ? parseInt(tmValue.substring(4, 6), 10) : 0;\n  const tmFracSecondsStr = tmValue.length >= 8\n    ? tmValue.substring(7, 10) : 0;\n  const tmMilliSeconds = tmFracSecondsStr === 0 ? 0\n    : parseInt(tmFracSecondsStr, 10) *\n      Math.pow(10, 3 - tmFracSecondsStr.length);\n  return {\n    hours: tmHours,\n    minutes: tmMinutes,\n    seconds: tmSeconds,\n    milliseconds: tmMilliSeconds\n  };\n}\n\n/**\n * Get a 'dateTime' object with {date, time} ready for the\n *   Date constructor from a DICOM element with vr=DT.\n *\n * @param {DataElement} element The DICOM element with date-time information.\n * @returns {{date, time}|undefined} The time object.\n */\nexport function getDateTime(element) {\n  if (typeof element === 'undefined') {\n    return undefined;\n  }\n  if (element.value.length !== 1) {\n    return undefined;\n  }\n  // format: YYYYMMDDHHMMSS.FFFFFF&ZZXX\n  const dtFullValue = element.value[0];\n  // remove offset (&ZZXX)\n  const dtValue = dtFullValue.split('&')[0];\n  const dateDataElement = new DataElement('DA');\n  dateDataElement.value = [dtValue.substring(0, 8)];\n  const dtDate = getDate(dateDataElement);\n  const timeDataElement = new DataElement('TM');\n  timeDataElement.value = [dtValue.substring(8)];\n  const dtTime = dtValue.length >= 9\n    ? getTime(timeDataElement) : undefined;\n  return {\n    date: dtDate,\n    time: dtTime\n  };\n}\n\n/**\n * Extract date values from a Date object.\n *\n * @param {Date} date The input date.\n * @returns {{year, monthIndex, day}} A 'date' object.\n */\nexport function dateToDateObj(date) {\n  return {\n    year: date.getFullYear().toString(),\n    monthIndex: padZeroTwoDigit((date.getMonth() + 1).toString()),\n    day: padZeroTwoDigit(date.getDate().toString())\n  };\n}\n\n/**\n * Extract time values from a Date object.\n *\n * @param {Date} date The input date.\n * @returns {{hours, minutes, seconds}} A 'time' object.\n */\nexport function dateToTimeObj(date) {\n  return {\n    hours: padZeroTwoDigit(date.getHours().toString()),\n    minutes: padZeroTwoDigit(date.getMinutes().toString()),\n    seconds: padZeroTwoDigit(date.getSeconds().toString())\n  };\n}\n\n/**\n * Get a DICOM formated date string.\n *\n * @param {{year, monthIndex, day}} dateObj The date to format.\n * @returns {string} The formated date.\n */\nexport function getDicomDate(dateObj) {\n  // YYYYMMDD\n  return (\n    dateObj.year +\n    dateObj.monthIndex +\n    dateObj.day\n  );\n}\n\n/**\n * Get a DICOM formated time string.\n *\n * @param {{hours, minutes, seconds}} dateObj The date to format.\n * @returns {string} The formated time.\n */\nexport function getDicomTime(dateObj) {\n  // HHMMSS\n  return (\n    dateObj.hours +\n    dateObj.minutes +\n    dateObj.seconds\n  );\n}\n\n/**\n * Get a DICOM formated datetime string.\n *\n * @param {{date, time}} datetime The datetime to format.\n * @returns {string} The formated datetime.\n */\nexport function getDicomDateTime(datetime) {\n  // HHMMSS\n  let res = getDicomDate(datetime.date);\n  if (typeof datetime.time !== 'undefined') {\n    res += getDicomTime(datetime.time);\n  }\n  return res;\n}\n","import {Vector3D} from './vector';\nimport {\n  Matrix33,\n  getIdentityMat33\n} from './matrix';\n\n/**\n * Create a 3x3 coronal (xzy) matrix.\n *\n * @returns {Matrix33} The coronal matrix.\n */\nexport function getCoronalMat33() {\n  /* eslint-disable @stylistic/js/array-element-newline */\n  return new Matrix33([\n    1, 0, 0,\n    0, 0, 1,\n    0, -1, 0\n  ]);\n  /* eslint-enable @stylistic/js/array-element-newline */\n}\n\n/**\n * Create a 3x3 sagittal (yzx) matrix.\n *\n * @returns {Matrix33} The sagittal matrix.\n */\nexport function getSagittalMat33() {\n  /* eslint-disable @stylistic/js/array-element-newline */\n  return new Matrix33([\n    0, 0, -1,\n    1, 0, 0,\n    0, -1, 0\n  ]);\n  /* eslint-enable @stylistic/js/array-element-newline */\n}\n\n/**\n * Default anatomical plane orientations.\n */\nexport const Orientation = {\n  /**\n   * Axial, also known as transverse.\n   */\n  Axial: 'axial',\n  /**\n   * Coronal, also known as frontal.\n   */\n  Coronal: 'coronal',\n  /**\n   * Sagittal, also known as anteroposterior.\n   */\n  Sagittal: 'sagittal'\n};\n\n/**\n * Get an orientation matrix from a name.\n *\n * @param {string} name The orientation name.\n * @returns {Matrix33|undefined} The orientation matrix.\n */\nexport function getMatrixFromName(name) {\n  let matrix;\n  if (name === Orientation.Axial) {\n    matrix = getIdentityMat33();\n  } else if (name === Orientation.Coronal) {\n    matrix = getCoronalMat33();\n  } else if (name === Orientation.Sagittal) {\n    matrix = getSagittalMat33();\n  }\n  return matrix;\n}\n\n/**\n * Get the orientation code of an orientation matrix. Each letter defines\n * the towards direction. Letters are: R (right), L (left),\n * A (anterior), P (posterior), I (inferior) and S (superior).\n *\n * @param {Matrix33} matrix The orientation matrix.\n * @returns {string} The orientation code.\n */\nexport function getOrientationStringLPS(matrix) {\n  const v0 = new Vector3D(\n    matrix.get(0, 0),\n    matrix.get(1, 0),\n    matrix.get(2, 0)\n  );\n  const v1 = new Vector3D(\n    matrix.get(0, 1),\n    matrix.get(1, 1),\n    matrix.get(2, 1)\n  );\n  const v2 = new Vector3D(\n    matrix.get(0, 2),\n    matrix.get(1, 2),\n    matrix.get(2, 2)\n  );\n  return getVectorStringLPS(v0) +\n    getVectorStringLPS(v1) +\n    getVectorStringLPS(v2);\n}\n\n/**\n * Get the orientation code of an orientation vector.\n * Credits: David Clunie, {@link https://www.dclunie.com/medical-image-faq/html/part2.html}.\n *\n * @param {Vector3D} vector The orientation vector.\n * @returns {string} The orientation code.\n */\nfunction getVectorStringLPS(vector) {\n  let abs = new Vector3D(\n    Math.abs(vector.getX()),\n    Math.abs(vector.getY()),\n    Math.abs(vector.getZ())\n  );\n\n  let orientation = '';\n  const orientationX = vector.getX() < 0 ? 'R' : 'L';\n  const orientationY = vector.getY() < 0 ? 'A' : 'P';\n  // as defined in DICOM\n  //const orientationZ = vector.getZ() < 0 ? 'F' : 'H';\n  const orientationZ = vector.getZ() < 0 ? 'I' : 'S';\n\n  const threshold = 0.0001;\n\n  for (let i = 0; i < 3; i++) {\n    if (abs.getX() > threshold &&\n      abs.getX() > abs.getY() &&\n      abs.getX() > abs.getZ()) {\n      orientation += orientationX;\n      abs = new Vector3D(0, abs.getY(), abs.getZ());\n    } else if (abs.getY() > threshold &&\n      abs.getY() > abs.getX() &&\n      abs.getY() > abs.getZ()) {\n      orientation += orientationY;\n      abs = new Vector3D(abs.getX(), 0, abs.getZ());\n    } else if (abs.getZ() > threshold &&\n      abs.getZ() > abs.getX() &&\n      abs.getZ() > abs.getY()) {\n      orientation += orientationZ;\n      abs = new Vector3D(abs.getX(), abs.getY(), 0);\n    } else {\n      break;\n    }\n  }\n\n  return orientation;\n}\n\n/**\n * Get the LPS 'group' (axial, coronal or sagittal) from a LPS code.\n *\n * @param {string} code The LPS code string.\n * @returns {string|undefined} The group.\n */\nfunction getLPSGroup(code) {\n  let orientStr;\n  const axialCodes =\n    ['LPS', 'LAI', 'RPI', 'RAS', 'ALS', 'ARI', 'PLI', 'PRS'];\n  const coronalCodes =\n    ['LSA', 'LIP', 'RSP', 'RIA', 'ILA', 'IRP', 'SLP', 'SRA'];\n  const sagittalCodes =\n    ['PSL', 'PIR', 'ASR', 'AIL', 'IAR', 'IPL', 'SAL', 'SPR'];\n  if (axialCodes.includes(code)) {\n    orientStr = Orientation.Axial;\n  } else if (coronalCodes.includes(code)) {\n    orientStr = Orientation.Coronal;\n  } else if (sagittalCodes.includes(code)) {\n    orientStr = Orientation.Sagittal;\n  }\n  return orientStr;\n}\n\n/**\n * Get the name of an image orientation patient.\n *\n * @param {number[]} cosines The image orientation\n *   patient cosines (6 values).\n * @returns {string|undefined} The orientation\n *   name: axial, coronal or sagittal.\n */\nexport function getOrientationName(cosines) {\n  let name;\n  const orientMatrix = getOrientationFromCosines(cosines);\n  if (typeof orientMatrix !== 'undefined') {\n    const lpsStr = getOrientationStringLPS(orientMatrix.asOneAndZeros());\n    name = getLPSGroup(lpsStr);\n  }\n  return name;\n}\n\n/**\n * Get the orientation matrix associated to the direction cosines.\n *\n * @param {number[]} cosines The image orientation\n *   patient cosines (6 values).\n * @returns {Matrix33|undefined} The orientation matrix.\n */\nexport function getOrientationFromCosines(cosines) {\n  let orientationMatrix;\n  if (typeof cosines !== 'undefined' && cosines.length === 6) {\n    const rowCosines = new Vector3D(cosines[0], cosines[1], cosines[2]);\n    const colCosines = new Vector3D(cosines[3], cosines[4], cosines[5]);\n    const normal = rowCosines.crossProduct(colCosines);\n    /* eslint-disable @stylistic/js/array-element-newline */\n    orientationMatrix = new Matrix33([\n      rowCosines.getX(), colCosines.getX(), normal.getX(),\n      rowCosines.getY(), colCosines.getY(), normal.getY(),\n      rowCosines.getZ(), colCosines.getZ(), normal.getZ()\n    ]);\n    /* eslint-enable @stylistic/js/array-element-newline */\n  }\n  return orientationMatrix;\n}\n\n/**\n * Get the direction cosines from an orientation matrix.\n *\n * @param {Matrix33} matrix The input matrix.\n * @returns {number[]} The image orientation\n *   patient cosines (6 values).\n */\nexport function getCosinesFromOrientation(matrix) {\n  return [\n    matrix.get(0, 0),\n    matrix.get(1, 0),\n    matrix.get(2, 0),\n    matrix.get(0, 1),\n    matrix.get(1, 1),\n    matrix.get(2, 1)\n  ];\n}\n\n/**\n * Get the view orientation according to an image and target orientation.\n * The view orientation is used to go from target to image space.\n *\n * @param {Matrix33} imageOrientation The image geometry.\n * @param {Matrix33} targetOrientation The target orientation.\n * @returns {Matrix33} The view orientation.\n */\nexport function getViewOrientation(imageOrientation, targetOrientation) {\n  let viewOrientation = getIdentityMat33();\n  if (typeof targetOrientation !== 'undefined') {\n    // i: image, v: view, t: target, O: orientation, P: point\n    // [Img] -- Oi --> [Real] <-- Ot -- [Target]\n    // Pi = (Oi)-1 * Ot * Pt = Ov * Pt\n    // -> Ov = (Oi)-1 * Ot\n    // TODO: asOneAndZeros simplifies but not nice...\n    viewOrientation =\n      imageOrientation.asOneAndZeros().getInverse().multiply(targetOrientation);\n  }\n  // TODO: why abs???\n  return viewOrientation.getAbs();\n}\n\n/**\n * Get the target orientation according to an image and view orientation.\n * The target orientation is used to go from target to real space.\n *\n * @param {Matrix33} imageOrientation The image geometry.\n * @param {Matrix33} viewOrientation The view orientation.\n * @returns {Matrix33} The target orientation.\n */\nexport function getTargetOrientation(imageOrientation, viewOrientation) {\n  // i: image, v: view, t: target, O: orientation, P: point\n  // [Img] -- Oi --> [Real] <-- Ot -- [Target]\n  // Pi = (Oi)-1 * Ot * Pt = Ov * Pt\n  // -> Ot = Oi * Ov\n  // note: asOneAndZeros as in getViewOrientation...\n  let targetOrientation =\n    imageOrientation.asOneAndZeros().multiply(viewOrientation);\n\n  // TODO: why abs???\n  const simpleImageOrientation = imageOrientation.asOneAndZeros().getAbs();\n  if (simpleImageOrientation.equals(getCoronalMat33().getAbs())) {\n    targetOrientation = targetOrientation.getAbs();\n  }\n\n  return targetOrientation;\n}\n","import {custom} from '../app/custom';\nimport {\n  DicomParser,\n  getTransferSyntaxName,\n  isJpeg2000TransferSyntax,\n  isJpegBaselineTransferSyntax,\n  isJpegLosslessTransferSyntax\n} from './dicomParser';\nimport {\n  getDate,\n  getTime,\n  getDateTime\n} from './dicomDate';\nimport {\n  isPixelDataTag,\n  isItemDelimitationItemTag,\n  isSequenceDelimitationItemTag,\n  getItemTag,\n  getItemDelimitationItemTag,\n  getSequenceDelimitationItemTag,\n  getPixelDataTag,\n  getTagFromKey\n} from './dicomTag';\nimport {isNativeLittleEndian} from './dataReader';\nimport {getOrientationFromCosines} from '../math/orientation';\nimport {Spacing} from '../image/spacing';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Tag} from './dicomTag';\nimport {DataElement} from './dataElement';\nimport {Matrix33} from '../math/matrix';\n/* eslint-enable no-unused-vars */\n\n/**\n * @typedef {Object<string, DataElement>} DataElements\n */\n\n/**\n * Dump the DICOM tags to a string in the same way as the\n * DCMTK `dcmdump` command (https://support.dcmtk.org/docs-dcmrt/dcmdump.html).\n *\n * @param {Object<string, DataElement>} dicomElements The dicom elements.\n * @returns {string} The dumped file.\n */\nexport function dcmdump(dicomElements) {\n  const keys = Object.keys(dicomElements);\n  let result = '\\n';\n  result += '# Dicom-File-Format\\n';\n  result += '\\n';\n  result += '# Dicom-Meta-Information-Header\\n';\n  result += '# Used TransferSyntax: ';\n  if (isNativeLittleEndian()) {\n    result += 'Little Endian Explicit\\n';\n  } else {\n    result += 'NOT Little Endian Explicit\\n';\n  }\n  let dicomElement = null;\n  let tag = null;\n  let checkHeader = true;\n  for (let i = 0, leni = keys.length; i < leni; ++i) {\n    dicomElement = dicomElements[keys[i]];\n    tag = getTagFromKey(keys[i]);\n    if (checkHeader && tag.getGroup() !== '0002') {\n      result += '\\n';\n      result += '# Dicom-Data-Set\\n';\n      result += '# Used TransferSyntax: ';\n      const syntax = dicomElements['00020010'].value[0];\n      result += getTransferSyntaxName(syntax);\n      result += '\\n';\n      checkHeader = false;\n    }\n    result += getElementAsString(tag, dicomElement) + '\\n';\n  }\n  return result;\n}\n\n/**\n * Get a data element value as a string.\n *\n * @param {Tag} tag The DICOM tag.\n * @param {object} dicomElement The DICOM element.\n * @param {boolean} [pretty] When set to true, returns a 'pretified' content.\n * @returns {string} A string representation of the DICOM element.\n */\nfunction getElementValueAsString(tag, dicomElement, pretty) {\n  let str = '';\n  const strLenLimit = 65;\n\n  // dafault to pretty output\n  if (typeof pretty === 'undefined') {\n    pretty = true;\n  }\n  // check dicom element input\n  if (typeof dicomElement === 'undefined' || dicomElement === null) {\n    return str;\n  }\n\n  // Polyfill for Number.isInteger.\n  const isInteger = Number.isInteger || function (value) {\n    return typeof value === 'number' &&\n      isFinite(value) &&\n      Math.floor(value) === value;\n  };\n\n  // TODO Support sequences.\n\n  if (dicomElement.vr !== 'SQ' &&\n    dicomElement.value.length === 1 && dicomElement.value[0] === '') {\n    str += '(no value available)';\n  } else if (isPixelDataTag(tag) &&\n    dicomElement.undefinedLength) {\n    str = '(PixelSequence)';\n  } else if (dicomElement.vr === 'DA' && pretty) {\n    const daObj = getDate(dicomElement);\n    const da = new Date(daObj.year, daObj.monthIndex, daObj.day);\n    str = da.toLocaleDateString();\n  } else if (dicomElement.vr === 'TM' && pretty) {\n    const tmObj = getTime(dicomElement);\n    str = tmObj.hours + ':' + tmObj.minutes + ':' + tmObj.seconds;\n  } else {\n    let isOtherVR = false;\n    if (dicomElement.vr.length !== 0) {\n      isOtherVR = (dicomElement.vr[0].toUpperCase() === 'O');\n    }\n    const isFloatNumberVR = (dicomElement.vr === 'FL' ||\n      dicomElement.vr === 'FD' ||\n      dicomElement.vr === 'DS');\n    let valueStr = '';\n    for (let k = 0, lenk = dicomElement.value.length; k < lenk; ++k) {\n      valueStr = '';\n      if (k !== 0) {\n        valueStr += '\\\\';\n      }\n      if (isFloatNumberVR) {\n        const num = Number(dicomElement.value[k]);\n        if (!isInteger(num) && pretty) {\n          valueStr += num.toPrecision(4);\n        } else {\n          valueStr += num.toString();\n        }\n      } else if (isOtherVR) {\n        let tmp = dicomElement.value[k].toString(16);\n        if (dicomElement.vr === 'OB') {\n          tmp = '00'.substring(0, 2 - tmp.length) + tmp;\n        } else {\n          tmp = '0000'.substring(0, 4 - tmp.length) + tmp;\n        }\n        valueStr += tmp;\n      } else {\n        valueStr += dicomElement.value[k];\n      }\n      // check length\n      if (str.length + valueStr.length <= strLenLimit) {\n        str += valueStr;\n      } else {\n        str += '...';\n        break;\n      }\n    }\n  }\n  return str;\n}\n\n/**\n * Get a data element as a string.\n *\n * @param {Tag} tag The DICOM tag.\n * @param {object} dicomElement The DICOM element.\n * @param {string} [prefix] A string to prepend this one.\n * @returns {string} The element as a string.\n */\nfunction getElementAsString(tag, dicomElement, prefix) {\n  // default prefix\n  prefix = prefix || '';\n\n  // get tag anme from dictionary\n  const tagName = tag.getNameFromDictionary();\n\n  let deSize = dicomElement.value.length;\n  let isOtherVR = false;\n  if (dicomElement.vr.length !== 0) {\n    isOtherVR = (dicomElement.vr[0].toUpperCase() === 'O');\n  }\n\n  // no size for delimitations\n  if (isItemDelimitationItemTag(tag) ||\n    isSequenceDelimitationItemTag(tag)) {\n    deSize = 0;\n  } else if (isOtherVR) {\n    deSize = 1;\n  }\n\n  const isPixSequence = (isPixelDataTag(tag) &&\n    dicomElement.undefinedLength);\n\n  let line = null;\n\n  // (group,element)\n  line = '(';\n  line += tag.getGroup().toLowerCase();\n  line += ',';\n  line += tag.getElement().toLowerCase();\n  line += ') ';\n  // value representation\n  line += dicomElement.vr;\n  // value\n  if (dicomElement.vr !== 'SQ' &&\n    dicomElement.value.length === 1 &&\n    dicomElement.value[0] === '') {\n    line += ' (no value available)';\n    deSize = 0;\n  } else {\n    // simple number display\n    if (dicomElement.vr === 'na') {\n      line += ' ';\n      line += dicomElement.value[0];\n    } else if (isPixSequence) {\n      // pixel sequence\n      line += ' (PixelSequence #=' + deSize + ')';\n    } else if (dicomElement.vr === 'SQ') {\n      line += ' (Sequence with';\n      if (dicomElement.undefinedLength) {\n        line += ' undefined';\n      } else {\n        line += ' explicit';\n      }\n      line += ' length #=';\n      line += dicomElement.value.length;\n      line += ')';\n    } else if (isOtherVR ||\n        dicomElement.vr === 'pi' ||\n        dicomElement.vr === 'UL' ||\n        dicomElement.vr === 'US' ||\n        dicomElement.vr === 'SL' ||\n        dicomElement.vr === 'SS' ||\n        dicomElement.vr === 'FL' ||\n        dicomElement.vr === 'FD' ||\n        dicomElement.vr === 'AT') {\n      // 'O'ther array, limited display length\n      line += ' ';\n      line += getElementValueAsString(tag, dicomElement, false);\n    } else {\n      // default\n      line += ' [';\n      line += getElementValueAsString(tag, dicomElement, false);\n      line += ']';\n    }\n  }\n\n  // align #\n  const nSpaces = 55 - line.length;\n  if (nSpaces > 0) {\n    for (let s = 0; s < nSpaces; ++s) {\n      line += ' ';\n    }\n  }\n  line += ' # ';\n  if (dicomElement.vl < 100) {\n    line += ' ';\n  }\n  if (dicomElement.vl < 10) {\n    line += ' ';\n  }\n  line += dicomElement.vl;\n  line += ', ';\n  line += deSize; //dictElement[1];\n  line += ' ';\n  if (tagName !== null) {\n    line += tagName;\n  } else {\n    line += 'Unknown Tag & Data';\n  }\n\n  let message = null;\n\n  // continue for sequence\n  if (dicomElement.vr === 'SQ') {\n    let item = null;\n    for (let l = 0, lenl = dicomElement.value.length; l < lenl; ++l) {\n      item = dicomElement.value[l];\n      const itemKeys = Object.keys(item);\n      if (itemKeys.length === 0) {\n        continue;\n      }\n\n      // get the item element\n      const itemTag = getItemTag();\n      const itemElement = item['FFFEE000'];\n      message = '(Item with';\n      if (itemElement.undefinedLength) {\n        message += ' undefined';\n      } else {\n        message += ' explicit';\n      }\n      message += ' length #=' + (itemKeys.length - 1) + ')';\n      itemElement.value = [message];\n      itemElement.vr = 'na';\n\n      line += '\\n';\n      line += getElementAsString(itemTag, itemElement, prefix + '  ');\n\n      for (let m = 0, lenm = itemKeys.length; m < lenm; ++m) {\n        const itemTag = getTagFromKey(itemKeys[m]);\n        if (itemKeys[m] !== 'xFFFEE000') {\n          line += '\\n';\n          line += getElementAsString(itemTag, item[itemKeys[m]],\n            prefix + '    ');\n        }\n      }\n\n      message = '(ItemDelimitationItem';\n      if (!itemElement.undefinedLength) {\n        message += ' for re-encoding';\n      }\n      message += ')';\n      const itemDelimTag = getItemDelimitationItemTag();\n      const itemDelimElement = {\n        vr: 'na',\n        vl: '0',\n        value: [message]\n      };\n      line += '\\n';\n      line += getElementAsString(\n        itemDelimTag, itemDelimElement, prefix + '  ');\n\n    }\n\n    message = '(SequenceDelimitationItem';\n    if (!dicomElement.undefinedLength) {\n      message += ' for re-encod.';\n    }\n    message += ')';\n    const sqDelimTag = getSequenceDelimitationItemTag();\n    const sqDelimElement = {\n      vr: 'na',\n      vl: '0',\n      value: [message]\n    };\n    line += '\\n';\n    line += getElementAsString(sqDelimTag, sqDelimElement, prefix);\n  } else if (isPixSequence) {\n    // pixel sequence\n    let pixItem = null;\n    for (let n = 0, lenn = dicomElement.value.length; n < lenn; ++n) {\n      pixItem = dicomElement.value[n];\n      line += '\\n';\n      pixItem.vr = 'pi';\n      line += getElementAsString(\n        getPixelDataTag(), pixItem, prefix + '  ');\n    }\n\n    const pixDelimTag = getSequenceDelimitationItemTag();\n    const pixDelimElement = {\n      vr: 'na',\n      vl: '0',\n      value: ['(SequenceDelimitationItem)']\n    };\n    line += '\\n';\n    line += getElementAsString(pixDelimTag, pixDelimElement, prefix);\n  }\n\n  return prefix + line;\n}\n\n/**\n * Extract the 2D size from dicom elements.\n *\n * @param {DataElements} elements The DICOM elements.\n * @returns {number[]} The size.\n */\nexport function getImage2DSize(elements) {\n  // rows\n  const rows = elements['00280010'];\n  if (typeof rows === 'undefined') {\n    throw new Error('Missing DICOM image number of rows');\n  }\n  if (rows.value.length === 0) {\n    throw new Error('Empty DICOM image number of rows');\n  }\n  // columns\n  const columns = elements['00280011'];\n  if (typeof columns === 'undefined') {\n    throw new Error('Missing DICOM image number of columns');\n  }\n  if (columns.value.length === 0) {\n    throw new Error('Empty DICOM image number of columns');\n  }\n  return [columns.value[0], rows.value[0]];\n}\n\n/**\n * Get the pixel spacing from the different spacing tags.\n *\n * @param {DataElements} elements The DICOM elements.\n * @returns {Spacing} The read spacing or the default [1,1].\n */\nexport function getPixelSpacing(elements) {\n  // default\n  let rowSpacing = 1;\n  let columnSpacing = 1;\n\n  // 1. PixelSpacing\n  // 2. ImagerPixelSpacing\n  // 3. NominalScannedPixelSpacing\n  // 4. PixelAspectRatio\n  const keys = ['00280030', '00181164', '00182010', '00280034'];\n  for (let k = 0; k < keys.length; ++k) {\n    const spacing = elements[keys[k]];\n    if (spacing && spacing.value.length === 2) {\n      // spacing order: [row, column]\n      rowSpacing = parseFloat(spacing.value[0]);\n      columnSpacing = parseFloat(spacing.value[1]);\n      break;\n    }\n  }\n\n  // check\n  if (columnSpacing === 0) {\n    logger.warn('Zero column spacing.');\n    columnSpacing = 1;\n  }\n  if (rowSpacing === 0) {\n    logger.warn('Zero row spacing.');\n    rowSpacing = 1;\n  }\n\n  // return\n  // (slice spacing will be calculated using the image position patient)\n  return new Spacing([columnSpacing, rowSpacing, 1]);\n}\n\n/**\n * Get the time from a list of tags. Defaults\n *   does nohting.\n *\n * @param {DataElements} elements The DICOM elements.\n * @returns {number|undefined} The time value if available.\n */\nexport function getTagTime(elements) {\n  if (typeof custom.getTagTime !== 'undefined') {\n    return custom.getTagTime(elements);\n  } else {\n    return;\n  }\n}\n\n/**\n * Get pixel data unit from a list of tags.\n *\n * @param {DataElements} elements The DICOM elements.\n * @returns {string|undefined} The unit value if available.\n */\nexport function getTagPixelUnit(elements) {\n  if (typeof custom.getTagPixelUnit !== 'undefined') {\n    return custom.getTagPixelUnit(elements);\n  } else {\n    return defaultGetTagPixelUnit(elements);\n  }\n}\n\n/**\n * Default get pixel data unit.\n *\n * @param {DataElements} elements The DICOM elements.\n * @returns {string|undefined} The unit value if available.\n */\nfunction defaultGetTagPixelUnit(elements) {\n  let unit;\n  // 1. RescaleType\n  // 2. Units (for PET)\n  const keys = ['00281054', '00541001'];\n  for (let i = 0; i < keys.length; ++i) {\n    const element = elements[keys[i]];\n    if (typeof element !== 'undefined') {\n      unit = element.value[0];\n      break;\n    }\n  }\n  // default rescale type for CT\n  if (typeof unit === 'undefined') {\n    const element = elements['00080060'];\n    if (typeof element !== 'undefined') {\n      const modality = element.value[0];\n      if (modality === 'CT') {\n        unit = 'HU';\n      }\n    }\n  }\n  return unit;\n}\n\n/**\n * Check the dimension organization from a dicom element.\n *\n * @param {DataElements} dataElements The root dicom element.\n * @returns {object} The dimension organizations and indices.\n */\nexport function getDimensionOrganization(dataElements) {\n  // Dimension Organization Sequence (required)\n  const orgSq = dataElements['00209221'];\n  if (typeof orgSq === 'undefined' || orgSq.value.length !== 1) {\n    throw new Error('Unsupported dimension organization sequence length');\n  }\n  // Dimension Organization UID\n  const orgUID = orgSq.value[0]['00209164'].value[0];\n\n  // Dimension Index Sequence (conditionally required)\n  const indices = [];\n  const indexSqElem = dataElements['00209222'];\n  if (typeof indexSqElem !== 'undefined') {\n    const indexSq = indexSqElem.value;\n    // expecting 2D index\n    if (indexSq.length !== 2) {\n      throw new Error('Unsupported dimension index sequence length');\n    }\n    let indexPointer;\n    for (let i = 0; i < indexSq.length; ++i) {\n      // Dimension Organization UID (required)\n      const indexOrg = indexSq[i]['00209164'].value[0];\n      if (indexOrg !== orgUID) {\n        throw new Error(\n          'Dimension Index Sequence contains a unknown Dimension Organization');\n      }\n      // Dimension Index Pointer (required)\n      indexPointer = indexSq[i]['00209165'].value[0];\n\n      const index = {\n        DimensionOrganizationUID: indexOrg,\n        DimensionIndexPointer: indexPointer\n      };\n      // Dimension Description Label (optional)\n      if (typeof indexSq[i]['00209421'] !== 'undefined') {\n        index.DimensionDescriptionLabel = indexSq[i]['00209421'].value[0];\n      }\n      // store\n      indices.push(index);\n    }\n    // expecting Image Position at last position\n    if (indexPointer !== '(0020,0032)') {\n      throw new Error('Unsupported non image position as last index');\n    }\n  }\n\n  return {\n    organizations: {\n      value: [\n        {\n          DimensionOrganizationUID: orgUID\n        }\n      ]\n    },\n    indices: {\n      value: indices\n    }\n  };\n}\n\n/**\n * Get a spacing object from a dicom measure element.\n *\n * @param {DataElements} dataElements The dicom element.\n * @returns {Spacing} A spacing object.\n */\nexport function getSpacingFromMeasure(dataElements) {\n  // Pixel Spacing\n  if (typeof dataElements['00280030'] === 'undefined') {\n    return null;\n  }\n  const pixelSpacing = dataElements['00280030'];\n  // spacing order: [row, column]\n  const spacingValues = [\n    parseFloat(pixelSpacing.value[1]),\n    parseFloat(pixelSpacing.value[0]),\n  ];\n  // Spacing Between Slices\n  if (typeof dataElements['00180088'] !== 'undefined') {\n    spacingValues.push(parseFloat(dataElements['00180088'].value[0]));\n  }\n  return new Spacing(spacingValues);\n}\n\n/**\n * Get an orientation matrix from a dicom orientation element.\n *\n * @param {DataElements} dataElements The dicom element.\n * @returns {Matrix33|undefined} The orientation matrix.\n */\nexport function getOrientationMatrix(dataElements) {\n  const imageOrientationPatient = dataElements['00200037'];\n  let orientationMatrix;\n  // slice orientation (cosines are matrices' columns)\n  // http://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.7.6.2.html#sect_C.7.6.2.1.1\n  if (typeof imageOrientationPatient !== 'undefined') {\n    orientationMatrix =\n      getOrientationFromCosines(\n        imageOrientationPatient.value.map((item) => parseFloat(item))\n      );\n  }\n  return orientationMatrix;\n}\n\n/**\n * Get a dicom item from a measure sequence.\n *\n * @param {Spacing} spacing The spacing object.\n * @returns {object} The dicom item.\n */\nexport function getDicomMeasureItem(spacing) {\n  return {\n    SpacingBetweenSlices: spacing.get(2),\n    PixelSpacing: [spacing.get(1), spacing.get(0)]\n  };\n}\n\n/**\n * Get a dicom element from a plane orientation sequence.\n *\n * @param {Matrix33} orientation The image orientation.\n * @returns {object} The dicom element.\n */\nexport function getDicomPlaneOrientationItem(orientation) {\n  return {\n    ImageOrientationPatient: [\n      orientation.get(0, 0),\n      orientation.get(1, 0),\n      orientation.get(2, 0),\n      orientation.get(0, 1),\n      orientation.get(1, 1),\n      orientation.get(2, 1)\n    ]\n  };\n}\n\n/**\n * Gets the sop class uid from the data elements.\n *\n * @param {object} dataElements The data elements. *.\n * @returns {string | undefined} The sop class uid value.\n */\nexport function getSopClassUid(dataElements) {\n  const SOPClassUID = dataElements['00080016'];\n  if (typeof SOPClassUID !== 'undefined') {\n    return SOPClassUID.value[0];\n  }\n  return;\n}\n\n/**\n * Check if the received string represents a secondary capture.\n *\n * @param {string} SOPClassUID The sop class uid.\n * @returns {boolean} True if it is secondary capture.\n */\nexport function isSecondatyCapture(SOPClassUID) {\n  const pattern = /^1\\.2\\.840\\.10008\\.5\\.1\\.4\\.1\\.1\\.7/;\n  return !SOPClassUID && pattern.test(SOPClassUID);\n}\n\n/**\n * Gets the photometric interpretation from the data elements.\n *\n * @param {object} dataElements The data elements.\n * @returns {string | undefined} The photometric interpretation value.\n */\nexport function getPhotometricInterpretation(dataElements) {\n  const photometricInterpretation = dataElements['00280004'];\n  const syntaxElement = dataElements['00020010'];\n  const spp = dataElements['00280002'];\n  // samplesPerPixel\n  let samplesPerPixel = 1;\n  if (typeof spp !== 'undefined') {\n    samplesPerPixel = spp.value[0];\n  }\n\n  if (typeof photometricInterpretation !== 'undefined' &&\n  typeof syntaxElement !== 'undefined') {\n    let photo = photometricInterpretation.value[0].toUpperCase();\n    // TransferSyntaxUID\n    const syntax = syntaxElement.value[0];\n    const jpeg2000 = isJpeg2000TransferSyntax(syntax);\n    const jpegBase = isJpegBaselineTransferSyntax(syntax);\n    const jpegLoss = isJpegLosslessTransferSyntax(syntax);\n    // jpeg decoders output RGB data\n    if ((jpeg2000 || jpegBase || jpegLoss) &&\n      (photo !== 'MONOCHROME1' && photo !== 'MONOCHROME2')) {\n      photo = 'RGB';\n    }\n    // check samples per pixels\n    if (photo === 'RGB' && samplesPerPixel === 1) {\n      photo = 'PALETTE COLOR';\n    }\n    return photo;\n  }\n}\n\n/**\n * Check if an input photometricInterpretation is monochrome.\n *\n * @param {string} photometricInterpretation The photometric interpretation.\n * @returns {boolean} True if the input string starts with 'MONOCHROME'.\n */\nexport function isMonochrome(photometricInterpretation) {\n  return typeof photometricInterpretation !== 'undefined' &&\n    photometricInterpretation.match(/MONOCHROME/) !== null;\n}\n\n/**\n * Check an input tag.\n *\n * @param {object} element The element to check.\n * @param {string} name The element name.\n * @param {Array} [values] The expected values.\n * @returns {string} A warning if the element is not as expected.\n */\nfunction checkTag(element, name, values) {\n  let warning = '';\n  if (typeof element === 'undefined') {\n    warning += ' ' + name + ' is undefined,';\n  } else if (element.value.length === 0) {\n    warning += ' ' + name + ' is empty,';\n  } else {\n    if (typeof values !== 'undefined') {\n      for (let i = 0; i < values.length; ++i) {\n\n        if (!element.value.includes(values[i])) {\n          warning += ' ' + name + ' does not contain ' + values[i] +\n            ' (value: ' + element.value + '),';\n        }\n      }\n    }\n  }\n  return warning;\n}\n\n/**\n * Get the decayed dose (Bq).\n *\n * @param {object} elements The DICOM elements to check.\n * @returns {object} The value and a warning if\n *   the elements are not as expected.\n */\nfunction getDecayedDose(elements) {\n  let warning = '';\n  let warn;\n\n  // SeriesDate (type1)\n  const seriesDateEl = elements['00080021'];\n  const seriesDateObj = getDate(seriesDateEl);\n\n  let totalDose;\n  let halfLife;\n  let radioStart;\n\n  const radioInfoSqStr = 'RadiopharmaceuticalInformationSequence (00540016)';\n  const radioInfoSq = elements['00540016'];\n  warning += checkTag(radioInfoSq, radioInfoSqStr);\n  if (typeof radioInfoSq !== 'undefined') {\n    if (radioInfoSq.value.length !== 1) {\n      logger.warn(\n        'Found more than 1 istopes in RadiopharmaceuticalInformation Sequence.'\n      );\n    }\n\n    // RadionuclideTotalDose (type3, Bq)\n    const totalDoseStr = 'RadionuclideTotalDose (00181074)';\n    const totalDoseEl = radioInfoSq.value[0]['00181074'];\n    warn = checkTag(totalDoseEl, totalDoseStr);\n    if (warn.length === 0) {\n      const dose = parseFloat(totalDoseEl.value[0]);\n      if (!isNaN(dose)) {\n        totalDose = dose;\n      } else {\n        warning += ' TotalDose is not a number';\n      }\n    } else {\n      warning += warn;\n    }\n\n    // RadionuclideHalfLife (type3, seconds)\n    const halfLifeStr = 'RadionuclideHalfLife (00181075)';\n    const halfLifeEl = radioInfoSq.value[0]['00181075'];\n    warn = checkTag(halfLifeEl, halfLifeStr);\n    if (warn.length === 0) {\n      const hl = parseFloat(halfLifeEl.value[0]);\n      if (!isNaN(hl)) {\n        halfLife = hl;\n      } else {\n        warning += ' HalfLife is not a number';\n      }\n    } else {\n      warning += warn;\n    }\n\n    // RadiopharmaceuticalStartDateTime (type3)\n    const radioStartDateTimeEl = radioInfoSq.value[0]['00181078'];\n    let radioStartDateObj;\n    let radioStartTimeObj;\n    if (typeof radioStartDateTimeEl === 'undefined') {\n      // use seriesDate as radioStartDate\n      radioStartDateObj = seriesDateObj;\n      // try RadiopharmaceuticalStartTime (type3)\n      const radioStartTimeEl = radioInfoSq.value[0]['00181072'];\n      radioStartTimeObj = getTime(radioStartTimeEl);\n    } else {\n      const radioStartDateTime = getDateTime(radioStartDateTimeEl);\n      radioStartDateObj = radioStartDateTime.date;\n      radioStartTimeObj = radioStartDateTime.time;\n    }\n    if (typeof radioStartTimeObj === 'undefined') {\n      radioStartTimeObj = {\n        hours: 0, minutes: 0, seconds: 0, milliseconds: 0\n      };\n    }\n    radioStart = new Date(\n      radioStartDateObj.year,\n      radioStartDateObj.monthIndex,\n      radioStartDateObj.day,\n      radioStartTimeObj.hours,\n      radioStartTimeObj.minutes,\n      radioStartTimeObj.seconds,\n      radioStartTimeObj.milliseconds\n    );\n  }\n\n  // SeriesTime (type1)\n  const seriesTimeEl = elements['00080031'];\n  const seriesTimeObj = getTime(seriesTimeEl);\n  // Series date/time\n  let scanStart = new Date(\n    seriesDateObj.year,\n    seriesDateObj.monthIndex,\n    seriesDateObj.day,\n    seriesTimeObj.hours,\n    seriesTimeObj.minutes,\n    seriesTimeObj.seconds,\n    seriesTimeObj.milliseconds\n  );\n\n  // scanStart Date check\n  // AcquisitionDate (type3)\n  const acqDateEl = elements['00080022'];\n  // AcquisitionTime (type3)\n  const acqTimeEl = elements['00080032'];\n  if (typeof acqDateEl !== 'undefined' &&\n    typeof acqTimeEl !== 'undefined') {\n    const acqDateObj = getDate(acqDateEl);\n    const acqTimeObj = getTime(acqTimeEl);\n    const acqDate = new Date(\n      acqDateObj.year,\n      acqDateObj.monthIndex,\n      acqDateObj.day,\n      acqTimeObj.hours,\n      acqTimeObj.minutes,\n      acqTimeObj.seconds,\n      acqTimeObj.milliseconds\n    );\n\n    if (scanStart > acqDate) {\n      const diff = scanStart.getTime() - acqDate.getTime();\n      const warn = 'Series date/time is after Aquisition date/time (diff=' +\n        diff.toString() + 'ms) ';\n      logger.debug(warn);\n\n      // back compute from center (average count rate) of time window\n      // for bed position (frame) in series (reliable in all cases)\n\n      let frameRefTime = 0;\n      const frameRefTimeElStr = 'FrameReferenceTime (00541300)';\n      const frameRefTimeEl = elements['00541300'];\n      warning += checkTag(frameRefTimeEl, frameRefTimeElStr);\n      if (typeof frameRefTimeEl !== 'undefined') {\n        frameRefTime = frameRefTimeEl.value[0];\n      }\n      let actualFrameDuration = 0;\n      const actualFrameDurationElStr = 'ActualFrameDuration (0018,1242)';\n      const actualFrameDurationEl = elements['00181242'];\n      warning += checkTag(actualFrameDurationEl, actualFrameDurationElStr);\n      if (typeof actualFrameDurationEl !== 'undefined') {\n        actualFrameDuration = actualFrameDurationEl.value[0];\n      }\n      if (frameRefTime > 0 && actualFrameDuration > 0) {\n        // convert to seconds\n        actualFrameDuration = actualFrameDuration / 1000;\n        frameRefTime = frameRefTime / 1000;\n        const decayConstant = Math.log(2) / halfLife;\n        const decayDuringFrame = decayConstant * actualFrameDuration;\n        const averageCountRateTimeWithinFrame =\n          1 /\n          decayConstant *\n          Math.log(decayDuringFrame / (1 - Math.exp(-decayDuringFrame)));\n        const offsetSeconds = averageCountRateTimeWithinFrame - frameRefTime;\n        scanStart = new Date(\n          acqDateObj.year,\n          acqDateObj.monthIndex,\n          acqDateObj.day,\n          acqTimeObj.hours,\n          acqTimeObj.minutes,\n          acqTimeObj.seconds + offsetSeconds,\n          acqTimeObj.milliseconds\n        );\n      }\n    }\n  }\n\n  // decayed dose (Bq)\n  let decayedDose;\n  if (typeof scanStart !== 'undefined' &&\n    typeof radioStart !== 'undefined' &&\n    typeof totalDose !== 'undefined' &&\n    typeof halfLife !== 'undefined') {\n    // decay time (s) (Date diff is in milliseconds)\n    const decayTime = (scanStart.getTime() - radioStart.getTime()) / 1000;\n    const decay = Math.pow(2, (-decayTime / halfLife));\n    decayedDose = totalDose * decay;\n  }\n\n  return {\n    value: decayedDose,\n    warning: warning\n  };\n}\n\n/**\n * Get the PET SUV factor.\n *\n * Ref:\n * - {@link https://qibawiki.rsna.org/index.php/Standardized_Uptake_Value_(SUV)#SUV_Calculation},\n * - {@link https://qibawiki.rsna.org/images/6/62/SUV_vendorneutral_pseudocode_happypathonly_20180626_DAC.pdf},\n * - {@link https://qibawiki.rsna.org/images/8/86/SUV_vendorneutral_pseudocode_20180626_DAC.pdf}.\n *\n * @param {object} elements The DICOM elements.\n * @returns {object} The value and a warning if\n *   the elements are not as expected.\n */\nexport function getSuvFactor(elements) {\n  let warning = '';\n  const result = {};\n\n\n  // CorrectedImage (type2): must contain ATTN and DECY\n  const corrImageTagStr = 'Corrected Image (00280051)';\n  const corrImageEl = elements['00280051'];\n  warning += checkTag(corrImageEl, corrImageTagStr, ['ATTN', 'DECY']);\n  // DecayCorrection (type1): must be START\n  const decayCorrTagStr = 'Decay Correction (00541102)';\n  const decayCorrEl = elements['00541102'];\n  warning += checkTag(decayCorrEl, decayCorrTagStr, ['START']);\n  // Units (type1): must be BQML\n  const unitTagStr = 'Units (00541001)';\n  const unitEl = elements['00541001'];\n  warning += checkTag(unitEl, unitTagStr, ['BQML']);\n\n  // PatientWeight (type3, kg)\n  let patWeight;\n  const patientWeightStr = ' PatientWeight (00101030)';\n  const patWeightEl = elements['00101030'];\n  const warn = checkTag(patWeightEl, patientWeightStr);\n  if (warn.length === 0) {\n    const weight = parseFloat(patWeightEl.value[0]);\n    if (!isNaN(weight)) {\n      patWeight = weight;\n    } else {\n      warning += ' PatientWeight is not a number';\n    }\n  } else {\n    warning += warn;\n  }\n\n  // Decayed dose (Bq)\n  const decayedDose = getDecayedDose(elements);\n  warning += decayedDose.warning;\n\n\n  if (warning.length !== 0) {\n    result.warning = 'Cannot calculate PET SUV:' + warning;\n  } else {\n    // SUV factor (grams/Bq)\n    result.value = (patWeight * 1000) / decayedDose.value;\n  }\n\n  return result;\n}\n\n\n/**\n * Get the file list from a DICOMDIR.\n *\n * @param {object} data The buffer data of the DICOMDIR.\n * @returns {Array|undefined} The file list as an array ordered by\n *   STUDY > SERIES > IMAGES.\n */\nexport function getFileListFromDicomDir(data) {\n  // parse file\n  const parser = new DicomParser();\n  parser.parse(data);\n  const elements = parser.getDicomElements();\n\n  // Directory Record Sequence\n  if (typeof elements['00041220'] === 'undefined' ||\n    typeof elements['00041220'].value === 'undefined') {\n    logger.warn('No Directory Record Sequence found in DICOMDIR.');\n    return undefined;\n  }\n  const dirSeq = elements['00041220'].value;\n\n  if (dirSeq.length === 0) {\n    logger.warn('The Directory Record Sequence of the DICOMDIR is empty.');\n    return undefined;\n  }\n\n  const records = [];\n  let series = null;\n  let study = null;\n  for (let i = 0; i < dirSeq.length; ++i) {\n    // Directory Record Type\n    if (typeof dirSeq[i]['00041430'] === 'undefined' ||\n      typeof dirSeq[i]['00041430'].value === 'undefined') {\n      continue;\n    }\n    const recType = dirSeq[i]['00041430'].value[0];\n\n    // supposed to come in order...\n    if (recType === 'STUDY') {\n      study = [];\n      records.push(study);\n    } else if (recType === 'SERIES') {\n      series = [];\n      study.push(series);\n    } else if (recType === 'IMAGE') {\n      // Referenced File ID\n      if (typeof dirSeq[i]['00041500'] === 'undefined' ||\n        typeof dirSeq[i]['00041500'].value === 'undefined') {\n        continue;\n      }\n      const refFileIds = dirSeq[i]['00041500'].value;\n      // join ids\n      series.push(refFileIds.join('/'));\n    }\n  }\n  return records;\n}\n","import {Size} from './size';\nimport {Geometry} from './geometry';\nimport {RescaleSlopeAndIntercept} from './rsi';\nimport {WindowLevel} from './windowLevel';\nimport {Image} from './image';\nimport {ColourMap} from './luts';\nimport {safeGet} from '../dicom/dataElement';\nimport {\n  isJpeg2000TransferSyntax,\n  isJpegBaselineTransferSyntax,\n  isJpegLosslessTransferSyntax\n} from '../dicom/dicomParser';\nimport {\n  getImage2DSize,\n  getPixelSpacing,\n  getTagPixelUnit,\n  getTagTime,\n  getSuvFactor,\n  getOrientationMatrix,\n  isSecondatyCapture,\n  getPhotometricInterpretation,\n  getSopClassUid,\n  isMonochrome\n} from '../dicom/dicomElementsWrapper';\nimport {Point3D} from '../math/point';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from '../dicom/dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * @typedef {Object<string, DataElement>} DataElements\n */\n\n/**\n * {@link Image} factory.\n */\nexport class ImageFactory {\n\n  /**\n   * Possible warning created by checkElements.\n   *\n   * @type {string|undefined}\n   */\n  #warning;\n\n  /**\n   * The PET SUV factor.\n   *\n   * @type {number|undefined}\n   */\n  #suvFactor;\n\n  /**\n   * Get a warning string if elements are not as expected.\n   * Created by checkElements.\n   *\n   * @returns {string|undefined} The warning.\n   */\n  getWarning() {\n    return this.#warning;\n  }\n\n  /**\n   * Check dicom elements.\n   *\n   * @param {DataElements} dataElements The DICOM data elements.\n   * @returns {string|undefined} A possible warning.\n   * @throws Error for missing or wrong data.\n   */\n  checkElements(dataElements) {\n    // reset\n    this.#warning = undefined;\n    // will throw if columns or rows is not defined\n    getImage2DSize(dataElements);\n    // check PET SUV\n    let modality;\n    const element = dataElements['00080060'];\n    if (typeof element !== 'undefined') {\n      modality = element.value[0];\n\n      if (modality === 'PT') {\n        const photometricInterpretation =\n        getPhotometricInterpretation(dataElements);\n        const SOPClassUID = getSopClassUid(dataElements);\n        if (isSecondatyCapture(SOPClassUID) ||\n                !isMonochrome(photometricInterpretation)) {\n          return this.#warning;\n        }\n        const suvFactor = getSuvFactor(dataElements);\n        this.#suvFactor = suvFactor.value;\n        this.#warning = suvFactor.warning;\n      }\n    }\n\n    return this.#warning;\n  }\n\n  /**\n   * Get an {@link Image} object from the read DICOM file.\n   *\n   * @param {DataElements} dataElements The DICOM tags.\n   * @param {Uint8Array | Int8Array |\n   *   Uint16Array | Int16Array |\n   *   Uint32Array | Int32Array} pixelBuffer The pixel buffer.\n   * @param {number} numberOfFiles The input number of files.\n   * @returns {Image} A new Image.\n   * @throws Error for missing or wrong data.\n   */\n  create(dataElements, pixelBuffer, numberOfFiles) {\n    const size2D = getImage2DSize(dataElements);\n    const sizeValues = [size2D[0], size2D[1], 1];\n\n    // NumberOfFrames\n    const numberOfFramesEl = dataElements['00280008'];\n    if (typeof numberOfFramesEl !== 'undefined') {\n      const number = parseInt(numberOfFramesEl.value[0], 10);\n      if (number > 1) {\n        sizeValues.push(number);\n      }\n    }\n\n    // image size\n    const size = new Size(sizeValues);\n\n    // image spacing\n    const spacing = getPixelSpacing(dataElements);\n\n    // TransferSyntaxUID\n    const syntax = dataElements['00020010'].value[0];\n    const jpeg2000 = isJpeg2000TransferSyntax(syntax);\n    const jpegBase = isJpegBaselineTransferSyntax(syntax);\n    const jpegLoss = isJpegLosslessTransferSyntax(syntax);\n\n    // ImagePositionPatient\n    const imagePositionPatient = dataElements['00200032'];\n    // slice position\n    let slicePosition = new Array(0, 0, 0);\n    if (typeof imagePositionPatient !== 'undefined') {\n      slicePosition = [\n        parseFloat(imagePositionPatient.value[0]),\n        parseFloat(imagePositionPatient.value[1]),\n        parseFloat(imagePositionPatient.value[2])\n      ];\n    }\n\n    // Image orientation patient\n    const orientationMatrix = getOrientationMatrix(dataElements);\n\n    // geometry\n    const origin = new Point3D(\n      slicePosition[0], slicePosition[1], slicePosition[2]);\n    const time = getTagTime(dataElements);\n    const geometry = new Geometry(\n      [origin], size, spacing, orientationMatrix, time);\n\n    // SOP Instance UID\n    let sopInstanceUid;\n    const siu = dataElements['00080018'];\n    if (typeof siu !== 'undefined') {\n      sopInstanceUid = siu.value[0];\n    }\n\n    // Sample per pixels\n    let samplesPerPixel = 1;\n    const spp = dataElements['00280002'];\n    if (typeof spp !== 'undefined') {\n      samplesPerPixel = spp.value[0];\n    }\n\n    // check buffer size\n    const bufferSize = size.getTotalSize() * samplesPerPixel;\n    if (bufferSize !== pixelBuffer.length) {\n      logger.warn('Badly sized pixel buffer: ' +\n        pixelBuffer.length + ' != ' + bufferSize);\n      if (bufferSize < pixelBuffer.length) {\n        pixelBuffer = pixelBuffer.slice(0, size.getTotalSize());\n      } else {\n        throw new Error('Underestimated buffer size, can\\'t fix it...');\n      }\n    }\n\n    // image\n    const image = new Image(geometry, pixelBuffer, [sopInstanceUid]);\n    // PhotometricInterpretation\n    const photometricInterpretation = dataElements['00280004'];\n    if (typeof photometricInterpretation !== 'undefined') {\n      let photo = photometricInterpretation.value[0].toUpperCase();\n      // jpeg decoders output RGB data\n      if ((jpeg2000 || jpegBase || jpegLoss) &&\n        (photo !== 'MONOCHROME1' && photo !== 'MONOCHROME2')) {\n        photo = 'RGB';\n      }\n      // check samples per pixels\n      if (photo === 'RGB' && samplesPerPixel === 1) {\n        photo = 'PALETTE COLOR';\n      }\n      image.setPhotometricInterpretation(photo);\n    }\n    // PlanarConfiguration\n    const planarConfiguration = dataElements['00280006'];\n    if (typeof planarConfiguration !== 'undefined') {\n      image.setPlanarConfiguration(planarConfiguration.value[0]);\n    }\n\n    // rescale slope and intercept\n    let slope = 1;\n    // RescaleSlope\n    const rescaleSlope = dataElements['00281053'];\n    if (typeof rescaleSlope !== 'undefined') {\n      const value = parseFloat(rescaleSlope.value[0]);\n      if (!isNaN(value)) {\n        slope = value;\n      }\n    }\n    let intercept = 0;\n    // RescaleIntercept\n    const rescaleIntercept = dataElements['00281052'];\n    if (typeof rescaleIntercept !== 'undefined') {\n      const value = parseFloat(rescaleIntercept.value[0]);\n      if (!isNaN(value)) {\n        intercept = value;\n      }\n    }\n\n    // meta information\n    const meta = {\n      numberOfFiles: numberOfFiles\n    };\n\n    // Modality\n    const modality = dataElements['00080060'];\n    if (typeof modality !== 'undefined') {\n      meta.Modality = modality.value[0];\n    }\n\n    // PET SUV\n    let isPetWithSuv = false;\n    let intensityFactor = 1;\n    if (typeof this.#suvFactor !== 'undefined') {\n      isPetWithSuv = true;\n      intensityFactor = this.#suvFactor;\n      logger.info('Applying PET SUV calibration: ' + intensityFactor);\n      slope *= intensityFactor;\n      intercept *= intensityFactor;\n    }\n    const rsi = new RescaleSlopeAndIntercept(slope, intercept);\n    image.setRescaleSlopeAndIntercept(rsi);\n\n    const safeGetLocal = function (key) {\n      return safeGet(dataElements, key);\n    };\n\n    // defaults\n    meta.TransferSyntaxUID = safeGetLocal('00020010');\n    meta.MediaStorageSOPClassUID = safeGetLocal('00020002');\n    meta.SOPClassUID = safeGetLocal('00080016');\n    meta.Modality = safeGetLocal('00080060');\n    meta.ImageType = safeGetLocal('00080008');\n    meta.SamplesPerPixel = safeGetLocal('00280002');\n    meta.PhotometricInterpretation = safeGetLocal('00280004');\n    meta.PixelRepresentation = safeGetLocal('00280103');\n    meta.BitsAllocated = safeGetLocal('00280100');\n    meta.BitsStored = safeGetLocal('00280101');\n    meta.HighBit = safeGetLocal('00280102');\n\n    // Study\n    meta.StudyDate = safeGetLocal('00080020');\n    meta.StudyTime = safeGetLocal('00080030');\n    meta.StudyInstanceUID = safeGetLocal('0020000D');\n    meta.StudyID = safeGetLocal('00200010');\n    // Series\n    meta.SeriesInstanceUID = safeGetLocal('0020000E');\n    meta.SeriesNumber = safeGetLocal('00200011');\n    // ReferringPhysicianName\n    meta.ReferringPhysicianName = safeGetLocal('00080090');\n    // patient info\n    meta.PatientName = safeGetLocal('00100010');\n    meta.PatientID = safeGetLocal('00100020');\n    meta.PatientBirthDate = safeGetLocal('00100030');\n    meta.PatientSex = safeGetLocal('00100040');\n    // General Equipment Module\n    meta.Manufacturer = safeGetLocal('00080070');\n    meta.ManufacturerModelName = safeGetLocal('00081090');\n    meta.DeviceSerialNumber = safeGetLocal('00181000');\n    meta.SoftwareVersions = safeGetLocal('00181020');\n\n    meta.ImageOrientationPatient = safeGetLocal('00200037');\n    meta.FrameOfReferenceUID = safeGetLocal('00200052');\n\n    // PixelRepresentation -> is signed\n    meta.IsSigned = meta.PixelRepresentation === 1;\n    // local pixel unit\n    if (isPetWithSuv) {\n      meta.pixelUnit = 'SUV';\n    } else {\n      const pixelUnit = getTagPixelUnit(dataElements);\n      if (typeof pixelUnit !== 'undefined') {\n        meta.pixelUnit = pixelUnit;\n      }\n    }\n    // window level presets\n    const windowPresets = {};\n    const windowCenter = dataElements['00281050'];\n    const windowWidth = dataElements['00281051'];\n    const windowCWExplanation = dataElements['00281055'];\n    if (typeof windowCenter !== 'undefined' &&\n      typeof windowWidth !== 'undefined') {\n      let name;\n      for (let j = 0; j < windowCenter.value.length; ++j) {\n        const center = parseFloat(windowCenter.value[j]);\n        let width = parseFloat(windowWidth.value[j]);\n        if (center && width && width !== 0) {\n          name = '';\n          if (typeof windowCWExplanation !== 'undefined') {\n            name = windowCWExplanation.value[j];\n          }\n          if (name === '') {\n            name = 'Default' + j;\n          }\n          width *= intensityFactor;\n          if (width < 1) {\n            width = 1;\n          }\n          windowPresets[name] = {\n            wl: [new WindowLevel(\n              center * intensityFactor,\n              width\n            )],\n            name: name\n          };\n        }\n        if (width === 0) {\n          logger.warn('Zero window width found in DICOM.');\n        }\n      }\n    }\n    meta.windowPresets = windowPresets;\n\n    // PALETTE COLOR luts\n    if (image.getPhotometricInterpretation() === 'PALETTE COLOR') {\n      // Red Palette Color Lookup Table Data\n      const redLutElement = dataElements['00281201'];\n      // Green Palette Color Lookup Table Data\n      const greenLutElement = dataElements['00281202'];\n      // Blue Palette Color Lookup Table Data\n      const blueLutElement = dataElements['00281203'];\n      let redLut;\n      let greenLut;\n      let blueLut;\n      // check red palette descriptor (should all be equal)\n      // Red Palette Color Lookup Table Descriptor\n      // 0: number of entries in the lookup table\n      // 1: first input value mapped\n      // 2: number of bits for each entry in the Lookup Table Data (8 or 16)\n      const descriptor = dataElements['00281101'];\n      if (typeof descriptor !== 'undefined' &&\n        descriptor.value.length === 3) {\n        if (descriptor.value[2] === 16) {\n          let doScale = false;\n          // (C.7.6.3.1.5 Palette Color Lookup Table Descriptor)\n          // Some implementations have encoded 8 bit entries with 16 bits\n          // allocated, padding the high bits;\n          let descSize = descriptor.value[0];\n          // (C.7.6.3.1.5 Palette Color Lookup Table Descriptor)\n          // The first Palette Color Lookup Table Descriptor value is the\n          // number of entries in the lookup table. When the number of table\n          // entries is equal to 216 then this value shall be 0.\n          if (descSize === 0) {\n            descSize = 65536;\n          }\n          // red palette VL\n          // TODO vl is undefined, find info elsewhere...\n          const vlSize = redLutElement.vl;\n          // check double size\n          if (vlSize !== 2 * descSize) {\n            doScale = true;\n            logger.info('16bits lut but size is not double. desc: ' +\n              descSize + ' vl: ' + vlSize);\n          }\n          // (C.7.6.3.1.6 Palette Color Lookup Table Data)\n          // Palette color values must always be scaled across the full\n          // range of available intensities\n          const bitsAllocated = parseInt(\n            dataElements['00280100'].value[0], 10);\n          if (bitsAllocated === 8) {\n            doScale = true;\n            logger.info(\n              'Scaling 16bits color lut since bits allocated is 8.');\n          }\n\n          if (doScale) {\n            const scaleTo8 = function (value) {\n              return value >> 8;\n            };\n\n            redLut = redLutElement.value.map(scaleTo8);\n            greenLut = greenLutElement.value.map(scaleTo8);\n            blueLut = blueLutElement.value.map(scaleTo8);\n          }\n        } else if (descriptor.value[2] === 8) {\n          // lut with vr=OW was read as Uint16, convert it to Uint8\n          logger.info(\n            'Scaling 16bits color lut since the lut descriptor is 8.');\n          let clone = redLutElement.value.slice(0);\n          // @ts-expect-error\n          redLut = Array.from(new Uint8Array(clone.buffer));\n          clone = greenLutElement.value.slice(0);\n          // @ts-expect-error\n          greenLut = Array.from(new Uint8Array(clone.buffer));\n          clone = blueLutElement.value.slice(0);\n          // @ts-expect-error\n          blueLut = Array.from(new Uint8Array(clone.buffer));\n        }\n      }\n      // set the palette\n      image.setPaletteColourMap(new ColourMap(redLut, greenLut, blueLut));\n    }\n\n    // RecommendedDisplayFrameRate\n    const recommendedDisplayFrameRate = dataElements['00082144'];\n    if (typeof recommendedDisplayFrameRate !== 'undefined') {\n      meta.RecommendedDisplayFrameRate = parseInt(\n        recommendedDisplayFrameRate.value[0], 10);\n    }\n\n    // store the meta data\n    image.setMeta(meta);\n\n    return image;\n  }\n\n}","/**\n * Data writer.\n */\nexport class DataWriter {\n\n  /**\n   * Is the endianness Little Endian.\n   *\n   * @type {boolean}\n   */\n  #isLittleEndian = true;\n\n  /**\n   * The main data view.\n   *\n   * @type {DataView}\n   */\n  #view;\n\n  /**\n   * @param {ArrayBuffer} buffer The input array buffer.\n   * @param {boolean} [isLittleEndian] Flag to tell if the data is\n   *   little or big endian.\n   */\n  constructor(buffer, isLittleEndian) {\n    // Set endian flag if not defined.\n    if (typeof isLittleEndian !== 'undefined') {\n      this.#isLittleEndian = isLittleEndian;\n    }\n    this.#view = new DataView(buffer);\n  }\n\n  /**\n   * Write Uint8 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint8(byteOffset, value) {\n    this.#view.setUint8(byteOffset, value);\n    return byteOffset + Uint8Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Int8 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt8(byteOffset, value) {\n    this.#view.setInt8(byteOffset, value);\n    return byteOffset + Int8Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Uint16 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint16(byteOffset, value) {\n    this.#view.setUint16(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Uint16Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Int16 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt16(byteOffset, value) {\n    this.#view.setInt16(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Int16Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Uint32 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint32(byteOffset, value) {\n    this.#view.setUint32(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Uint32Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Uint64 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {bigint} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint64(byteOffset, value) {\n    this.#view.setBigUint64(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + BigUint64Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Int32 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt32(byteOffset, value) {\n    this.#view.setInt32(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Int32Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Int64 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {bigint} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt64(byteOffset, value) {\n    this.#view.setBigInt64(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + BigInt64Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Float32 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeFloat32(byteOffset, value) {\n    this.#view.setFloat32(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Float32Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write Float64 data.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {number} value The data to write.\n   * @returns {number} The new offset position.\n   */\n  writeFloat64(byteOffset, value) {\n    this.#view.setFloat64(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Float64Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write string data of length 4 as hexadecimal (no '0x' prefix).\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {string} str The hexadecimal string to write ('####').\n   * @returns {number} The new offset position.\n   */\n  writeHex(byteOffset, str) {\n    // remove first two chars and parse\n    const value = parseInt(str, 16);\n    this.#view.setUint16(byteOffset, value, this.#isLittleEndian);\n    return byteOffset + Uint16Array.BYTES_PER_ELEMENT;\n  }\n\n  /**\n   * Write a boolean array as binary.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeBinaryArray(byteOffset, array) {\n    if (array.length % 8 !== 0) {\n      throw new Error('Cannot write boolean array as binary.');\n    }\n    let byte = null;\n    let val = null;\n    for (let i = 0, len = array.length; i < len; i += 8) {\n      byte = 0;\n      for (let j = 0; j < 8; ++j) {\n        val = array[i + j] === 0 ? 0 : 1;\n        byte += val << j;\n      }\n      byteOffset = this.writeUint8(byteOffset, byte);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Uint8 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array|Uint8Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint8Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeUint8(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Int8 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt8Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeInt8(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Uint16 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint16Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeUint16(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Int16 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt16Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeInt16(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Uint32 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint32Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeUint32(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Uint64 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeUint64Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeUint64(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Int32 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt32Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeInt32(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Int64 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeInt64Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeInt64(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Float32 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeFloat32Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeFloat32(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n  /**\n   * Write Float64 array.\n   *\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} array The array to write.\n   * @returns {number} The new offset position.\n   */\n  writeFloat64Array(byteOffset, array) {\n    for (let i = 0, len = array.length; i < len; ++i) {\n      byteOffset = this.writeFloat64(byteOffset, array[i]);\n    }\n    return byteOffset;\n  }\n\n} // class DataWriter\n","import {\n  is32bitVLVR,\n  isCharSetStringVR,\n  vrTypes\n} from './dictionary';\nimport {\n  Tag,\n  getTagFromDictionary,\n  getTagFromKey,\n  getItemTag,\n  getItemDelimitationItemTag,\n  getSequenceDelimitationItemTag,\n  getFileMetaInformationGroupLengthTag,\n  isPixelDataTag,\n  isItemTag,\n  isItemDelimitationItemTag,\n  tagCompareFunction\n} from './dicomTag';\nimport {\n  getDwvVersion,\n  isImplicitTransferSyntax,\n  isBigEndianTransferSyntax,\n  getDataElementPrefixByteSize\n} from './dicomParser';\nimport {DataElement} from './dataElement';\nimport {DataWriter} from './dataWriter';\nimport {DataReader} from './dataReader';\nimport {logger} from '../utils/logger';\n\n/**\n * Get the dwv UID prefix.\n * Issued by Medical Connections Ltd (www.medicalconnections.co.uk)\n *   on 25/10/2017.\n *\n * @returns {string} The dwv UID prefix.\n */\nfunction getDwvUIDPrefix() {\n  return '1.2.826.0.1.3680043.9.7278.1';\n}\n\n// local generated uid counter\nlet _uidCount = 0;\n\n/**\n * Writer rule.\n */\nexport class WriterRule {\n  /**\n   * Rule action: `copy`, `remove`, `clear` or `replace`.\n   *\n   * @type {string}\n   */\n  action;\n  /**\n   * Optional value to use for replace action.\n   *\n   * @type {any|undefined}\n   */\n  value;\n\n  /**\n   * @param {string} action The rule action.\n   */\n  constructor(action) {\n    this.action = action;\n  }\n}\n\n/**\n * Possible writer actions.\n *\n * @type {Object<string, Function>}\n */\nconst writerActions = {\n  copy: function (item) {\n    return item;\n  },\n  remove: function () {\n    return null;\n  },\n  clear: function (item) {\n    item.value = [];\n    return item;\n  },\n  replace: function (item, value) {\n    item.value = [value];\n    return item;\n  }\n};\n\n/**\n * Get simple (non official) DICOM anonymisation rules.\n *\n * @returns {Object<string, WriterRule>} The rules.\n */\nexport function getDefaultAnonymisationRules() {\n  return {\n    default: {action: 'copy', value: null},\n    PatientName: {action: 'replace', value: 'Anonymized'}, // tag\n    'Meta Element': {action: 'copy', value: null}, // group '0002'\n    Acquisition: {action: 'copy', value: null}, // group '0018'\n    'Image Presentation': {action: 'copy', value: null}, // group '0028'\n    Procedure: {action: 'copy', value: null}, // group '0040'\n    'Pixel Data': {action: 'copy', value: null} // group '7fe0'\n  };\n}\n\n/**\n * Get a UID for a DICOM tag.\n *\n * Note: Use {@link https://github.com/uuidjs/uuid}?\n *\n * Ref:\n * - {@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/chapter_9.html},\n * - {@link http://dicomiseasy.blogspot.com/2011/12/chapter-4-dicom-objects-in-chapter-3.html},\n * - {@link https://stackoverflow.com/questions/46304306/how-to-generate-unique-dicom-uid}.\n *\n * @param {string} tagName The input tag.\n * @returns {string} The corresponding UID.\n */\nexport function getUID(tagName) {\n  const prefix = getDwvUIDPrefix() + '.';\n  let uid = '';\n  if (tagName === 'ImplementationClassUID') {\n    uid = prefix + getDwvVersion();\n  } else {\n    // date (only numbers), do not keep milliseconds\n    const date = (new Date()).toISOString().replace(/\\D/g, '');\n    const datePart = '.' + date.substring(0, 14);\n    // count\n    _uidCount += 1;\n    const countPart = '.' + _uidCount;\n\n    // uid = prefix . tag . date . count\n    uid = prefix;\n\n    // limit tag part to not exceed 64 length\n    const nonTagLength = prefix.length + countPart.length + datePart.length;\n    const leni = Math.min(tagName.length, 64 - nonTagLength);\n    if (leni > 1) {\n      let tagNumber = '';\n      for (let i = 0; i < leni; ++i) {\n        tagNumber += tagName.charCodeAt(i);\n      }\n      uid += tagNumber.substring(0, leni);\n    }\n\n    // finish\n    uid += datePart + countPart;\n  }\n  return uid;\n}\n\n/**\n * Return true if the input number is even.\n *\n * @param {number} number The number to check.\n * @returns {boolean} True is the number is even.\n */\nfunction isEven(number) {\n  return number % 2 === 0;\n}\n\n/**\n * Is the input VR a VR that stores data in a typed array.\n * TODO: include ox and xs?\n *\n * @param {string} vr The element VR.\n * @returns {boolean} True if the VR is a typed array one.\n */\nfunction isTypedArrayVr(vr) {\n  const vrType = vrTypes[vr];\n  return typeof vrType !== 'undefined' &&\n    vrType !== 'string';\n}\n\n/**\n * Is the input VR a string VR.\n *\n * @param {string} vr The element VR.\n * @returns {boolean} True if the VR is a string one.\n */\nfunction isStringVr(vr) {\n  const vrType = vrTypes[vr];\n  return typeof vrType !== 'undefined' &&\n    vrType === 'string';\n}\n\n/**\n * Is the input VR a VR that could need padding.\n *\n * See {@link http://dicom.nema.org/medical/dicom/2022a/output/chtml/part05/sect_6.2.html}.\n *\n * @param {string} vr The element VR.\n * @returns {boolean} True if the VR needs padding.\n */\nfunction isVrToPad(vr) {\n  return isStringVr(vr) || vr === 'OB';\n}\n\n/**\n * Get the VR specific padding value.\n *\n * @param {string} vr The element VR.\n * @returns {string} The value used to pad.\n */\nfunction getVrPad(vr) {\n  let pad = '';\n  if (isStringVr(vr)) {\n    if (vr === 'UI') {\n      pad = '\\0';\n    } else {\n      pad = ' ';\n    }\n  }\n  return pad;\n}\n\n/**\n * Push a value at the end of an input Uint8Array.\n *\n * @param {Array|Uint8Array} arr The input array.\n * @param {Array|Uint8Array} value The value to push.\n * @returns {Uint8Array} The new array.\n */\nfunction uint8ArrayPush(arr, value) {\n  const newArr = new Uint8Array(arr.length + 1);\n  newArr.set(arr);\n  newArr.set(value, arr.length);\n  return newArr;\n}\n\n/**\n * Pad an input OB value.\n *\n * @param {Array|Uint8Array} value The input value.\n * @returns {Array|Uint8Array} The padded input.\n */\nfunction padOBValue(value) {\n  if (value !== null &&\n    typeof value !== 'undefined' &&\n    typeof value.length !== 'undefined') {\n    // calculate size and pad if needed\n    if (value.length !== 0 &&\n      typeof value[0].length !== 'undefined') {\n      // handle array of array\n      let size = 0;\n      for (let i = 0; i < value.length; ++i) {\n        size += value[i].length;\n      }\n      if (!isEven(size)) {\n        value[value.length - 1] = uint8ArrayPush(\n          value[value.length - 1], [0]);\n      }\n    } else {\n      if (!isEven(value.length)) {\n        value = uint8ArrayPush(value, [0]);\n      }\n    }\n  } else {\n    throw new Error('Cannot pad undefined or null OB value.');\n  }\n  // uint8ArrayPush may create a new array so we\n  // need to return it\n  return value;\n}\n\n/**\n * Helper method to flatten an array of typed arrays to 2D typed array.\n *\n * @param {Array} initialArray Array of typed arrays.\n * @returns {object} A typed array containing all values.\n */\nfunction flattenArrayOfTypedArrays(initialArray) {\n  const initialArrayLength = initialArray.length;\n  const arrayLength = initialArray[0].length;\n  // If this is not a array of arrays, just return the initial one:\n  if (typeof arrayLength === 'undefined') {\n    return initialArray;\n  }\n\n  const flattenendArrayLength = initialArrayLength * arrayLength;\n\n  const flattenedArray = new initialArray[0].constructor(flattenendArrayLength);\n\n  for (let i = 0; i < initialArrayLength; i++) {\n    const indexFlattenedArray = i * arrayLength;\n    flattenedArray.set(initialArray[i], indexFlattenedArray);\n  }\n  return flattenedArray;\n}\n\n/**\n * Default text encoder.\n */\nclass DefaultTextEncoder {\n  /**\n   * Encode an input string.\n   *\n   * @param {string} str The string to encode.\n   * @returns {Uint8Array} The encoded string.\n   */\n  encode(str) {\n    const result = new Uint8Array(str.length);\n    for (let i = 0, leni = str.length; i < leni; ++i) {\n      result[i] = str.charCodeAt(i);\n    }\n    return result;\n  }\n}\n\n/**\n * Small list of used tag keys.\n */\nconst TagKeys = {\n  TransferSyntax: '00020010',\n  SpecificCharacterSet: '00080005',\n  BitsAllocated: '00280100',\n};\n\n/**\n * DICOM writer.\n *\n * @example\n * // add link to html\n * const link = document.createElement(\"a\");\n * link.appendChild(document.createTextNode(\"download\"));\n * const div = document.getElementById(\"dwv\");\n * div.appendChild(link);\n * // XMLHttpRequest onload callback\n * const onload = function (event) {\n *   const parser = new dwv.DicomParser();\n *   parser.parse(event.target.response);\n *   // create writer\n *   const writer = new dwv.DicomWriter();\n *   // get buffer using default rules\n *   const dicomBuffer = writer.getBuffer(parser.getDicomElements());\n *   // create blob\n *   const blob = new Blob([dicomBuffer], {type: 'application/dicom'});\n *   // add blob to download link\n *   link.href = URL.createObjectURL(blob);\n *   link.download = \"anonym.dcm\";\n * };\n * // DICOM file request\n * const request = new XMLHttpRequest();\n * const url = 'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm';\n * request.open('GET', url);\n * request.responseType = 'arraybuffer';\n * request.onload = onload;\n * request.send();\n */\nexport class DicomWriter {\n\n  /**\n   * Flag to use VR=UN for private sequences, default to false\n   * (mainly used in tests).\n   *\n   * @type {boolean}\n   */\n  #useUnVrForPrivateSq = false;\n\n  /**\n   * Flag to activate or not the vr=UN tag check and fix\n   * if present in the dictionary. Default to true.\n   *\n   * @type {boolean}\n   */\n  #fixUnknownVR = true;\n\n  /**\n   * Default rules: just copy.\n   *\n   * @type {Object<string, WriterRule>}\n   */\n  #defaultRules = {\n    default: {action: 'copy', value: null}\n  };\n\n  /**\n   * Writing rules.\n   *\n   * @type {Object<string, WriterRule>}\n   */\n  #rules = this.#defaultRules;\n\n  /**\n   * List of compulsory tags keys.\n   *\n   * @type {string[]}\n   */\n  #compulsoryTags = [];\n\n  /**\n   * Default text encoder.\n   *\n   * @type {DefaultTextEncoder}\n   */\n  #defaultTextEncoder = new DefaultTextEncoder();\n\n  /**\n   * Special text encoder.\n   *\n   * @type {DefaultTextEncoder|TextEncoder}\n   */\n  #textEncoder = this.#defaultTextEncoder;\n\n  /**\n   * Set the use UN VR for private sequence flag.\n   *\n   * @param {boolean} flag True to use UN VR.\n   */\n  setUseUnVrForPrivateSq(flag) {\n    this.#useUnVrForPrivateSq = flag;\n  }\n\n  /**\n   * Set the vr=UN check and fix flag.\n   *\n   * @param {boolean} flag True to activate the check and fix.\n   */\n  setFixUnknownVR(flag) {\n    this.#fixUnknownVR = flag;\n  }\n\n  /**\n   * Set the writing rules.\n   * List of writer rules indexed by either `default`,\n   *   tagKey, tagName or groupName.\n   * Each DICOM element will be checked to see if a rule is applicable.\n   * First checked by tagKey, tagName and then by groupName,\n   * if nothing is found the default rule is applied.\n   *\n   * @param {Object<string, WriterRule>} rules The input rules.\n   * @param {boolean} [addMissingTags] If true, explicit tags that\n   *   have replace rule and a value will be\n   *   added if missing. Defaults to false.\n   */\n  setRules(rules, addMissingTags) {\n    this.#rules = rules;\n\n    // default compulsory list is empty\n    this.#compulsoryTags = [];\n\n    // use replace rule tags as compulsory tags\n    if (addMissingTags) {\n      const keys = Object.keys(rules);\n      for (const key of keys) {\n        const rule = rules[key];\n        if (rule.action === 'replace' &&\n          typeof rule.value !== 'undefined' &&\n          rule.value !== null) {\n          // check if key really exists\n          let isKey = false;\n          if (key.length === 8) {\n            const tag = getTagFromKey(key);\n            isKey = typeof tag.getNameFromDictionary() !== 'undefined';\n          }\n          // get tag key, rules can use key or tag name\n          let tagKey;\n          if (isKey) {\n            tagKey = key;\n          } else {\n            // try tag name\n            const tag = getTagFromDictionary(key);\n            if (typeof tag !== 'undefined') {\n              tagKey = tag.getKey();\n            }\n          }\n          // add to list\n          if (typeof tagKey !== 'undefined') {\n            this.#compulsoryTags.push(tagKey);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Encode string data.\n   *\n   * @param {string} str The string to encode.\n   * @returns {Uint8Array} The encoded string.\n   */\n  #encodeString(str) {\n    return this.#defaultTextEncoder.encode(str);\n  }\n\n  /**\n   * Encode data as a UTF-8.\n   *\n   * @param {string} str The string to write.\n   * @returns {Uint8Array} The encoded string.\n   */\n  #encodeSpecialString(str) {\n    return this.#textEncoder.encode(str);\n  }\n\n  /**\n   * Use a TextEncoder instead of the default text decoder.\n   */\n  useSpecialTextEncoder() {\n    /**\n     * The text encoder.\n     *\n     * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder}.\n     *\n     * @external TextEncoder\n     */\n    this.#textEncoder = new TextEncoder();\n  }\n\n  /**\n   * Get the element to write according to the class rules.\n   * Priority order: tagName, groupName, default.\n   *\n   * @param {DataElement} element The element to check.\n   * @returns {DataElement|null} The element to write, can be null.\n   */\n  getElementToWrite(element) {\n    // get group and tag string name\n    const groupName = element.tag.getGroupName();\n    const tagName = element.tag.getNameFromDictionary();\n\n    // apply rules:\n    let rule;\n    if (typeof this.#rules[element.tag.getKey()] !== 'undefined') {\n      // 1. tag itself\n      rule = this.#rules[element.tag.getKey()];\n    } else if (typeof tagName !== 'undefined' &&\n      typeof this.#rules[tagName] !== 'undefined') {\n      // 2. tag name\n      rule = this.#rules[tagName];\n    } else if (typeof this.#rules[groupName] !== 'undefined') {\n      // 3. group name\n      rule = this.#rules[groupName];\n    } else {\n      // 4. default\n      rule = this.#rules['default'];\n    }\n    // apply action on element and return\n    return writerActions[rule.action](element, rule.value);\n  }\n\n  /**\n   * Write a list of items.\n   *\n   * @param {DataWriter} writer The raw data writer.\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} items The list of items to write.\n   * @param {boolean} isImplicit Is the DICOM VR implicit?\n   * @returns {number} The new offset position.\n   */\n  #writeDataElementItems(\n    writer, byteOffset, items, isImplicit) {\n    let item;\n    for (let i = 0; i < items.length; ++i) {\n      item = items[i];\n      if (item.length === 0) {\n        continue;\n      }\n      // item element (create new to not modify original)\n      let undefinedLength = false;\n      const itemTag = item.find((subItem) => isItemTag(subItem.tag));\n      if (typeof itemTag !== 'undefined' &&\n        typeof itemTag.undefinedLength !== 'undefined') {\n        undefinedLength = itemTag.undefinedLength;\n      }\n      const itemElement = new DataElement('NONE');\n      itemElement.vl = undefinedLength ? 0xffffffff : itemTag.vl,\n      itemElement.tag = getItemTag();\n      itemElement.value = [];\n      byteOffset = this.#writeDataElement(\n        writer, itemElement, byteOffset, isImplicit);\n      // write rest\n      for (const subItem of item) {\n        if (!isItemTag(subItem.tag) &&\n          !isItemDelimitationItemTag(subItem.tag)) {\n          byteOffset = this.#writeDataElement(\n            writer, subItem, byteOffset, isImplicit);\n        }\n      }\n      // item delimitation\n      if (undefinedLength) {\n        const itemDelimElement = new DataElement('NONE');\n        itemDelimElement.vl = 0;\n        itemDelimElement.tag = getItemDelimitationItemTag();\n        itemDelimElement.value = [];\n        byteOffset = this.#writeDataElement(\n          writer, itemDelimElement, byteOffset, isImplicit);\n      }\n    }\n\n    // return new offset\n    return byteOffset;\n  }\n\n  /**\n   * Write data with a specific Value Representation (VR).\n   *\n   * @param {DataWriter} writer The raw data writer.\n   * @param {DataElement} element The element to write.\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} value The array to write.\n   * @param {boolean} isImplicit Is the DICOM VR implicit?\n   * @returns {number} The new offset position.\n   */\n  #writeDataElementValue(\n    writer, element, byteOffset, value, isImplicit) {\n\n    const startOffset = byteOffset;\n\n    if (element.vr === 'NONE') {\n      // nothing to do!\n    } else if (value instanceof Uint8Array) {\n      // binary data has been expanded 8 times at read\n      if (value.length === 8 * element.vl) {\n        byteOffset = writer.writeBinaryArray(byteOffset, value);\n      } else {\n        byteOffset = writer.writeUint8Array(byteOffset, value);\n      }\n    } else if (value instanceof Int8Array) {\n      byteOffset = writer.writeInt8Array(byteOffset, value);\n    } else if (value instanceof Uint16Array) {\n      byteOffset = writer.writeUint16Array(byteOffset, value);\n    } else if (value instanceof Int16Array) {\n      byteOffset = writer.writeInt16Array(byteOffset, value);\n    } else if (value instanceof Uint32Array) {\n      byteOffset = writer.writeUint32Array(byteOffset, value);\n    } else if (value instanceof Int32Array) {\n      byteOffset = writer.writeInt32Array(byteOffset, value);\n    } else if (value instanceof BigUint64Array) {\n      byteOffset = writer.writeUint64Array(byteOffset, value);\n    } else if (value instanceof BigInt64Array) {\n      byteOffset = writer.writeInt64Array(byteOffset, value);\n    } else {\n      // switch according to VR if input type is undefined\n      const vrType = vrTypes[element.vr];\n      if (typeof vrType !== 'undefined') {\n        if (vrType === 'Uint8') {\n          byteOffset = writer.writeUint8Array(byteOffset, value);\n        } else if (vrType === 'Uint16') {\n          byteOffset = writer.writeUint16Array(byteOffset, value);\n        } else if (vrType === 'Int16') {\n          byteOffset = writer.writeInt16Array(byteOffset, value);\n        } else if (vrType === 'Uint32') {\n          byteOffset = writer.writeUint32Array(byteOffset, value);\n        } else if (vrType === 'Int32') {\n          byteOffset = writer.writeInt32Array(byteOffset, value);\n        } else if (vrType === 'Uint64') {\n          byteOffset = writer.writeUint64Array(byteOffset, value);\n        } else if (vrType === 'Int64') {\n          byteOffset = writer.writeInt64Array(byteOffset, value);\n        } else if (vrType === 'Float32') {\n          byteOffset = writer.writeFloat32Array(byteOffset, value);\n        } else if (vrType === 'Float64') {\n          byteOffset = writer.writeFloat64Array(byteOffset, value);\n        } else if (vrType === 'string') {\n          byteOffset = writer.writeUint8Array(byteOffset, value);\n        } else {\n          throw new Error('Unknown VR type: ' + vrType);\n        }\n      } else if (element.vr === 'SQ') {\n        byteOffset = this.#writeDataElementItems(\n          writer, byteOffset, value, isImplicit);\n      } else if (element.vr === 'AT') {\n        for (let i = 0; i < value.length; ++i) {\n          const hexString = value[i] + '';\n          const hexString1 = hexString.substring(1, 5);\n          const hexString2 = hexString.substring(6, 10);\n          const dec1 = parseInt(hexString1, 16);\n          const dec2 = parseInt(hexString2, 16);\n          const atValue = [dec1, dec2];\n          byteOffset = writer.writeUint16Array(byteOffset, atValue);\n        }\n      } else if (element.vr === 'xs') {\n        // TODO would be better to use pixelRepresentation in if\n        if (value instanceof Int16Array) {\n          byteOffset = writer.writeInt16Array(byteOffset, value);\n        } else {\n          byteOffset = writer.writeUint16Array(byteOffset, value);\n        }\n      } else {\n        logger.warn('Unknown VR: ' + element.vr);\n      }\n    }\n\n    if (element.vr !== 'SQ' && element.vr !== 'NONE') {\n      const diff = byteOffset - startOffset;\n      if (diff !== element.vl) {\n        let message = 'Offset difference and VL are not equal: ' +\n          diff + ' != ' + element.vl;\n        message += ' (';\n        if (typeof element.tag !== 'undefined') {\n          message += element.tag + ', ';\n        }\n        message += 'vr:' + element.vr + ')';\n        logger.warn(message);\n      }\n    }\n\n    // return new offset\n    return byteOffset;\n  }\n\n  /**\n   * Write a pixel data element.\n   *\n   * @param {DataWriter} writer The raw data writer.\n   * @param {DataElement} element The element to write.\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {Array} value The array to write.\n   * @param {boolean} isImplicit Is the DICOM VR implicit?\n   * @returns {number} The new offset position.\n   */\n  #writePixelDataElementValue(\n    writer, element, byteOffset, value, isImplicit) {\n    // undefined length flag\n    let undefinedLength = false;\n    if (typeof element.undefinedLength !== 'undefined') {\n      undefinedLength = element.undefinedLength;\n    }\n    // explicit length\n    if (!undefinedLength) {\n      let finalValue = value[0];\n      // flatten multi frame\n      if (value.length > 1) {\n        finalValue = flattenArrayOfTypedArrays(value);\n      }\n      // write\n      byteOffset = this.#writeDataElementValue(\n        writer, element, byteOffset, finalValue, isImplicit);\n    } else {\n      // pixel data as sequence\n      const item = {};\n      // first item: basic offset table\n      item['FFFEE000'] = {\n        tag: getItemTag(),\n        vr: 'NONE',\n        vl: 0,\n        value: []\n      };\n      // data\n      for (let i = 0; i < value.length; ++i) {\n        item[i] = {\n          tag: getItemTag(),\n          vr: element.vr,\n          vl: value[i].length,\n          value: value[i]\n        };\n      }\n      // write\n      byteOffset = this.#writeDataElementItems(\n        writer, byteOffset, [item], isImplicit);\n    }\n\n    // return new offset\n    return byteOffset;\n  }\n\n  /**\n   * Write a data element.\n   *\n   * @param {DataWriter} writer The raw data writer.\n   * @param {DataElement} element The DICOM data element to write.\n   * @param {number} byteOffset The offset to start writing from.\n   * @param {boolean} isImplicit Is the DICOM VR implicit?\n   * @returns {number} The new offset position.\n   */\n  #writeDataElement(\n    writer, element, byteOffset, isImplicit) {\n    const isTagWithVR = element.tag.isWithVR();\n    const is32bitVL = (isImplicit || !isTagWithVR)\n      ? true : is32bitVLVR(element.vr);\n    // group\n    byteOffset = writer.writeHex(byteOffset, element.tag.getGroup());\n    // element\n    byteOffset = writer.writeHex(byteOffset, element.tag.getElement());\n    // VR\n    let vr = element.vr;\n    // use VR=UN for private sequence\n    if (this.#useUnVrForPrivateSq &&\n      element.tag.isPrivate() &&\n      vr === 'SQ') {\n      logger.warn('Write element using VR=UN for private sequence.');\n      vr = 'UN';\n    }\n    if (isTagWithVR && !isImplicit) {\n      byteOffset = writer.writeUint8Array(byteOffset, this.#encodeString(vr));\n      // reserved 2 bytes for 32bit VL\n      if (is32bitVL) {\n        byteOffset += 2;\n      }\n    }\n\n    let undefinedLengthSequence = false;\n    if (element.vr === 'SQ' ||\n      isPixelDataTag(element.tag)) {\n      if (typeof element.undefinedLength !== 'undefined') {\n        undefinedLengthSequence = element.undefinedLength;\n      }\n    }\n    let undefinedLengthItem = false;\n    if (isItemTag(element.tag)) {\n      if (typeof element.undefinedLength !== 'undefined') {\n        undefinedLengthItem = element.undefinedLength;\n      }\n    }\n\n    // update vl for sequence or item with undefined length\n    let vl = element.vl;\n    if (undefinedLengthSequence || undefinedLengthItem) {\n      vl = 0xffffffff;\n    }\n    // VL\n    if (is32bitVL) {\n      byteOffset = writer.writeUint32(byteOffset, vl);\n    } else {\n      byteOffset = writer.writeUint16(byteOffset, vl);\n    }\n\n    // value\n    let value = element.value;\n    // check value\n    if (typeof value === 'undefined') {\n      value = [];\n    }\n    // write\n    if (isPixelDataTag(element.tag)) {\n      byteOffset = this.#writePixelDataElementValue(\n        writer, element, byteOffset, value, isImplicit);\n    } else {\n      byteOffset = this.#writeDataElementValue(\n        writer, element, byteOffset, value, isImplicit);\n    }\n\n    // sequence delimitation item for sequence with undefined length\n    if (undefinedLengthSequence) {\n      const seqDelimElement = new DataElement('NONE');\n      seqDelimElement.vl = 0;\n      seqDelimElement.tag = getSequenceDelimitationItemTag();\n      seqDelimElement.value = [];\n      byteOffset = this.#writeDataElement(\n        writer, seqDelimElement, byteOffset, isImplicit);\n    }\n\n    // return new offset\n    return byteOffset;\n  }\n\n  /**\n   * Get the ArrayBuffer corresponding to input DICOM elements.\n   *\n   * @param {Object<string, DataElement>} dataElements The elements to write.\n   * @returns {ArrayBuffer} The elements as a buffer.\n   */\n  getBuffer(dataElements) {\n    // Transfer Syntax\n    const syntax = dataElements[TagKeys.TransferSyntax].value[0];\n    const isImplicit = isImplicitTransferSyntax(syntax);\n    const isBigEndian = isBigEndianTransferSyntax(syntax);\n    // Specific CharacterSet\n    if (typeof dataElements[TagKeys.SpecificCharacterSet] !== 'undefined') {\n      const oldscs = dataElements[TagKeys.SpecificCharacterSet].value[0];\n      // force UTF-8 if not default character set\n      if (typeof oldscs !== 'undefined' && oldscs !== 'ISO-IR 6') {\n        logger.debug('Change charset to UTF, was: ' + oldscs);\n        this.useSpecialTextEncoder();\n        dataElements[TagKeys.SpecificCharacterSet].value = ['ISO_IR 192'];\n      }\n    }\n    // Bits Allocated (for image data)\n    let bitsAllocated;\n    if (typeof dataElements[TagKeys.BitsAllocated] !== 'undefined') {\n      bitsAllocated = dataElements[TagKeys.BitsAllocated].value[0];\n    }\n\n    // calculate buffer size and split elements (meta and non meta)\n    let totalSize = 128 + 4; // DICM\n    let localSize = 0;\n    const metaElements = [];\n    const rawElements = [];\n    let element;\n    let groupName;\n    let metaLength = 0;\n    // FileMetaInformationGroupLength\n    const fmiglTag = getFileMetaInformationGroupLengthTag();\n    // FileMetaInformationVersion\n    const fmivTag = new Tag('0002', '0001');\n    // ImplementationClassUID\n    const icUIDTag = new Tag('0002', '0012');\n    // ImplementationVersionName\n    const ivnTag = new Tag('0002', '0013');\n\n    // missing tag list: start as a copy of compulsory\n    const missingTags = this.#compulsoryTags.slice();\n\n    // loop through elements to get the buffer size\n    const keys = Object.keys(dataElements);\n    for (let i = 0, leni = keys.length; i < leni; ++i) {\n      const originalElement = dataElements[keys[i]];\n      originalElement.tag = getTagFromKey(keys[i]);\n      element = this.getElementToWrite(originalElement);\n      if (element !== null &&\n        !fmiglTag.equals(element.tag) &&\n        !fmivTag.equals(element.tag) &&\n        !icUIDTag.equals(element.tag) &&\n        !ivnTag.equals(element.tag)) {\n        localSize = 0;\n\n        // check if compulsory tag, if present remove from missing list\n        const index = missingTags.indexOf(element.tag.getKey());\n        if (index !== -1) {\n          missingTags.splice(index, 1);\n        }\n\n        // XB7 2020-04-17\n        // Check if UN can be converted to correct VR.\n        // This check must be done BEFORE calculating totalSize,\n        // otherwise there may be extra null bytes at the end of the file\n        // (dcmdump may crash because of these bytes)\n        if (this.#fixUnknownVR) {\n          checkAndFixUnknownVR(element, !isBigEndian);\n        }\n\n        // update value and vl\n        this.#setElementValue(\n          element, element.value, isImplicit, bitsAllocated);\n\n        // tag group name\n        groupName = element.tag.getGroupName();\n\n        // prefix\n        if (groupName === 'Meta Element') {\n          localSize += getDataElementPrefixByteSize(element.vr, false);\n        } else {\n          localSize += getDataElementPrefixByteSize(\n            element.vr, isImplicit);\n        }\n\n        // value\n        localSize += element.vl;\n\n        // sort elements\n        if (groupName === 'Meta Element') {\n          metaElements.push(element);\n          metaLength += localSize;\n        } else {\n          rawElements.push(element);\n        }\n\n        // add to total size\n        totalSize += localSize;\n      }\n    }\n\n    // add compulsory tags to output data if not present\n    for (const key of missingTags) {\n      const tag = getTagFromKey(key);\n      const dataElement = new DataElement(tag.getVrFromDictionary());\n      dataElement.tag = tag;\n      // rules are indexed by key or tag name\n      let value;\n      if (typeof this.#rules[key] !== 'undefined') {\n        value = this.#rules[key].value;\n      } else {\n        const name = tag.getNameFromDictionary();\n        value = this.#rules[name].value;\n      }\n      // add element\n      let size = getDataElementPrefixByteSize(dataElement.vr, isImplicit);\n      size += this.#setElementValue(dataElement, [value], isImplicit);\n      rawElements.push(dataElement);\n      totalSize += size;\n    }\n\n    // FileMetaInformationVersion\n    const fmiv = getDataElement('FileMetaInformationVersion');\n    let fmivSize = getDataElementPrefixByteSize(fmiv.vr, false);\n    fmivSize += this.#setElementValue(fmiv, [0, 1], false);\n    metaElements.push(fmiv);\n    metaLength += fmivSize;\n    totalSize += fmivSize;\n    // ImplementationClassUID\n    const icUID = getDataElement('ImplementationClassUID');\n    let icUIDSize = getDataElementPrefixByteSize(icUID.vr, false);\n    const icUIDValue =\n      getUID('ImplementationClassUID').replace('-beta', '.99');\n    icUIDSize += this.#setElementValue(icUID, [icUIDValue], false);\n    metaElements.push(icUID);\n    metaLength += icUIDSize;\n    totalSize += icUIDSize;\n    // ImplementationVersionName\n    const ivn = getDataElement('ImplementationVersionName');\n    let ivnSize = getDataElementPrefixByteSize(ivn.vr, false);\n    const dwvVersion = getDwvVersion().replace('-beta', '.99');\n    const ivnValue = 'DWV_' + dwvVersion;\n    ivnSize += this.#setElementValue(ivn, [ivnValue], false);\n    metaElements.push(ivn);\n    metaLength += ivnSize;\n    totalSize += ivnSize;\n\n    // sort elements\n    const elemSortFunc = function (a, b) {\n      return tagCompareFunction(a.tag, b.tag);\n    };\n    metaElements.sort(elemSortFunc);\n    rawElements.sort(elemSortFunc);\n\n    // create the FileMetaInformationGroupLength element\n    const fmigl = getDataElement('FileMetaInformationGroupLength');\n    let fmiglSize = getDataElementPrefixByteSize(fmigl.vr, false);\n    fmiglSize += this.#setElementValue(\n      fmigl, new Uint32Array([metaLength]), false);\n    totalSize += fmiglSize;\n\n    // create buffer\n    const buffer = new ArrayBuffer(totalSize);\n    const metaWriter = new DataWriter(buffer);\n    const dataWriter = new DataWriter(buffer, !isBigEndian);\n\n    let offset = 128;\n    // DICM\n    offset = metaWriter.writeUint8Array(offset, this.#encodeString('DICM'));\n    // FileMetaInformationGroupLength\n    offset = this.#writeDataElement(metaWriter, fmigl, offset, false);\n    // write meta\n    for (let j = 0, lenj = metaElements.length; j < lenj; ++j) {\n      offset = this.#writeDataElement(\n        metaWriter, metaElements[j], offset, false);\n    }\n\n    // check meta position\n    const preambleSize = 128 + 4;\n    const metaOffset = preambleSize + fmiglSize + metaLength;\n    if (offset !== metaOffset) {\n      logger.warn('Bad size calculation... meta offset: ' + offset +\n        ', calculated size:' + metaOffset +\n        ' (diff:' + (offset - metaOffset) + ')');\n    }\n\n    // write non meta\n    for (let k = 0, lenk = rawElements.length; k < lenk; ++k) {\n      offset = this.#writeDataElement(\n        dataWriter, rawElements[k], offset, isImplicit);\n    }\n\n    // check final position\n    if (offset !== totalSize) {\n      logger.warn('Bad size calculation... final offset: ' + offset +\n        ', calculated size:' + totalSize +\n        ' (diff:' + (offset - totalSize) + ')');\n    }\n    // return\n    return buffer;\n  }\n\n  /**\n   * Set a DICOM element value according to its VR (Value Representation).\n   *\n   * @param {DataElement} element The DICOM element to set the value.\n   * @param {object} value The value to set.\n   * @param {boolean} isImplicit Does the data use implicit VR?\n   * @param {number} [bitsAllocated] Bits allocated used for pixel data.\n   * @returns {number} The total element size.\n   */\n  #setElementValue(\n    element, value, isImplicit, bitsAllocated) {\n    // byte size of the element\n    let size = 0;\n    // special sequence case\n    if (element.vr === 'SQ') {\n\n      if (value !== null && value !== 0) {\n        const newItems = [];\n\n        // explicit or undefined length sequence\n        let undefinedLength = false;\n        if (typeof element.undefinedLength !== 'undefined') {\n          undefinedLength = element.undefinedLength;\n          delete element.undefinedLength;\n        }\n\n        // items\n        for (let i = 0; i < value.length; ++i) {\n          const oldItemElements = value[i];\n          const newItemElements = [];\n          let subSize = 0;\n\n          // check data\n          if (oldItemElements === null || oldItemElements === 0) {\n            continue;\n          }\n\n          // possible local bitsAllocated\n          let sqBitsAllocated = bitsAllocated;\n          const dataElement = oldItemElements[TagKeys.BitsAllocated];\n          if (typeof dataElement !== 'undefined' &&\n            typeof dataElement.value !== 'undefined') {\n            sqBitsAllocated = dataElement.value[0];\n          }\n\n          // elements\n          const itemKeys = Object.keys(oldItemElements);\n          for (let j = 0, lenj = itemKeys.length; j < lenj; ++j) {\n            const itemKey = itemKeys[j];\n            const subElement = oldItemElements[itemKey];\n            subElement.tag = getTagFromKey(itemKey);\n\n            if (isItemTag(subElement.tag)) {\n              continue;\n            }\n            // set item value\n            subSize += this.#setElementValue(\n              subElement, subElement.value, isImplicit, sqBitsAllocated);\n            newItemElements.push(subElement);\n            // add prefix size\n            subSize += getDataElementPrefixByteSize(\n              subElement.vr, isImplicit);\n          }\n\n          // add item element (used to store its size)\n          const itemElement = {\n            tag: getItemTag(),\n            vr: 'NONE',\n            vl: subSize,\n            value: []\n          };\n          if (undefinedLength) {\n            itemElement.undefinedLength = undefinedLength;\n          }\n          newItemElements.push(itemElement);\n          subSize += getDataElementPrefixByteSize(\n            itemElement.vr, isImplicit);\n\n          // add item delimitation size\n          if (undefinedLength) {\n            subSize += getDataElementPrefixByteSize(\n              'NONE', isImplicit);\n          }\n\n          // sort\n          const elemSortFunc = function (a, b) {\n            return tagCompareFunction(a.tag, b.tag);\n          };\n          newItemElements.sort(elemSortFunc);\n\n          size += subSize;\n          newItems.push(newItemElements);\n        }\n\n        // add sequence delimitation size\n        if (undefinedLength) {\n          size += getDataElementPrefixByteSize('NONE', isImplicit);\n        }\n\n        // update sequence element\n        element.value = newItems;\n        element.vl = size;\n        if (undefinedLength) {\n          element.undefinedLength = undefinedLength;\n        }\n      }\n    } else {\n      // pad if necessary\n      if (isVrToPad(element.vr)) {\n        const padStr = getVrPad(element.vr);\n        // encode string\n        // TODO: not sure for UN...\n        if (isStringVr(element.vr)) {\n          let pad;\n          if (isCharSetStringVR(element.vr)) {\n            value = this.#encodeSpecialString(value.join('\\\\'));\n            pad = this.#encodeSpecialString(padStr);\n          } else {\n            value = this.#encodeString(value.join('\\\\'));\n            pad = this.#encodeString(padStr);\n          }\n          if (!isEven(value.length)) {\n            value = uint8ArrayPush(value, pad);\n          }\n        } else if (element.vr === 'OB') {\n          value = padOBValue(value);\n        }\n      }\n\n      // calculate byte size\n      size = 0;\n      if (element.vr === 'AT') {\n        size = 4 * value.length;\n      } else if (element.vr === 'xs') {\n        size = value.length * Uint16Array.BYTES_PER_ELEMENT;\n      } else if (isTypedArrayVr(element.vr) || element.vr === 'ox') {\n        if (isPixelDataTag(element.tag) &&\n          Array.isArray(value)) {\n          size = 0;\n          for (let b = 0; b < value.length; ++b) {\n            size += value[b].length;\n          }\n        } else {\n          size = value.length;\n        }\n\n        // convert size to bytes\n        const vrType = vrTypes[element.vr];\n        if (isPixelDataTag(element.tag) || element.vr === 'ox') {\n          if (element.undefinedLength) {\n            const itemPrefixSize =\n              getDataElementPrefixByteSize('NONE', isImplicit);\n            // offset table\n            size += itemPrefixSize;\n            // pixel items\n            size += itemPrefixSize * value.length;\n            // add sequence delimitation size\n            size += itemPrefixSize;\n          } else {\n            // use bitsAllocated for pixel data\n            // no need to multiply for 8 bits\n            if (typeof bitsAllocated !== 'undefined') {\n              if (bitsAllocated === 1) {\n                // binary data\n                size /= 8;\n              } else if (bitsAllocated === 16) {\n                size *= Uint16Array.BYTES_PER_ELEMENT;\n              }\n            }\n          }\n        } else if (typeof vrType !== 'undefined') {\n          const bpe = getBpeForVrType(vrType);\n          if (typeof bpe !== 'undefined') {\n            size *= bpe;\n          } else {\n            throw new Error('Unknown bytes per element for VR type: ' + vrType);\n          }\n        } else {\n          throw new Error('Unsupported element: ' + element.vr);\n        }\n      } else {\n        size = value.length;\n      }\n\n      element.value = value;\n      element.vl = size;\n    }\n\n    // return the size of that data\n    return size;\n  }\n\n} // class DicomWriter\n\n/**\n * Fix for broken DICOM elements: replace \"UN\" with correct VR if the\n * element exists in dictionary.\n *\n * @param {DataElement} element The DICOM element.\n * @param {boolean} [isLittleEndian] Flag to tell if the data is little\n *   or big endian (default: true).\n */\nfunction checkAndFixUnknownVR(element, isLittleEndian) {\n  if (element.vr === 'UN') {\n    const dictVr = element.tag.getVrFromDictionary();\n    if (typeof dictVr !== 'undefined' && element.vr !== dictVr) {\n      element.vr = dictVr;\n      // cast typed array value from Uint8 to vr type\n      const vrType = vrTypes[element.vr];\n      if (typeof vrType !== 'undefined' &&\n        vrType !== 'Uint8' &&\n        vrType !== 'string') {\n        const data = getUint8ToVrValue(\n          element.value, element.vr, isLittleEndian);\n        if (typeof data !== 'undefined') {\n          element.value = data;\n        }\n      }\n      logger.info('Element ' + element.tag.getGroup() +\n        ' ' + element.tag.getElement() +\n        ' VR changed from UN to ' + element.vr);\n    }\n  }\n}\n\n/**\n * Get the casted typed array value from Uint8 to vr type.\n *\n * @param {object} value The value to cast.\n * @param {string} vr The DICOM element VR.\n * @param {boolean} [isLittleEndian] Flag to tell if the data is little\n *   or big endian (default: true).\n * @returns {object} The element value casted to the vr type.\n */\nfunction getUint8ToVrValue(value, vr, isLittleEndian) {\n  let data;\n  if (typeof value.buffer === 'undefined') {\n    return data;\n  }\n  const reader = new DataReader(value.buffer, isLittleEndian);\n  const offset = value.byteOffset;\n  const vl = value.length; // size before cast\n  const vrType = vrTypes[vr];\n  if (vrType === 'Uint16') {\n    data = reader.readUint16Array(offset, vl);\n  } else if (vrType === 'Uint32') {\n    data = reader.readUint32Array(offset, vl);\n  } else if (vrType === 'Uint64') {\n    data = reader.readUint64Array(offset, vl);\n  } else if (vrType === 'Int16') {\n    data = Array.from(reader.readInt16Array(offset, vl));\n  } else if (vrType === 'Int32') {\n    data = Array.from(reader.readInt32Array(offset, vl));\n  } else if (vrType === 'Int64') {\n    data = reader.readInt64Array(offset, vl);\n  } else if (vrType === 'Float32') {\n    data = Array.from(reader.readFloat32Array(offset, vl));\n  } else if (vrType === 'Float64') {\n    data = Array.from(reader.readFloat64Array(offset, vl));\n  }\n  return data;\n}\n\n/**\n * Get a DICOM element from its tag name (value set separatly).\n *\n * @param {string} tagName The string tag name.\n * @returns {DataElement} The DICOM element.\n */\nfunction getDataElement(tagName) {\n  const tag = getTagFromDictionary(tagName);\n  const element = new DataElement(tag.getVrFromDictionary());\n  element.tag = tag;\n  return element;\n}\n\n/**\n * Get the number of bytes per element for a given VR type.\n *\n * @param {string} vrType The VR type as defined in the dictionary.\n * @returns {number} The bytes per element.\n */\nfunction getBpeForVrType(vrType) {\n  let bpe;\n  if (vrType === 'Uint8') {\n    bpe = Uint8Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Uint16') {\n    bpe = Uint16Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Int16') {\n    bpe = Int16Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Uint32') {\n    bpe = Uint32Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Int32') {\n    bpe = Int32Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Float32') {\n    bpe = Float32Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Float64') {\n    bpe = Float64Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Uint64') {\n    bpe = BigUint64Array.BYTES_PER_ELEMENT;\n  } else if (vrType === 'Int64') {\n    bpe = BigInt64Array.BYTES_PER_ELEMENT;\n  }\n  return bpe;\n}\n\n/**\n * Get the DICOM elements from a 'simple' DICOM tags object.\n * The input object is a simplified version of the oficial DICOM json with\n * tag names instead of keys and direct values (no value property) for\n * simple tags. See synthetic test data (in tests/dicom) for examples.\n *\n * @param {Object<string, any>} simpleTags The 'simple' DICOM\n *   tags object.\n * @returns {Object<string, DataElement>} The DICOM elements.\n */\nexport function getElementsFromJSONTags(simpleTags) {\n  const keys = Object.keys(simpleTags);\n  const dataElements = {};\n  for (let k = 0, len = keys.length; k < len; ++k) {\n    // get the DICOM element definition from its name\n    const tag = getTagFromDictionary(keys[k]);\n    if (typeof tag === 'undefined') {\n      continue;\n    }\n    const vr = tag.getVrFromDictionary();\n    // tag value\n    let value;\n    let undefinedLength = false;\n    const simpleTag = simpleTags[keys[k]];\n    if (vr === 'SQ') {\n      const items = [];\n      if (typeof simpleTag.undefinedLength !== 'undefined') {\n        undefinedLength = simpleTag.undefinedLength;\n      }\n      if (typeof simpleTag.value !== 'undefined' &&\n        simpleTag.value !== null) {\n        for (let i = 0; i < simpleTag.value.length; ++i) {\n          items.push(getElementsFromJSONTags(simpleTag.value[i]));\n        }\n      } else {\n        logger.trace('Undefined or null simpleTag SQ value.');\n      }\n      value = items;\n    } else {\n      if (Array.isArray(simpleTag)) {\n        value = simpleTag;\n      } else {\n        value = [simpleTag];\n      }\n    }\n    // create element\n    const dataElement = new DataElement(vr);\n    dataElement.tag = tag;\n    dataElement.value = value;\n    if (undefinedLength) {\n      dataElement.undefinedLength = undefinedLength;\n    }\n    // store\n    dataElements[tag.getKey()] = dataElement;\n  }\n  // return\n  // @ts-expect-error\n  return dataElements;\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * DICOM code tag keys.\n */\nconst TagKeys = {\n  CodeValue: '00080100',\n  CodingSchemeDesignator: '00080102',\n  CodeMeaning: '00080104',\n  LongCodeValue: '00080119',\n  URNCodeValue: '00080120'\n};\n\n/**\n * DICOM code: item of a basic code sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_8.8.html}.\n */\nexport class DicomCode {\n  /**\n   * Code meaning.\n   *\n   * @type {string}\n   */\n  meaning;\n  /**\n   * Code value.\n   *\n   * @type {string|undefined}\n   */\n  value;\n  /**\n   * Long code value.\n   *\n   * @type {string|undefined}\n   */\n  longValue;\n  /**\n   * URN code value.\n   *\n   * @type {string|undefined}\n   */\n  urnValue;\n  /**\n   * Coding scheme designator.\n   *\n   * @type {string|undefined}\n   */\n  schemeDesignator;\n\n  /**\n   * @param {string} meaning The code meaning.\n   */\n  constructor(meaning) {\n    this.meaning = meaning;\n  }\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The code as string.\n   */\n  toString() {\n    return '(' + this.value + ', ' +\n      this.schemeDesignator + ', \\'' +\n      this.meaning + '\\')';\n  }\n}\n\n/**\n * Check if two code objects are equal.\n *\n * @param {DicomCode} code1 The first code.\n * @param {DicomCode} code2 The second code.\n * @returns {boolean} True if both codes are equal.\n */\nexport function isEqualCode(code1, code2) {\n  return Object.keys(code1).length === Object.keys(code2).length &&\n  Object.keys(code1).every(key =>\n    Object.prototype.hasOwnProperty.call(code2, key) &&\n    code1[key] === code2[key]\n  );\n}\n\n/**\n * Get a code object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {DicomCode} A code object.\n */\nexport function getCode(dataElements) {\n  // meaning -> CodeMeaning (type1)\n  const code = new DicomCode(dataElements[TagKeys.CodeMeaning].value[0]);\n  // value -> CodeValue (type1C)\n  // longValue -> LongCodeValue (type1C)\n  // urnValue -> URNCodeValue (type1C)\n  if (typeof dataElements[TagKeys.CodeValue] !== 'undefined') {\n    code.value = dataElements[TagKeys.CodeValue].value[0];\n  } else if (typeof dataElements[TagKeys.LongCodeValue] !== 'undefined') {\n    code.longValue = dataElements[TagKeys.LongCodeValue].value[0];\n  } else if (typeof dataElements[TagKeys.URNCodeValue] !== 'undefined') {\n    code.urnValue = dataElements[TagKeys.URNCodeValue].value[0];\n  } else {\n    throw new Error(\n      'Invalid code with no value, no long value and no urn value.');\n  }\n  // schemeDesignator -> CodingSchemeDesignator (type1C)\n  if (typeof code.value !== 'undefined' ||\n    typeof code.longValue !== 'undefined') {\n    if (typeof dataElements[TagKeys.CodingSchemeDesignator] !== 'undefined') {\n      code.schemeDesignator =\n        dataElements[TagKeys.CodingSchemeDesignator].value[0];\n    } else {\n      throw new Error(\n        'No coding sheme designator when code value or long value is present');\n    }\n  }\n  return code;\n}\n\n/**\n * Get a simple dicom element item from a code object.\n *\n * @param {DicomCode} code The code object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomCodeItem(code) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n  // value\n  if (typeof code.value !== 'undefined') {\n    item.CodeValue = code.value;\n  } else if (typeof code.longValue !== 'undefined') {\n    item.LongCodeValue = code.longValue;\n  } else if (typeof code.urnValue !== 'undefined') {\n    item.URNCodeValue = code.urnValue;\n  }\n  // CodingSchemeDesignator\n  if (typeof code.schemeDesignator !== 'undefined') {\n    item.CodingSchemeDesignator = code.schemeDesignator;\n  }\n  // CodeMeaning\n  item.CodeMeaning = code.meaning;\n  // return\n  return item;\n}\n\n/**\n * DICOM codes.\n * List: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part16/chapter_d.html}.\n */\nconst DcmCodes = {\n  111030: 'Image Region',\n  112039: 'Tracking Identifier',\n  112040: 'Tracking Unique Identifier',\n  113048: 'Pixel by pixel Maximum',\n  113049: 'Pixel by pixel mean',\n  113051: 'Pixel by pixel Minimum',\n  113061: 'Standard Deviation',\n  113076: 'Segmentation',\n  121055: 'Path',\n  121207: 'Height',\n  121322: 'Source image for image processing operation',\n  121324: 'Source Image',\n  122438: 'Reference Points',\n  125007: 'Measurement Group',\n  125309: 'Short label',\n  128773: 'Reference Geometry'\n};\n\n/**\n * SNOMED-CT codes.\n * List: {@link https://browser.ihtsdotools.org}.\n */\nconst SctCodes = {\n  1483009: 'Angle',\n  42798000: 'Area',\n  103355008: 'Width',\n  103339001: 'Long axis',\n  103340004: 'Short axis',\n  131190003: 'Radius',\n  261665006: 'Unknown',\n  410668003: 'Length',\n  718499004: 'Color'\n};\n\n/**\n * UCUM codes.\n * Definition: {@link https://unitsofmeasure.org/ucum}.\n * List: {@link https://ucum.nlm.nih.gov/ucum-lhc/demo.html}.\n */\nconst UcumCodes = {\n  1: 'No units',\n  mm: 'Millimeter',\n  deg: 'Degree - plane angle',\n  cm2: 'Square centimeter',\n  'cm2/ml': 'Square centimeter per milliliter',\n  '/cm': 'Per centimeter',\n  'g/ml': 'Gram per milliliter',\n  'g/ml{SUVbw}': 'Standardized Uptake Value body weight',\n  'mg/ml': 'Milligram per milliliter',\n  'umol/ml': 'Micromole per milliliter',\n  'Bq/ml': 'Becquerels per milliliter',\n  'mg/min/ml': 'Milligrams per minute per milliliter',\n  'umol/min/ml': 'Micromole per minute per milliliter',\n  'ml/min/g': 'Milliliter per minute per gram',\n  'ml/g': 'Milliliter per gram',\n  'ml/min/ml': 'Milliliter per minute per milliliter',\n  'ml/ml': 'Milliliter per milliliter',\n  '%': 'Percentage',\n  '[hnsf\\'U]': 'Hounsfield unit',\n  '10*23/ml': 'Electron density',\n  '{counts}': 'Counts',\n  '{counts}/s': 'Counts per second',\n  '{propcounts}': 'Proportional to counts',\n  '{propcounts}/s': 'Proportional to counts per second',\n};\n\n/**\n * Get a DICOM code from a value (~id).\n *\n * @param {string} value The code value.\n * @param {string} scheme The scheme designator.\n * @returns {DicomCode|undefined} The DICOM code.\n */\nfunction getDicomCode(value, scheme) {\n  let meaning;\n  if (scheme === 'DCM') {\n    meaning = DcmCodes[value];\n  } else if (scheme === 'SCT') {\n    meaning = SctCodes[value];\n  } else if (scheme === 'UCUM') {\n    meaning = UcumCodes[value];\n  }\n  let code;\n  if (typeof meaning !== 'undefined') {\n    code = new DicomCode(meaning);\n    code.schemeDesignator = scheme;\n    code.value = value;\n  }\n  return code;\n}\n\n/**\n * Get a measurement group DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getMeasurementGroupCode() {\n  return getDicomCode('125007', 'DCM');\n}\n\n/**\n * Get an image region DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getImageRegionCode() {\n  return getDicomCode('111030', 'DCM');\n}\n\n/**\n * Get a reference geometry DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getReferenceGeometryCode() {\n  return getDicomCode('128773', 'DCM');\n}\n\n/**\n * Get a path DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getPathCode() {\n  return getDicomCode('121055', 'DCM');\n}\n\n/**\n * Get a source image DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getSourceImageCode() {\n  return getDicomCode('121324', 'DCM');\n}\n\n/**\n * Get a tracking identifier DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getTrackingIdentifierCode() {\n  return getDicomCode('112039', 'DCM');\n}\n\n/**\n * Get a segmentation DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getSegmentationCode() {\n  return getDicomCode('113076', 'DCM');\n}\n\n/**\n * Get a source image for processing DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getSourceImageForProcessingCode() {\n  return getDicomCode('121322', 'DCM');\n}\n\n/**\n * Get a short label DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getShortLabelCode() {\n  return getDicomCode('125309', 'DCM');\n}\n\n/**\n * Get a reference points DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getReferencePointsCode() {\n  return getDicomCode('122438', 'DCM');\n}\n\n/**\n * Get a colour DICOM code.\n *\n * @returns {DicomCode} The code.\n */\nexport function getColourCode() {\n  return getDicomCode('718499004', 'SCT');\n}\n\n/**\n * Quantification name to dictionary item.\n */\nconst QuantificationName2DictItem = {\n  angle: {key: '1483009', scheme: 'SCT'},\n  length: {key: '410668003', scheme: 'SCT'},\n  surface: {key: '42798000', scheme: 'SCT'},\n  height: {key: '121207', scheme: 'DCM'},\n  width: {key: '103355008', scheme: 'SCT'},\n  radius: {key: '131190003', scheme: 'SCT'},\n  a: {key: '103339001', scheme: 'SCT'},\n  b: {key: '103340004', scheme: 'SCT'},\n  min: {key: '113051', scheme: 'DCM'},\n  max: {key: '113048', scheme: 'DCM'},\n  mean: {key: '113049', scheme: 'DCM'},\n  stddev: {key: '113061', scheme: 'DCM'},\n  // median\n  // 25th percentile\n  // 75th percentile\n};\n\n/**\n * Get a concept name DICOM code.\n *\n * @param {string} name The measurment name as defined\n *   in a quantification object.\n * @returns {DicomCode|undefined} The code.\n */\nexport function getConceptNameCode(name) {\n  const item = QuantificationName2DictItem[name];\n  let code;\n  if (typeof item !== 'undefined') {\n    code = getDicomCode(item.key, item.scheme);\n  }\n  return code;\n}\n\n/**\n * Get the DICOM code for a quantification name.\n *\n * @param {DicomCode} code The Dicom code.\n * @returns {string|undefined} The quantification name.\n */\nexport function getQuantificationName(code) {\n  let name;\n  for (const propKey in QuantificationName2DictItem) {\n    const item = QuantificationName2DictItem[propKey];\n    if (item.scheme === code.schemeDesignator &&\n      item.key === code.value) {\n      name = propKey;\n      break;\n    }\n  }\n  return name;\n}\n\n/**\n * Quantification unit to UCUM key. Associated tags:\n * - Rescale type {@link https://dicom.innolitics.com/ciods/computed-radiography-image/modality-lut/00281054},\n * - Units {@link https://dicom.innolitics.com/ciods/positron-emission-tomography-image/pet-series/00541001}.\n * - SUV {@link https://dicom.nema.org/medical/dicom/current/output/chtml/part16/sect_CID_85.html}.\n */\nconst QuantificationUnit2UcumKey = {\n  'unit.mm': 'mm',\n  'unit.cm2': 'cm2',\n  'unit.degree': 'deg',\n  // OD optical density\n  HU: '[hnsf\\'U]',\n  // US: '1', // duplicates 'NONE'\n  MGML: 'mg/ml',\n  // Z_EFF Effective Atomic Number (i.e., Effective-Z)\n  ED: '10*23/ml',\n  // EDW Electron density normalized\n  // HU_MOD Modified Hounsfield Unit\n  PCT: '%',\n  CNTS: '{counts}',\n  NONE: '1',\n  CM2: 'cm2',\n  CM2ML: 'cm2/ml',\n  PCNT: '%',\n  CPS: '{counts}/s',\n  BQML: 'Bq/ml',\n  MGMINML: 'mg/min/ml',\n  UMOLMINML: 'umol/min/ml',\n  MLMING: 'ml/min/g',\n  MLG: 'ml/g',\n  '1CM': '/cm',\n  UMOLML: 'umol/ml',\n  PROPCNTS: '{propcounts}',\n  PROPCPS: '{propcounts}/s',\n  MLMINML: 'ml/min/ml',\n  MLML: 'ml/ml',\n  GML: 'g/ml',\n  //STDDEV\n  SUV: 'g/ml{SUVbw}',\n};\n\n/**\n * Get a measurement units DICOM code.\n *\n * @param {string} name The unit name as defined in a quantification object.\n * @returns {DicomCode|undefined} The code.\n */\nexport function getMeasurementUnitsCode(name) {\n  const key = QuantificationUnit2UcumKey[name];\n  let code;\n  if (typeof key !== 'undefined') {\n    code = getDicomCode(key, 'UCUM');\n  } else if (typeof key === 'undefined') {\n    // no unit\n    code = getDicomCode('1', 'UCUM');\n  }\n  return code;\n}\n\n/**\n * Get a quantification unit name.\n *\n * @param {DicomCode} code The code to get the unit from.\n * @returns {string} The quantification unit.\n */\nexport function getQuantificationUnit(code) {\n  let unit;\n  for (const propKey in QuantificationUnit2UcumKey) {\n    const ucumKey = QuantificationUnit2UcumKey[propKey];\n    if (code.schemeDesignator === 'UCUM' &&\n      ucumKey === code.value) {\n      unit = propKey;\n      break;\n    }\n  }\n  return unit;\n}\n","import {\n  isEqualRgb,\n  cielabToSrgb,\n  uintLabToLab,\n  labToUintLab,\n  srgbToCielab\n} from '../utils/colour';\nimport {\n  getCode,\n  getDicomCodeItem\n} from './dicomCode';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {RGB} from '../utils/colour';\nimport {DataElement} from './dataElement';\nimport {DicomCode} from './dicomCode';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  SegmentNumber: '00620004',\n  SegmentLabel: '00620005',\n  SegmentAlgorithmType: '00620008',\n  SegmentAlgorithmName: '00620009',\n  RecommendedDisplayGrayscaleValue: '0062000C',\n  RecommendedDisplayCIELabValue: '0062000D',\n  SegmentedPropertyCategoryCodeSequence: '00620003',\n  SegmentedPropertyTypeCodeSequence: '0062000F',\n  TrackingID: '00620020',\n  TrackingUID: '00620021'\n};\n\n/**\n * DICOM (mask) segment: item of a SegmentSequence (0062,0002).\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.8.20.4.html}.\n */\nexport class MaskSegment {\n  /**\n   * Segment number (0062,0004).\n   *\n   * @type {number}\n   */\n  number;\n  /**\n   * Segment label (0062,0005).\n   *\n   * @type {string}\n   */\n  label;\n  /**\n   * Segment algorithm type (0062,0008).\n   *\n   * @type {string}\n   */\n  algorithmType;\n  /**\n   * Segment algorithm name (0062,0009).\n   *\n   * @type {string|undefined}\n   */\n  algorithmName;\n  /**\n   * Segment display value as simple value.\n   *\n   * @type {number|undefined}\n   */\n  displayValue;\n  /**\n   * Segment display value as RGB colour ({r,g,b}).\n   *\n   * @type {RGB|undefined}\n   */\n  displayRGBValue;\n  /**\n   * Segment property code: specific property\n   * the segment represents (0062,000F).\n   *\n   * @type {DicomCode|undefined}\n   */\n  propertyTypeCode;\n  /**\n   * Segment property category code: general category\n   * of the property the segment represents (0062,0003).\n   *\n   * @type {DicomCode|undefined}\n   */\n  propertyCategoryCode;\n  /**\n   * Segment tracking UID (0062,0021).\n   *\n   * @type {string|undefined}\n   */\n  trackingUid;\n  /**\n   * Segment tracking id: text label for the UID (0062,0020).\n   *\n   * @type {string|undefined}\n   */\n  trackingId;\n\n  /**\n   * @param {number} number The segment number.\n   * @param {string} label The segment label.\n   * @param {string} algorithmType The segment number.\n   */\n  constructor(number, label, algorithmType) {\n    this.number = number;\n    this.label = label;\n    this.algorithmType = algorithmType;\n  }\n}\n\n/**\n * Get a segment object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {MaskSegment} A segment object.\n */\nexport function getSegment(dataElements) {\n  // number -> SegmentNumber (type1)\n  // label -> SegmentLabel (type1)\n  // algorithmType -> SegmentAlgorithmType (type1)\n  const segment = new MaskSegment(\n    dataElements[TagKeys.SegmentNumber].value[0],\n    dataElements[TagKeys.SegmentLabel]\n      ? dataElements[TagKeys.SegmentLabel].value[0] : 'n/a',\n    dataElements[TagKeys.SegmentAlgorithmType].value[0]\n  );\n  // algorithmName -> SegmentAlgorithmName (type1C)\n  if (typeof dataElements[TagKeys.SegmentAlgorithmName] !== 'undefined') {\n    segment.algorithmName = dataElements[TagKeys.SegmentAlgorithmName].value[0];\n  }\n  // // required if type is not MANUAL\n  // if (segment.algorithmType !== 'MANUAL' &&\n  //   (typeof segment.algorithmName === 'undefined' ||\n  //   segment.algorithmName.length === 0)) {\n  //   throw new Error('Empty algorithm name for non MANUAL algorithm type.');\n  // }\n  // displayValue ->\n  // - RecommendedDisplayGrayscaleValue\n  // - RecommendedDisplayCIELabValue converted to RGB\n  if (typeof dataElements[TagKeys.RecommendedDisplayGrayscaleValue] !==\n    'undefined') {\n    segment.displayValue =\n      dataElements[TagKeys.RecommendedDisplayGrayscaleValue].value[0];\n  } else if (typeof dataElements[TagKeys.RecommendedDisplayCIELabValue] !==\n    'undefined') {\n    const cielabElement =\n      dataElements[TagKeys.RecommendedDisplayCIELabValue].value;\n    const rgb = cielabToSrgb(uintLabToLab({\n      l: cielabElement[0],\n      a: cielabElement[1],\n      b: cielabElement[2]\n    }));\n    segment.displayRGBValue = rgb;\n  }\n  // Segmented Property Category Code Sequence (type1, only one)\n  if (typeof dataElements[TagKeys.SegmentedPropertyCategoryCodeSequence] !==\n    'undefined') {\n    segment.propertyCategoryCode =\n      getCode(\n        dataElements[TagKeys.SegmentedPropertyCategoryCodeSequence].value[0]\n      );\n  } else {\n    throw new Error('Missing Segmented Property Category Code Sequence.');\n  }\n  // Segmented Property Type Code Sequence (type1)\n  if (typeof dataElements[TagKeys.SegmentedPropertyTypeCodeSequence] !==\n    'undefined') {\n    segment.propertyTypeCode =\n      getCode(dataElements[TagKeys.SegmentedPropertyTypeCodeSequence].value[0]);\n  } else {\n    throw new Error('Missing Segmented Property Type Code Sequence.');\n  }\n  // tracking Id and UID (type1C)\n  if (typeof dataElements[TagKeys.TrackingID] !== 'undefined') {\n    segment.trackingId = dataElements[TagKeys.TrackingID].value[0];\n    segment.trackingUid = dataElements[TagKeys.TrackingUID].value[0];\n  }\n\n  return segment;\n}\n\n/**\n * Check if two segment objects are equal.\n *\n * @param {MaskSegment} seg1 The first segment.\n * @param {MaskSegment} seg2 The second segment.\n * @returns {boolean} True if both segment are equal.\n */\nexport function isEqualSegment(seg1, seg2) {\n  // basics\n  if (typeof seg1 === 'undefined' ||\n    typeof seg2 === 'undefined' ||\n    seg1 === null ||\n    seg2 === null) {\n    return false;\n  }\n  let isEqual = seg1.number === seg2.number &&\n    seg1.label === seg2.label &&\n    seg1.algorithmType === seg2.algorithmType;\n  // display value\n  if (typeof seg1.displayRGBValue !== 'undefined' &&\n    typeof seg2.displayRGBValue !== 'undefined') {\n    isEqual = isEqual &&\n      isEqualRgb(seg1.displayRGBValue, seg2.displayRGBValue);\n  } else if (typeof seg1.displayValue !== 'undefined' &&\n    typeof seg2.displayValue !== 'undefined') {\n    isEqual = isEqual &&\n      seg1.displayValue === seg2.displayValue;\n  } else {\n    isEqual = false;\n  }\n  // algorithmName\n  if (typeof seg1.algorithmName !== 'undefined') {\n    if (typeof seg2.algorithmName === 'undefined') {\n      isEqual = false;\n    } else {\n      isEqual = isEqual &&\n        seg1.algorithmName === seg2.algorithmName;\n    }\n  }\n\n  return isEqual;\n}\n\n/**\n * Check if two segment objects are similar: either the\n * number or the displayValue are equal.\n *\n * @param {MaskSegment} seg1 The first segment.\n * @param {MaskSegment} seg2 The second segment.\n * @returns {boolean} True if both segment are similar.\n */\nexport function isSimilarSegment(seg1, seg2) {\n  // basics\n  if (typeof seg1 === 'undefined' ||\n    typeof seg2 === 'undefined' ||\n    seg1 === null ||\n    seg2 === null) {\n    return false;\n  }\n  let isSimilar = seg1.number === seg2.number;\n  // display value\n  if (typeof seg1.displayRGBValue !== 'undefined' &&\n    typeof seg2.displayRGBValue !== 'undefined') {\n    isSimilar = isSimilar ||\n      isEqualRgb(seg1.displayRGBValue, seg2.displayRGBValue);\n  } else if (typeof seg1.displayValue !== 'undefined' &&\n    typeof seg2.displayValue !== 'undefined') {\n    isSimilar = isSimilar ||\n      seg1.displayValue === seg2.displayValue;\n  } else {\n    isSimilar = false;\n  }\n\n  return isSimilar;\n}\n\n/**\n * Get a dicom simple tag from a segment object.\n *\n * @param {MaskSegment} segment The segment object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSegmentItem(segment) {\n  let algoType = segment.algorithmType;\n  if (algoType === undefined) {\n    algoType = 'MANUAL';\n  }\n  // dicom item (tags are in group/element order)\n  const segmentItem = {\n    SegmentNumber: segment.number,\n    SegmentLabel: segment.label,\n    SegmentAlgorithmType: algoType\n  };\n  // SegmentAlgorithmName\n  if (algoType !== 'MANUAL' && segment.algorithmName !== undefined) {\n    segmentItem.SegmentAlgorithmName = segment.algorithmName;\n  }\n  // RecommendedDisplay value\n  if (segment.displayRGBValue) {\n    const cieLab = labToUintLab(srgbToCielab(segment.displayRGBValue));\n    segmentItem.RecommendedDisplayCIELabValue = [\n      Math.round(cieLab.l),\n      Math.round(cieLab.a),\n      Math.round(cieLab.b)\n    ];\n  } else {\n    segmentItem.RecommendedDisplayGrayscaleValue = segment.displayValue;\n  }\n  // SegmentedPropertyCategoryCodeSequence\n  if (segment.propertyCategoryCode) {\n    segmentItem.SegmentedPropertyCategoryCodeSequence = {\n      value: [getDicomCodeItem(segment.propertyCategoryCode)]\n    };\n  }\n  // SegmentedPropertyTypeCodeSequence\n  if (segment.propertyTypeCode) {\n    segmentItem.SegmentedPropertyTypeCodeSequence = {\n      value: [getDicomCodeItem(segment.propertyTypeCode)]\n    };\n  }\n  // tracking\n  if (segment.trackingId) {\n    segmentItem.TrackingID = segment.trackingId;\n    segmentItem.TrackingUID = segment.trackingUid;\n  }\n  // return\n  return segmentItem;\n}\n","import {getSpacingFromMeasure} from './dicomElementsWrapper';\nimport {logger} from '../utils/logger';\nimport {arrayEquals} from '../utils/array';\nimport {\n  getDicomCodeItem,\n  getSegmentationCode,\n  getSourceImageForProcessingCode\n} from './dicomCode';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\nimport {Spacing} from '../image/spacing';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  DerivationImageSequence: '00089124',\n  SourceImageSequence: '00082112',\n  ReferencedSOPClassUID: '00081150',\n  ReferencedSOPInstanceUID: '00081155',\n  FrameContentSequence: '00209111',\n  DimensionIndexValue: '00209157',\n  SegmentIdentificationSequence: '0062000A',\n  ReferencedSegmentNumber: '0062000B',\n  PlanePositionSequence: '00209113',\n  ImagePosition: '00200032',\n  PlaneOrientationSequence: '00209116',\n  ImageOrientation: '00200037',\n  PixelMeasuresSequence: '00289110'\n};\n\n/**\n * DICOM segment frame info: item of a\n *  PerframeFunctionalGroupsSequence (5200,9230).\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.7.6.16.html}.\n */\nexport class DicomSegmentFrameInfo {\n  /**\n   * The dimension index.\n   *\n   * @type {number[]}\n   */\n  dimIndex;\n  /**\n   * The frame image position patient.\n   *\n   * @type {number[]}\n   */\n  imagePosPat;\n  /**\n   * List of derivation images.\n   *\n   * @type {Array}\n   */\n  derivationImages;\n  /**\n   * The reference segment number.\n   *\n   * @type {number}\n   */\n  refSegmentNumber;\n\n  /**\n   * The frame image orientation.\n   *\n   * @type {number[]|undefined}\n   */\n  imageOrientationPatient;\n  /**\n   * The frame spacing.\n   *\n   * @type {Spacing|undefined}\n   */\n  spacing;\n\n  /**\n   * @param {number[]} dimIndex The dimension index.\n   * @param {number[]} imagePosPat The frame image position patient.\n   * @param {Array} derivationImages List of derivation images.\n   * @param {number} refSegmentNumber The reference segment number.\n   */\n  constructor(dimIndex, imagePosPat, derivationImages, refSegmentNumber) {\n    this.dimIndex = dimIndex;\n    this.imagePosPat = imagePosPat;\n    this.derivationImages = derivationImages;\n    this.refSegmentNumber = refSegmentNumber;\n  }\n}\n\n/**\n * Get a frame information object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {DicomSegmentFrameInfo} A frame information object.\n */\nexport function getSegmentFrameInfo(dataElements) {\n  // Derivation Image Sequence\n  const derivationImages = [];\n  if (typeof dataElements[TagKeys.DerivationImageSequence] !== 'undefined') {\n    const derivationImageSq =\n      dataElements[TagKeys.DerivationImageSequence].value;\n    // Source Image Sequence\n    for (let i = 0; i < derivationImageSq.length; ++i) {\n      const sourceImages = [];\n      if (typeof derivationImageSq[i][TagKeys.SourceImageSequence] !==\n        'undefined') {\n        const sourceImageSq =\n          derivationImageSq[i][TagKeys.SourceImageSequence].value;\n        for (let j = 0; j < sourceImageSq.length; ++j) {\n          const sourceImage = {};\n          // Referenced SOP Class UID\n          if (typeof sourceImageSq[j][TagKeys.ReferencedSOPClassUID] !==\n            'undefined') {\n            sourceImage.referencedSOPClassUID =\n              sourceImageSq[j][TagKeys.ReferencedSOPClassUID].value[0];\n          }\n          // Referenced SOP Instance UID\n          if (typeof sourceImageSq[j][TagKeys.ReferencedSOPInstanceUID] !==\n            'undefined') {\n            sourceImage.referencedSOPInstanceUID =\n              sourceImageSq[j][TagKeys.ReferencedSOPInstanceUID].value[0];\n          }\n          sourceImages.push(sourceImage);\n        }\n      }\n      derivationImages.push({\n        sourceImages: sourceImages\n      });\n    }\n  }\n  // Frame Content Sequence (required, only one)\n  const frameContentSq = dataElements[TagKeys.FrameContentSequence].value;\n  // Dimension Index Value\n  const dimIndex = frameContentSq[0][TagKeys.DimensionIndexValue].value;\n  // Segment Identification Sequence (required, only one)\n  const segmentIdSq = dataElements[TagKeys.SegmentIdentificationSequence].value;\n  // Referenced Segment Number\n  const refSegmentNumber =\n    parseInt(segmentIdSq[0][TagKeys.ReferencedSegmentNumber].value[0], 0);\n  // Plane Position Sequence (required, only one)\n  const planePosSq = dataElements[TagKeys.PlanePositionSequence].value;\n  // Image Position (Patient) (conditionally required)\n  const imagePosPat = planePosSq[0][TagKeys.ImagePosition].value;\n  for (let p = 0; p < imagePosPat.length; ++p) {\n    imagePosPat[p] = parseFloat(imagePosPat[p]);\n  }\n  const frameInfo = new DicomSegmentFrameInfo(\n    dimIndex,\n    imagePosPat,\n    derivationImages,\n    refSegmentNumber\n  );\n  // Plane Orientation Sequence\n  if (typeof dataElements[TagKeys.PlaneOrientationSequence] !== 'undefined') {\n    const framePlaneOrientationSeq =\n      dataElements[TagKeys.PlaneOrientationSequence];\n    if (framePlaneOrientationSeq.value.length !== 0) {\n      // should only be one Image Orientation (Patient)\n      const frameImageOrientation =\n        framePlaneOrientationSeq.value[0][TagKeys.ImageOrientation].value;\n      if (typeof frameImageOrientation !== 'undefined') {\n        frameInfo.imageOrientationPatient = frameImageOrientation;\n      }\n    }\n  }\n  // Pixel Measures Sequence\n  if (typeof dataElements[TagKeys.PixelMeasuresSequence] !== 'undefined') {\n    const framePixelMeasuresSeq = dataElements[TagKeys.PixelMeasuresSequence];\n    if (framePixelMeasuresSeq.value.length !== 0) {\n      // should only be one\n      const frameSpacing =\n        getSpacingFromMeasure(framePixelMeasuresSeq.value[0]);\n      if (typeof frameSpacing !== 'undefined') {\n        frameInfo.spacing = frameSpacing;\n      }\n    } else {\n      logger.warn(\n        'No shared functional group pixel measure sequence items.');\n    }\n  }\n\n  return frameInfo;\n}\n\n/**\n * Check if two frame info objects are equal.\n *\n * @param {DicomSegmentFrameInfo} dsfi1 The first frame info.\n * @param {DicomSegmentFrameInfo} dsfi2 The second frame info.\n * @returns {boolean} True if both frame info are equal.\n */\nexport function isEqualSegmentFrameInfo(dsfi1, dsfi2) {\n  // basics\n  if (typeof dsfi1 === 'undefined' ||\n    typeof dsfi2 === 'undefined' ||\n    dsfi1 === null ||\n    dsfi2 === null) {\n    return false;\n  }\n  let isEqual =\n    arrayEquals(dsfi1.dimIndex, dsfi2.dimIndex) &&\n    arrayEquals(dsfi1.imagePosPat, dsfi2.imagePosPat) &&\n    dsfi1.refSegmentNumber === dsfi2.refSegmentNumber;\n\n  isEqual = isEqual &&\n    dsfi1.derivationImages.length === dsfi2.derivationImages.length;\n  for (let i = 0; i < dsfi1.derivationImages.length; ++i) {\n    const derivationImage1 = dsfi1.derivationImages[i];\n    const derivationImage2 = dsfi2.derivationImages[i];\n    isEqual = isEqual &&\n      derivationImage1.sourceImages.length ===\n        derivationImage2.sourceImages.length;\n    for (let j = 0; j < derivationImage1.length; ++j) {\n      const sourceImage1 = derivationImage1.sourceImages[j];\n      const sourceImage2 = derivationImage2.sourceImages[j];\n      isEqual = isEqual &&\n        sourceImage1.referencedSOPClassUID ===\n          sourceImage2.referencedSOPClassUID &&\n        sourceImage1.referencedSOPInstanceUID ===\n          sourceImage2.referencedSOPInstanceUID;\n    }\n  }\n\n  return isEqual;\n}\n\n/**\n * Get a dicom item from a frame information object.\n *\n * @param {object} frameInfo The frame information object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSegmentFrameInfoItem(frameInfo) {\n  const item = {\n    FrameContentSequence: {\n      value: [\n        {\n          DimensionIndexValues: frameInfo.dimIndex\n        }\n      ]\n    },\n    PlanePositionSequence: {\n      value: [\n        {\n          ImagePositionPatient: frameInfo.imagePosPat\n        }\n      ]\n    },\n    SegmentIdentificationSequence: {\n      value: [\n        {\n          ReferencedSegmentNumber: frameInfo.refSegmentNumber\n        }\n      ]\n    }\n  };\n  // optional DerivationImageSequence\n  if (frameInfo.derivationImages !== undefined) {\n    const sourceImgPurposeOfReferenceCode =\n      getDicomCodeItem(getSourceImageForProcessingCode());\n    const segDerivationCode =\n      getDicomCodeItem(getSegmentationCode());\n\n    const derivationImageItems = [];\n    for (const derivationImage of frameInfo.derivationImages) {\n      const sourceImages = [];\n      for (const sourceImage of derivationImage.sourceImages) {\n        sourceImages.push({\n          PurposeOfReferenceCodeSequence: {\n            value: [sourceImgPurposeOfReferenceCode]\n          },\n          ReferencedSOPClassUID: sourceImage.referencedSOPClassUID,\n          ReferencedSOPInstanceUID: sourceImage.referencedSOPInstanceUID\n        });\n      }\n\n      derivationImageItems.push({\n        DerivationCodeSequence: {\n          value: [segDerivationCode]\n        },\n        SourceImageSequence: {\n          value: sourceImages\n        }\n      });\n    }\n\n    item.DerivationImageSequence = {\n      value: derivationImageItems\n    };\n  }\n\n  return item;\n}\n","import {\n  dateToDateObj,\n  getDicomDate,\n  dateToTimeObj,\n  getDicomTime,\n} from '../dicom/dicomDate';\nimport {safeGet} from '../dicom/dataElement';\nimport {\n  getImage2DSize,\n  getSpacingFromMeasure,\n  getDimensionOrganization,\n  getDicomMeasureItem,\n  getDicomPlaneOrientationItem\n} from '../dicom/dicomElementsWrapper';\nimport {Tag} from '../dicom/dicomTag';\nimport {getElementsFromJSONTags} from '../dicom/dicomWriter';\nimport {\n  getSegment,\n  getDicomSegmentItem,\n} from '../dicom/dicomSegment';\nimport {\n  getSegmentFrameInfo,\n  getDicomSegmentFrameInfoItem\n} from '../dicom/dicomSegmentFrameInfo';\nimport {transferSyntaxKeywords} from '../dicom/dictionary';\nimport {Image} from '../image/image';\nimport {Geometry} from '../image/geometry';\nimport {Point, Point3D} from '../math/point';\nimport {Vector3D} from '../math/vector';\nimport {Index} from '../math/index';\nimport {Matrix33, REAL_WORLD_EPSILON} from '../math/matrix';\nimport {logger} from '../utils/logger';\nimport {arraySortEquals} from '../utils/array';\nimport {Size} from './size';\nimport {ColourMap} from './luts';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from '../dicom/dataElement';\nimport {MaskSegment} from '../dicom/dicomSegment';\n/* eslint-enable no-unused-vars */\n\n/**\n * @typedef {Object<string, DataElement>} DataElements\n */\n\n/**\n * Check two position patients for equality.\n *\n * @param {*} pos1 The first position patient.\n * @param {*} pos2 The second position patient.\n * @returns {boolean} True is equal.\n */\nfunction equalPosPat(pos1, pos2) {\n  return JSON.stringify(pos1) === JSON.stringify(pos2);\n}\n\n/**\n * @callback compareFn\n * @param {object} a The first object.\n * @param {object} b The first object.\n * @returns {number} >0 to sort a after b, <0 to sort a before b,\n *   0 to not change order.\n */\n\n/**\n * Get a position patient compare function accroding to an\n * input orientation.\n *\n * @param {Matrix33} orientation The orientation matrix.\n * @returns {compareFn} The position compare function.\n */\nfunction getComparePosPat(orientation) {\n  const invOrientation = orientation.getInverse();\n  return function (pos1, pos2) {\n    const p1 = invOrientation.multiplyArray3D(pos1);\n    const p2 = invOrientation.multiplyArray3D(pos2);\n    return p1[2] - p2[2];\n  };\n}\n\n/**\n * Merge two tag lists.\n *\n * @param {object} tags1 Base list, will be modified.\n * @param {object} tags2 List to merge.\n */\nfunction mergeTags(tags1, tags2) {\n  const keys2 = Object.keys(tags2);\n  for (const tagName2 of keys2) {\n    if (tags1[tagName2] !== undefined) {\n      logger.trace('Overwritting tag: ' + tagName2);\n    }\n    tags1[tagName2] = tags2[tagName2];\n  }\n}\n\n/**\n * Check that a DICOM tag definition is present in a parsed element.\n *\n * @param {DataElements} dataElements The root dicom element.\n * @param {object} tagDefinition The tag definition as {name, tag, type, enum}.\n */\nfunction checkTag(dataElements, tagDefinition) {\n  const element = dataElements[tagDefinition.tag];\n  // check null and undefined\n  if (tagDefinition.type === 1 || tagDefinition.type === 2) {\n    if (typeof element === 'undefined') {\n      throw new Error('Missing or empty ' + tagDefinition.name);\n    }\n  } else {\n    if (typeof element === 'undefined') {\n      // non mandatory value, exit\n      return;\n    }\n  }\n  let includes = false;\n  let tagValue;\n  if (element.value.length === 1) {\n    tagValue = element.value[0];\n  } else {\n    tagValue = element.value;\n  }\n  if (Array.isArray(tagValue)) {\n    for (let i = 0; i < tagDefinition.enum.length; ++i) {\n      if (!Array.isArray(tagDefinition.enum[i])) {\n        throw new Error('Cannot compare array and non array tag value.');\n      }\n      if (arraySortEquals(tagDefinition.enum[i], tagValue)) {\n        includes = true;\n        break;\n      }\n    }\n  } else {\n    includes = tagDefinition.enum.includes(tagValue);\n  }\n  if (!includes) {\n    throw new Error(\n      'Unsupported ' + tagDefinition.name + ' value: ' + tagValue);\n  }\n}\n\n/**\n * Create ROI slice buffers.\n *\n * @param {Image} image The mask image.\n * @param {MaskSegment[]} segments The mask segments.\n * @param {number} sliceOffset The slice offset.\n * @returns {object} The ROI slice image buffers.\n */\nfunction createRoiSliceBuffers(\n  image,\n  segments,\n  sliceOffset\n) {\n  // create binary mask buffers\n  const geometry = image.getGeometry();\n  const size = geometry.getSize();\n  const sliceSize = size.getDimSize(2);\n  const buffers = {};\n  for (let o = 0; o < sliceSize; ++o) {\n    const inputOffset = sliceOffset + o;\n    const pixelValue = image.getValueAtOffset(inputOffset);\n    for (const segment of segments) {\n      const segmentIndex = segment.number - 1;\n      if (pixelValue === segment.number) {\n        if (buffers[segmentIndex] === undefined) {\n          buffers[segmentIndex] = new Uint8Array(sliceSize);\n        }\n        buffers[segmentIndex][o] = 1;\n      }\n    }\n  }\n  return buffers;\n}\n\n/**\n * Create ROI buffers.\n *\n * @param {Image} image The mask image.\n * @param {MaskSegment[]} segments The mask segments.\n * @returns {object} The ROI buffers.\n */\nfunction createRoiBuffers(image, segments) {\n  const geometry = image.getGeometry();\n  const size = geometry.getSize();\n\n  // image buffer to multi frame\n  const sliceSize = size.getDimSize(2);\n  const roiBuffers = {};\n  for (let k = 0; k < size.get(2); ++k) {\n    const sliceOffset = k * sliceSize;\n    // create slice buffers\n    const buffers = createRoiSliceBuffers(image, segments, sliceOffset);\n    // store slice buffers\n    const keys0 = Object.keys(buffers);\n    for (const key0 of keys0) {\n      if (roiBuffers[key0] === undefined) {\n        roiBuffers[key0] = {};\n      }\n      // ordering by slice index (follows posPat)\n      roiBuffers[key0][k] = buffers[key0];\n    }\n  }\n  return roiBuffers;\n}\n\n/**\n * List of DICOM Seg required tags.\n */\nconst RequiredDicomSegTags = [\n  {\n    name: 'TransferSyntaxUID',\n    tag: '00020010',\n    type: '1',\n    enum: [\n      transferSyntaxKeywords.ImplicitVRLittleEndian,\n      transferSyntaxKeywords.ExplicitVRLittleEndian,\n      transferSyntaxKeywords.ExplicitVRBigEndian\n    ]\n  },\n  {\n    name: 'MediaStorageSOPClassUID',\n    tag: '00020002',\n    type: '1',\n    enum: ['1.2.840.10008.5.1.4.1.1.66.4']\n  },\n  {\n    name: 'SOPClassUID',\n    tag: '00020002',\n    type: '1',\n    enum: ['1.2.840.10008.5.1.4.1.1.66.4']\n  },\n  {\n    name: 'Modality',\n    tag: '00080060',\n    type: '1',\n    enum: ['SEG']\n  },\n  {\n    name: 'SegmentationType',\n    tag: '00620001',\n    type: '1',\n    enum: ['BINARY']\n  },\n  {\n    name: 'DimensionOrganizationType',\n    tag: '00209311',\n    type: '3',\n    enum: ['3D']\n  },\n  {\n    name: 'ImageType',\n    tag: '00080008',\n    type: '1',\n    enum: [['DERIVED', 'PRIMARY']]\n  },\n  {\n    name: 'SamplesPerPixel',\n    tag: '00280002',\n    type: '1',\n    enum: [1]\n  },\n  {\n    name: 'PhotometricInterpretation',\n    tag: '00280004',\n    type: '1',\n    enum: ['MONOCHROME2']\n  },\n  {\n    name: 'PixelRepresentation',\n    tag: '00280103',\n    type: '1',\n    enum: [0]\n  },\n  {\n    name: 'BitsAllocated',\n    tag: '00280100',\n    type: '1',\n    enum: [1]\n  },\n  {\n    name: 'BitsStored',\n    tag: '00280101',\n    type: '1',\n    enum: [1]\n  },\n  {\n    name: 'HighBit',\n    tag: '00280102',\n    type: '1',\n    enum: [0]\n  },\n];\n\n/**\n * Get the default DICOM seg tags as an object.\n *\n * @returns {object} The default tags.\n */\nexport function getDefaultDicomSegJson() {\n  const tags = {};\n  for (let i = 0; i < RequiredDicomSegTags.length; ++i) {\n    const reqTag = RequiredDicomSegTags[i];\n    tags[reqTag.name] = reqTag.enum[0];\n  }\n  return tags;\n}\n\n/**\n * Mask {@link Image} factory.\n */\nexport class MaskFactory {\n\n  /**\n   * Possible warning created by checkElements.\n   *\n   * @type {string|undefined}\n   */\n  #warning;\n\n  /**\n   * Get a warning string if elements are not as expected.\n   * Created by checkElements.\n   *\n   * @returns {string|undefined} The warning.\n   */\n  getWarning() {\n    return this.#warning;\n  }\n\n  /**\n   * Check dicom elements.\n   *\n   * @param {Object<string, DataElement>} _dicomElements The DICOM tags.\n   * @returns {string|undefined} A possible warning.\n   * @throws Error for missing or wrong data.\n   */\n  checkElements(_dicomElements) {\n    // does nothing\n    return;\n  }\n\n  /**\n   * Get an {@link Image} object from the read DICOM file.\n   *\n   * @param {Object<string, DataElement>} dataElements The DICOM tags.\n   * @param {Uint8Array | Int8Array |\n   *   Uint16Array | Int16Array |\n   *   Uint32Array | Int32Array} pixelBuffer The pixel buffer.\n   * @returns {Image} A new Image.\n   * @throws Error for missing or wrong data.\n   */\n  create(dataElements, pixelBuffer) {\n    // check required and supported tags\n    for (let d = 0; d < RequiredDicomSegTags.length; ++d) {\n      checkTag(dataElements, RequiredDicomSegTags[d]);\n    }\n\n    // image size\n    const size2D = getImage2DSize(dataElements);\n    const size = new Size([size2D[0], size2D[1], 1]);\n\n    const sliceSize = size.getTotalSize();\n\n    // frames\n    let frames = 1;\n    const framesElem = dataElements['00280008'];\n    if (typeof framesElem !== 'undefined') {\n      frames = parseInt(framesElem.value[0], 10);\n    }\n\n    if (frames !== pixelBuffer.length / sliceSize) {\n      throw new Error(\n        'Buffer and numberOfFrames meta are not equal.' +\n        frames + ' ' + pixelBuffer.length / sliceSize);\n    }\n\n    // Dimension Organization and Index\n    const dimension = getDimensionOrganization(dataElements);\n\n    // Segment Sequence\n    const segSequence = dataElements['00620002'];\n    if (typeof segSequence === 'undefined') {\n      throw new Error('Missing or empty segmentation sequence');\n    }\n    const segments = [];\n    // segment number is unique and starts at 1, use 0 as background\n    const redLut = [0];\n    const greenLut = [0];\n    const blueLut = [0];\n    for (let i = 0; i < segSequence.value.length; ++i) {\n      const segment = getSegment(segSequence.value[i]);\n      if (typeof segment.displayRGBValue !== 'undefined') {\n        // add palette colour\n        redLut[segment.number] = segment.displayRGBValue.r;\n        greenLut[segment.number] = segment.displayRGBValue.g;\n        blueLut[segment.number] = segment.displayRGBValue.b;\n      }\n      // store\n      segments.push(segment);\n    }\n\n    let hasDisplayRGBValue = false;\n    let paletteColourMap;\n    if (redLut.length > 1) {\n      hasDisplayRGBValue = true;\n      paletteColourMap = new ColourMap(redLut, greenLut, blueLut);\n    }\n\n    // Shared Functional Groups Sequence\n    let spacing;\n    let imageOrientationPatient;\n    const sharedFunctionalGroupsSeq = dataElements['52009229'];\n    if (typeof sharedFunctionalGroupsSeq !== 'undefined') {\n      // should be only one\n      const funcGroup0 = sharedFunctionalGroupsSeq.value[0];\n      // Plane Orientation Sequence\n      if (typeof funcGroup0['00209116'] !== 'undefined') {\n        const planeOrientationSeq = funcGroup0['00209116'];\n        if (planeOrientationSeq.value.length !== 0) {\n          // should be only one\n          imageOrientationPatient =\n            planeOrientationSeq.value[0]['00200037'].value;\n        } else {\n          logger.warn(\n            'No shared functional group plane orientation sequence items.');\n        }\n      }\n      // Pixel Measures Sequence\n      if (typeof funcGroup0['00289110'] !== 'undefined') {\n        const pixelMeasuresSeq = funcGroup0['00289110'];\n        if (pixelMeasuresSeq.value.length !== 0) {\n          // should be only one\n          spacing = getSpacingFromMeasure(pixelMeasuresSeq.value[0]);\n        } else {\n          logger.warn(\n            'No shared functional group pixel measure sequence items.');\n        }\n      }\n    }\n\n    const includesPosPat = function (arr, val) {\n      return arr.some(function (arrVal) {\n        return equalPosPat(val, arrVal);\n      });\n    };\n\n    const findIndexPosPat = function (arr, val) {\n      return arr.findIndex(function (arrVal) {\n        return equalPosPat(val, arrVal);\n      });\n    };\n\n    // Per-frame Functional Groups Sequence\n    const perFrameFuncGroupSequence = dataElements['52009230'];\n    if (typeof perFrameFuncGroupSequence === 'undefined') {\n      throw new Error('Missing or empty per frame functional sequence');\n    }\n    if (frames !== perFrameFuncGroupSequence.value.length) {\n      throw new Error(\n        'perFrameFuncGroupSequence meta and numberOfFrames are not equal.');\n    }\n    // create frame info object from per frame func\n    const frameInfos = [];\n    for (let j = 0; j < perFrameFuncGroupSequence.value.length; ++j) {\n      frameInfos.push(\n        getSegmentFrameInfo(perFrameFuncGroupSequence.value[j]));\n    }\n\n    // check frame infos\n    const framePosPats = [];\n    for (let ii = 0; ii < frameInfos.length; ++ii) {\n      if (!includesPosPat(framePosPats, frameInfos[ii].imagePosPat)) {\n        framePosPats.push(frameInfos[ii].imagePosPat);\n      }\n      // store orientation if needed, avoid multi\n      if (typeof frameInfos[ii].imageOrientationPatient !== 'undefined') {\n        if (typeof imageOrientationPatient === 'undefined') {\n          imageOrientationPatient = frameInfos[ii].imageOrientationPatient;\n        } else {\n          if (!arraySortEquals(\n            imageOrientationPatient, frameInfos[ii].imageOrientationPatient)) {\n            throw new Error('Unsupported multi orientation dicom seg.');\n          }\n        }\n      }\n      // store spacing if needed, avoid multi\n      if (typeof frameInfos[ii].spacing !== 'undefined') {\n        if (typeof spacing === 'undefined') {\n          spacing = frameInfos[ii].spacing;\n        } else {\n          if (!spacing.equals(frameInfos[ii].spacing)) {\n            throw new Error('Unsupported multi resolution dicom seg.');\n          }\n        }\n      }\n    }\n\n    // check spacing and orientation\n    if (typeof spacing === 'undefined') {\n      throw new Error('No spacing found for DICOM SEG');\n    }\n    if (spacing.length() !== 3) {\n      throw new Error('Incomplete spacing found for DICOM SEG');\n    }\n    if (typeof imageOrientationPatient === 'undefined') {\n      throw new Error('No imageOrientationPatient found for DICOM SEG');\n    }\n    if (imageOrientationPatient.length !== 6) {\n      throw new Error('Incomplete imageOrientationPatient found for DICOM SEG');\n    }\n\n    // orientation\n    const rowCosines = new Vector3D(\n      parseFloat(imageOrientationPatient[0]),\n      parseFloat(imageOrientationPatient[1]),\n      parseFloat(imageOrientationPatient[2]));\n    const colCosines = new Vector3D(\n      parseFloat(imageOrientationPatient[3]),\n      parseFloat(imageOrientationPatient[4]),\n      parseFloat(imageOrientationPatient[5]));\n    const normal = rowCosines.crossProduct(colCosines);\n    /* eslint-disable @stylistic/js/array-element-newline */\n    const orientationMatrix = new Matrix33([\n      rowCosines.getX(), colCosines.getX(), normal.getX(),\n      rowCosines.getY(), colCosines.getY(), normal.getY(),\n      rowCosines.getZ(), colCosines.getZ(), normal.getZ()\n    ]);\n    /* eslint-enable @stylistic/js/array-element-newline */\n\n    // sort positions patient\n    framePosPats.sort(getComparePosPat(orientationMatrix));\n\n    const point3DFromArray = function (arr) {\n      return new Point3D(arr[0], arr[1], arr[2]);\n    };\n\n    // frame origins\n    const frameOrigins = [];\n    for (let n = 0; n < framePosPats.length; ++n) {\n      frameOrigins.push(point3DFromArray(framePosPats[n]));\n    }\n\n    // tmp geometry with correct spacing but only one slice\n    const tmpGeometry = new Geometry(\n      [frameOrigins[0]], size, spacing, orientationMatrix);\n\n    // origin distance test\n    // TODO: maybe use sliceSpacing / 10\n    const isAboveEpsilon = function (value) {\n      let res = value > REAL_WORLD_EPSILON;\n      if (res) {\n        // try larger epsilon\n        res = value > REAL_WORLD_EPSILON * 10;\n        if (!res) {\n          // warn if epsilon < value < epsilon * 10\n          logger.warn(\n            'Using larger real world epsilon in SEG pos pat adding'\n          );\n        } else {\n          res = value > REAL_WORLD_EPSILON * 100;\n          if (!res) {\n            // warn if epsilon < value < epsilon * 100\n            logger.warn(\n              'Using larger+ real world epsilon in SEG pos pat adding'\n            );\n          }\n        }\n      }\n      return res;\n    };\n\n    // add possibly missing posPats\n    const posPats = [];\n    posPats.push(framePosPats[0]);\n    let sliceIndex = 0;\n    for (let g = 1; g < framePosPats.length; ++g) {\n      ++sliceIndex;\n      let index = new Index([0, 0, sliceIndex]);\n      let point = tmpGeometry.indexToWorld(index).get3D();\n      const frameOrigin = frameOrigins[g];\n      // check if more pos pats are needed\n      let dist = frameOrigin.getDistance(point);\n      const distPrevious = dist;\n      // TODO: good threshold?\n      while (isAboveEpsilon(dist)) {\n        logger.debug('Adding intermediate pos pats for DICOM seg at ' +\n          point.toString());\n        posPats.push([point.getX(), point.getY(), point.getZ()]);\n        ++sliceIndex;\n        index = new Index([0, 0, sliceIndex]);\n        point = tmpGeometry.indexToWorld(index).get3D();\n        dist = frameOrigin.getDistance(point);\n        if (dist > distPrevious) {\n          throw new Error(\n            'Test distance is increasing when adding intermediate pos pats');\n        }\n      }\n      // add frame pos pat\n      posPats.push(framePosPats[g]);\n    }\n\n    // as many slices as posPats\n    const numberOfSlices = posPats.length;\n\n    // final geometry\n    const geometry = new Geometry(\n      [frameOrigins[0]], size, spacing, orientationMatrix);\n    const uids = ['0'];\n    for (let m = 1; m < numberOfSlices; ++m) {\n      geometry.appendOrigin(point3DFromArray(posPats[m]), m);\n      uids.push(m.toString());\n    }\n\n    const getFindSegmentFunc = function (number) {\n      return function (item) {\n        return item.number === number;\n      };\n    };\n\n    // create output buffer\n    const buffer =\n      // @ts-ignore\n      new pixelBuffer.constructor(sliceSize * numberOfSlices);\n    buffer.fill(0);\n    // merge frame buffers\n    let sliceOffset = null;\n    let frameOffset = null;\n    for (let f = 0; f < frameInfos.length; ++f) {\n      // get the slice index from the position in the posPat array\n      sliceIndex = findIndexPosPat(posPats, frameInfos[f].imagePosPat);\n      frameOffset = sliceSize * f;\n      sliceOffset = sliceSize * sliceIndex;\n      // get the frame display value\n      const frameSegment = segments.find(\n        getFindSegmentFunc(frameInfos[f].refSegmentNumber)\n      );\n      for (let l = 0; l < sliceSize; ++l) {\n        if (pixelBuffer[frameOffset + l] !== 0) {\n          const offset = sliceOffset + l;\n          if (hasDisplayRGBValue) {\n            buffer[offset] = frameSegment.number;\n          } else {\n            buffer[offset] = frameSegment.displayValue;\n          }\n        }\n      }\n    }\n\n    // create image\n    const image = new Image(geometry, buffer, uids);\n    if (hasDisplayRGBValue) {\n      image.setPhotometricInterpretation('PALETTE COLOR');\n      image.setPaletteColourMap(paletteColourMap);\n    }\n    // meta information\n    const meta = getDefaultDicomSegJson();\n    const safeGetLocal = function (key) {\n      return safeGet(dataElements, key);\n    };\n    // Study\n    meta.StudyDate = safeGetLocal('00080020');\n    meta.StudyTime = safeGetLocal('00080030');\n    meta.StudyInstanceUID = safeGetLocal('0020000D');\n    meta.StudyID = safeGetLocal('00200010');\n    // Series\n    meta.SeriesDate = safeGetLocal('00080021');\n    meta.SeriesTime = safeGetLocal('00080031');\n    meta.SeriesInstanceUID = safeGetLocal('0020000E');\n    meta.SeriesNumber = safeGetLocal('00200011');\n    // ReferringPhysicianName\n    meta.ReferringPhysicianName = safeGetLocal('00080090');\n    // patient info\n    meta.PatientName = safeGetLocal('00100010');\n    meta.PatientID = safeGetLocal('00100020');\n    meta.PatientBirthDate = safeGetLocal('00100030');\n    meta.PatientSex = safeGetLocal('00100040');\n    // Enhanced General Equipment Module\n    meta.Manufacturer = safeGetLocal('00080070');\n    meta.ManufacturerModelName = safeGetLocal('00081090');\n    meta.DeviceSerialNumber = safeGetLocal('00181000');\n    meta.SoftwareVersions = safeGetLocal('00181020');\n    // dicom seg dimension\n    meta.DimensionOrganizationSequence = dimension.organizations;\n    meta.DimensionIndexSequence = dimension.indices;\n    // custom\n    meta.custom = {\n      segments: segments,\n      frameInfos: frameInfos,\n      SOPInstanceUID: dataElements['00080018'].value[0]\n    };\n\n    // number of files: in this case equal to number slices,\n    //   used to calculate buffer size\n    meta.numberOfFiles = numberOfSlices;\n    // FrameOfReferenceUID (optional)\n    const frameOfReferenceUID = dataElements['00200052'];\n    if (frameOfReferenceUID) {\n      meta.FrameOfReferenceUID = frameOfReferenceUID.value[0];\n    }\n    // LossyImageCompression (optional)\n    const lossyImageCompression = dataElements['00282110'];\n    if (lossyImageCompression) {\n      meta.LossyImageCompression = lossyImageCompression.value[0];\n    }\n\n    image.setMeta(meta);\n\n    return image;\n  }\n\n  /**\n   * Convert a mask image into a DICOM segmentation object.\n   *\n   * @param {Image} image The mask image.\n   * @param {MaskSegment[]} segments The mask segments.\n   * @param {Image} sourceImage The source image.\n   * @param {Object<string, any>} [extraTags] Optional list of extra tags.\n   * @returns {Object<string, DataElement>} A list of dicom elements.\n   */\n  toDicom(\n    image,\n    segments,\n    sourceImage,\n    extraTags\n  ) {\n    // original image tags\n    const tags = image.getMeta();\n\n    // use image segments if not provided as input\n    if (segments === undefined) {\n      segments = tags.segments;\n    }\n\n    const geometry = image.getGeometry();\n    const size = geometry.getSize();\n\n    // (not in meta)\n    tags.Rows = size.get(1);\n    tags.Columns = size.get(0);\n    // update content tags\n    const now = new Date();\n    tags.ContentDate = getDicomDate(dateToDateObj(now));\n    tags.ContentTime = getDicomTime(dateToTimeObj(now));\n\n    // keep source image StudyInstanceUID\n    if (sourceImage !== undefined) {\n      tags.StudyInstanceUID = (sourceImage.getMeta()).StudyInstanceUID;\n    }\n\n    // segments\n    const segmentItems = [];\n    for (const segment of segments) {\n      segmentItems.push(getDicomSegmentItem(segment));\n    }\n    tags.SegmentSequence = {\n      value: segmentItems\n    };\n\n    // Shared Functional Groups Sequence\n    tags.SharedFunctionalGroupsSequence = {\n      value: [\n        {\n          PlaneOrientationSequence: {\n            value: [getDicomPlaneOrientationItem(geometry.getOrientation())]\n          },\n          PixelMeasuresSequence: {\n            value: [getDicomMeasureItem(geometry.getSpacing())]\n          }\n        }\n      ]\n    };\n\n    // image buffer to multi frame\n    const roiBuffers = createRoiBuffers(image, segments);\n\n    const frameInfos = [];\n\n    // flatten buffer array\n    const finalBuffers = [];\n    const referencedSOPs = [];\n    for (const segment of segments) {\n      const number40 = segment.number;\n      const number4 = number40 - 1;\n      // check if buffer has values\n      if (roiBuffers[number4] === undefined) {\n        continue;\n      }\n      const keys1 = Object.keys(roiBuffers[number4]);\n      // revert slice order\n      for (let k1 = keys1.length - 1; k1 >= 0; --k1) {\n        const key1 = Number.parseInt(keys1[k1], 10);\n        finalBuffers.push(roiBuffers[number4][key1]);\n        // frame info\n        const posPat = image.getGeometry().getOrigins()[key1];\n        const posPatArray = [posPat.getX(), posPat.getY(), posPat.getZ()];\n        const frameInfo = {\n          dimIndex: [number40, keys1.length - k1],\n          imagePosPat: posPatArray,\n          refSegmentNumber: number40\n        };\n        // derivation image info\n        if (sourceImage !== undefined) {\n          const sourceGeometry = sourceImage.getGeometry();\n          const sourceIndex = sourceGeometry.worldToIndex(\n            new Point([posPat.getX(), posPat.getY(), posPat.getZ()])\n          );\n          frameInfo.derivationImages = [\n            {\n              sourceImages: [\n                {\n                  referencedSOPInstanceUID:\n                    sourceImage.getImageUid(sourceIndex),\n                  referencedSOPClassUID:\n                    (sourceImage.getMeta()).SOPClassUID\n                }\n              ]\n            }\n          ];\n          // store as tag\n          referencedSOPs.push({\n            ReferencedSOPInstanceUID:\n              sourceImage.getImageUid(sourceIndex),\n            ReferencedSOPClassUID:\n              (sourceImage.getMeta()).SOPClassUID\n          });\n        }\n        frameInfos.push(frameInfo);\n      }\n    }\n\n    tags.NumberOfFrames = finalBuffers.length.toString();\n\n    // frame infos\n    const frameInfosTag = [];\n    for (const frameInfo of frameInfos) {\n      frameInfosTag.push(getDicomSegmentFrameInfoItem(frameInfo));\n    }\n    tags.PerFrameFunctionalGroupsSequence = {\n      value: frameInfosTag\n    };\n\n    // also store referenced SOPs in ReferencedSeriesSequence\n    if (sourceImage !== undefined) {\n      const refSeriesTag = [];\n      refSeriesTag.push({\n        ReferencedInstanceSequence: {\n          value: referencedSOPs\n        },\n        SeriesInstanceUID: (sourceImage.getMeta()).SeriesInstanceUID\n      });\n      tags.ReferencedSeriesSequence = {\n        value: refSeriesTag\n      };\n    }\n\n    // merge extra tags if provided\n    if (extraTags !== undefined) {\n      mergeTags(tags, extraTags);\n    }\n\n    // convert JSON to DICOM element object\n    const dicomElements = getElementsFromJSONTags(tags);\n\n    // pixel value length: divide by 8 to trigger binary write\n    const sliceSize = size.getDimSize(2);\n    const pixVl = (finalBuffers.length * sliceSize) / 8;\n    const de = new DataElement('OB');\n    de.tag = new Tag('7FE0', '0010');\n    de.vl = pixVl;\n    de.value = finalBuffers;\n    dicomElements['7FE00010'] = de;\n\n    return dicomElements;\n  }\n\n} // class MaskFactory\n","import {Index} from '../math/index';\nimport {Point3D} from '../math/point';\nimport {logger} from '../utils/logger';\nimport {arrayContains} from '../utils/array';\nimport {getTypedArray} from '../dicom/dicomParser';\nimport {ListenerHandler} from '../utils/listen';\nimport {valueRange} from './iterator';\nimport {RescaleSlopeAndIntercept} from './rsi';\nimport {ImageFactory} from './imageFactory';\nimport {MaskFactory} from './maskFactory';\nimport {isMonochrome} from '../dicom/dicomElementsWrapper';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Geometry} from './geometry';\nimport {Matrix33} from '../math/matrix';\nimport {NumberRange} from '../math/stats';\nimport {DataElement} from '../dicom/dataElement';\nimport {RGB} from '../utils/colour';\nimport {ColourMap} from './luts';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get the slice index of an input slice into a volume geometry.\n *\n * @param {Geometry} volumeGeometry The volume geometry.\n * @param {Geometry} sliceGeometry The slice geometry.\n * @returns {Index} The index of the slice in the volume geomtry.\n */\nfunction getSliceIndex(volumeGeometry, sliceGeometry) {\n  // possible time\n  const timeId = sliceGeometry.getInitialTime();\n  // index values\n  const values = [];\n  // x, y\n  values.push(0);\n  values.push(0);\n  // z\n  values.push(volumeGeometry.getSliceIndex(sliceGeometry.getOrigin(), timeId));\n  // time\n  if (typeof timeId !== 'undefined') {\n    values.push(timeId);\n  }\n  // return index\n  return new Index(values);\n}\n\n/**\n * Create an Image from DICOM elements.\n *\n * @param {Object<string, DataElement>} elements The DICOM elements.\n * @returns {Image} The Image object.\n */\nexport function createImage(elements) {\n  const factory = new ImageFactory();\n  return factory.create(\n    elements,\n    elements['7FE00010'].value[0],\n    1\n  );\n}\n\n/**\n * Create a mask Image from DICOM elements.\n *\n * @param {Object<string, DataElement>} elements The DICOM elements.\n * @returns {Image} The mask Image object.\n */\nexport function createMaskImage(elements) {\n  const factory = new MaskFactory();\n  return factory.create(\n    elements,\n    elements['7FE00010'].value[0]\n  );\n}\n\n/**\n * Image class.\n * Usable once created, optional are:\n * - rescale slope and intercept (default 1:0),\n * - photometric interpretation (default MONOCHROME2),\n * - planar configuration (default RGBRGB...).\n *\n * @example\n * // XMLHttpRequest onload callback\n * const onload = function (event) {\n *   // parse the dicom buffer\n *   const dicomParser = new dwv.DicomParser();\n *   dicomParser.parse(event.target.response);\n *   // create the image object\n *   const image = dwv.createImage(dicomParser.getDicomElements());\n *   // result div\n *   const div = document.getElementById('dwv');\n *   // display the image size\n *   const size = image.getGeometry().getSize();\n *   div.appendChild(document.createTextNode(\n *     'Size: ' + size.toString() +\n *     ' (should be 256,256,1)'));\n *   // break line\n *   div.appendChild(document.createElement('br'));\n *   // display a pixel value\n *   div.appendChild(document.createTextNode(\n *     'Pixel @ [128,40,0]: ' +\n *     image.getRescaledValue(128,40,0) +\n *     ' (should be 101)'));\n * };\n * // DICOM file request\n * const request = new XMLHttpRequest();\n * const url = 'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm';\n * request.open('GET', url);\n * request.responseType = 'arraybuffer';\n * request.onload = onload;\n * request.send();\n */\nexport class Image {\n\n  /**\n   * Data geometry.\n   *\n   * @type {Geometry}\n   */\n  #geometry;\n\n  /**\n   * List of compatible typed arrays.\n   *\n   * @typedef {(\n   *   Uint8Array | Int8Array |\n   *   Uint16Array | Int16Array |\n   *   Uint32Array | Int32Array\n   * )} TypedArray\n   */\n\n  /**\n   * Data buffer.\n   *\n   * @type {TypedArray}\n   */\n  #buffer;\n\n  /**\n   * Image UIDs.\n   *\n   * @type {string[]}\n   */\n  #imageUids;\n\n  /**\n   * Constant rescale slope and intercept (default).\n   *\n   * @type {RescaleSlopeAndIntercept}\n   */\n  #rsi = new RescaleSlopeAndIntercept(1, 0);\n\n  /**\n   * Varying rescale slope and intercept.\n   *\n   * @type {RescaleSlopeAndIntercept[]}\n   */\n  #rsis = null;\n\n  /**\n   * Flag to know if the RSIs are all identity (1,0).\n   *\n   * @type {boolean}\n   */\n  #isIdentityRSI = true;\n\n  /**\n   * Flag to know if the RSIs are all equals.\n   *\n   * @type {boolean}\n   */\n  #isConstantRSI = true;\n\n  /**\n   * Photometric interpretation (MONOCHROME, RGB...).\n   *\n   * @type {string}\n   */\n  #photometricInterpretation = 'MONOCHROME2';\n\n  /**\n   * Palette colour map.\n   *\n   * @type {ColourMap}\n   */\n  #paletteColourMap;\n\n  /**\n   * Planar configuration for RGB data (`0:RGBRGBRGBRGB...` or\n   *   `1:RRR...GGG...BBB...`).\n   *\n   * @type {number}\n   */\n  #planarConfiguration = 0;\n\n  /**\n   * Number of components.\n   *\n   * @type {number}\n   */\n  #numberOfComponents;\n\n  /**\n   * Meta information.\n   *\n   * @type {Object<string, any>}\n   */\n  #meta = {};\n\n  /**\n   * Data range.\n   *\n   * @type {NumberRange}\n   */\n  #dataRange = null;\n\n  /**\n   * Rescaled data range.\n   *\n   * @type {NumberRange}\n   */\n  #rescaledDataRange = null;\n\n  /**\n   * Histogram.\n   *\n   * @type {Array}\n   */\n  #histogram = null;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * @param {Geometry} geometry The geometry of the image.\n   * @param {TypedArray} buffer The image data as a one dimensional buffer.\n   * @param {string[]} [imageUids] An array of Uids indexed to slice number.\n   */\n  constructor(geometry, buffer, imageUids) {\n    this.#geometry = geometry;\n    this.#buffer = buffer;\n    this.#imageUids = imageUids;\n\n    this.#numberOfComponents = this.#buffer.length / (\n      this.#geometry.getSize().getTotalSize());\n  }\n\n  /**\n   * Get the image UID at a given index.\n   *\n   * @param {Index} [index] The index at which to get the id.\n   * @returns {string} The UID.\n   */\n  getImageUid(index) {\n    let uid = this.#imageUids[0];\n    if (this.#imageUids.length !== 1 && typeof index !== 'undefined') {\n      uid = this.#imageUids[this.getSecondaryOffset(index)];\n    }\n    return uid;\n  }\n\n  /**\n   * Get the image origin for a image UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {Point3D|undefined} The origin.\n   */\n  getOriginForImageUid(uid) {\n    let origin;\n    const uidIndex = this.#imageUids.indexOf(uid);\n    if (uidIndex !== -1) {\n      const origins = this.getGeometry().getOrigins();\n      origin = origins[uidIndex];\n    }\n    return origin;\n  }\n\n  /**\n   * Check if the image includes an UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {boolean} True if present.\n   */\n  includesImageUid(uid) {\n    return this.#imageUids.includes(uid);\n  }\n\n  /**\n   * Check if this image includes the input uids.\n   *\n   * @param {string[]} uids UIDs to test for presence.\n   * @returns {boolean} True if all uids are in this image uids.\n   */\n  containsImageUids(uids) {\n    return arrayContains(this.#imageUids, uids);\n  }\n\n  /**\n   * Get the geometry of the image.\n   *\n   * @returns {Geometry} The geometry.\n   */\n  getGeometry() {\n    return this.#geometry;\n  }\n\n  /**\n   * Get the data buffer of the image.\n   *\n   * @todo Dangerous...\n   * @returns {TypedArray} The data buffer of the image.\n   */\n  getBuffer() {\n    return this.#buffer;\n  }\n\n  /**\n   * Can the image values be quantified?\n   *\n   * @returns {boolean} True if only one component.\n   */\n  canQuantify() {\n    return this.getNumberOfComponents() === 1;\n  }\n\n  /**\n   * Can window and level be applied to the data?\n   *\n   * @returns {boolean} True if the data is monochrome.\n   * @deprecated Since v0.33, please use isMonochrome instead.\n   */\n  canWindowLevel() {\n    return this.isMonochrome();\n  }\n\n  /**\n   * Is the data monochrome.\n   *\n   * @returns {boolean} True if the data is monochrome.\n   */\n  isMonochrome() {\n    return isMonochrome(this.getPhotometricInterpretation());\n  }\n\n  /**\n   * Can the data be scrolled?\n   *\n   * @param {Matrix33} viewOrientation The view orientation.\n   * @returns {boolean} True if the data has a third dimension greater than one\n   *   after applying the view orientation.\n   */\n  canScroll(viewOrientation) {\n    const size = this.getGeometry().getSize();\n    // also check the numberOfFiles in case we are in the middle of a load\n    let nFiles = 1;\n    if (typeof this.#meta.numberOfFiles !== 'undefined') {\n      nFiles = this.#meta.numberOfFiles;\n    }\n    return size.canScroll(viewOrientation) || nFiles !== 1;\n  }\n\n  /**\n   * Get the secondary offset max.\n   *\n   * @returns {number} The maximum offset.\n   */\n  #getSecondaryOffsetMax() {\n    return this.#geometry.getSize().getTotalSize(2);\n  }\n\n  /**\n   * Get the secondary offset: an offset that takes into account\n   *   the slice and above dimension numbers.\n   *\n   * @param {Index} index The index.\n   * @returns {number} The offset.\n   */\n  getSecondaryOffset(index) {\n    return this.#geometry.getSize().indexToOffset(index, 2);\n  }\n\n  /**\n   * Get the rescale slope and intercept.\n   *\n   * @param {Index} [index] The index (only needed for non constant rsi).\n   * @returns {RescaleSlopeAndIntercept} The rescale slope and intercept.\n   */\n  getRescaleSlopeAndIntercept(index) {\n    let res = this.#rsi;\n    if (!this.isConstantRSI()) {\n      if (typeof index === 'undefined') {\n        throw new Error('Cannot get non constant RSI with empty slice index.');\n      }\n      const offset = this.getSecondaryOffset(index);\n      if (typeof this.#rsis[offset] !== 'undefined') {\n        res = this.#rsis[offset];\n      } else {\n        logger.warn('undefined non constant rsi at ' + offset);\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Get the rsi at a specified (secondary) offset.\n   *\n   * @param {number} offset The desired (secondary) offset.\n   * @returns {RescaleSlopeAndIntercept} The coresponding rsi.\n   */\n  #getRescaleSlopeAndInterceptAtOffset(offset) {\n    return this.#rsis[offset];\n  }\n\n  /**\n   * Set the rescale slope and intercept.\n   *\n   * @param {RescaleSlopeAndIntercept} inRsi The input rescale\n   *   slope and intercept.\n   * @param {number} [offset] The rsi offset (only needed for non constant rsi).\n   */\n  setRescaleSlopeAndIntercept(inRsi, offset) {\n    // update identity flag\n    this.#isIdentityRSI = this.#isIdentityRSI && inRsi.isID();\n    // update constant flag\n    if (!this.#isConstantRSI) {\n      if (typeof offset === 'undefined') {\n        throw new Error(\n          'Cannot store non constant RSI with empty slice index.');\n      }\n      this.#rsis.splice(offset, 0, inRsi);\n    } else {\n      if (!this.#rsi.equals(inRsi)) {\n        if (typeof offset === 'undefined') {\n          // no slice index, replace existing\n          this.#rsi = inRsi;\n        } else {\n          // first non constant rsi\n          this.#isConstantRSI = false;\n          // switch to non constant mode\n          this.#rsis = [];\n          // initialise RSIs\n          for (let i = 0, leni = this.#getSecondaryOffsetMax(); i < leni; ++i) {\n            this.#rsis.push(this.#rsi);\n          }\n          // store\n          this.#rsi = null;\n          this.#rsis.splice(offset, 0, inRsi);\n        }\n      }\n    }\n  }\n\n  /**\n   * Are all the RSIs identity (1,0).\n   *\n   * @returns {boolean} True if they are.\n   */\n  isIdentityRSI() {\n    return this.#isIdentityRSI;\n  }\n\n  /**\n   * Are all the RSIs equal.\n   *\n   * @returns {boolean} True if they are.\n   */\n  isConstantRSI() {\n    return this.#isConstantRSI;\n  }\n\n  /**\n   * Get the photometricInterpretation of the image.\n   *\n   * @returns {string} The photometricInterpretation of the image.\n   */\n  getPhotometricInterpretation() {\n    return this.#photometricInterpretation;\n  }\n\n  /**\n   * Set the photometricInterpretation of the image.\n   *\n   * @param {string} interp The photometricInterpretation of the image.\n   */\n  setPhotometricInterpretation(interp) {\n    this.#photometricInterpretation = interp;\n  }\n\n  /**\n   * Set the palette colour map.\n   *\n   * @param {ColourMap} map The colour map.\n   */\n  setPaletteColourMap(map) {\n    this.#paletteColourMap = map;\n    // fire imagecontentchange\n    this.#fireEvent({type: 'imagecontentchange'});\n  }\n\n  /**\n   * Get the palette colour map.\n   *\n   * @returns {ColourMap} The colour map.\n   */\n  getPaletteColourMap() {\n    return this.#paletteColourMap;\n  }\n\n  /**\n   * Update the palette colour map.\n   *\n   * @param {number} index The index to change the colour of.\n   * @param {RGB} colour The colour to use at index.\n   */\n  updatePaletteColourMap(index, colour) {\n    this.#paletteColourMap.red[index] = colour.r;\n    this.#paletteColourMap.green[index] = colour.g;\n    this.#paletteColourMap.blue[index] = colour.b;\n    // fire imagecontentchange\n    this.#fireEvent({type: 'imagecontentchange'});\n  }\n\n  /**\n   * Get the planarConfiguration of the image.\n   *\n   * @returns {number} The planarConfiguration of the image.\n   */\n  getPlanarConfiguration() {\n    return this.#planarConfiguration;\n  }\n\n  /**\n   * Set the planarConfiguration of the image.\n   *\n   * @param {number} config The planarConfiguration of the image.\n   */\n  setPlanarConfiguration(config) {\n    this.#planarConfiguration = config;\n  }\n\n  /**\n   * Get the numberOfComponents of the image.\n   *\n   * @returns {number} The numberOfComponents of the image.\n   */\n  getNumberOfComponents() {\n    return this.#numberOfComponents;\n  }\n\n  /**\n   * Get the meta information of the image.\n   *\n   * @returns {Object<string, any>} The meta information of the image.\n   */\n  getMeta() {\n    return this.#meta;\n  }\n\n  /**\n   * Set the meta information of the image.\n   *\n   * @param {Object<string, any>} rhs The meta information of the image.\n   */\n  setMeta(rhs) {\n    this.#meta = rhs;\n  }\n\n  /**\n   * Get value at offset. Warning: No size check...\n   *\n   * @param {number} offset The desired offset.\n   * @returns {number} The value at offset.\n   */\n  getValueAtOffset(offset) {\n    return this.#buffer[offset];\n  }\n\n  /**\n   * Get the offsets where the buffer equals the input value.\n   * Loops through the whole volume, can get long for big data...\n   *\n   * @param {number|RGB} value The value to check.\n   * @returns {number[]} The list of offsets.\n   */\n  getOffsets(value) {\n    // value to array\n    let bufferValue;\n    if (typeof value === 'number') {\n      if (this.#numberOfComponents !== 1) {\n        throw new Error(\n          'Number of components is not 1 for getting single value.');\n      }\n      bufferValue = [value];\n    } else if (typeof value.r !== 'undefined' &&\n      typeof value.g !== 'undefined' &&\n      typeof value.b !== 'undefined') {\n      if (this.#numberOfComponents !== 3) {\n        throw new Error(\n          'Number of components is not 3 for getting RGB value.');\n      }\n      bufferValue = [value.r, value.g, value.b];\n    }\n\n    // main loop\n    const offsets = [];\n    let equal;\n    for (let i = 0; i < this.#buffer.length; i = i + this.#numberOfComponents) {\n      equal = true;\n      for (let j = 0; j < this.#numberOfComponents; ++j) {\n        if (this.#buffer[i + j] !== bufferValue[j]) {\n          equal = false;\n          break;\n        }\n      }\n      if (equal) {\n        offsets.push(i);\n      }\n    }\n    return offsets;\n  }\n\n  /**\n   * Check if the input values are in the buffer.\n   * Could loop through the whole volume, can get long for big data...\n   *\n   * @param {Array} values The values to check.\n   * @returns {boolean[]} A list of booleans for each input value,\n   *   set to true if the value is present in the buffer.\n   */\n  hasValues(values) {\n    // check input\n    if (typeof values === 'undefined' ||\n      values.length === 0) {\n      return [];\n    }\n    // final array value\n    const finalValues = [];\n    for (let v1 = 0; v1 < values.length; ++v1) {\n      if (this.#numberOfComponents === 1) {\n        finalValues.push([values[v1]]);\n      } else if (this.#numberOfComponents === 3) {\n        finalValues.push([\n          values[v1].r,\n          values[v1].g,\n          values[v1].b\n        ]);\n      }\n    }\n    // find callback\n    let equalFunc;\n    if (this.#numberOfComponents === 1) {\n      equalFunc = function (a, b) {\n        return a[0] === b[0];\n      };\n    } else if (this.#numberOfComponents === 3) {\n      equalFunc = function (a, b) {\n        return a[0] === b[0] &&\n          a[1] === b[1] &&\n          a[2] === b[2];\n      };\n    }\n    const getEqualCallback = function (value) {\n      return function (item) {\n        return equalFunc(item, value);\n      };\n    };\n    // main loop\n    const res = new Array(values.length);\n    res.fill(false);\n    const valuesToFind = finalValues.slice();\n    let equal;\n    let indicesToRemove;\n    for (let i = 0, leni = this.#buffer.length;\n      i < leni; i = i + this.#numberOfComponents) {\n      indicesToRemove = [];\n      for (let v = 0; v < valuesToFind.length; ++v) {\n        equal = true;\n        // check value(s)\n        for (let j = 0; j < this.#numberOfComponents; ++j) {\n          if (this.#buffer[i + j] !== valuesToFind[v][j]) {\n            equal = false;\n            break;\n          }\n        }\n        // if found, store answer and add to indices to remove\n        if (equal) {\n          const valIndex = finalValues.findIndex(\n            getEqualCallback(valuesToFind[v]));\n          res[valIndex] = true;\n          indicesToRemove.push(v);\n        }\n      }\n      // remove found values\n      for (let r = 0; r < indicesToRemove.length; ++r) {\n        valuesToFind.splice(indicesToRemove[r], 1);\n      }\n      // exit if no values to find\n      if (valuesToFind.length === 0) {\n        break;\n      }\n    }\n    // return\n    return res;\n  }\n\n  /**\n   * Clone the image.\n   *\n   * @returns {Image} A clone of this image.\n   */\n  clone() {\n    // clone the image buffer\n    const clonedBuffer = this.#buffer.slice(0);\n    // create the image copy\n    const copy = new Image(this.getGeometry(), clonedBuffer, this.#imageUids);\n    // copy the RSI(s)\n    if (this.isConstantRSI()) {\n      copy.setRescaleSlopeAndIntercept(this.getRescaleSlopeAndIntercept());\n    } else {\n      for (let i = 0; i < this.#getSecondaryOffsetMax(); ++i) {\n        copy.setRescaleSlopeAndIntercept(\n          this.#getRescaleSlopeAndInterceptAtOffset(i), i);\n      }\n    }\n    // copy extras\n    copy.setPhotometricInterpretation(this.getPhotometricInterpretation());\n    copy.setPlanarConfiguration(this.getPlanarConfiguration());\n    copy.setMeta(this.getMeta());\n    // return\n    return copy;\n  }\n\n  /**\n   * Re-allocate buffer memory to an input size.\n   *\n   * @param {number} size The new size.\n   */\n  #realloc(size) {\n    // save buffer\n    let tmpBuffer = this.#buffer;\n    // create new\n    this.#buffer = getTypedArray(\n      this.#buffer.BYTES_PER_ELEMENT * 8,\n      this.#meta.IsSigned ? 1 : 0,\n      size);\n    if (this.#buffer === null) {\n      throw new Error('Cannot reallocate data for image.');\n    }\n    // put old in new\n    this.#buffer.set(tmpBuffer);\n    // clean\n    tmpBuffer = null;\n  }\n\n  /**\n   * Append a slice to the image.\n   *\n   * @param {Image} rhs The slice to append.\n   * @fires Image#imagegeometrychange\n   */\n  appendSlice(rhs) {\n    // check input\n    if (rhs === null) {\n      throw new Error('Cannot append null slice');\n    }\n    const rhsSize = rhs.getGeometry().getSize();\n    let size = this.#geometry.getSize();\n    if (rhsSize.get(2) !== 1) {\n      throw new Error('Cannot append more than one slice');\n    }\n    if (size.get(0) !== rhsSize.get(0)) {\n      throw new Error('Cannot append a slice with different number of columns');\n    }\n    if (size.get(1) !== rhsSize.get(1)) {\n      throw new Error('Cannot append a slice with different number of rows');\n    }\n    if (!this.#geometry.getOrientation().equals(\n      rhs.getGeometry().getOrientation(), 0.0001)) {\n      throw new Error('Cannot append a slice with different orientation');\n    }\n    if (this.#photometricInterpretation !==\n      rhs.getPhotometricInterpretation()) {\n      throw new Error(\n        'Cannot append a slice with different photometric interpretation');\n    }\n    // all meta should be equal\n    for (const key in this.#meta) {\n      if (key === 'windowPresets' || key === 'numberOfFiles' ||\n        key === 'custom') {\n        continue;\n      }\n      if (this.#meta[key] !== rhs.getMeta()[key]) {\n        throw new Error('Cannot append a slice with different ' + key +\n          ': ' + this.#meta[key] + ' != ' + rhs.getMeta()[key]);\n      }\n    }\n\n    // update ranges\n    const rhsRange = rhs.getDataRange();\n    const range = this.getDataRange();\n    this.#dataRange = {\n      min: Math.min(rhsRange.min, range.min),\n      max: Math.max(rhsRange.max, range.max),\n    };\n    const rhsResRange = rhs.getRescaledDataRange();\n    const resRange = this.getRescaledDataRange();\n    this.#rescaledDataRange = {\n      min: Math.min(rhsResRange.min, resRange.min),\n      max: Math.max(rhsResRange.max, resRange.max),\n    };\n\n    // possible time\n    const timeId = rhs.getGeometry().getInitialTime();\n\n    // append frame if needed\n    let isNewFrame = false;\n    if (typeof timeId !== 'undefined' &&\n      !this.#geometry.hasSlicesAtTime(timeId)) {\n      // update grometry\n      this.appendFrame(timeId, rhs.getGeometry().getOrigin());\n      // update size\n      size = this.#geometry.getSize();\n      // update flag\n      isNewFrame = true;\n    }\n\n    // get slice index\n    const index = getSliceIndex(this.#geometry, rhs.getGeometry());\n\n    // calculate slice size\n    const sliceSize = this.#numberOfComponents * size.getDimSize(2);\n\n    // create full buffer if not done yet\n    if (typeof this.#meta.numberOfFiles === 'undefined') {\n      throw new Error('Missing number of files for buffer manipulation.');\n    }\n    const fullBufferSize = sliceSize * this.#meta.numberOfFiles;\n    if (this.#buffer.length !== fullBufferSize) {\n      this.#realloc(fullBufferSize);\n    }\n\n    // slice index\n    const sliceIndex = index.get(2);\n\n    // slice index including possible 4D\n    let fullSliceIndex = sliceIndex;\n    if (typeof timeId !== 'undefined') {\n      fullSliceIndex +=\n        this.#geometry.getCurrentNumberOfSlicesBeforeTime(timeId);\n    }\n    // offset of the input slice\n    const indexOffset = fullSliceIndex * sliceSize;\n    const maxOffset =\n      this.#geometry.getCurrentTotalNumberOfSlices() * sliceSize;\n    // move content if needed\n    if (indexOffset < maxOffset) {\n      this.#buffer.set(\n        this.#buffer.subarray(indexOffset, maxOffset),\n        indexOffset + sliceSize\n      );\n    }\n    // add new slice content\n    this.#buffer.set(rhs.getBuffer(), indexOffset);\n\n    // update geometry\n    if (!isNewFrame) {\n      this.#geometry.appendOrigin(\n        rhs.getGeometry().getOrigin(), sliceIndex, timeId);\n    }\n    // update rsi\n    // (rhs should just have one rsi)\n    this.setRescaleSlopeAndIntercept(\n      rhs.getRescaleSlopeAndIntercept(), fullSliceIndex);\n\n    // current number of images\n    const numberOfImages = this.#imageUids.length;\n\n    // insert sop instance UIDs\n    this.#imageUids.splice(fullSliceIndex, 0, rhs.getImageUid());\n\n    // update window presets\n    if (typeof this.#meta.windowPresets !== 'undefined') {\n      const windowPresets = this.#meta.windowPresets;\n      const rhsPresets = rhs.getMeta().windowPresets;\n      const keys = Object.keys(rhsPresets);\n      let pkey = null;\n      for (let i = 0; i < keys.length; ++i) {\n        pkey = keys[i];\n        const rhsPreset = rhsPresets[pkey];\n        const windowPreset = windowPresets[pkey];\n        if (typeof windowPreset !== 'undefined') {\n          // if not set or false, check perslice\n          if (typeof windowPreset.perslice === 'undefined' ||\n            windowPreset.perslice === false) {\n            // if different preset.wl, mark it as perslice\n            if (!windowPreset.wl[0].equals(rhsPreset.wl[0])) {\n              windowPreset.perslice = true;\n              // fill wl array with copy of wl[0]\n              // (loop on number of images minus the existing one)\n              for (let j = 0; j < numberOfImages - 1; ++j) {\n                windowPreset.wl.push(windowPreset.wl[0]);\n              }\n            }\n          }\n          // store (first) rhs preset.wl if needed\n          if (typeof windowPreset.perslice !== 'undefined' &&\n            windowPreset.perslice === true) {\n            windowPresets[pkey].wl.splice(\n              fullSliceIndex, 0, rhsPreset.wl[0]);\n          }\n        } else {\n          // if not defined (it should be), store all\n          windowPresets[pkey] = rhsPresets[pkey];\n        }\n      }\n    }\n    /**\n     * Image geometry change event.\n     *\n     * @event Image#imagegeometrychange\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    this.#fireEvent({\n      type: 'imagegeometrychange'\n    });\n  }\n\n  /**\n   * Append a frame buffer to the image.\n   *\n   * @param {object} frameBuffer The frame buffer to append.\n   * @param {number} frameIndex The frame index.\n   */\n  appendFrameBuffer(frameBuffer, frameIndex) {\n    // create full buffer if not done yet\n    const size = this.#geometry.getSize();\n    const frameSize = this.#numberOfComponents * size.getDimSize(2);\n    if (typeof this.#meta.numberOfFiles === 'undefined') {\n      throw new Error('Missing number of files for frame buffer manipulation.');\n    }\n    const fullBufferSize = frameSize * this.#meta.numberOfFiles;\n    if (this.#buffer.length !== fullBufferSize) {\n      this.#realloc(fullBufferSize);\n    }\n    // check index\n    if (frameIndex >= this.#meta.numberOfFiles) {\n      logger.warn('Ignoring frame at index ' + frameIndex +\n        ' (size: ' + this.#meta.numberOfFiles + ')');\n      return;\n    }\n    // append\n    this.#buffer.set(frameBuffer, frameSize * frameIndex);\n    // update geometry\n    this.appendFrame(frameIndex, new Point3D(0, 0, 0));\n  }\n\n  /**\n   * Append a frame to the image.\n   *\n   * @param {number} time The frame time value.\n   * @param {Point3D} origin The origin of the frame.\n   */\n  appendFrame(time, origin) {\n    this.#geometry.appendFrame(origin, time);\n    /**\n     * Append frame event.\n     *\n     * @event Image#appendframe\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    this.#fireEvent({\n      type: 'appendframe'\n    });\n    // memory will be updated at the first appendSlice or appendFrameBuffer\n  }\n\n  /**\n   * Get the data range.\n   *\n   * @returns {NumberRange} The data range.\n   */\n  getDataRange() {\n    if (!this.#dataRange) {\n      this.#dataRange = this.calculateDataRange();\n    }\n    return this.#dataRange;\n  }\n\n  /**\n   * Get the rescaled data range.\n   *\n   * @returns {NumberRange} The rescaled data range.\n   */\n  getRescaledDataRange() {\n    if (!this.#rescaledDataRange) {\n      this.#rescaledDataRange = this.calculateRescaledDataRange();\n    }\n    return this.#rescaledDataRange;\n  }\n\n  /**\n   * Get the histogram.\n   *\n   * @returns {Array} The histogram.\n   */\n  getHistogram() {\n    if (!this.#histogram) {\n      const res = this.calculateHistogram();\n      this.#dataRange = res.dataRange;\n      this.#rescaledDataRange = res.rescaledDataRange;\n      this.#histogram = res.histogram;\n    }\n    return this.#histogram;\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  // ****************************************\n  // image data modifiers... carefull...\n  // ****************************************\n\n  /**\n   * Set the inner buffer values at given offsets.\n   *\n   * @param {number[]} offsets List of offsets where to set the data.\n   * @param {number|RGB} value The value to set at the given offsets.\n   * @fires Image#imagecontentchange\n   */\n  setAtOffsets(offsets, value) {\n    // value to array\n    let bufferValue;\n    if (typeof value === 'number') {\n      if (this.#numberOfComponents !== 1) {\n        throw new Error(\n          'Number of components is not 1 for setting single value.');\n      }\n      bufferValue = [value];\n    } else if (typeof value.r !== 'undefined' &&\n      typeof value.g !== 'undefined' &&\n      typeof value.b !== 'undefined') {\n      if (this.#numberOfComponents !== 3) {\n        throw new Error(\n          'Number of components is not 3 for setting RGB value.');\n      }\n      bufferValue = [value.r, value.g, value.b];\n    }\n\n    let offset;\n    for (let i = 0, leni = offsets.length; i < leni; ++i) {\n      offset = offsets[i];\n      for (let j = 0; j < this.#numberOfComponents; ++j) {\n        this.#buffer[offset + j] = bufferValue[j];\n      }\n    }\n    // fire imagecontentchange\n    this.#fireEvent({type: 'imagecontentchange'});\n  }\n\n  /**\n   * Set the inner buffer values at given offsets.\n   *\n   * @param {number[][]} offsetsLists List of offset lists where\n   *   to set the data.\n   * @param {number} value The value to set at the given offsets.\n   * @returns {Array} A list of objects representing the original values before\n   *  replacing them.\n   * @fires Image#imagecontentchange\n   */\n  setAtOffsetsAndGetOriginals(offsetsLists, value) {\n    const originalValuesLists = [];\n\n    // update and store\n    for (let j = 0; j < offsetsLists.length; ++j) {\n      const offsets = offsetsLists[j];\n      // first value\n      let offset = offsets[0];\n      let previousValue = this.#buffer[offset];\n      // original value storage\n      const originalValues = [];\n      originalValues.push({\n        index: 0,\n        value: previousValue\n      });\n      for (let i = 0; i < offsets.length; ++i) {\n        offset = offsets[i];\n        const currentValue = this.#buffer[offset];\n        // check if new value\n        if (previousValue !== currentValue) {\n          // store new value\n          originalValues.push({\n            index: i,\n            value: currentValue\n          });\n          previousValue = currentValue;\n        }\n        // write update value\n        this.#buffer[offset] = value;\n      }\n      originalValuesLists.push(originalValues);\n    }\n    // fire imagecontentchange\n    this.#fireEvent({type: 'imagecontentchange'});\n    return originalValuesLists;\n  }\n\n  /**\n   * Set the inner buffer values at given offsets.\n   *\n   * @param {number[][]} offsetsLists List of offset lists\n   *   where to set the data.\n   * @param {number|Array} value The value to set at the given offsets.\n   * @fires Image#imagecontentchange\n   */\n  setAtOffsetsWithIterator(offsetsLists, value) {\n    const isValueArray = Array.isArray(value);\n\n    for (let j = 0; j < offsetsLists.length; ++j) {\n      const offsets = offsetsLists[j];\n      let iterator;\n      if (isValueArray) {\n        // input value is a list of iterators\n        // created by setAtOffsetsAndGetOriginals\n        iterator = valueRange(\n          value[j], offsets.length);\n      } else {\n        // input value is a simple color\n        iterator = valueRange(\n          [{index: 0, value: value}], offsets.length);\n      }\n\n      // set values\n      let ival = iterator.next();\n      while (!ival.done) {\n        const offset = offsets[ival.index];\n        this.#buffer[offset] = ival.value;\n        ival = iterator.next();\n      }\n    }\n    /**\n     * Image content change event.\n     *\n     * @event Image#imagecontentchange\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    this.#fireEvent({type: 'imagecontentchange'});\n  }\n\n  /**\n   * Get the value of the image at a specific coordinate.\n   *\n   * @param {number} i The X index.\n   * @param {number} j The Y index.\n   * @param {number} k The Z index.\n   * @param {number} f The frame number.\n   * @returns {number} The value at the desired position.\n   * Warning: No size check...\n   */\n  getValue(i, j, k, f) {\n    const frame = (f || 0);\n    const index = new Index([i, j, k, frame]);\n    return this.getValueAtOffset(\n      this.getGeometry().getSize().indexToOffset(index));\n  }\n\n  /**\n   * Get the value of the image at a specific index.\n   *\n   * @param {Index} index The index.\n   * @returns {number} The value at the desired position.\n   * Warning: No size check...\n   */\n  getValueAtIndex(index) {\n    return this.getValueAtOffset(\n      this.getGeometry().getSize().indexToOffset(index));\n  }\n\n  /**\n   * Get the rescaled value of the image at a specific position.\n   *\n   * @param {number} i The X index.\n   * @param {number} j The Y index.\n   * @param {number} k The Z index.\n   * @param {number} f The frame number.\n   * @returns {number} The rescaled value at the desired position.\n   * Warning: No size check...\n   */\n  getRescaledValue(i, j, k, f) {\n    if (typeof f === 'undefined') {\n      f = 0;\n    }\n    let val = this.getValue(i, j, k, f);\n    if (!this.isIdentityRSI()) {\n      if (this.isConstantRSI()) {\n        val = this.getRescaleSlopeAndIntercept().apply(val);\n      } else {\n        const values = [i, j, k, f];\n        const index = new Index(values);\n        val = this.getRescaleSlopeAndIntercept(index).apply(val);\n      }\n    }\n    return val;\n  }\n\n  /**\n   * Get the rescaled value of the image at a specific index.\n   *\n   * @param {Index} index The index.\n   * @returns {number} The rescaled value at the desired position.\n   * Warning: No size check...\n   */\n  getRescaledValueAtIndex(index) {\n    return this.getRescaledValueAtOffset(\n      this.getGeometry().getSize().indexToOffset(index)\n    );\n  }\n\n  /**\n   * Get the rescaled value of the image at a specific offset.\n   *\n   * @param {number} offset The desired offset.\n   * @returns {number} The rescaled value at the desired offset.\n   * Warning: No size check...\n   */\n  getRescaledValueAtOffset(offset) {\n    let val = this.getValueAtOffset(offset);\n    if (!this.isIdentityRSI()) {\n      if (this.isConstantRSI()) {\n        val = this.getRescaleSlopeAndIntercept().apply(val);\n      } else {\n        const index = this.getGeometry().getSize().offsetToIndex(offset);\n        val = this.getRescaleSlopeAndIntercept(index).apply(val);\n      }\n    }\n    return val;\n  }\n\n  /**\n   * Calculate the data range of the image.\n   * WARNING: for speed reasons, only calculated on the first frame...\n   *\n   * @returns {object} The range {min, max}.\n   */\n  calculateDataRange() {\n    let min = this.getValueAtOffset(0);\n    let max = min;\n    let value = 0;\n    const size = this.getGeometry().getSize();\n    let leni = size.getTotalSize();\n    // max to 3D\n    if (size.length() >= 3) {\n      leni = size.getDimSize(3);\n    }\n    for (let i = 0; i < leni; ++i) {\n      value = this.getValueAtOffset(i);\n      if (value > max) {\n        max = value;\n      }\n      if (value < min) {\n        min = value;\n      }\n    }\n    // return\n    return {min: min, max: max};\n  }\n\n  /**\n   * Calculate the rescaled data range of the image.\n   * WARNING: for speed reasons, only calculated on the first frame...\n   *\n   * @returns {object} The range {min, max}.\n   */\n  calculateRescaledDataRange() {\n    if (this.isIdentityRSI()) {\n      return this.getDataRange();\n    } else if (this.isConstantRSI()) {\n      const range = this.getDataRange();\n      const resmin = this.getRescaleSlopeAndIntercept().apply(range.min);\n      const resmax = this.getRescaleSlopeAndIntercept().apply(range.max);\n      return {\n        min: ((resmin < resmax) ? resmin : resmax),\n        max: ((resmin > resmax) ? resmin : resmax)\n      };\n    } else {\n      let rmin = this.getRescaledValueAtOffset(0);\n      let rmax = rmin;\n      let rvalue = 0;\n      const size = this.getGeometry().getSize();\n      let leni = size.getTotalSize();\n      // max to 3D\n      if (size.length() === 3) {\n        leni = size.getDimSize(3);\n      }\n      for (let i = 0; i < leni; ++i) {\n        rvalue = this.getRescaledValueAtOffset(i);\n        if (rvalue > rmax) {\n          rmax = rvalue;\n        }\n        if (rvalue < rmin) {\n          rmin = rvalue;\n        }\n      }\n      // return\n      return {min: rmin, max: rmax};\n    }\n  }\n\n  /**\n   * Calculate the histogram of the image.\n   *\n   * @returns {object} The histogram, data range and rescaled data range.\n   */\n  calculateHistogram() {\n    const size = this.getGeometry().getSize();\n    const histo = [];\n    let min = this.getValueAtOffset(0);\n    let max = min;\n    let value = 0;\n    let rmin = this.getRescaledValueAtOffset(0);\n    let rmax = rmin;\n    let rvalue = 0;\n    for (let i = 0, leni = size.getTotalSize(); i < leni; ++i) {\n      value = this.getValueAtOffset(i);\n      if (value > max) {\n        max = value;\n      }\n      if (value < min) {\n        min = value;\n      }\n      rvalue = this.getRescaledValueAtOffset(i);\n      if (rvalue > rmax) {\n        rmax = rvalue;\n      }\n      if (rvalue < rmin) {\n        rmin = rvalue;\n      }\n      histo[rvalue] = (histo[rvalue] || 0) + 1;\n    }\n    // set data range\n    const dataRange = {min: min, max: max};\n    const rescaledDataRange = {min: rmin, max: rmax};\n    // generate data for plotting\n    const histogram = [];\n    for (let b = rmin; b <= rmax; ++b) {\n      histogram.push([b, (histo[b] || 0)]);\n    }\n    // return\n    return {\n      dataRange: dataRange,\n      rescaledDataRange: rescaledDataRange,\n      histogram: histogram\n    };\n  }\n\n  /**\n   * Convolute the image with a given 2D kernel.\n   *\n   * Note: Uses raw buffer values.\n   *\n   * @param {number[]} weights The weights of the 2D kernel as a 3x3 matrix.\n   * @returns {Image} The convoluted image.\n   */\n  convolute2D(weights) {\n    if (weights.length !== 9) {\n      throw new Error(\n        'The convolution matrix does not have a length of 9; it has ' +\n        weights.length);\n    }\n\n    const newImage = this.clone();\n    const newBuffer = newImage.getBuffer();\n\n    const imgSize = this.getGeometry().getSize();\n    const dimOffset = imgSize.getDimSize(2) * this.getNumberOfComponents();\n    for (let k = 0; k < imgSize.get(2); ++k) {\n      this.convoluteBuffer(weights, newBuffer, k * dimOffset);\n    }\n\n    return newImage;\n  }\n\n  /**\n   * Convolute an image buffer with a given 2D kernel.\n   *\n   * Note: Uses raw buffer values.\n   *\n   * @param {number[]} weights The weights of the 2D kernel as a 3x3 matrix.\n   * @param {TypedArray} buffer The buffer to convolute.\n   * @param {number} startOffset The index to start at.\n   */\n  convoluteBuffer(\n    weights, buffer, startOffset) {\n    const imgSize = this.getGeometry().getSize();\n    const ncols = imgSize.get(0);\n    const nrows = imgSize.get(1);\n    const ncomp = this.getNumberOfComponents();\n\n    // number of component and planar configuration vars\n    let factor = 1;\n    let componentOffset = 1;\n    if (ncomp === 3) {\n      if (this.getPlanarConfiguration() === 0) {\n        factor = 3;\n      } else {\n        componentOffset = imgSize.getDimSize(2);\n      }\n    }\n\n    // allow special indent for matrices\n    /*jshint indent:false */\n\n    // default weight offset matrix\n    const wOff = [];\n    wOff[0] = (-ncols - 1) * factor;\n    wOff[1] = (-ncols) * factor;\n    wOff[2] = (-ncols + 1) * factor;\n    wOff[3] = -factor;\n    wOff[4] = 0;\n    wOff[5] = 1 * factor;\n    wOff[6] = (ncols - 1) * factor;\n    wOff[7] = (ncols) * factor;\n    wOff[8] = (ncols + 1) * factor;\n\n    // border weight offset matrices\n    // borders are extended (see http://en.wikipedia.org/wiki/Kernel_%28image_processing%29)\n\n    // i=0, j=0\n    const wOff00 = [];\n    wOff00[0] = wOff[4]; wOff00[1] = wOff[4]; wOff00[2] = wOff[5];\n    wOff00[3] = wOff[4]; wOff00[4] = wOff[4]; wOff00[5] = wOff[5];\n    wOff00[6] = wOff[7]; wOff00[7] = wOff[7]; wOff00[8] = wOff[8];\n    // i=0, j=*\n    const wOff0x = [];\n    wOff0x[0] = wOff[1]; wOff0x[1] = wOff[1]; wOff0x[2] = wOff[2];\n    wOff0x[3] = wOff[4]; wOff0x[4] = wOff[4]; wOff0x[5] = wOff[5];\n    wOff0x[6] = wOff[7]; wOff0x[7] = wOff[7]; wOff0x[8] = wOff[8];\n    // i=0, j=nrows\n    const wOff0n = [];\n    wOff0n[0] = wOff[1]; wOff0n[1] = wOff[1]; wOff0n[2] = wOff[2];\n    wOff0n[3] = wOff[4]; wOff0n[4] = wOff[4]; wOff0n[5] = wOff[5];\n    wOff0n[6] = wOff[4]; wOff0n[7] = wOff[4]; wOff0n[8] = wOff[5];\n\n    // i=*, j=0\n    const wOffx0 = [];\n    wOffx0[0] = wOff[3]; wOffx0[1] = wOff[4]; wOffx0[2] = wOff[5];\n    wOffx0[3] = wOff[3]; wOffx0[4] = wOff[4]; wOffx0[5] = wOff[5];\n    wOffx0[6] = wOff[6]; wOffx0[7] = wOff[7]; wOffx0[8] = wOff[8];\n    // i=*, j=* -> wOff\n    // i=*, j=nrows\n    const wOffxn = [];\n    wOffxn[0] = wOff[0]; wOffxn[1] = wOff[1]; wOffxn[2] = wOff[2];\n    wOffxn[3] = wOff[3]; wOffxn[4] = wOff[4]; wOffxn[5] = wOff[5];\n    wOffxn[6] = wOff[3]; wOffxn[7] = wOff[4]; wOffxn[8] = wOff[5];\n\n    // i=ncols, j=0\n    const wOffn0 = [];\n    wOffn0[0] = wOff[3]; wOffn0[1] = wOff[4]; wOffn0[2] = wOff[4];\n    wOffn0[3] = wOff[3]; wOffn0[4] = wOff[4]; wOffn0[5] = wOff[4];\n    wOffn0[6] = wOff[6]; wOffn0[7] = wOff[7]; wOffn0[8] = wOff[7];\n    // i=ncols, j=*\n    const wOffnx = [];\n    wOffnx[0] = wOff[0]; wOffnx[1] = wOff[1]; wOffnx[2] = wOff[1];\n    wOffnx[3] = wOff[3]; wOffnx[4] = wOff[4]; wOffnx[5] = wOff[4];\n    wOffnx[6] = wOff[6]; wOffnx[7] = wOff[7]; wOffnx[8] = wOff[7];\n    // i=ncols, j=nrows\n    const wOffnn = [];\n    wOffnn[0] = wOff[0]; wOffnn[1] = wOff[1]; wOffnn[2] = wOff[1];\n    wOffnn[3] = wOff[3]; wOffnn[4] = wOff[4]; wOffnn[5] = wOff[4];\n    wOffnn[6] = wOff[3]; wOffnn[7] = wOff[4]; wOffnn[8] = wOff[4];\n\n    // restore indent for rest of method\n    /*jshint indent:4 */\n\n    // loop vars\n    let pixelOffset = startOffset;\n    let newValue = 0;\n    let wOffFinal = [];\n    for (let c = 0; c < ncomp; ++c) {\n      // component offset\n      pixelOffset += c * componentOffset;\n      for (let j = 0; j < nrows; ++j) {\n        for (let i = 0; i < ncols; ++i) {\n          wOffFinal = wOff;\n          // special border cases\n          if (i === 0 && j === 0) {\n            wOffFinal = wOff00;\n          } else if (i === 0 && j === (nrows - 1)) {\n            wOffFinal = wOff0n;\n          } else if (i === (ncols - 1) && j === 0) {\n            wOffFinal = wOffn0;\n          } else if (i === (ncols - 1) && j === (nrows - 1)) {\n            wOffFinal = wOffnn;\n          } else if (i === 0 && j !== (nrows - 1) && j !== 0) {\n            wOffFinal = wOff0x;\n          } else if (i === (ncols - 1) && j !== (nrows - 1) && j !== 0) {\n            wOffFinal = wOffnx;\n          } else if (i !== 0 && i !== (ncols - 1) && j === 0) {\n            wOffFinal = wOffx0;\n          } else if (i !== 0 && i !== (ncols - 1) && j === (nrows - 1)) {\n            wOffFinal = wOffxn;\n          }\n          // calculate the weighed sum of the source image pixels that\n          // fall under the convolution matrix\n          newValue = 0;\n          for (let wi = 0; wi < 9; ++wi) {\n            newValue += this.getValueAtOffset(\n              pixelOffset + wOffFinal[wi]) * weights[wi];\n          }\n          buffer[pixelOffset] = newValue;\n          // increment pixel offset\n          pixelOffset += factor;\n        }\n      }\n    }\n  }\n\n  /**\n   * Transform an image using a specific operator.\n   * WARNING: no size check!\n   *\n   * @param {Function} operator The operator to use when transforming.\n   * @returns {Image} The transformed image.\n   * Note: Uses the raw buffer values.\n   */\n  transform(operator) {\n    const newImage = this.clone();\n    const newBuffer = newImage.getBuffer();\n    for (let i = 0, leni = newBuffer.length; i < leni; ++i) {\n      newBuffer[i] = operator(newImage.getValueAtOffset(i));\n    }\n    return newImage;\n  }\n\n  /**\n   * Compose this image with another one and using a specific operator.\n   * WARNING: no size check!\n   *\n   * @param {Image} rhs The image to compose with.\n   * @param {Function} operator The operator to use when composing.\n   * @returns {Image} The composed image.\n   * Note: Uses the raw buffer values.\n   */\n  compose(rhs, operator) {\n    const newImage = this.clone();\n    const newBuffer = newImage.getBuffer();\n    for (let i = 0, leni = newBuffer.length; i < leni; ++i) {\n      // using the operator on the local buffer, i.e. the\n      // latest (not original) data\n      newBuffer[i] = Math.floor(\n        operator(this.getValueAtOffset(i), rhs.getValueAtOffset(i))\n      );\n    }\n    return newImage;\n  }\n\n} // class Image\n","import {custom} from '../app/custom';\nimport {View} from './view';\nimport {WindowLevel} from './windowLevel';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {DataElement} from '../dicom/dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * List of default window level presets.\n *\n * @type {Object.<string, Object.<string, WindowLevel>>}\n */\nconst defaultWlPresets = {\n  CT: {\n    mediastinum: new WindowLevel(40, 400),\n    lung: new WindowLevel(-500, 1500),\n    bone: new WindowLevel(500, 2000),\n    brain: new WindowLevel(40, 80),\n    head: new WindowLevel(90, 350)\n  }\n};\n\n/**\n * {@link View} factory.\n */\nexport class ViewFactory {\n\n  /**\n   * Get an View object from the read DICOM file.\n   *\n   * @param {Object<string, DataElement>} dataElements The DICOM tags.\n   * @param {Image} image The associated image.\n   * @returns {View} The new View.\n   */\n  create(dataElements, image) {\n    // view\n    const view = new View(image);\n\n    // default color map\n    if (image.getPhotometricInterpretation() === 'MONOCHROME1') {\n      view.setColourMap('invPlain');\n    }\n\n    // window level presets\n    let windowPresets = {};\n    // image presets\n    if (typeof image.getMeta().windowPresets !== 'undefined') {\n      windowPresets = image.getMeta().windowPresets;\n    }\n    // min/max\n    // Not filled yet since it is stil too costly to calculate min/max\n    // for each slice... It will be filled at first use\n    // (see view.setWindowLevelPreset).\n    // Order is important, if no wl from DICOM, this will be the default.\n    windowPresets.minmax = {name: 'minmax'};\n    // optional modality presets\n    const modality = image.getMeta().Modality;\n    let wlPresets;\n    if (typeof custom.wlPresets !== 'undefined' &&\n      typeof custom.wlPresets[modality] !== 'undefined') {\n      wlPresets = custom.wlPresets[modality];\n    } else {\n      wlPresets = defaultWlPresets[modality];\n    }\n    for (const key in wlPresets) {\n      const preset = wlPresets[key];\n      windowPresets[key] = {\n        wl: [new WindowLevel(preset.center, preset.width)],\n        name: key\n      };\n    }\n\n    // store\n    view.setWindowPresets(windowPresets);\n\n    // initialise the view\n    view.init();\n\n    return view;\n  }\n\n} // class ViewFactory\n","import {Index} from '../math/index';\nimport {ModalityLut} from './modalityLut';\nimport {WindowLut} from './windowLut';\nimport {luts} from './luts';\nimport {VoiLut} from './voiLut';\nimport {WindowLevel} from './windowLevel';\nimport {generateImageDataMonochrome} from './viewMonochrome';\nimport {generateImageDataPaletteColor} from './viewPaletteColor';\nimport {generateImageDataRgb} from './viewRgb';\nimport {generateImageDataYbrFull} from './viewYbrFull';\nimport {ViewFactory} from './viewFactory';\nimport {isIdentityMat33} from '../math/matrix';\nimport {getSliceIterator} from '../image/iterator';\nimport {ListenerHandler} from '../utils/listen';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {RescaleSlopeAndIntercept} from './rsi';\nimport {ColourMap} from './luts';\nimport {Matrix33} from '../math/matrix';\nimport {\n  Point,\n  Point3D\n} from '../math/point';\nimport {DataElement} from '../dicom/dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * List of view event names.\n *\n * @type {string[]}\n */\nexport const viewEventNames = [\n  'wlchange',\n  'wlpresetadd',\n  'colourmapchange',\n  'positionchange',\n  'opacitychange',\n  'alphafuncchange'\n];\n\n/**\n * Create a View from DICOM elements and image.\n *\n * @param {Object<string, DataElement>} elements The DICOM elements.\n * @param {Image} image The associated image.\n * @returns {View} The View object.\n */\nexport function createView(elements, image) {\n  const factory = new ViewFactory();\n  return factory.create(elements, image);\n}\n\n/**\n * View class.\n *\n * Need to set the window lookup table once created\n * (either directly or with helper methods).\n *\n * @example\n * // XMLHttpRequest onload callback\n * const onload = function (event) {\n *   // parse the dicom buffer\n *   const dicomParser = new dwv.DicomParser();\n *   dicomParser.parse(event.target.response);\n *   // create the image object\n *   const image = dwv.createImage(dicomParser.getDicomElements());\n *   // create the view\n *   const view = dwv.createView(dicomParser.getDicomElements(), image);\n *   // setup canvas\n *   const canvas = document.createElement('canvas');\n *   canvas.width = 256;\n *   canvas.height = 256;\n *   const ctx = canvas.getContext(\"2d\");\n *   // update the image data\n *   const imageData = ctx.createImageData(256, 256);\n *   view.generateImageData(imageData);\n *   ctx.putImageData(imageData, 0, 0);\n *   // update html\n *   const div = document.getElementById('dwv');\n *   div.appendChild(canvas);;\n * };\n * // DICOM file request\n * const request = new XMLHttpRequest();\n * const url = 'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm';\n * request.open('GET', url);\n * request.responseType = 'arraybuffer';\n * request.onload = onload;\n * request.send();\n */\nexport class View {\n\n  /**\n   * The associated image.\n   *\n   * @type {Image}\n   */\n  #image;\n\n  /**\n   * Window lookup tables, indexed per Rescale Slope and Intercept (RSI).\n   *\n   * @type {WindowLut}\n   */\n  #windowLut;\n\n  /**\n   * Flag for image constant RSI.\n   *\n   * @type {boolean}\n   */\n  #isConstantRSI;\n\n  /**\n   * Window presets.\n   * Minmax will be filled at first use (see view.setWindowLevelPreset).\n   *\n   * @type {object}\n   */\n  #windowPresets = {minmax: {name: 'minmax'}};\n\n  /**\n   * Current window preset name.\n   *\n   * @type {string}\n   */\n  #currentPresetName = null;\n\n  /**\n   * Current window level.\n   *\n   * @type {WindowLevel}\n   */\n  #currentWl;\n\n  /**\n   * Colour map name.\n   *\n   * @type {string}\n   */\n  #colourMapName = 'plain';\n\n  /**\n   * Current position as a Point.\n   * Store position and not index to stay geometry independent.\n   *\n   * @type {Point}\n   */\n  #currentPosition = null;\n\n  /**\n   * View orientation. Undefined will use the original slice ordering.\n   *\n   * @type {Matrix33}\n   */\n  #orientation;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * @param {Image} image The associated image.\n   */\n  constructor(image) {\n    this.#image = image;\n\n    // listen to appendframe event to update the current position\n    //   to add the extra dimension\n    this.#image.addEventListener('appendframe', () => {\n      // update current position if first appendFrame\n      const index = this.getCurrentIndex();\n      if (index.length() === 3) {\n        // add dimension\n        const values = index.getValues();\n        values.push(0);\n        this.setCurrentIndex(new Index(values));\n      }\n    });\n  }\n\n  /**\n   * Get the associated image.\n   *\n   * @returns {Image} The associated image.\n   */\n  getImage() {\n    return this.#image;\n  }\n\n  /**\n   * Set the associated image.\n   *\n   * @param {Image} inImage The associated image.\n   */\n  setImage(inImage) {\n    this.#image = inImage;\n  }\n\n  /**\n   * Get the view orientation.\n   *\n   * @returns {Matrix33} The orientation matrix.\n   */\n  getOrientation() {\n    return this.#orientation;\n  }\n\n  /**\n   * Set the view orientation.\n   *\n   * @param {Matrix33} mat33 The orientation matrix.\n   */\n  setOrientation(mat33) {\n    this.#orientation = mat33;\n  }\n\n  /**\n   * Initialise the view: set initial index.\n   */\n  init() {\n    this.setInitialIndex();\n  }\n\n  /**\n   * Set the initial index to the middle position.\n   */\n  setInitialIndex() {\n    const geometry = this.#image.getGeometry();\n    const size = geometry.getSize();\n    const values = new Array(size.length());\n    values.fill(0);\n    // middle\n    values[0] = Math.floor(size.get(0) / 2);\n    values[1] = Math.floor(size.get(1) / 2);\n    values[2] = Math.floor(size.get(2) / 2);\n    this.setCurrentIndex(new Index(values), true);\n  }\n\n  /**\n   * Get the milliseconds per frame from frame rate.\n   *\n   * @param {number} recommendedDisplayFrameRate Recommended Display Frame Rate.\n   * @returns {number} The milliseconds per frame.\n   */\n  getPlaybackMilliseconds(recommendedDisplayFrameRate) {\n    if (!recommendedDisplayFrameRate) {\n      // Default to 10 FPS if none is found in the meta\n      recommendedDisplayFrameRate = 10;\n    }\n    // round milliseconds per frame to nearest whole number\n    return Math.round(1000 / recommendedDisplayFrameRate);\n  }\n\n  /**\n   * Per value alpha function.\n   *\n   * @param {number[]|number} _value The pixel value.\n   *   Can be a number for monochrome data or an array for RGB data.\n   * @param {number} _index The index of the value.\n   * @returns {number} The coresponding alpha [0,255].\n   */\n  #alphaFunction = function (_value, _index) {\n    // default always returns fully visible\n    return 0xff;\n  };\n\n  /**\n   * @callback alphaFn\n   * @param {number[]|number} value The pixel value.\n   * @param {number} index The values' index.\n   * @returns {number} The opacity of the input value.\n   */\n\n  /**\n   * Get the alpha function.\n   *\n   * @returns {alphaFn} The function.\n   */\n  getAlphaFunction() {\n    return this.#alphaFunction;\n  }\n\n  /**\n   * Set alpha function.\n   *\n   * @param {alphaFn} func The function.\n   * @fires View#alphafuncchange\n   */\n  setAlphaFunction(func) {\n    this.#alphaFunction = func;\n    /**\n     * Alpha func change event.\n     *\n     * @event View#alphafuncchange\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    this.#fireEvent({\n      type: 'alphafuncchange'\n    });\n  }\n\n  /**\n   * Get the window LUT of the image.\n   * Warning: can be undefined in no window/level was set.\n   *\n   * @returns {WindowLut} The window LUT of the image.\n   * @fires View#wlchange\n   */\n  #getCurrentWindowLut() {\n    // special case for 'perslice' presets\n    if (this.#currentPresetName &&\n      typeof this.#windowPresets[this.#currentPresetName] !== 'undefined' &&\n      typeof this.#windowPresets[this.#currentPresetName].perslice !==\n        'undefined' &&\n      this.#windowPresets[this.#currentPresetName].perslice === true) {\n      // check position\n      if (!this.getCurrentIndex()) {\n        this.setInitialIndex();\n      }\n      // get the slice window level\n      const currentIndex = this.getCurrentIndex();\n      const offset = this.#image.getSecondaryOffset(currentIndex);\n      const currentPreset = this.#windowPresets[this.#currentPresetName];\n      const sliceWl = currentPreset.wl[offset];\n      // set window level: will send a change event, mark it as silent as\n      // this change is always triggered by a position change\n      this.setWindowLevel(sliceWl, this.#currentPresetName, true);\n    }\n\n    // if no current, use first id\n    if (typeof this.#currentWl === 'undefined') {\n      this.setWindowLevelPresetById(0, true);\n    }\n\n    // get the window lut\n    if (typeof this.#isConstantRSI === 'undefined' ||\n      this.#image.isConstantRSI() !== this.#isConstantRSI) {\n      this.#isConstantRSI = this.#image.isConstantRSI();\n      // set or update windowLut if isConstantRSI has changed\n      // (can be different at first slice and after having loaded\n      //  the full volume...)\n      let rsi;\n      let isDiscrete;\n      if (this.#isConstantRSI) {\n        rsi = this.#image.getRescaleSlopeAndIntercept();\n        isDiscrete = true;\n      } else {\n        rsi = new RescaleSlopeAndIntercept(1, 0);\n        isDiscrete = false;\n      }\n      // create the rescale lookup table\n      const modalityLut = new ModalityLut(\n        rsi,\n        this.#image.getMeta().BitsStored);\n      // create the window lookup table\n      this.#windowLut = new WindowLut(\n        modalityLut,\n        this.#image.getMeta().IsSigned,\n        isDiscrete);\n    }\n\n    // update VOI lut if not present or its window level\n    // is different from the current one\n    const voiLut = this.#windowLut.getVoiLut();\n    let voiLutWl;\n    if (typeof voiLut !== 'undefined') {\n      voiLutWl = voiLut.getWindowLevel();\n    }\n    if (typeof voiLut === 'undefined' ||\n      !this.#currentWl.equals(voiLutWl)) {\n      // set lut window level\n      const voiLut = new VoiLut(this.#currentWl);\n      this.#windowLut.setVoiLut(voiLut);\n    }\n\n    // return\n    return this.#windowLut;\n  }\n\n  /**\n   * Get the window presets.\n   *\n   * @returns {object} The window presets.\n   */\n  getWindowPresets() {\n    return this.#windowPresets;\n  }\n\n  /**\n   * Get the window presets names.\n   *\n   * @returns {string[]} The list of window presets names.\n   */\n  getWindowPresetsNames() {\n    return Object.keys(this.#windowPresets);\n  }\n\n  /**\n   * Set the window presets.\n   *\n   * @param {object} presets The window presets.\n   */\n  setWindowPresets(presets) {\n    this.#windowPresets = presets;\n  }\n\n  /**\n   * Add window presets to the existing ones.\n   *\n   * @param {object} presets The window presets.\n   */\n  addWindowPresets(presets) {\n    const keys = Object.keys(presets);\n    let key = null;\n    for (let i = 0; i < keys.length; ++i) {\n      key = keys[i];\n      if (typeof this.#windowPresets[key] !== 'undefined') {\n        if (typeof this.#windowPresets[key].perslice !== 'undefined' &&\n          this.#windowPresets[key].perslice === true) {\n          throw new Error('Cannot add perslice preset');\n        } else {\n          // update existing\n          this.#windowPresets[key] = presets[key];\n        }\n      } else {\n        // add new\n        this.#windowPresets[key] = presets[key];\n        // fire event\n        /**\n         * Window/level add preset event.\n         *\n         * @event View#wlpresetadd\n         * @type {object}\n         * @property {string} type The event type.\n         * @property {string} name The name of the preset.\n         */\n        this.#fireEvent({\n          type: 'wlpresetadd',\n          name: key\n        });\n      }\n    }\n  }\n\n  /**\n   * Get the current window level preset name.\n   *\n   * @returns {string} The preset name.\n   */\n  getCurrentWindowPresetName() {\n    return this.#currentPresetName;\n  }\n\n  /**\n   * Get the colour map of the image.\n   *\n   * @returns {string} The colour map name.\n   */\n  getColourMap() {\n    return this.#colourMapName;\n  }\n\n  /**\n   * Get the colour map object.\n   *\n   * @returns {ColourMap} The colour map.\n   */\n  #getColourMapLut() {\n    return luts[this.#colourMapName];\n  }\n\n  /**\n   * Set the colour map of the image.\n   *\n   * @param {string} name The colour map name.\n   * @fires View#colourmapchange\n   */\n  setColourMap(name) {\n    // check if we have it\n    if (!luts[name]) {\n      throw new Error('Unknown colour map: \\'' + name + '\\'');\n    }\n\n    this.#colourMapName = name;\n\n    /**\n     * Color change event.\n     *\n     * @event View#colourmapchange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} value The changed value.\n     */\n    this.#fireEvent({\n      type: 'colourmapchange',\n      value: [name]\n    });\n  }\n\n  /**\n   * Get the current position.\n   *\n   * @returns {Point} The current position.\n   */\n  getCurrentPosition() {\n    return this.#currentPosition;\n  }\n\n  /**\n   * Get the current index.\n   *\n   * @returns {Index} The current index.\n   */\n  getCurrentIndex() {\n    const position = this.getCurrentPosition();\n    if (!position) {\n      return null;\n    }\n    const geometry = this.getImage().getGeometry();\n    return geometry.worldToIndex(position);\n  }\n\n  /**\n   * Get the SOP image UID of the current image.\n   *\n   * @returns {string} The UID.\n   */\n  getCurrentImageUid() {\n    return this.#image.getImageUid(this.getCurrentIndex());\n  }\n\n  /**\n   * Get the image origin for a image UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {Point3D|undefined} The origin.\n   */\n  getOriginForImageUid(uid) {\n    return this.#image.getOriginForImageUid(uid);\n  }\n\n  /**\n   * Check if the image includes an UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {boolean} True if present.\n   */\n  includesImageUid(uid) {\n    return this.#image.includesImageUid(uid);\n  }\n\n  /**\n   * Check if the current position (default) or\n   * the provided position is in bounds.\n   *\n   * @param {Point} [position] Optional position.\n   * @returns {boolean} True is the position is in bounds.\n   */\n  isPositionInBounds(position) {\n    if (typeof position === 'undefined') {\n      position = this.#currentPosition;\n    }\n    const geometry = this.#image.getGeometry();\n    const index = geometry.worldToIndex(position);\n    const dirs = [this.getScrollDimIndex()];\n    if (index.length() === 4) {\n      dirs.push(3);\n    }\n    return geometry.isIndexInBounds(index, dirs);\n  }\n\n  /**\n   * Get the first origin or at a given position.\n   *\n   * @param {Point} [position] Optional position.\n   * @returns {Point3D} The origin.\n   */\n  getOrigin(position) {\n    const geometry = this.#image.getGeometry();\n    let originIndex = 0;\n    if (typeof position !== 'undefined') {\n      const index = geometry.worldToIndex(position);\n      // index is reoriented, 2 is scroll index\n      originIndex = index.get(2);\n    }\n    return geometry.getOrigins()[originIndex];\n  }\n\n  /**\n   * Set the current position via an index.\n   *\n   * @param {Index} index The new index.\n   * @param {boolean} [silent] Flag to fire event or not.\n   * @returns {boolean} False if not in bounds.\n   * @fires View#positionchange\n   */\n  setCurrentIndex(index, silent) {\n    const geometry = this.#image.getGeometry();\n    const position = geometry.indexToWorld(index);\n    return this.setCurrentPosition(position, silent);\n  }\n\n  /**\n   * Set current position.\n   *\n   * @param {Point} position The new position.\n   * @param {boolean} [silent] Flag to fire event or not.\n   * @returns {boolean} False if not in bounds.\n   * @fires View#positionchange\n   */\n  setCurrentPosition(position, silent) {\n    // check input\n    if (typeof silent === 'undefined') {\n      silent = false;\n    }\n\n    const geometry = this.#image.getGeometry();\n    const index = geometry.worldToIndex(position);\n\n    // check if possible\n    const dirs = [this.getScrollDimIndex()];\n    if (index.length() === 4) {\n      dirs.push(3);\n    }\n    if (!geometry.isIndexInBounds(index, dirs)) {\n      this.#currentPosition = position;\n      if (!silent) {\n        // fire event with valid: false\n        this.#fireEvent({\n          type: 'positionchange',\n          value: [\n            index.getValues(),\n            position.getValues(),\n          ],\n          valid: false\n        });\n      }\n\n      // do no send invalid positionchange event: avoid empty repaint\n      return false;\n    }\n\n    // calculate diff dims before updating internal\n    let diffDims = null;\n    let currentIndex = null;\n    if (this.getCurrentPosition()) {\n      currentIndex = this.getCurrentIndex();\n    }\n    if (currentIndex) {\n      if (currentIndex.canCompare(index)) {\n        diffDims = currentIndex.compare(index);\n      } else {\n        diffDims = [];\n        const minLen = Math.min(currentIndex.length(), index.length());\n        for (let i = 0; i < minLen; ++i) {\n          if (currentIndex.get(i) !== index.get(i)) {\n            diffDims.push(i);\n          }\n        }\n        const maxLen = Math.max(currentIndex.length(), index.length());\n        for (let j = minLen; j < maxLen; ++j) {\n          diffDims.push(j);\n        }\n      }\n    } else {\n      diffDims = [];\n      for (let k = 0; k < index.length(); ++k) {\n        diffDims.push(k);\n      }\n    }\n\n    // assign\n    this.#currentPosition = position;\n\n    if (!silent) {\n      /**\n       * Position change event.\n       *\n       * @event View#positionchange\n       * @type {object}\n       * @property {Array} value The changed value as [index, pixelValue].\n       * @property {number[]} diffDims An array of modified indices.\n       */\n      const posEvent = {\n        type: 'positionchange',\n        value: [\n          index.getValues(),\n          position.getValues(),\n        ],\n        diffDims: diffDims,\n        data: {\n          imageUid: this.#image.getImageUid(index)\n        }\n      };\n\n      // add value if possible\n      if (this.#image.canQuantify()) {\n        const pixValue = this.#image.getRescaledValueAtIndex(index);\n        posEvent.value.push(pixValue);\n      }\n\n      // fire\n      this.#fireEvent(posEvent);\n    }\n\n    // all good\n    return true;\n  }\n\n  /**\n   * Set the view window/level.\n   *\n   * @param {WindowLevel} wl The window and level.\n   * @param {string} [name] Associated preset name, defaults to 'manual'.\n   * Warning: uses the latest set rescale LUT or the default linear one.\n   * @param {boolean} [silent] Flag to launch events with skipGenerate.\n   * @fires View#wlchange\n   */\n  setWindowLevel(wl, name, silent) {\n    // check input\n    if (typeof name === 'undefined') {\n      name = 'manual';\n    }\n    if (name !== 'manual' &&\n      typeof this.#windowPresets[name] === 'undefined') {\n      throw new Error('Unknown window level preset: \\'' + name + '\\'');\n    }\n    if (typeof silent === 'undefined') {\n      silent = false;\n    }\n\n    // check if new wl\n    const isNewWl = !wl.equals(this.#currentWl);\n    // check if new name\n    const isNewName = this.#currentPresetName !== name;\n\n    // compare to previous if present\n    if (isNewWl || isNewName) {\n      // assign\n      this.#currentWl = wl;\n      this.#currentPresetName = name;\n\n      // update manual\n      if (name === 'manual') {\n        if (typeof this.#windowPresets[name] !== 'undefined') {\n          this.#windowPresets[name].wl[0] = wl;\n        } else {\n          // add if not present\n          this.addWindowPresets({\n            manual: {\n              wl: [wl],\n              name: 'manual'\n            }\n          });\n        }\n      }\n\n      /**\n       * Window/level change event.\n       *\n       * @event View#wlchange\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {Array} value The changed value.\n       * @property {number} wc The new window center value.\n       * @property {number} ww The new window wdth value.\n       * @property {boolean} skipGenerate Flag to skip view generation.\n       */\n      this.#fireEvent({\n        type: 'wlchange',\n        value: [wl.center, wl.width, name],\n        wc: wl.center,\n        ww: wl.width,\n        skipGenerate: silent\n      });\n    }\n  }\n\n  /**\n   * Get the window/level.\n   *\n   * @returns {WindowLevel} The window and level.\n   */\n  getWindowLevel() {\n    // same as #currentWl...\n    const windowLut = this.#getCurrentWindowLut();\n    return windowLut.getVoiLut().getWindowLevel();\n  }\n\n  /**\n   * Set the window level to the preset with the input name.\n   *\n   * @param {string} name The name of the preset to activate.\n   * @param {boolean} [silent] Flag to launch events with skipGenerate.\n   */\n  setWindowLevelPreset(name, silent) {\n    const preset = this.getWindowPresets()[name];\n    if (typeof preset === 'undefined') {\n      throw new Error('Unknown window level preset: \\'' + name + '\\'');\n    }\n    // special min/max\n    if (name === 'minmax' && typeof preset.wl === 'undefined') {\n      preset.wl = [this.getWindowLevelMinMax()];\n    }\n    // default to first\n    let wl = preset.wl[0];\n    // check if 'perslice' case\n    if (typeof preset.perslice !== 'undefined' &&\n      preset.perslice === true) {\n      const offset = this.#image.getSecondaryOffset(this.getCurrentIndex());\n      wl = preset.wl[offset];\n    }\n    // set w/l\n    this.setWindowLevel(wl, name, silent);\n  }\n\n  /**\n   * Set the window level to the preset with the input id.\n   *\n   * @param {number} id The id of the preset to activate.\n   * @param {boolean} [silent] Flag to launch events with skipGenerate.\n   */\n  setWindowLevelPresetById(id, silent) {\n    const keys = Object.keys(this.getWindowPresets());\n    this.setWindowLevelPreset(keys[id], silent);\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  /**\n   * Get the image window/level that covers the full data range.\n   * Warning: uses the latest set rescale LUT or the default linear one.\n   *\n   * @returns {WindowLevel} A min/max window level.\n   */\n  getWindowLevelMinMax() {\n    const range = this.getImage().getRescaledDataRange();\n    const min = range.min;\n    const max = range.max;\n    let width = max - min;\n    // full black / white images, defaults to 1.\n    if (width < 1) {\n      logger.warn('Zero or negative window width, defaulting to one.');\n      width = 1;\n    }\n    const center = min + width / 2;\n    return new WindowLevel(center, width);\n  }\n\n  /**\n   * Set the image window/level to cover the full data range.\n   * Warning: uses the latest set rescale LUT or the default linear one.\n   */\n  setWindowLevelMinMax() {\n    // calculate center and width\n    const wl = this.getWindowLevelMinMax();\n    // set window level\n    this.setWindowLevel(wl, 'minmax');\n  }\n\n  /**\n   * Generate display image data to be given to a canvas.\n   *\n   * @param {ImageData} data The iamge data to fill in.\n   * @param {Index} index Optional index at which to generate,\n   *   otherwise generates at current index.\n   */\n  generateImageData(data, index) {\n    // check index\n    if (typeof index === 'undefined') {\n      if (!this.getCurrentIndex()) {\n        this.setInitialIndex();\n      }\n      index = this.getCurrentIndex();\n    }\n\n    const image = this.getImage();\n    const isRescaled = !image.isConstantRSI();\n    const iterator = getSliceIterator(\n      image, index, isRescaled, this.getOrientation());\n\n    const photoInterpretation = image.getPhotometricInterpretation();\n    switch (photoInterpretation) {\n    case 'MONOCHROME1':\n    case 'MONOCHROME2':\n      generateImageDataMonochrome(\n        data,\n        iterator,\n        this.getAlphaFunction(),\n        this.#getCurrentWindowLut(),\n        this.#getColourMapLut()\n      );\n      break;\n\n    case 'PALETTE COLOR':\n      generateImageDataPaletteColor(\n        data,\n        iterator,\n        this.getAlphaFunction(),\n        image.getPaletteColourMap(),\n        image.getMeta().BitsStored === 16\n      );\n      break;\n\n    case 'RGB':\n      generateImageDataRgb(\n        data,\n        iterator,\n        this.getAlphaFunction()\n      );\n      break;\n\n    case 'YBR_FULL':\n      generateImageDataYbrFull(\n        data,\n        iterator,\n        this.getAlphaFunction()\n      );\n      break;\n\n    default:\n      throw new Error(\n        'Unsupported photometric interpretation: ' + photoInterpretation);\n    }\n  }\n\n  /**\n   * Get the scroll dimension index.\n   *\n   * @returns {number} The index.\n   */\n  getScrollDimIndex() {\n    let index = null;\n    const orientation = this.getOrientation();\n    if (typeof orientation !== 'undefined') {\n      index = orientation.getThirdColMajorDirection();\n    } else {\n      index = 2;\n    }\n    return index;\n  }\n\n  /**\n   * Is this view in the same orientation as the image aquisition.\n   *\n   * @returns {boolean} True if in aquisition plane.\n   */\n  isAquisitionOrientation() {\n    return isIdentityMat33(this.#orientation);\n  }\n\n} // class View\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {WindowLut} from './windowLut';\nimport {ColourMap} from './luts';\n/* eslint-enable no-unused-vars */\n\n/**\n * Generate image data for 'MONOCHROME*' photometric interpretation.\n *\n * @param {ImageData} array The array to store the outut data.\n * @param {object} iterator Position iterator.\n * @param {Function} alphaFunc The alpha function.\n * @param {WindowLut} windowLut The window/level LUT.\n * @param {ColourMap} colourMap The colour map.\n */\nexport function generateImageDataMonochrome(\n  array,\n  iterator,\n  alphaFunc,\n  windowLut,\n  colourMap) {\n  let index = 0;\n  let pxValue = 0;\n  let ival = iterator.next();\n  while (!ival.done) {\n    // pixel value\n    pxValue = windowLut.getValue(ival.value);\n    // store data\n    array.data[index] = colourMap.red[pxValue];\n    array.data[index + 1] = colourMap.green[pxValue];\n    array.data[index + 2] = colourMap.blue[pxValue];\n    array.data[index + 3] = alphaFunc(ival.value, ival.index);\n    // increment\n    index += 4;\n    ival = iterator.next();\n  }\n}\n","import {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {ColourMap} from './luts';\n/* eslint-enable no-unused-vars */\n\n/**\n * Generate image data for 'PALETTE COLOR' photometric interpretation.\n *\n * @param {ImageData} array The array to store the outut data.\n * @param {object} iterator Position iterator.\n * @param {Function} alphaFunc The alpha function.\n * @param {ColourMap} colourMap The colour map.\n * @param {boolean} is16BitsStored Flag to know if the data is 16bits.\n */\nexport function generateImageDataPaletteColor(\n  array,\n  iterator,\n  alphaFunc,\n  colourMap,\n  is16BitsStored) {\n  // right shift 8\n  const to8 = function (value) {\n    return value >> 8;\n  };\n\n  if (is16BitsStored) {\n    logger.info('Scaling 16bits data to 8bits.');\n  }\n\n  let index = 0;\n  let pxValue = 0;\n  let ival = iterator.next();\n  while (!ival.done) {\n    // pixel value\n    pxValue = ival.value;\n    // store data\n    // TODO check pxValue fits in lut\n    if (is16BitsStored) {\n      array.data[index] = to8(colourMap.red[pxValue]);\n      array.data[index + 1] = to8(colourMap.green[pxValue]);\n      array.data[index + 2] = to8(colourMap.blue[pxValue]);\n    } else {\n      array.data[index] = colourMap.red[pxValue];\n      array.data[index + 1] = colourMap.green[pxValue];\n      array.data[index + 2] = colourMap.blue[pxValue];\n    }\n    array.data[index + 3] = alphaFunc(pxValue, ival.index);\n    // increment\n    index += 4;\n    ival = iterator.next();\n  }\n}\n","/**\n * Generate image data for 'RGB' photometric interpretation.\n *\n * @param {ImageData} array The array to store the outut data.\n * @param {object} iterator Position iterator.\n * @param {Function} alphaFunc The alpha function.\n */\nexport function generateImageDataRgb(\n  array,\n  iterator,\n  alphaFunc) {\n  let index = 0;\n  let ival = iterator.next();\n  while (!ival.done) {\n    // store data\n    array.data[index] = ival.value[0];\n    array.data[index + 1] = ival.value[1];\n    array.data[index + 2] = ival.value[2];\n    array.data[index + 3] = alphaFunc(ival.value, ival.index);\n    // increment\n    index += 4;\n    ival = iterator.next();\n  }\n}\n","import {ybrToRgb} from '../utils/colour';\n\n/**\n * Generate image data for 'YBR_FULL' photometric interpretation.\n *\n * @param {ImageData} array The array to store the outut data.\n * @param {object} iterator Position iterator.\n * @param {Function} alphaFunc The alpha function.\n */\nexport function generateImageDataYbrFull(\n  array,\n  iterator,\n  alphaFunc) {\n  let index = 0;\n  let rgb = null;\n  let ival = iterator.next();\n  while (!ival.done) {\n    // convert ybr to rgb\n    rgb = ybrToRgb(ival.value[0], ival.value[1], ival.value[2]);\n    // store data\n    array.data[index] = rgb.r;\n    array.data[index + 1] = rgb.g;\n    array.data[index + 2] = rgb.b;\n    array.data[index + 3] = alphaFunc(ival.value, ival.index);\n    // increment\n    index += 4;\n    ival = iterator.next();\n  }\n}\n","import {Vector3D} from '../math/vector';\nimport {Point3D, Point2D} from '../math/point';\nimport {isIdentityMat33} from '../math/matrix';\nimport {\n  getCosinesFromOrientation,\n  getTargetOrientation\n} from '../math/orientation';\nimport {getOrientedArray3D, getDeOrientedArray3D} from './geometry';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point} from '../math/point';\nimport {Index} from '../math/index';\nimport {Geometry} from '../image/geometry';\nimport {Matrix33} from '../math/matrix';\nimport {Spacing} from './spacing';\nimport {Scalar2D, Scalar3D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Plane geometry helper.\n */\nexport class PlaneHelper {\n\n  /**\n   * The image geometry.\n   *\n   * @type {Geometry}\n   */\n  #imageGeometry;\n\n  /**\n   * The associated spacing.\n   *\n   * @type {Spacing}\n   */\n  #spacing;\n\n  /**\n   * The image orientation.\n   *\n   * @type {Matrix33}\n   */\n  #imageOrientation;\n\n  /**\n   * The viewe orientation.\n   *\n   * @type {Matrix33}\n   */\n  #viewOrientation;\n\n  /**\n   * The target orientation.\n   *\n   * @type {Matrix33}\n   */\n  #targetOrientation;\n\n  /**\n   * @param {Geometry} imageGeometry The image geometry.\n   * @param {Matrix33} viewOrientation The view orientation.\n   */\n  constructor(imageGeometry, viewOrientation) {\n    this.#imageGeometry = imageGeometry;\n    this.#spacing = imageGeometry.getRealSpacing();\n    this.#imageOrientation = imageGeometry.getOrientation();\n    this.#viewOrientation = viewOrientation;\n\n    this.#targetOrientation = getTargetOrientation(\n      this.#imageOrientation, viewOrientation);\n  }\n\n  /**\n   * Get the view orientation.\n   *\n   * @returns {Matrix33} The orientation matrix.\n   */\n  getViewOrientation() {\n    return this.#viewOrientation;\n  }\n\n  /**\n   * Get the target orientation.\n   *\n   * @returns {Matrix33} The orientation matrix.\n   */\n  getTargetOrientation() {\n    return this.#targetOrientation;\n  }\n\n  /**\n   * Get a 3D offset from a plane one.\n   *\n   * @param {Scalar2D} offset2D The plane offset as {x,y}.\n   * @returns {Vector3D} The 3D world offset.\n   */\n  getOffset3DFromPlaneOffset(offset2D) {\n    // make 3D\n    const planeOffset = new Vector3D(\n      offset2D.x, offset2D.y, 0);\n    // de-orient\n    const pixelOffset = this.getTargetDeOrientedVector3D(planeOffset);\n    // ~indexToWorld\n    return new Vector3D(\n      pixelOffset.getX() * this.#spacing.get(0),\n      pixelOffset.getY() * this.#spacing.get(1),\n      pixelOffset.getZ() * this.#spacing.get(2));\n  }\n\n  /**\n   * Get a plane offset from a 3D one.\n   *\n   * @param {Scalar3D} offset3D The 3D offset as {x,y,z}.\n   * @returns {Scalar2D} The plane offset as {x,y}.\n   */\n  getPlaneOffsetFromOffset3D(offset3D) {\n    // ~worldToIndex\n    const pixelOffset = new Vector3D(\n      offset3D.x / this.#spacing.get(0),\n      offset3D.y / this.#spacing.get(1),\n      offset3D.z / this.#spacing.get(2));\n    // orient\n    const planeOffset = this.getTargetOrientedVector3D(pixelOffset);\n    // make 2D\n    return {\n      x: planeOffset.getX(),\n      y: planeOffset.getY()\n    };\n  }\n\n  /**\n   * Orient an input vector from real to target space.\n   *\n   * @param {Vector3D} vector The input vector.\n   * @returns {Vector3D} The oriented vector.\n   */\n  getTargetOrientedVector3D(vector) {\n    let planeVector = vector;\n    if (typeof this.#targetOrientation !== 'undefined') {\n      planeVector =\n        this.#targetOrientation.getInverse().multiplyVector3D(vector);\n    }\n    return planeVector;\n  }\n\n  /**\n   * De-orient an input vector from target to real space.\n   *\n   * @param {Vector3D} planeVector The input vector.\n   * @returns {Vector3D} The de-orienteded vector.\n   */\n  getTargetDeOrientedVector3D(planeVector) {\n    let vector = planeVector;\n    if (typeof this.#targetOrientation !== 'undefined') {\n      vector = this.#targetOrientation.multiplyVector3D(planeVector);\n    }\n    return vector;\n  }\n\n  /**\n   * De-orient an input point from target to real space.\n   *\n   * @param {Point3D} planePoint The input point.\n   * @returns {Point3D} The de-orienteded point.\n   */\n  getTargetDeOrientedPoint3D(planePoint) {\n    let point = planePoint;\n    if (typeof this.#targetOrientation !== 'undefined') {\n      point = this.#targetOrientation.multiplyPoint3D(planePoint);\n    }\n    return point;\n  }\n\n  /**\n   * Orient an input vector from target to image space.\n   *\n   * @param {Vector3D} planeVector The input vector.\n   * @returns {Vector3D} The orienteded vector.\n   */\n  getImageOrientedVector3D(planeVector) {\n    let vector = planeVector;\n    if (typeof this.#viewOrientation !== 'undefined') {\n      // image oriented => view de-oriented\n      const values = getDeOrientedArray3D(\n        [\n          planeVector.getX(),\n          planeVector.getY(),\n          planeVector.getZ()\n        ],\n        this.#viewOrientation);\n      vector = new Vector3D(\n        values[0],\n        values[1],\n        values[2]\n      );\n    }\n    return vector;\n  }\n\n  /**\n   * Orient an input point from target to image space.\n   *\n   * @param {Point3D} planePoint The input vector.\n   * @returns {Point3D} The orienteded vector.\n   */\n  getImageOrientedPoint3D(planePoint) {\n    let point = planePoint;\n    if (typeof this.#viewOrientation !== 'undefined') {\n      // image oriented => view de-oriented\n      const values = getDeOrientedArray3D(\n        [\n          planePoint.getX(),\n          planePoint.getY(),\n          planePoint.getZ()\n        ],\n        this.#viewOrientation);\n      point = new Point3D(\n        values[0],\n        values[1],\n        values[2]\n      );\n    }\n    return point;\n  }\n\n  /**\n   * De-orient an input vector from image to target space.\n   *\n   * @param {Vector3D} vector The input vector.\n   * @returns {Vector3D} The de-orienteded vector.\n   */\n  getImageDeOrientedVector3D(vector) {\n    let planeVector = vector;\n    if (typeof this.#viewOrientation !== 'undefined') {\n      // image de-oriented => view oriented\n      const orientedValues = getOrientedArray3D(\n        [\n          vector.getX(),\n          vector.getY(),\n          vector.getZ()\n        ],\n        this.#viewOrientation);\n      planeVector = new Vector3D(\n        orientedValues[0],\n        orientedValues[1],\n        orientedValues[2]\n      );\n    }\n    return planeVector;\n  }\n\n  /**\n   * De-orient an input point from image to target space.\n   *\n   * @param {Point3D} point The input point.\n   * @returns {Point3D} The de-orienteded point.\n   */\n  getImageDeOrientedPoint3D(point) {\n    let planePoint = point;\n    if (typeof this.#viewOrientation !== 'undefined') {\n      // image de-oriented => view oriented\n      const orientedValues = getOrientedArray3D(\n        [\n          point.getX(),\n          point.getY(),\n          point.getZ()\n        ],\n        this.#viewOrientation);\n      planePoint = new Point3D(\n        orientedValues[0],\n        orientedValues[1],\n        orientedValues[2]\n      );\n    }\n    return planePoint;\n  }\n\n  /**\n   * Get a world position from a 2D plane position.\n   *\n   * @param {Point2D} point2D The plane point.\n   * @param {number} k The slice index.\n   * @returns {Point3D} The world position.\n   */\n  getPositionFromPlanePoint(point2D, k) {\n    const planePoint = new Point3D(point2D.getX(), point2D.getY(), k);\n    // de-orient\n    const point = this.getImageOrientedPoint3D(planePoint);\n    // ~indexToWorld to not loose precision\n    return this.#imageGeometry.pointToWorld(point);\n  }\n\n  /**\n   * Get a 2D plane position from a world position.\n   *\n   * @param {Point} point The world position.\n   * @returns {Point3D} The plane point.\n   */\n  getPlanePointFromPosition(point) {\n    const point3D = this.#imageGeometry.worldToPoint(point);\n    return this.getImageDeOrientedPoint3D(point3D);\n  }\n\n  /**\n   * Get the cosines of this plane.\n   *\n   * @returns {number[]} The 2 cosines vectors (3D).\n   */\n  getCosines() {\n    return getCosinesFromOrientation(this.#targetOrientation);\n  }\n\n  /**\n   * Get a list of points that define the plane at input position,\n   *   given this classes orientation.\n   *\n   * @param {Point} position The position.\n   * @returns {Point3D[]} An origin and 2 cosines vectors.\n   */\n  getPlanePoints(position) {\n    // snap to grid\n    const index = this.worldToIndex(position);\n    const snapPosition = this.indexToWorld(index);\n    // get plane point\n    const planePoint = this.getPlanePointFromPosition(snapPosition);\n    // get origin\n    const planeOrigin = this.getPositionFromPlanePoint(\n      new Point2D(0, 0), planePoint.getZ());\n    // find image origin\n    const origins = this.#imageGeometry.getOrigins();\n    const closestOriginIndex = planeOrigin.getClosest(origins);\n    const imageOrigin = origins[closestOriginIndex];\n\n    // use image origin for scroll to cope with\n    // possible irregular slice spacing\n    const pValues = planeOrigin.getValues();\n    const iValues = imageOrigin.getValues();\n    const scrollDimIndex = this.getNativeScrollDimIndex();\n    pValues[scrollDimIndex] = iValues[scrollDimIndex];\n\n    // plane cosines\n    const cosines = this.getCosines();\n\n    return [\n      new Point3D(pValues[0], pValues[1], pValues[2]),\n      new Point3D(cosines[0], cosines[1], cosines[2]),\n      new Point3D(cosines[3], cosines[4], cosines[5])\n    ];\n  }\n\n  /**\n   * Image world to index.\n   *\n   * @param {Point} point The input point.\n   * @returns {Index} The corresponding index.\n   */\n  worldToIndex(point) {\n    return this.#imageGeometry.worldToIndex(point);\n  }\n\n  /**\n   * Image index to world.\n   *\n   * @param {Index} index The input index.\n   * @returns {Point} The corresponding point.\n   */\n  indexToWorld(index) {\n    return this.#imageGeometry.indexToWorld(index);\n  }\n\n  /**\n   * Is this view in the same orientation as the image aquisition.\n   *\n   * @returns {boolean} True if in aquisition plane.\n   */\n  isAquisitionOrientation() {\n    return isIdentityMat33(this.#viewOrientation);\n  }\n\n  /**\n   * Reorder values to follow target orientation.\n   *\n   * @param {Scalar3D} values Values as {x,y,z}.\n   * @returns {Scalar3D} Reoriented values as {x,y,z}.\n   */\n  getTargetOrientedPositiveXYZ(values) {\n    const orientedValues = getOrientedArray3D(\n      [\n        values.x,\n        values.y,\n        values.z\n      ],\n      this.#targetOrientation);\n    return {\n      x: orientedValues[0],\n      y: orientedValues[1],\n      z: orientedValues[2]\n    };\n  }\n\n  /**\n   * Get the (view) scroll dimension index.\n   *\n   * @returns {number} The index.\n   */\n  getScrollDimIndex() {\n    let index = null;\n    if (typeof this.#viewOrientation !== 'undefined') {\n      index = this.#viewOrientation.getThirdColMajorDirection();\n    } else {\n      index = 2;\n    }\n    return index;\n  }\n\n  /**\n   * Get the native (image) scroll dimension index.\n   *\n   * @returns {number} The index.\n   */\n  getNativeScrollDimIndex() {\n    let index = null;\n    if (typeof this.#imageOrientation !== 'undefined') {\n      index = this.#imageOrientation.getThirdColMajorDirection();\n    } else {\n      index = 2;\n    }\n    return index;\n  }\n\n} // class PlaneHelper\n","import {mergeGeometries} from './geometry';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point} from '../math/point';\nimport {Index} from '../math/index';\nimport {View} from './view';\nimport {Geometry} from './geometry';\n/* eslint-enable no-unused-vars */\n\nclass ViewPositionAccessor {\n  /**\n   * @type {View}\n   */\n  #view;\n  /**\n   * @param {View} view The view.\n   */\n  constructor(view) {\n    this.#view = view;\n  }\n  /**\n   * Get the current position.\n   *\n   * @returns {Point} The position.\n   */\n  getCurrentPosition() {\n    return this.#view.getCurrentPosition();\n  }\n  /**\n   * Set the current position.\n   *\n   * @param {Point} position The position.\n   * @param {boolean} [silent] Flag to fire event or not.\n   * @returns {boolean} True if possible and in bounds.\n   */\n  setCurrentPosition(position, silent) {\n    let res = false;\n    if (typeof position !== 'undefined') {\n      res = this.#view.setCurrentPosition(position, silent);\n    }\n    return res;\n  }\n}\n\n/**\n * Position helper.\n */\nexport class PositionHelper {\n\n  /**\n   * @type {ViewPositionAccessor}\n   */\n  #positionAccessor;\n\n  /**\n   * @type {Geometry}\n   */\n  #geometry;\n\n  /**\n   * @type {number}\n   */\n  #scrollDimIndex;\n\n  /**\n   * @param {View} view The associated view.\n   */\n  constructor(view) {\n    this.#positionAccessor = new ViewPositionAccessor(view);\n    this.#geometry = view.getImage().getGeometry();\n    this.#scrollDimIndex = view.getScrollDimIndex();\n  }\n\n  /**\n   * Get the geometry.\n   *\n   * @returns {Geometry} The geometry.\n   */\n  getGeometry() {\n    return this.#geometry;\n  }\n\n  /**\n   * Get the scroll index.\n   *\n   * @returns {number} The scroll index.\n   */\n  getScrollDimIndex() {\n    return this.#scrollDimIndex;\n  }\n\n  /**\n   * Get the maximum dimension value.\n   *\n   * @param {number} dim The dimension.\n   * @returns {number} The maximum value.\n   */\n  getMaximumDimValue(dim) {\n    return this.#geometry.getSize().get(dim) - 1;\n  }\n\n  /**\n   * Get the maximum scroll value.\n   *\n   * @returns {number} The maximum value.\n   */\n  getMaximumScrollValue() {\n    return this.getMaximumDimValue(this.#scrollDimIndex);\n  }\n\n  /**\n   * Get the current position.\n   *\n   * @returns {Point} The current position.\n   */\n  getCurrentPosition() {\n    return this.#positionAccessor.getCurrentPosition();\n  }\n\n  /**\n   * Get the value at dimension index for the current position.\n   *\n   * @param {number} dim The dimension.\n   * @returns {number} The value.\n   */\n  getCurrentPositionDimValue(dim) {\n    return this.getCurrentIndex().get(dim);\n  }\n\n  /**\n   * Get the value at scroll index for the current position.\n   *\n   * @returns {number} The value.\n   */\n  getCurrentPositionScrollValue() {\n    return this.getCurrentPositionDimValue(this.#scrollDimIndex);\n  }\n\n  /**\n   * Get the current position updated at the provided dimension index\n   *   with the input value.\n   *\n   * @param {number} dim The dimension.\n   * @param {number} value The value to used at dimension index.\n   * @returns {Point} The position.\n   */\n  getCurrentPositionAtDimValue(dim, value) {\n    const values = this.getCurrentIndex().getValues();\n    values[dim] = value;\n    return this.#geometry.indexToWorld(new Index(values));\n  }\n\n  /**\n   * Get the current position updated at scroll index with the input value.\n   *\n   * @param {number} value The value to use at scroll index.\n   * @returns {Point} The position.\n   */\n  getCurrentPositionAtScrollValue(value) {\n    return this.getCurrentPositionAtDimValue(this.#scrollDimIndex, value);\n  }\n\n  /**\n   * Get the current index.\n   *\n   * @returns {Index} The current index.\n   */\n  getCurrentIndex() {\n    return this.#geometry.worldToIndex(this.getCurrentPosition());\n  }\n\n  /**\n   * Set the current position.\n   *\n   * @param {Point} position The position.\n   * @param {boolean} [silent] Flag to fire event or not.\n   * @returns {boolean} True if possible and in bounds.\n   */\n  setCurrentPosition(position, silent) {\n    let res = false;\n    if (typeof position !== 'undefined') {\n      res = this.#positionAccessor.setCurrentPosition(position, silent);\n    }\n    return res;\n  }\n\n  /**\n   * Set the current position only if it is in the geometry bounds.\n   *\n   * @param {Point} position The position.\n   * @param {boolean} [silent] Flag to fire event or not.\n   * @returns {boolean} True if possible and in bounds.\n   */\n  setCurrentPositionSafe(position, silent) {\n    let res = false;\n    if (this.isPositionInBounds(position)) {\n      res = this.setCurrentPosition(position, silent);\n    }\n    return res;\n  }\n\n  /**\n   * Merge with another helper.\n   *\n   * @param {PositionHelper} rhs The helper to merge with this one.\n   */\n  merge(rhs) {\n    // check compatibility\n    if (this.#scrollDimIndex !== rhs.getScrollDimIndex()) {\n      throw new Error(\n        'Cannot merge helper of a view with different orientation'\n      );\n    }\n    // merge geometries\n    this.#geometry = mergeGeometries(this.#geometry, rhs.getGeometry());\n  }\n\n  /**\n   * Check if the current position (default) or\n   * the provided position is in bounds.\n   *\n   * @param {Point} position Optional position.\n   * @returns {boolean} True is the position is in bounds.\n   */\n  isPositionInBounds(position) {\n    const index = this.#geometry.worldToIndex(position);\n    const dirs = [this.#scrollDimIndex];\n    if (index.length() === 4) {\n      dirs.push(3);\n    }\n    return this.#geometry.isIndexInBounds(index, dirs);\n  }\n\n  /**\n   * Get the current position incremented in the input direction.\n   *\n   * @param {number} dim The direction in which to increment.\n   * @returns {Point} The resulting point.\n   */\n  getIncrementPosition(dim) {\n    const nextIndex = this.getCurrentIndex().next(dim);\n    return this.#geometry.indexToWorld(nextIndex);\n  }\n\n  /**\n   * Get the current position decremented in the input direction.\n   *\n   * @param {number} dim The direction in which to decrement.\n   * @returns {Point} The resulting point.\n   */\n  getDecrementPosition(dim) {\n    const previousIndex = this.getCurrentIndex().previous(dim);\n    return this.#geometry.indexToWorld(previousIndex);\n  }\n\n  /**\n   * Increment the current position along the provided dim.\n   *\n   * @param {number} dim The direction in which to increment.\n   * @returns {boolean} True if possible and in bounds.\n   */\n  incrementPosition(dim) {\n    return this.setCurrentPositionSafe(this.getIncrementPosition(dim));\n  }\n\n  /**\n   * Decrement the current position along the provided dim.\n   *\n   * @param {number} dim The direction in which to decrement.\n   * @returns {boolean} True if possible and in bounds.\n   */\n  decrementPosition(dim) {\n    return this.setCurrentPositionSafe(this.getDecrementPosition(dim));\n  }\n\n  /**\n   * Increment the current position along the scroll dimension.\n   *\n   * @returns {boolean} True if possible and in bounds.\n   */\n  incrementPositionAlongScroll() {\n    return this.incrementPosition(this.#scrollDimIndex);\n  }\n\n  /**\n   * Decrement the current position along the scroll dimension.\n   *\n   * @returns {boolean} True if possible and in bounds.\n   */\n  decrementPositionAlongScroll() {\n    return this.decrementPosition(this.#scrollDimIndex);\n  }\n\n}","import {Index} from '../math/index';\nimport {Vector3D} from '../math/vector';\nimport {Point3D} from '../math/point';\nimport {isIdentityMat33} from '../math/matrix';\nimport {Size} from '../image/size';\nimport {Spacing} from '../image/spacing';\nimport {Image} from '../image/image';\nimport {Geometry} from '../image/geometry';\nimport {PlaneHelper} from '../image/planeHelper';\nimport {\n  getSliceIterator,\n  getIteratorValues,\n  getRegionSliceIterator,\n  getVariableRegionSliceIterator\n} from '../image/iterator';\nimport {PositionHelper} from '../image/positionHelper';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {View} from '../image/view';\nimport {WindowLevel} from '../image/windowLevel';\nimport {Point, Point2D} from '../math/point';\nimport {Scalar2D} from '../math/scalar';\nimport {Matrix33} from '../math/matrix';\nimport {ViewLayer} from '../gui/viewLayer';\n/* eslint-enable no-unused-vars */\n\n/**\n * View controller.\n */\nexport class ViewController {\n\n  /**\n   * Associated View.\n   *\n   * @type {View}\n   */\n  #view;\n\n  /**\n   * Plane helper.\n   *\n   * @type {PlaneHelper}\n   */\n  #planeHelper;\n\n  /**\n   * Position helper.\n   *\n   * @type {PositionHelper}\n   */\n  #positionHelper;\n\n  /**\n   * Third dimension player ID (created by setInterval).\n   *\n   * @type {number|undefined}\n   */\n  #playerID;\n\n  /**\n   * Is DICOM seg mask flag.\n   *\n   * @type {boolean}\n   */\n  #isMask = false;\n\n  /**\n   * @param {View} view The associated view.\n   */\n  constructor(view) {\n    // check view\n    if (typeof view.getImage() === 'undefined') {\n      throw new Error('View does not have an image, cannot setup controller');\n    }\n\n    this.#view = view;\n\n    // setup the plane helper\n    this.#planeHelper = new PlaneHelper(\n      view.getImage().getGeometry(),\n      view.getOrientation()\n    );\n\n    // position helper\n    this.#positionHelper = new PositionHelper(view);\n\n    // mask segment helper\n    if (view.getImage().getMeta().Modality === 'SEG') {\n      this.#isMask = true;\n    }\n  }\n\n  /**\n   * Get the plane helper.\n   *\n   * @returns {PlaneHelper} The helper.\n   */\n  getPlaneHelper() {\n    return this.#planeHelper;\n  }\n\n  /**\n   * Check is the associated image is a mask.\n   *\n   * @returns {boolean} True if the associated image is a mask.\n   */\n  isMask() {\n    return this.#isMask;\n  }\n\n  /**\n   * Initialise the controller.\n   */\n  initialise() {\n    // set window/level to first preset\n    this.setWindowLevelPresetById(0);\n    // default position\n    this.setCurrentPosition(this.getPositionFromPlanePoint(\n      new Point2D(0, 0)\n    ));\n  }\n\n  /**\n   * Get the image modality.\n   *\n   * @returns {string} The modality.\n   */\n  getModality() {\n    return this.#view.getImage().getMeta().Modality;\n  }\n\n  /**\n   * Get the window/level presets names.\n   *\n   * @returns {string[]} The presets names.\n   */\n  getWindowLevelPresetsNames() {\n    return this.#view.getWindowPresetsNames();\n  }\n\n  /**\n   * Add window/level presets to the view.\n   *\n   * @param {object} presets A preset object.\n   * @returns {object} The list of presets.\n   */\n  addWindowLevelPresets(presets) {\n    return this.#view.addWindowPresets(presets);\n  }\n\n  /**\n   * Set the window level to the preset with the input name.\n   *\n   * @param {string} name The name of the preset to activate.\n   */\n  setWindowLevelPreset(name) {\n    this.#view.setWindowLevelPreset(name);\n  }\n\n  /**\n   * Set the window level to the preset with the input id.\n   *\n   * @param {number} id The id of the preset to activate.\n   */\n  setWindowLevelPresetById(id) {\n    this.#view.setWindowLevelPresetById(id);\n  }\n\n  /**\n   * Check if the controller is playing.\n   *\n   * @returns {boolean} True if the controler is playing.\n   */\n  isPlaying() {\n    return (typeof this.#playerID !== 'undefined');\n  }\n\n  /**\n   * Get the position helper.\n   *\n   * @returns {PositionHelper} The helper.\n   */\n  getPositionHelper() {\n    return this.#positionHelper;\n  }\n\n  /**\n   * Get the current position.\n   *\n   * @returns {Point} The position.\n   */\n  getCurrentPosition() {\n    return this.#positionHelper.getCurrentPosition();\n  }\n\n  /**\n   * Get the current index.\n   *\n   * @returns {Index} The current index.\n   */\n  getCurrentIndex() {\n    return this.#positionHelper.getCurrentIndex();\n  }\n\n  /**\n   * Get the SOP image UID of the current image.\n   *\n   * @returns {string} The UID.\n   */\n  getCurrentImageUid() {\n    return this.#view.getCurrentImageUid();\n  }\n\n  /**\n   * Get the image origin for a image UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {Point3D|undefined} The origin.\n   */\n  getOriginForImageUid(uid) {\n    return this.#view.getOriginForImageUid(uid);\n  }\n\n  /**\n   * Check if the image includes an UID.\n   *\n   * @param {string} uid The UID.\n   * @returns {boolean} True if present.\n   */\n  includesImageUid(uid) {\n    return this.#view.includesImageUid(uid);\n  }\n\n  /**\n   * Get the current oriented index.\n   *\n   * @returns {Index} The index.\n   */\n  getCurrentOrientedIndex() {\n    let res = this.getCurrentIndex();\n    if (typeof this.#view.getOrientation() !== 'undefined') {\n      // view oriented => image de-oriented\n      const vector = this.#planeHelper.getImageDeOrientedVector3D(\n        new Vector3D(res.get(0), res.get(1), res.get(2))\n      );\n      res = new Index([\n        vector.getX(), vector.getY(), vector.getZ()\n      ]);\n    }\n    return res;\n  }\n\n  /**\n   * Get the scroll dimension index.\n   *\n   * @returns {number} The index.\n   */\n  getScrollDimIndex() {\n    return this.#view.getScrollDimIndex();\n  }\n\n  /**\n   * Get the current index scroll value.\n   *\n   * @returns {number} The value.\n   */\n  getCurrentIndexScrollValue() {\n    return this.getCurrentIndex().get(this.#view.getScrollDimIndex());\n  }\n\n  /**\n   * Get the first origin or at a given position.\n   *\n   * @param {Point} [position] Optional position.\n   * @returns {Point3D} The origin.\n   */\n  getOrigin(position) {\n    return this.#view.getOrigin(position);\n  }\n\n  /**\n   * Is this view in the same orientation as the image aquisition.\n   *\n   * @returns {boolean} True if in aquisition plane.\n   */\n  isAquisitionOrientation() {\n    return this.#view.isAquisitionOrientation();\n  }\n\n  /**\n   * Get a list of points that define the plane at input position,\n   *   given this classes orientation.\n   *\n   * @param {Point} position The position.\n   * @returns {Point3D[]} An origin and 2 cosines vectors.\n   */\n  getPlanePoints(position) {\n    return this.#planeHelper.getPlanePoints(position);\n  }\n\n  /**\n   * Get the current scroll position value.\n   *\n   * @returns {number} The value.\n   */\n  getCurrentScrollPosition() {\n    const scrollDimIndex = this.#view.getScrollDimIndex();\n    return this.#view.getCurrentPosition().get(scrollDimIndex);\n  }\n\n  /**\n   * Generate display image data to be given to a canvas.\n   *\n   * @param {ImageData} array The array to fill in.\n   * @param {Index} [index] Optional index at which to generate,\n   *   otherwise generates at current index.\n   */\n  generateImageData(array, index) {\n    this.#view.generateImageData(array, index);\n  }\n\n  /**\n   * Set the associated image.\n   *\n   * @param {Image} img The associated image.\n   */\n  setImage(img) {\n    this.#view.setImage(img);\n  }\n\n  /**\n   * Get the current view (2D) spacing.\n   *\n   * @returns {Scalar2D} The spacing as a 2D array.\n   */\n  get2DSpacing() {\n    const spacing = this.#view.getImage().getGeometry().getSpacing(\n      this.#view.getOrientation());\n    return spacing.get2D();\n  }\n\n  /**\n   * Get the image rescaled value at the input position.\n   *\n   * @param {Point} position The input position.\n   * @returns {number|undefined} The image value or undefined if out of bounds\n   *   or no quantifiable (for ex RGB).\n   */\n  getRescaledImageValue(position) {\n    const image = this.#view.getImage();\n    if (!image.canQuantify()) {\n      return;\n    }\n    const geometry = image.getGeometry();\n    const index = geometry.worldToIndex(position);\n    let value;\n    if (geometry.isIndexInBounds(index)) {\n      value = image.getRescaledValueAtIndex(index);\n    }\n    return value;\n  }\n\n  /**\n   * Get the image pixel unit.\n   *\n   * @returns {string} The unit.\n   */\n  getPixelUnit() {\n    return this.#view.getImage().getMeta().pixelUnit;\n  }\n\n  /**\n   * Extract a slice from an image at the given index and orientation.\n   *\n   * @param {Image} image The image to parse.\n   * @param {Index} index The index at which to get the\n   *   image values.\n   * @param {boolean} isRescaled Flag for rescaled values (default false).\n   * @param {Matrix33} orientation The desired orientation.\n   * @returns {Image} The extracted slice.\n   */\n  #getSlice(image, index, isRescaled, orientation) {\n    // generate slice values\n    const sliceIter = getSliceIterator(\n      image,\n      index,\n      isRescaled,\n      orientation\n    );\n    const sliceValues = getIteratorValues(sliceIter);\n    // oriented geometry\n    const orientedSize = image.getGeometry().getSize(orientation);\n    const sizeValues = orientedSize.getValues();\n    sizeValues[2] = 1;\n    const sliceSize = new Size(sizeValues);\n    const orientedSpacing = image.getGeometry().getSpacing(orientation);\n    const spacingValues = orientedSpacing.getValues();\n    spacingValues[2] = 1;\n    const sliceSpacing = new Spacing(spacingValues);\n    const sliceOrigin = new Point3D(0, 0, 0);\n    const sliceGeometry =\n      new Geometry([sliceOrigin], sliceSize, sliceSpacing);\n    // slice image\n    // @ts-ignore\n    return new Image(sliceGeometry, sliceValues);\n  }\n\n  /**\n   * Get some values from the associated image in a region.\n   *\n   * @param {Point2D} min Minimum point.\n   * @param {Point2D} max Maximum point.\n   * @param {Index} index The index at which to get the\n   *   image values (combined with min/max).\n   * @returns {Array} A list of values.\n   */\n  getImageRegionValues(min, max, index) {\n    let image = this.#view.getImage();\n    const orientation = this.#view.getOrientation();\n    let imageIndex = index;\n    let rescaled = true;\n\n    // create oriented slice if needed\n    if (!isIdentityMat33(orientation)) {\n      image = this.#getSlice(image, imageIndex, rescaled, orientation);\n      // update position\n      imageIndex = new Index([0, 0, 0]);\n      rescaled = false;\n    }\n\n    // get region values\n    const iter = getRegionSliceIterator(\n      image, imageIndex, rescaled, min, max);\n    let values = [];\n    if (iter) {\n      values = getIteratorValues(iter);\n    }\n    return values;\n  }\n\n  /**\n   * Get some values from the associated image in variable regions.\n   *\n   * @param {number[][][]} regions A list of [x, y] pairs (min, max).\n   * @param {Index} index The index at which to get the\n   *   image values (combined with regions min/max).\n   * @returns {Array} A list of values.\n   */\n  getImageVariableRegionValues(regions, index) {\n    let image = this.#view.getImage();\n    const orientation = this.#view.getOrientation();\n    let imageIndex = index;\n    let rescaled = true;\n\n    // create oriented slice if needed\n    if (!isIdentityMat33(orientation)) {\n      image = this.#getSlice(image, imageIndex, rescaled, orientation);\n      // update position\n      imageIndex = new Index([0, 0, 0]);\n      rescaled = false;\n    }\n\n    // get region values\n    const iter = getVariableRegionSliceIterator(\n      image, imageIndex, rescaled, regions);\n    let values = [];\n    if (iter) {\n      values = getIteratorValues(iter);\n    }\n    return values;\n  }\n\n  /**\n   * Can the image values be quantified?\n   *\n   * @returns {boolean} True if possible.\n   */\n  canQuantifyImage() {\n    return this.#view.getImage().canQuantify();\n  }\n\n  /**\n   * Can window and level be applied to the data?\n   *\n   * @returns {boolean} True if possible.\n   * @deprecated Since v0.33, please use isMonochrome instead.\n   */\n  canWindowLevel() {\n    return this.isMonochrome();\n  }\n\n  /**\n   * Is the data monochrome.\n   *\n   * @returns {boolean} True if the data is monochrome.\n   */\n  isMonochrome() {\n    return this.#view.getImage().isMonochrome();\n  }\n\n  /**\n   * Can the data be scrolled?\n   *\n   * @returns {boolean} True if the data has either the third dimension\n   * or above greater than one.\n   */\n  canScroll() {\n    return this.#view.getImage().canScroll(this.#view.getOrientation());\n  }\n\n  /**\n   * Get the oriented image size.\n   *\n   * @returns {Size} The size.\n   */\n  getImageSize() {\n    return this.#view.getImage().getGeometry().getSize(\n      this.#view.getOrientation());\n  }\n\n\n  /**\n   * Is the data size larger than one in the given dimension?\n   *\n   * @param {number} dim The dimension.\n   * @returns {boolean} True if the image size is larger than one\n   *   in the given dimension.\n   */\n  moreThanOne(dim) {\n    return this.getImageSize().moreThanOne(dim);\n  }\n\n  /**\n   * Get the image world (mm) 2D size.\n   *\n   * @returns {Scalar2D} The 2D size as {x,y}.\n   */\n  getImageWorldSize() {\n    const geometry = this.#view.getImage().getGeometry();\n    const size = geometry.getSize(this.#view.getOrientation()).get2D();\n    const spacing = geometry.getSpacing(this.#view.getOrientation()).get2D();\n    return {\n      x: size.x * spacing.x,\n      y: size.y * spacing.y\n    };\n  }\n\n  /**\n   * Get the image rescaled data range.\n   *\n   * @returns {object} The range as {min, max}.\n   */\n  getImageRescaledDataRange() {\n    return this.#view.getImage().getRescaledDataRange();\n  }\n\n  /**\n   * Compare the input meta data to the associated image one.\n   *\n   * @param {object} meta The meta data.\n   * @returns {boolean} True if the associated image has equal meta data.\n   */\n  equalImageMeta(meta) {\n    const imageMeta = this.#view.getImage().getMeta();\n    // loop through input meta keys\n    const metaKeys = Object.keys(meta);\n    for (let i = 0; i < metaKeys.length; ++i) {\n      const metaKey = metaKeys[i];\n      if (typeof imageMeta[metaKey] === 'undefined') {\n        return false;\n      }\n      if (imageMeta[metaKey] !== meta[metaKey]) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  /**\n   * Check if the current position (default) or\n   * the provided position is in bounds.\n   *\n   * @param {Point} [position] Optional position.\n   * @returns {boolean} True is the position is in bounds.\n   */\n  isPositionInBounds(position) {\n    return this.#view.isPositionInBounds(position);\n  }\n\n  /**\n   * Set the current position.\n   *\n   * @param {Point} pos The position.\n   * @param {boolean} [silent] If true, does not fire a\n   *   positionchange event.\n   * @returns {boolean} False if not in bounds.\n   */\n  setCurrentPosition(pos, silent) {\n    return this.#view.setCurrentPosition(pos, silent);\n  }\n\n  /**\n   * Get a world position from a 2D plane position.\n   *\n   * @param {Point2D} point2D The input point.\n   * @param {number} [k] Optional slice index,\n   *   if undefined, uses the current one.\n   * @returns {Point} The associated position.\n   */\n  getPositionFromPlanePoint(point2D, k) {\n    // keep third direction\n    if (typeof k === 'undefined') {\n      k = this.getCurrentIndexScrollValue();\n    }\n    const planePoint = new Point3D(point2D.getX(), point2D.getY(), k);\n    // de-orient\n    const point = this.#planeHelper.getImageOrientedPoint3D(planePoint);\n    // ~indexToWorld to not loose precision\n    const geometry = this.#view.getImage().getGeometry();\n    const point3D = geometry.pointToWorld(point);\n    // merge with current position to keep extra dimensions\n    return this.getCurrentPosition().mergeWith3D(point3D);\n  }\n\n  /**\n   * Get a 2D plane position from a world position.\n   *\n   * @param {Point} point The 3D position.\n   * @returns {Point2D} The 2D position.\n   */\n  getPlanePositionFromPosition(point) {\n    // orient\n    const geometry = this.#view.getImage().getGeometry();\n    // ~worldToIndex to not loose precision\n    const point3D = geometry.worldToPoint(point);\n    const planePoint = this.#planeHelper.getImageDeOrientedPoint3D(point3D);\n    // return\n    return new Point2D(\n      planePoint.getX(),\n      planePoint.getY(),\n    );\n  }\n\n  /**\n   * Get the index of a world position.\n   *\n   * @param {Point} point The 3D position.\n   * @returns {Index} The index.\n   */\n  getIndexFromPosition(point) {\n    // orient\n    const geometry = this.#view.getImage().getGeometry();\n    // ~worldToIndex to not loose precision\n    return geometry.worldToIndex(point);\n  }\n\n  /**\n   * Set the current index.\n   *\n   * @param {Index} index The index.\n   * @param {boolean} [silent] If true, does not fire a positionchange event.\n   * @returns {boolean} False if not in bounds.\n   */\n  setCurrentIndex(index, silent) {\n    return this.#view.setCurrentIndex(index, silent);\n  }\n\n  /**\n   * Get a plane 3D position from a plane 2D position: does not compensate\n   *   for the image origin. Needed for setting the scale center...\n   *\n   * @param {Point2D} point2D The 2D position.\n   * @returns {Point3D} The 3D point.\n   */\n  getPlanePositionFromPlanePoint(point2D) {\n    // keep third direction\n    const k = this.getCurrentIndexScrollValue();\n    const planePoint = new Point3D(point2D.getX(), point2D.getY(), k);\n    // de-orient\n    const point = this.#planeHelper.getTargetDeOrientedPoint3D(planePoint);\n    // ~indexToWorld to not loose precision\n    const geometry = this.#view.getImage().getGeometry();\n    const spacing = geometry.getRealSpacing();\n    return new Point3D(\n      point.getX() * spacing.get(0),\n      point.getY() * spacing.get(1),\n      point.getZ() * spacing.get(2));\n  }\n\n  /**\n   * Get a 3D offset from a plane one.\n   *\n   * @param {Scalar2D} offset2D The plane offset as {x,y}.\n   * @returns {Vector3D} The 3D world offset.\n   */\n  getOffset3DFromPlaneOffset(offset2D) {\n    return this.#planeHelper.getOffset3DFromPlaneOffset(offset2D);\n  }\n\n  /**\n   * Scroll play: loop through all slices.\n   */\n  play() {\n    // ensure data is scrollable: dim >= 3\n    if (!this.canScroll()) {\n      return;\n    }\n    if (typeof this.#playerID === 'undefined') {\n      const image = this.#view.getImage();\n      const recommendedDisplayFrameRate =\n        image.getMeta().RecommendedDisplayFrameRate;\n      const milliseconds = this.#view.getPlaybackMilliseconds(\n        recommendedDisplayFrameRate);\n      const size = image.getGeometry().getSize();\n      const canScroll3D = size.canScroll3D();\n\n      this.#playerID = window.setInterval(() => {\n        let canDoMore = false;\n        if (canScroll3D) {\n          canDoMore = this.#positionHelper.incrementPositionAlongScroll();\n        } else {\n          canDoMore = this.#positionHelper.incrementPosition(3);\n        }\n        // end of scroll, loop back\n        if (!canDoMore) {\n          const pos1 = this.getCurrentIndex();\n          const values = pos1.getValues();\n          const orientation = this.#view.getOrientation();\n          if (canScroll3D) {\n            values[orientation.getThirdColMajorDirection()] = 0;\n          } else {\n            values[3] = 0;\n          }\n          const index = new Index(values);\n          const geometry = this.#view.getImage().getGeometry();\n          this.setCurrentPosition(geometry.indexToWorld(index));\n        }\n      }, milliseconds);\n    } else {\n      this.stop();\n    }\n  }\n\n  /**\n   * Stop scroll playing.\n   */\n  stop() {\n    if (typeof this.#playerID !== 'undefined') {\n      clearInterval(this.#playerID);\n      this.#playerID = undefined;\n    }\n  }\n\n  /**\n   * Get the window/level.\n   *\n   * @returns {WindowLevel} The window and level.\n   */\n  getWindowLevel() {\n    return this.#view.getWindowLevel();\n  }\n\n  /**\n   * Get the current window level preset name.\n   *\n   * @returns {string} The preset name.\n   */\n  getCurrentWindowPresetName() {\n    return this.#view.getCurrentWindowPresetName();\n  }\n\n  /**\n   * Set the window and level.\n   *\n   * @param {WindowLevel} wl The window and level.\n   */\n  setWindowLevel(wl) {\n    this.#view.setWindowLevel(wl);\n  }\n\n  /**\n   * Get the colour map.\n   *\n   * @returns {string} The colour map name.\n   */\n  getColourMap() {\n    return this.#view.getColourMap();\n  }\n\n  /**\n   * Set the colour map.\n   *\n   * @param {string} name The colour map name.\n   */\n  setColourMap(name) {\n    this.#view.setColourMap(name);\n  }\n\n  /**\n   * @callback alphaFn\n   * @param {number[]|number} value The pixel value.\n   * @param {number} index The values' index.\n   * @returns {number} The opacity of the input value.\n   */\n\n  /**\n   * Set the view per value alpha function.\n   *\n   * @param {alphaFn} func The function.\n   */\n  setViewAlphaFunction(func) {\n    this.#view.setAlphaFunction(func);\n  }\n\n  /**\n   * Bind the view image to the provided layer.\n   *\n   * @param {ViewLayer} viewLayer The layer to bind.\n   */\n  bindImageAndLayer(viewLayer) {\n    const image = this.#view.getImage();\n    image.addEventListener('imagecontentchange',\n      viewLayer.onimagecontentchange\n    );\n    image.addEventListener('imagegeometrychange',\n      viewLayer.onimagegeometrychange\n    );\n  }\n\n  /**\n   * Unbind the view image to the provided layer.\n   *\n   * @param {ViewLayer} viewLayer The layer to bind.\n   */\n  unbindImageAndLayer(viewLayer) {\n    const image = this.#view.getImage();\n    image.removeEventListener('imagecontentchange',\n      viewLayer.onimagecontentchange\n    );\n    image.removeEventListener('imagegeometrychange',\n      viewLayer.onimagegeometrychange\n    );\n  }\n\n} // class ViewController\n","import {logger} from '../utils/logger';\nimport {Point2D} from '../math/point';\n\n/**\n * List of interaction event names.\n */\nexport const InteractionEventNames = [\n  'mousedown',\n  'mousemove',\n  'mouseup',\n  'mouseout',\n  'wheel',\n  'dblclick',\n  'touchstart',\n  'touchmove',\n  'touchend'\n];\n\n/**\n * Get the positions (without the parent offset) of a list of touch events.\n *\n * @param {Array} touches The list of touch events.\n * @returns {Point2D[]} The list of positions of the touch events.\n */\nfunction getTouchesPositions(touches) {\n  // get the touch offset from all its parents\n  let offsetLeft = 0;\n  let offsetTop = 0;\n  if (touches.length !== 0 &&\n    typeof touches[0].target !== 'undefined') {\n    let offsetParent = touches[0].target.offsetParent;\n    while (offsetParent) {\n      if (!isNaN(offsetParent.offsetLeft)) {\n        offsetLeft += offsetParent.offsetLeft;\n      }\n      if (!isNaN(offsetParent.offsetTop)) {\n        offsetTop += offsetParent.offsetTop;\n      }\n      offsetParent = offsetParent.offsetParent;\n    }\n  } else {\n    logger.debug('No touch target offset parent.');\n  }\n  // set its position\n  const positions = [];\n  for (let i = 0; i < touches.length; ++i) {\n    positions.push(new Point2D(\n      touches[i].pageX - offsetLeft,\n      touches[i].pageY - offsetTop\n    ));\n  }\n  return positions;\n}\n\n/**\n * Get the offsets of an input touch event.\n *\n * @param {object} event The event to get the offset from.\n * @returns {Point2D[]} The array of points.\n */\nexport function getTouchPoints(event) {\n  let positions = [];\n  if (typeof event.targetTouches !== 'undefined' &&\n    event.targetTouches.length !== 0) {\n    // see https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/targetTouches\n    positions = getTouchesPositions(event.targetTouches);\n  } else if (typeof event.changedTouches !== 'undefined' &&\n    event.changedTouches.length !== 0) {\n    // see https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/changedTouches\n    positions = getTouchesPositions(event.changedTouches);\n  }\n  return positions;\n}\n\n/**\n * Get the offset of an input mouse event.\n *\n * @param {object} event The event to get the offset from.\n * @returns {Point2D} The 2D point.\n */\nexport function getMousePoint(event) {\n  // offsetX/Y: the offset in the X coordinate of the mouse pointer\n  // between that event and the padding edge of the target node\n  // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/offsetX\n  // https://caniuse.com/mdn-api_mouseevent_offsetx\n  return new Point2D(\n    event.offsetX,\n    event.offsetY\n  );\n}\n\n/**\n * Test if a canvas with the input size can be created.\n *\n * Ref:\n * - {@link https://github.com/ivmartel/dwv/issues/902},\n * - {@link https://github.com/jhildenbiddle/canvas-size/blob/v1.2.4/src/canvas-test.js}.\n *\n * @param {number} width The canvas width.\n * @param {number} height The canvas height.\n * @returns {boolean} True is the canvas can be created.\n */\nexport function canCreateCanvas(width, height) {\n  // test canvas with input size\n  const testCvs = document.createElement('canvas');\n  testCvs.width = width;\n  testCvs.height = height;\n  // crop canvas to speed up test\n  const cropCvs = document.createElement('canvas');\n  cropCvs.width = 1;\n  cropCvs.height = 1;\n  // contexts\n  const testCtx = testCvs.getContext('2d');\n  const cropCtx = cropCvs.getContext('2d');\n  // set data\n  if (testCtx) {\n    testCtx.fillRect(width - 1, height - 1, 1, 1);\n    // Render the test pixel in the bottom-right corner of the\n    // test canvas in the top-left of the 1x1 crop canvas. This\n    // dramatically reducing the time for getImageData to complete.\n    cropCtx.drawImage(testCvs, width - 1, height - 1, 1, 1, 0, 0, 1, 1);\n  }\n  // Verify image data (alpha component, Pass = 255, Fail = 0)\n  return cropCtx && cropCtx.getImageData(0, 0, 1, 1).data[3] !== 0;\n}\n","import {Index} from '../math/index';\nimport {ListenerHandler} from '../utils/listen';\nimport {viewEventNames} from '../image/view';\nimport {ViewController} from '../app/viewController';\nimport {Point2D} from '../math/point';\nimport {\n  canCreateCanvas,\n  InteractionEventNames\n} from './generic';\nimport {getScaledOffset} from './layerGroup';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Vector3D} from '../math/vector';\nimport {Point, Point3D} from '../math/point';\nimport {Scalar2D, Scalar3D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * View layer.\n */\nexport class ViewLayer {\n\n  /**\n   * Container div.\n   *\n   * @type {HTMLElement}\n   */\n  #containerDiv;\n\n  /**\n   * The view controller.\n   *\n   * @type {ViewController}\n   */\n  #viewController = null;\n\n  /**\n   * The main display canvas.\n   *\n   * @type {object}\n   */\n  #canvas = null;\n\n  /**\n   * The offscreen canvas: used to store the raw, unscaled pixel data.\n   *\n   * @type {object}\n   */\n  #offscreenCanvas = null;\n\n  /**\n   * The associated CanvasRenderingContext2D.\n   *\n   * @type {object}\n   */\n  #context = null;\n\n  /**\n   * Flag to know if the current position is valid.\n   *\n   * @type {boolean}\n   */\n  #isValidPosition = true;\n\n  /**\n   * The image data array.\n   *\n   * @type {ImageData}\n   */\n  #imageData = null;\n\n  /**\n   * The layer base size as {x,y}.\n   *\n   * @type {Scalar2D}\n   */\n  #baseSize;\n\n  /**\n   * The layer base spacing as {x,y}.\n   *\n   * @type {Scalar2D}\n   */\n  #baseSpacing;\n\n  /**\n   * The layer opacity.\n   *\n   * @type {number}\n   */\n  #opacity = 1;\n\n  /**\n   * The layer scale.\n   *\n   * @type {Scalar2D}\n   */\n  #scale = {x: 1, y: 1};\n\n  /**\n   * The layer fit scale.\n   *\n   * @type {Scalar2D}\n   */\n  #fitScale = {x: 1, y: 1};\n\n  /**\n   * The layer flip scale.\n   *\n   * @type {Scalar3D}\n   */\n  #flipScale = {x: 1, y: 1, z: 1};\n\n  /**\n   * The layer offset.\n   *\n   * @type {Scalar2D}\n   */\n  #offset = {x: 0, y: 0};\n\n  /**\n   * The base layer offset.\n   *\n   * @type {Scalar2D}\n   */\n  #baseOffset = {x: 0, y: 0};\n\n  /**\n   * The view offset.\n   *\n   * @type {Scalar2D}\n   */\n  #viewOffset = {x: 0, y: 0};\n\n  /**\n   * The zoom offset.\n   *\n   * @type {Scalar2D}\n   */\n  #zoomOffset = {x: 0, y: 0};\n\n  /**\n   * The flip offset.\n   *\n   * @type {Scalar2D}\n   */\n  #flipOffset = {x: 0, y: 0};\n\n  /**\n   * Data update flag.\n   *\n   * @type {boolean}\n   */\n  #needsDataUpdate = null;\n\n  /**\n   * The associated data id.\n   *\n   * @type {string}\n   */\n  #dataId;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Image smoothing flag.\n   *\n   * See: {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingEnabled}.\n   *\n   * @type {boolean}\n   */\n  #imageSmoothing = false;\n\n  /**\n   * Layer group origin.\n   *\n   * @type {Point3D}\n   */\n  #layerGroupOrigin;\n\n  /**\n   * Layer group first origin.\n   *\n   * @type {Point3D}\n   */\n  #layerGroupOrigin0;\n\n  /**\n   * @param {HTMLElement} containerDiv The layer div, its id will be used\n   *   as this layer id.\n   */\n  constructor(containerDiv) {\n    this.#containerDiv = containerDiv;\n    // specific css class name\n    this.#containerDiv.className += ' viewLayer';\n  }\n\n  /**\n   * Get the associated data id.\n   *\n   * @returns {string} The data id.\n   */\n  getDataId() {\n    return this.#dataId;\n  }\n\n  /**\n   * Get the layer scale.\n   *\n   * @returns {Scalar2D} The scale as {x,y}.\n   */\n  getScale() {\n    return this.#scale;\n  }\n\n  /**\n   * Get the layer zoom offset without the fit scale.\n   *\n   * @returns {Scalar2D} The offset as {x,y}.\n   */\n  getAbsoluteZoomOffset() {\n    return {\n      x: this.#zoomOffset.x * this.#fitScale.x,\n      y: this.#zoomOffset.y * this.#fitScale.y\n    };\n  }\n\n  /**\n   * Set the imageSmoothing flag value.\n   *\n   * @param {boolean} flag True to enable smoothing.\n   */\n  setImageSmoothing(flag) {\n    this.#imageSmoothing = flag;\n  }\n\n  /**\n   * Set the associated view.\n   *\n   * @param {object} view The view.\n   * @param {string} dataId The associated data id.\n   */\n  setView(view, dataId) {\n    this.#dataId = dataId;\n    // local listeners\n    view.addEventListener('wlchange', this.#onWLChange);\n    view.addEventListener('colourmapchange', this.#onColourMapChange);\n    view.addEventListener('positionchange', this.#onPositionChange);\n    view.addEventListener('alphafuncchange', this.#onAlphaFuncChange);\n    // view events\n    for (let j = 0; j < viewEventNames.length; ++j) {\n      view.addEventListener(viewEventNames[j], this.#fireEvent);\n    }\n    // create view controller\n    this.#viewController = new ViewController(view);\n    // bind layer and image\n    this.bindImage();\n  }\n\n  /**\n   * Get the view controller.\n   *\n   * @returns {ViewController} The controller.\n   */\n  getViewController() {\n    return this.#viewController;\n  }\n\n  /**\n   * Get the canvas image data.\n   *\n   * @returns {object} The image data.\n   */\n  getImageData() {\n    return this.#imageData;\n  }\n\n  /**\n   * Handle an image set event.\n   *\n   * @param {object} event The event.\n   * @function\n   */\n  onimageset = (event) => {\n    // event.value = [index, image]\n    if (this.#dataId === event.dataid) {\n      this.#viewController.setImage(event.value[0]);\n      this.#setBaseSize(this.#viewController.getImageSize().get2D());\n      this.#needsDataUpdate = true;\n    }\n  };\n\n  /**\n   * Bind this layer to the view image.\n   */\n  bindImage() {\n    if (this.#viewController) {\n      this.#viewController.bindImageAndLayer(this);\n    }\n  }\n\n  /**\n   * Unbind this layer to the view image.\n   */\n  unbindImage() {\n    if (this.#viewController) {\n      this.#viewController.unbindImageAndLayer(this);\n    }\n  }\n\n  /**\n   * Handle an image content change event.\n   *\n   * @param {object} event The event.\n   * @function\n   */\n  onimagecontentchange = (event) => {\n    // event.value = [index]\n    if (this.#dataId === event.dataid) {\n      this.#isValidPosition = this.#viewController.isPositionInBounds();\n      // flag update and draw\n      this.#needsDataUpdate = true;\n      this.draw();\n    }\n  };\n\n  /**\n   * Handle an image change event.\n   *\n   * @param {object} event The event.\n   * @function\n   */\n  onimagegeometrychange = (event) => {\n    // event.value = [index]\n    if (this.#dataId === event.dataid) {\n      const vcSize = this.#viewController.getImageSize().get2D();\n      if (this.#baseSize.x !== vcSize.x ||\n        this.#baseSize.y !== vcSize.y) {\n        // size changed, recalculate base offset\n        // in case origin changed\n        if (typeof this.#layerGroupOrigin !== 'undefined' &&\n          typeof this.#layerGroupOrigin0 !== 'undefined') {\n          const origin0 = this.#viewController.getOrigin();\n          const scrollOffset = this.#layerGroupOrigin0.minus(origin0);\n          const origin = this.#viewController.getOrigin(\n            this.#viewController.getCurrentPosition()\n          );\n          const planeOffset = this.#layerGroupOrigin.minus(origin);\n          this.setBaseOffset(scrollOffset, planeOffset);\n        }\n        // update base size\n        this.#setBaseSize(vcSize);\n        // flag update and draw\n        this.#needsDataUpdate = true;\n        this.draw();\n      }\n    }\n  };\n\n  // common layer methods [start] ---------------\n\n  /**\n   * Get the id of the layer.\n   *\n   * @returns {string} The string id.\n   */\n  getId() {\n    return this.#containerDiv.id;\n  }\n\n  /**\n   * Remove the HTML element from the DOM.\n   */\n  removeFromDOM() {\n    this.#containerDiv.remove();\n  }\n\n  /**\n   * Get the layer base size (without scale).\n   *\n   * @returns {Scalar2D} The size as {x,y}.\n   */\n  getBaseSize() {\n    return this.#baseSize;\n  }\n\n  /**\n   * Get the image world (mm) 2D size.\n   *\n   * @returns {Scalar2D} The 2D size as {x,y}.\n   */\n  getImageWorldSize() {\n    return this.#viewController.getImageWorldSize();\n  }\n\n  /**\n   * Get the layer opacity.\n   *\n   * @returns {number} The opacity ([0:1] range).\n   */\n  getOpacity() {\n    return this.#opacity;\n  }\n\n  /**\n   * Set the layer opacity.\n   *\n   * @param {number} alpha The opacity ([0:1] range).\n   */\n  setOpacity(alpha) {\n    if (alpha === this.#opacity) {\n      return;\n    }\n\n    this.#opacity = Math.min(Math.max(alpha, 0), 1);\n\n    /**\n     * Opacity change event.\n     *\n     * @event App#opacitychange\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    const event = {\n      type: 'opacitychange',\n      value: [this.#opacity]\n    };\n    this.#fireEvent(event);\n  }\n\n  /**\n   * Add a flip offset along the layer X axis.\n   */\n  addFlipOffsetX() {\n    this.#flipOffset.x += this.#canvas.width / this.#scale.x;\n    this.#offset.x += this.#flipOffset.x;\n  }\n\n  /**\n   * Add a flip offset along the layer Y axis.\n   */\n  addFlipOffsetY() {\n    this.#flipOffset.y += this.#canvas.height / this.#scale.y;\n    this.#offset.y += this.#flipOffset.y;\n  }\n\n  /**\n   * Flip the scale along the layer X axis.\n   */\n  flipScaleX() {\n    this.#flipScale.x *= -1;\n  }\n\n  /**\n   * Flip the scale along the layer Y axis.\n   */\n  flipScaleY() {\n    this.#flipScale.y *= -1;\n  }\n\n  /**\n   * Flip the scale along the layer Z axis.\n   */\n  flipScaleZ() {\n    this.#flipScale.z *= -1;\n  }\n\n  /**\n   * Set the layer scale.\n   *\n   * @param {Scalar3D} newScale The scale as {x,y,z}.\n   * @param {Point3D} [center] The scale center.\n   */\n  setScale(newScale, center) {\n    const helper = this.#viewController.getPlaneHelper();\n    const orientedNewScale = helper.getTargetOrientedPositiveXYZ({\n      x: newScale.x * this.#flipScale.x,\n      y: newScale.y * this.#flipScale.y,\n      z: newScale.z * this.#flipScale.z,\n    });\n    const finalNewScale = {\n      x: this.#fitScale.x * orientedNewScale.x,\n      y: this.#fitScale.y * orientedNewScale.y\n    };\n\n    if (Math.abs(newScale.x) === 1 &&\n      Math.abs(newScale.y) === 1 &&\n      Math.abs(newScale.z) === 1) {\n      // reset zoom offset for scale=1\n      const resetOffset = {\n        x: this.#offset.x - this.#zoomOffset.x,\n        y: this.#offset.y - this.#zoomOffset.y\n      };\n      // store new offset\n      this.#zoomOffset = {x: 0, y: 0};\n      this.#offset = resetOffset;\n    } else {\n      if (typeof center !== 'undefined') {\n        let worldCenter = helper.getPlaneOffsetFromOffset3D({\n          x: center.getX(),\n          y: center.getY(),\n          z: center.getZ()\n        });\n        // center was obtained with viewLayer.displayToMainPlanePos\n        // compensated for baseOffset\n        // TODO: justify...\n        worldCenter = {\n          x: worldCenter.x + this.#baseOffset.x,\n          y: worldCenter.y + this.#baseOffset.y\n        };\n\n        const newOffset = getScaledOffset(\n          this.#offset, this.#scale, finalNewScale, worldCenter);\n\n        const newZoomOffset = {\n          x: this.#zoomOffset.x + newOffset.x - this.#offset.x,\n          y: this.#zoomOffset.y + newOffset.y - this.#offset.y\n        };\n        // store new offset\n        this.#zoomOffset = newZoomOffset;\n        this.#offset = newOffset;\n      }\n    }\n\n    // store new scale\n    this.#scale = finalNewScale;\n  }\n\n  /**\n   * Initialise the layer scale.\n   *\n   * @param {Scalar3D} newScale The scale as {x,y,z}.\n   * @param {Scalar2D} absoluteZoomOffset The zoom offset as {x,y}\n   *   without the fit scale (as provided by getAbsoluteZoomOffset).\n   */\n  initScale(newScale, absoluteZoomOffset) {\n    const helper = this.#viewController.getPlaneHelper();\n    const orientedNewScale = helper.getTargetOrientedPositiveXYZ({\n      x: newScale.x * this.#flipScale.x,\n      y: newScale.y * this.#flipScale.y,\n      z: newScale.z * this.#flipScale.z,\n    });\n    const finalNewScale = {\n      x: this.#fitScale.x * orientedNewScale.x,\n      y: this.#fitScale.y * orientedNewScale.y\n    };\n    this.#scale = finalNewScale;\n\n    this.#zoomOffset = {\n      x: absoluteZoomOffset.x / this.#fitScale.x,\n      y: absoluteZoomOffset.y / this.#fitScale.y\n    };\n    this.#offset = {\n      x: this.#offset.x + this.#zoomOffset.x,\n      y: this.#offset.y + this.#zoomOffset.y\n    };\n  }\n\n  /**\n   * Set the base layer offset. Updates the layer offset.\n   *\n   * @param {Vector3D} scrollOffset The scroll offset vector.\n   * @param {Vector3D} planeOffset The plane offset vector.\n   * @param {Point3D} [layerGroupOrigin] The layer group origin.\n   * @param {Point3D} [layerGroupOrigin0] The layer group first origin.\n   * @returns {boolean} True if the offset was updated.\n   */\n  setBaseOffset(\n    scrollOffset, planeOffset,\n    layerGroupOrigin, layerGroupOrigin0) {\n    const helper = this.#viewController.getPlaneHelper();\n    const scrollDimIndex = helper.getNativeScrollDimIndex();\n    const newOffset = helper.getPlaneOffsetFromOffset3D({\n      x: scrollDimIndex === 0 ? scrollOffset.getX() : planeOffset.getX(),\n      y: scrollDimIndex === 1 ? scrollOffset.getY() : planeOffset.getY(),\n      z: scrollDimIndex === 2 ? scrollOffset.getZ() : planeOffset.getZ(),\n    });\n    const needsUpdate = this.#baseOffset.x !== newOffset.x ||\n      this.#baseOffset.y !== newOffset.y;\n    // store layer group origins\n    if (typeof layerGroupOrigin !== 'undefined' &&\n      typeof layerGroupOrigin0 !== 'undefined') {\n      this.#layerGroupOrigin = layerGroupOrigin;\n      this.#layerGroupOrigin0 = layerGroupOrigin0;\n    }\n    // reset offset if needed\n    if (needsUpdate) {\n      this.#offset = {\n        x: this.#offset.x - this.#baseOffset.x + newOffset.x,\n        y: this.#offset.y - this.#baseOffset.y + newOffset.y\n      };\n      this.#baseOffset = newOffset;\n    }\n    return needsUpdate;\n  }\n\n  /**\n   * Set the layer offset.\n   *\n   * @param {Scalar3D} newOffset The offset as {x,y,z}.\n   */\n  setOffset(newOffset) {\n    const helper = this.#viewController.getPlaneHelper();\n    const planeNewOffset = helper.getPlaneOffsetFromOffset3D(newOffset);\n    this.#offset = {\n      x: planeNewOffset.x +\n        this.#viewOffset.x +\n        this.#baseOffset.x +\n        this.#zoomOffset.x +\n        this.#flipOffset.x,\n      y: planeNewOffset.y +\n        this.#viewOffset.y +\n        this.#baseOffset.y +\n        this.#zoomOffset.y +\n        this.#flipOffset.y\n    };\n  }\n\n  /**\n   * Transform a display position to a 2D index.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {Index} The equivalent 2D index.\n   */\n  displayToPlaneIndex(point2D) {\n    const planePos = this.displayToPlanePos(point2D);\n    return new Index([\n      Math.floor(planePos.getX()),\n      Math.floor(planePos.getY())\n    ]);\n  }\n\n  /**\n   * Remove scale from a display position.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {Point2D} The de-scaled point.\n   */\n  displayToPlaneScale(point2D) {\n    return new Point2D(\n      point2D.getX() / this.#scale.x,\n      point2D.getY() / this.#scale.y\n    );\n  }\n\n  /**\n   * Get a plane position from a display position.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {Point2D} The plane position.\n   */\n  displayToPlanePos(point2D) {\n    const deScaled = this.displayToPlaneScale(point2D);\n    return new Point2D(\n      deScaled.getX() + this.#offset.x,\n      deScaled.getY() + this.#offset.y\n    );\n  }\n\n  /**\n   * Get a display position from a plane position.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {Point2D} The display position, can be individually\n   *   undefined if out of bounds.\n   */\n  planePosToDisplay(point2D) {\n    let posX =\n      (point2D.getX() - this.#offset.x + this.#baseOffset.x) * this.#scale.x;\n    let posY =\n      (point2D.getY() - this.#offset.y + this.#baseOffset.y) * this.#scale.y;\n    // check if in bounds\n    if (posX < 0 || posX >= this.#canvas.width) {\n      posX = undefined;\n    }\n    if (posY < 0 || posY >= this.#canvas.height) {\n      posY = undefined;\n    }\n    return new Point2D(posX, posY);\n  }\n\n  /**\n   * Get a main plane position from a display position.\n   *\n   * @param {Point2D} point2D The input point.\n   * @returns {Point2D} The main plane position.\n   */\n  displayToMainPlanePos(point2D) {\n    const planePos = this.displayToPlanePos(point2D);\n    return new Point2D(\n      planePos.getX() - this.#baseOffset.x,\n      planePos.getY() - this.#baseOffset.y\n    );\n  }\n\n  /**\n   * Display the layer.\n   *\n   * @param {boolean} flag Whether to display the layer or not.\n   */\n  display(flag) {\n    this.#containerDiv.style.display = flag ? '' : 'none';\n  }\n\n  /**\n   * Check if the layer is visible.\n   *\n   * @returns {boolean} True if the layer is visible.\n   */\n  isVisible() {\n    return this.#containerDiv.style.display === '';\n  }\n\n  /**\n   * Draw the content (imageData) of the layer.\n   * The imageData variable needs to be set.\n   *\n   * @fires App#renderstart\n   * @fires App#renderend\n   */\n  draw() {\n    // skip for non valid position\n    if (!this.#isValidPosition) {\n      return;\n    }\n\n    /**\n     * Render start event.\n     *\n     * @event App#renderstart\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    let event = {\n      type: 'renderstart',\n      layerid: this.getId(),\n      dataid: this.getDataId()\n    };\n    this.#fireEvent(event);\n\n    // update data if needed\n    if (this.#needsDataUpdate) {\n      this.#updateImageData();\n    }\n\n    // context opacity\n    this.#context.globalAlpha = this.#opacity;\n\n    // clear context\n    this.clear();\n\n    // draw the cached canvas on the context\n    // transform takes as input a, b, c, d, e, f to create\n    // the transform matrix (column-major order):\n    // [ a c e ]\n    // [ b d f ]\n    // [ 0 0 1 ]\n    this.#context.setTransform(\n      this.#scale.x,\n      0,\n      0,\n      this.#scale.y,\n      -1 * this.#offset.x * this.#scale.x,\n      -1 * this.#offset.y * this.#scale.y\n    );\n\n    // disable smoothing (set just before draw, could be reset by resize)\n    this.#context.imageSmoothingEnabled = this.#imageSmoothing;\n    // draw image\n    this.#context.drawImage(this.#offscreenCanvas, 0, 0);\n\n    /**\n     * Render end event.\n     *\n     * @event App#renderend\n     * @type {object}\n     * @property {string} type The event type.\n     */\n    event = {\n      type: 'renderend',\n      layerid: this.getId(),\n      dataid: this.getDataId()\n    };\n    this.#fireEvent(event);\n  }\n\n  /**\n   * Initialise the layer: set the canvas and context.\n   *\n   * @param {Scalar2D} size The image size as {x,y}.\n   * @param {Scalar2D} spacing The image spacing as {x,y}.\n   * @param {number} alpha The initial data opacity.\n   */\n  initialise(size, spacing, alpha) {\n    // set locals\n    this.#baseSpacing = spacing;\n    this.#opacity = Math.min(Math.max(alpha, 0), 1);\n\n    // create canvas\n    // (canvas size is set in fitToContainer)\n    this.#canvas = document.createElement('canvas');\n    this.#containerDiv.appendChild(this.#canvas);\n\n    // check that the getContext method exists\n    if (!this.#canvas.getContext) {\n      alert('Error: no canvas.getContext method.');\n      return;\n    }\n    // get the 2D context\n    this.#context = this.#canvas.getContext('2d');\n    if (!this.#context) {\n      alert('Error: failed to get the 2D context.');\n      return;\n    }\n\n    // off screen canvas\n    this.#offscreenCanvas = document.createElement('canvas');\n\n    // set base size: needs an existing context and off screen canvas\n    this.#setBaseSize(size);\n\n    // update data on first draw\n    this.#needsDataUpdate = true;\n  }\n\n  /**\n   * Set the base size of the layer.\n   *\n   * @param {Scalar2D} size The size as {x,y}.\n   */\n  #setBaseSize(size) {\n    // check canvas creation\n    if (!canCreateCanvas(size.x, size.y)) {\n      throw new Error('Cannot create canvas with size ' +\n        size.x + ', ' + size.y);\n    }\n\n    // set local\n    this.#baseSize = size;\n\n    // off screen canvas\n    this.#offscreenCanvas.width = this.#baseSize.x;\n    this.#offscreenCanvas.height = this.#baseSize.y;\n    // original empty image data array\n    this.#context.clearRect(0, 0, this.#baseSize.x, this.#baseSize.y);\n    this.#imageData = this.#context.createImageData(\n      this.#baseSize.x, this.#baseSize.y);\n  }\n\n  /**\n   * Fit the layer to its parent container.\n   *\n   * @param {Scalar2D} containerSize The fit size as {x,y}.\n   * @param {number} divToWorldSizeRatio The div to world size ratio.\n   * @param {Scalar2D} fitOffset The fit offset as {x,y}.\n   */\n  fitToContainer(containerSize, divToWorldSizeRatio, fitOffset) {\n    let needsDraw = false;\n\n    // set canvas size if different from previous\n    if (this.#canvas.width !== containerSize.x ||\n      this.#canvas.height !== containerSize.y) {\n      if (!canCreateCanvas(containerSize.x, containerSize.y)) {\n        throw new Error('Cannot resize canvas ' +\n          containerSize.x + ', ' + containerSize.y);\n      }\n      // canvas size change triggers canvas reset\n      this.#canvas.width = containerSize.x;\n      this.#canvas.height = containerSize.y;\n      // update draw flag\n      needsDraw = true;\n    }\n\n    // fit scale\n    const divToImageSizeRatio = {\n      x: divToWorldSizeRatio * this.#baseSpacing.x,\n      y: divToWorldSizeRatio * this.#baseSpacing.y\n    };\n    // #scale = inputScale * fitScale * flipScale\n    // flipScale does not change here, we can omit it\n    // newScale = (#scale / fitScale) * newFitScale\n    const newScale = {\n      x: this.#scale.x * divToImageSizeRatio.x / this.#fitScale.x,\n      y: this.#scale.y * divToImageSizeRatio.y / this.#fitScale.y\n    };\n\n    // set scales if different from previous\n    if (this.#scale.x !== newScale.x ||\n      this.#scale.y !== newScale.y) {\n      this.#fitScale = divToImageSizeRatio;\n      this.#scale = newScale;\n      // update draw flag\n      needsDraw = true;\n    }\n\n    // view offset\n    const newViewOffset = {\n      x: fitOffset.x / divToImageSizeRatio.x,\n      y: fitOffset.y / divToImageSizeRatio.y\n    };\n    // flip offset\n    const scaledImageSize = {\n      x: containerSize.x / divToImageSizeRatio.x,\n      y: containerSize.y / divToImageSizeRatio.y\n    };\n    const newFlipOffset = {\n      x: this.#flipOffset.x !== 0 ? scaledImageSize.x : 0,\n      y: this.#flipOffset.y !== 0 ? scaledImageSize.y : 0,\n    };\n\n    // set offsets if different from previous\n    if (this.#viewOffset.x !== newViewOffset.x ||\n      this.#viewOffset.y !== newViewOffset.y ||\n      this.#flipOffset.x !== newFlipOffset.x ||\n      this.#flipOffset.y !== newFlipOffset.y) {\n      // update global offset\n      this.#offset = {\n        x: this.#offset.x +\n          newViewOffset.x - this.#viewOffset.x +\n          newFlipOffset.x - this.#flipOffset.x,\n        y: this.#offset.y +\n          newViewOffset.y - this.#viewOffset.y +\n          newFlipOffset.y - this.#flipOffset.y,\n      };\n      // update private local offsets\n      this.#flipOffset = newFlipOffset;\n      this.#viewOffset = newViewOffset;\n      // update draw flag\n      needsDraw = true;\n    }\n\n    // draw if needed\n    if (needsDraw) {\n      this.draw();\n    }\n  }\n\n  /**\n   * Enable and listen to container interaction events.\n   */\n  bindInteraction() {\n    // allow pointer events\n    this.#containerDiv.style.pointerEvents = 'auto';\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      const eventName = names[i];\n      const passive = eventName !== 'wheel';\n      this.#containerDiv.addEventListener(\n        eventName, this.#fireEvent, {passive: passive});\n    }\n  }\n\n  /**\n   * Disable and stop listening to container interaction events.\n   */\n  unbindInteraction() {\n    // disable pointer events\n    this.#containerDiv.style.pointerEvents = 'none';\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      this.#containerDiv.removeEventListener(names[i], this.#fireEvent);\n    }\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    event.srclayerid = this.getId();\n    event.dataid = this.#dataId;\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  // common layer methods [end] ---------------\n\n  /**\n   * Update the canvas image data.\n   */\n  #updateImageData() {\n    // generate image data\n    this.#viewController.generateImageData(this.#imageData);\n    // pass the data to the off screen canvas\n    this.#offscreenCanvas.getContext('2d').putImageData(this.#imageData, 0, 0);\n    // update data flag\n    this.#needsDataUpdate = false;\n  }\n\n  /**\n   * Handle window/level change.\n   *\n   * @param {object} event The event fired when changing the window/level.\n   */\n  #onWLChange = (event) => {\n    // generate and draw if no skip flag\n    const skip = typeof event.skipGenerate !== 'undefined' &&\n      event.skipGenerate === true;\n    if (!skip) {\n      this.#needsDataUpdate = true;\n      this.draw();\n    }\n  };\n\n  /**\n   * Handle colour map change.\n   *\n   * @param {object} event The event fired when changing the colour map.\n   */\n  #onColourMapChange = (event) => {\n    const skip = typeof event.skipGenerate !== 'undefined' &&\n      event.skipGenerate === true;\n    if (!skip) {\n      this.#needsDataUpdate = true;\n      this.draw();\n    }\n  };\n\n  /**\n   * Handle position change.\n   *\n   * @param {object} event The event fired when changing the position.\n   */\n  #onPositionChange = (event) => {\n    const skip = typeof event.skipGenerate !== 'undefined' &&\n      event.skipGenerate === true;\n    if (!skip) {\n      let valid = true;\n      if (typeof event.valid !== 'undefined') {\n        valid = event.valid;\n      }\n      // clear for non valid events\n      if (!valid) {\n        // clear only once\n        if (this.#isValidPosition) {\n          this.#isValidPosition = false;\n          this.clear();\n        }\n      } else {\n        // 3D dimensions\n        const dims3D = [0, 1, 2];\n        // remove scroll index\n        const indexScrollDimIndex =\n          dims3D.indexOf(this.#viewController.getScrollDimIndex());\n        dims3D.splice(indexScrollDimIndex, 1);\n        // remove non scroll index from diff dims\n        const diffDims = event.diffDims.filter(function (item) {\n          return dims3D.indexOf(item) === -1;\n        });\n        // update if we have something left\n        if (diffDims.length !== 0 || !this.#isValidPosition) {\n          // reset valid flag\n          this.#isValidPosition = true;\n          // reset update flag\n          this.#needsDataUpdate = true;\n          this.draw();\n        }\n      }\n    }\n  };\n\n  /**\n   * Handle alpha function change.\n   *\n   * @param {object} event The event fired when changing the function.\n   */\n  #onAlphaFuncChange = (event) => {\n    const skip = typeof event.skipGenerate !== 'undefined' &&\n      event.skipGenerate === true;\n    if (!skip) {\n      this.#needsDataUpdate = true;\n      this.draw();\n    }\n  };\n\n  /**\n   * Set the current position.\n   *\n   * @param {Point} position The new position.\n   * @param {Index} _index The new index.\n   * @returns {boolean} True if the position was updated.\n   */\n  setCurrentPosition(position, _index) {\n    return this.#viewController.setCurrentPosition(position);\n  }\n\n  /**\n   * Clear the context.\n   */\n  clear() {\n    // clear the context: reset the transform first\n    // store the current transformation matrix\n    this.#context.save();\n    // use the identity matrix while clearing the canvas\n    this.#context.setTransform(1, 0, 0, 1, 0, 0);\n    this.#context.clearRect(0, 0, this.#canvas.width, this.#canvas.height);\n    // restore the transform\n    this.#context.restore();\n  }\n\n} // ViewLayer class\n","import {getLayerDetailsFromEvent} from '../gui/layerGroup';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get a normalised spin speed in the Y direction to try to support\n * trackpads (small and large deltaY) and mouse wheel (large deltaY).\n * Should return 1 or -1 for a single mouse wheel tick.\n *\n * @param {object} event The wheel event.\n * @returns {number} The normalised spin Y.\n */\nfunction getSpinY(event) {\n  // (notes of 03/2024)\n\n  // firefox seems to change the value of deltaY\n  // if you ask for deltaMode before (?????)\n\n  // deltaY (for a single mouse wheel tick):\n  // - chrome: [linux] 120, [mac]: 4\n  // - firefox: [linux] 132, [mac]: 16\n\n  // wheelDelta (for a single mouse wheel tick):\n  // - chrome: [linux] 120, [mac]: 240\n  // - firefox: [linux] 120, [mac]: 48\n\n  // -> using wheelDelta for mouse wheel detection as\n  //    it is consistently larger than trackpad scroll\n\n  // wheelDeltaY and deltaY do not go in the same direction,\n  // using -deltaY so that they do...\n\n  if (typeof event.wheelDeltaY === 'undefined') {\n    //logger.warn('No wheel delta, scroll could be tricky...);\n    return -event.deltaY;\n  } else {\n    const threshold = 45;\n    if (event.wheelDeltaY > threshold) {\n      return 1;\n    } else if (event.wheelDeltaY < -threshold) {\n      return -1;\n    } else {\n      return -event.deltaY / 60;\n    }\n  }\n}\n\n/**\n * Class to sum wheel events and know if that sum\n * corresponds to a 'tick'.\n */\nclass ScrollSum {\n  /**\n   * The scroll sum.\n   *\n   * @type {number}\n   */\n  #sum = 0;\n\n  /**\n   * Get the scroll sum.\n   *\n   * @returns {number} The scroll sum.\n   */\n  getSum() {\n    return this.#sum;\n  }\n\n  /**\n   * Add scroll.\n   *\n   * @param {object} event The wheel event.\n   */\n  add(event) {\n    this.#sum += getSpinY(event);\n  }\n\n  /**\n   * Clear the scroll sum.\n   */\n  clear() {\n    this.#sum = 0;\n  }\n\n  /**\n   * Does the accumulated scroll correspond to a 'tick'.\n   *\n   * @returns {boolean} True if the sum corresponds to a 'tick'.\n   */\n  isTick() {\n    return Math.abs(this.#sum) >= 1;\n  }\n}\n\n/**\n * Scroll wheel class: provides a wheel event handler\n *   that scroll the corresponding data.\n */\nexport class ScrollWheel {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Accumulated scroll.\n   *\n   * @type {ScrollSum}\n   */\n  #scrollSum = new ScrollSum();\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {WheelEvent} event The mouse wheel event.\n   */\n  wheel(event) {\n    this.#scrollSum.add(event);\n    const up = this.#scrollSum.getSum() >= 0;\n\n    // exit if no tick\n    if (!this.#scrollSum.isTick()) {\n      return;\n    } else {\n      this.#scrollSum.clear();\n    }\n\n    // prevent default page scroll\n    event.preventDefault();\n\n    const layerDetails = getLayerDetailsFromEvent(event);\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    const positionHelper = layerGroup.getPositionHelper();\n\n    if (layerGroup.canScroll()) {\n      if (up) {\n        positionHelper.incrementPositionAlongScroll();\n      } else {\n        positionHelper.decrementPositionAlongScroll();\n      }\n    } else if (layerGroup.moreThanOne(3)) {\n      if (up) {\n        positionHelper.incrementPosition(3);\n      } else {\n        positionHelper.decrementPosition(3);\n      }\n    }\n  }\n\n} // ScrollWheel class\n","import {Point2D} from './point';\nimport {\n  isSimilar,\n  REAL_WORLD_EPSILON,\n} from './matrix';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {ViewController} from '../app/viewController';\nimport {Scalar2D} from './scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Line shape.\n */\nexport class Line {\n\n  /**\n   * Line begin point.\n   *\n   * @type {Point2D}\n   */\n  #begin;\n\n  /**\n   * Line end point.\n   *\n   * @type {Point2D}\n   */\n  #end;\n\n  /**\n   * @param {Point2D} begin A Point2D representing the beginning\n   *   of the line.\n   * @param {Point2D} end A Point2D representing the end of the line.\n   */\n  constructor(begin, end) {\n    this.#begin = begin;\n    this.#end = end;\n  }\n\n  /**\n   * Get the begin point of the line.\n   *\n   * @returns {Point2D} The beginning point of the line.\n   */\n  getBegin() {\n    return this.#begin;\n  }\n\n  /**\n   * Get the end point of the line.\n   *\n   * @returns {Point2D} The ending point of the line.\n   */\n  getEnd() {\n    return this.#end;\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Line} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.getBegin().equals(rhs.getBegin()) &&\n      this.getEnd().equals(rhs.getEnd());\n  }\n\n  /**\n   * Get the line delta in the X direction.\n   *\n   * @returns {number} The delta in the X direction.\n   */\n  getDeltaX() {\n    return this.getEnd().getX() - this.getBegin().getX();\n  }\n\n  /**\n   * Get the line delta in the Y direction.\n   *\n   * @returns {number} The delta in the Y direction.\n   */\n  getDeltaY() {\n    return this.getEnd().getY() - this.getBegin().getY();\n  }\n\n  /**\n   * Get the length of the line.\n   *\n   * @returns {number} The length of the line.\n   */\n  getLength() {\n    return Math.sqrt(\n      this.getDeltaX() * this.getDeltaX() +\n      this.getDeltaY() * this.getDeltaY()\n    );\n  }\n\n  /**\n   * Get the length of the line according to a  spacing.\n   *\n   * @param {Scalar2D} spacing2D The 2D spacing.\n   * @returns {number} The length of the line with spacing\n   *  or null for null spacings.\n   */\n  getWorldLength(spacing2D) {\n    let wlen = null;\n    if (spacing2D !== null) {\n      const dxs = this.getDeltaX() * spacing2D.x;\n      const dys = this.getDeltaY() * spacing2D.y;\n      wlen = Math.sqrt(dxs * dxs + dys * dys);\n    }\n    return wlen;\n  }\n\n  /**\n   * Get the mid point of the line.\n   *\n   * @returns {Point2D} The mid point of the line.\n   */\n  getMidpoint() {\n    return new Point2D(\n      (this.getBegin().getX() + this.getEnd().getX()) / 2,\n      (this.getBegin().getY() + this.getEnd().getY()) / 2\n    );\n  }\n\n  /**\n   * Get the centroid of the line.\n   *\n   * @returns {Point2D} THe centroid point.\n   */\n  getCentroid() {\n    return this.getMidpoint();\n  }\n\n  /**\n   * Get the slope of the line.\n   *\n   * @returns {number} The slope of the line.\n   */\n  getSlope() {\n    return this.getDeltaY() / this.getDeltaX();\n  }\n\n  /**\n   * Get the intercept of the line.\n   *\n   * @returns {number} The slope of the line.\n   */\n  getIntercept() {\n    return (\n      this.getEnd().getX() * this.getBegin().getY() -\n      this.getBegin().getX() * this.getEnd().getY()\n    ) / this.getDeltaX();\n  }\n\n  /**\n   * Get the inclination of the line.\n   *\n   * @returns {number} The inclination of the line.\n   */\n  getInclination() {\n    // tan(theta) = slope\n    const angle =\n      Math.atan2(this.getDeltaY(), this.getDeltaX()) * 180 / Math.PI;\n    // shift?\n    return 180 - angle;\n  }\n\n  /**\n   * Quantify a line according to view information.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   * @returns {object} A quantification object.\n   */\n  quantify(viewController) {\n    const quant = {};\n    // length\n    const spacing2D = viewController.get2DSpacing();\n    const length = this.getWorldLength(spacing2D);\n    if (length !== null) {\n      quant.length = {value: length, unit: 'unit.mm'};\n    }\n    // return\n    return quant;\n  }\n\n} // Line class\n\n/**\n * Get the angle between two lines in degree.\n *\n * @param {Line} line0 The first line.\n * @param {Line} line1 The second line.\n * @returns {number} The angle.\n */\nexport function getAngle(line0, line1) {\n  const dx0 = line0.getDeltaX();\n  const dy0 = line0.getDeltaY();\n  const dx1 = line1.getDeltaX();\n  const dy1 = line1.getDeltaY();\n  // dot = ||a||*||b||*cos(theta)\n  const dot = dx0 * dx1 + dy0 * dy1;\n  // cross = ||a||*||b||*sin(theta)\n  const det = dx0 * dy1 - dy0 * dx1;\n  // tan = sin / cos\n  const angle = Math.atan2(det, dot) * 180 / Math.PI;\n  // complementary angle\n  // shift?\n  return 360 - (180 - angle);\n}\n\n/**\n * Check if two lines are orthogonal.\n *\n * @param {Line} line0 The first line.\n * @param {Line} line1 The second line.\n * @returns {boolean} True if both lines are orthogonal.\n */\nexport function areOrthogonal(line0, line1) {\n  const dx0 = line0.getDeltaX();\n  const dy0 = line0.getDeltaY();\n  const dx1 = line1.getDeltaX();\n  const dy1 = line1.getDeltaY();\n  // dot = ||a||*||b||*cos(theta)\n  return (dx0 * dx1 + dy0 * dy1) === 0;\n}\n\n/**\n * Check if a point is in a line coordinate range.\n *\n * @param {Point2D} point The input point.\n * @param {Line} line The input line.\n * @returns {boolean} True if the input point is in the line coordinate range.\n */\nexport function isPointInLineRange(point, line) {\n  const minX = Math.min(line.getBegin().getX(), line.getEnd().getX());\n  const maxX = Math.max(line.getBegin().getX(), line.getEnd().getX());\n  const minY = Math.min(line.getBegin().getY(), line.getEnd().getY());\n  const maxY = Math.max(line.getBegin().getY(), line.getEnd().getY());\n  return point.getX() >= minX &&\n    point.getX() <= maxX &&\n    point.getY() >= minY &&\n    point.getY() <= maxY;\n}\n\n/**\n * Get a perpendicular line to an input one at a given point.\n *\n * @param {Line} line The line to be perpendicular to.\n * @param {Point2D} point The middle point of the perpendicular line.\n * @param {number} length The length of the perpendicular line.\n * @param {Scalar2D} [spacing] Optional image spacing, default to [1,1].\n * @returns {Line} The perpendicular line.\n */\nexport function getPerpendicularLine(line, point, length, spacing) {\n  if (typeof spacing === 'undefined') {\n    spacing = {x: 1, y: 1};\n  }\n  const sx2 = spacing.x * spacing.x;\n  const sy2 = spacing.y * spacing.y;\n  // a0 * a1 = -1 (in square space)\n  const perpSlope = -sx2 / (sy2 * line.getSlope());\n  // y0 = a1*x0 + b1 -> b1 = y0 - a1*x0\n  const prepIntercept = point.getY() - perpSlope * point.getX();\n  // return\n  return getLineFromEquation(perpSlope, prepIntercept, point, length, spacing);\n}\n\n/**\n * Get a perpendicular line to an input one at a given distance\n *   of its begin point.\n *\n * @param {Line} line The line to be perpendicular to.\n * @param {number} distance The distance to the input line begin point.\n * @param {number} length The length of the perpendicular line.\n * @param {Scalar2D} [spacing] Optional image spacing, default to [1,1].\n * @returns {Line} The perpendicular line.\n */\nexport function getPerpendicularLineAtDistance(\n  line, distance, length, spacing) {\n  // get a line along the input one and centered on begin point\n  const lineFromEq = getLineFromEquation(\n    line.getSlope(),\n    line.getIntercept(),\n    line.getBegin(),\n    distance,\n    spacing\n  );\n  // select the point on the input line\n  let startPoint;\n  if (isPointInLineRange(lineFromEq.getBegin(), line)) {\n    startPoint = lineFromEq.getBegin();\n  } else {\n    startPoint = lineFromEq.getEnd();\n  }\n  // use it as base for a perpendicular line\n  return getPerpendicularLine(line, startPoint, length, spacing);\n}\n\n/**\n * Get a line from an equation, a middle point and a length.\n *\n * @param {number} slope The line slope.\n * @param {number} intercept The line intercept.\n * @param {Point2D} point The middle point of the line.\n * @param {number} length The line length.\n * @param {Scalar2D} [spacing] Optional image spacing, default to [1,1].\n * @returns {Line} The resulting line.\n */\nexport function getLineFromEquation(slope, intercept, point, length, spacing) {\n  if (typeof spacing === 'undefined') {\n    spacing = {x: 1, y: 1};\n  }\n  // begin point\n  let beginX = 0;\n  let beginY = 0;\n  // end point\n  let endX = 0;\n  let endY = 0;\n\n  if (isSimilar(slope, 0, REAL_WORLD_EPSILON)) {\n    // slope = ~0 -> horizontal input line\n    beginX = point.getX() - length / (2 * spacing.x);\n    beginY = point.getY();\n    endX = point.getX() + length / (2 * spacing.x);\n    endY = point.getY();\n  } else if (Math.abs(slope) > 1e6) {\n    // slope = ~(+/-)Infinity -> vertical input line\n    beginX = point.getX();\n    beginY = point.getY() - length / (2 * spacing.y);\n    endX = point.getX();\n    endY = point.getY() + length / (2 * spacing.y);\n  } else {\n    const sx2 = spacing.x * spacing.x;\n    const sy2 = spacing.y * spacing.y;\n\n    // 1. [length] sx^2 * (x - x0)^2 + sy^2 * (y - y0)^2 = d^2\n    // 2. [slope] a = (y - y0) / (x - x0) -> y - y0 = a*(x - x0)\n    // ->  sx^2 * (x - x0)^2 + sy^2 * a^2 * (x - x0)^2 = d^2\n    // ->  (x - x0)^2 = d^2 / (sx^2 + sy^2 * a^2)\n    // -> x = x0 +- d / sqrt(sx^2 + sy^2 * a^2)\n\n    // length is the distance between begin and end,\n    // point is half way between both -> d = length / 2\n    const dx = length / (2 * Math.sqrt(sx2 + sy2 * slope * slope));\n\n    // begin point\n    beginX = point.getX() - dx;\n    beginY = slope * beginX + intercept;\n    // end point\n    endX = point.getX() + dx;\n    endY = slope * endX + intercept;\n  }\n  return new Line(\n    new Point2D(beginX, beginY),\n    new Point2D(endX, endY));\n}\n","// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DrawLayer} from '../gui/drawLayer';\nimport {Annotation} from '../image/annotation';\nimport {DrawController} from '../app/drawController';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get the display name of the input shape.\n *\n * @param {Konva.Shape} shape The Konva shape.\n * @returns {string} The display name.\n */\nexport function getShapeDisplayName(shape) {\n  let displayName = 'shape';\n  if (shape instanceof Konva.Line) {\n    if (shape.points().length === 4) {\n      displayName = 'line';\n    } else if (shape.points().length === 6) {\n      displayName = 'protractor';\n    } else {\n      displayName = 'roi';\n    }\n  } else if (shape instanceof Konva.Rect) {\n    displayName = 'rectangle';\n  } else if (shape instanceof Konva.Ellipse) {\n    displayName = 'ellipse';\n  }\n  // return\n  return displayName;\n}\n\n/**\n * Add annotation command.\n */\nexport class AddAnnotationCommand {\n  /**\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * @type {DrawController}\n   */\n  #drawController;\n\n  /**\n   * @param {Annotation} annotation The annotation to add.\n   * @param {DrawController} drawController The associated draw controller.\n   */\n  constructor(annotation, drawController) {\n    this.#annotation = annotation;\n    this.#drawController = drawController;\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'AddAnnotation-' + this.#annotation.id;\n  }\n\n  /**\n   * Execute the command.\n   */\n  execute() {\n    this.#drawController.addAnnotation(this.#annotation);\n  }\n\n  /**\n   * Undo the command.\n   */\n  undo() {\n    this.#drawController.removeAnnotation(this.#annotation.id);\n  }\n}\n\n/**\n * Remove annotation command.\n */\nexport class RemoveAnnotationCommand {\n  /**\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * @type {DrawController}\n   */\n  #drawController;\n\n  /**\n   * @param {Annotation} annotation The annotation to remove.\n   * @param {DrawController} drawController The associated draw controller.\n   */\n  constructor(annotation, drawController) {\n    this.#annotation = annotation;\n    this.#drawController = drawController;\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'RemoveAnnotation-' + this.#annotation.id;\n  }\n\n  /**\n   * Execute the command.\n   */\n  execute() {\n    this.#drawController.removeAnnotation(this.#annotation.id);\n  }\n\n  /**\n   * Undo the command.\n   */\n  undo() {\n    this.#drawController.addAnnotation(this.#annotation);\n  }\n}\n\n/**\n * Update annotation command.\n */\nexport class UpdateAnnotationCommand {\n  /**\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * @type {DrawController}\n   */\n  #drawController;\n\n  /**\n   * Original annotation properties.\n   *\n   * @type {object}\n   */\n  #originalProps;\n\n  /**\n   * New annotation properties.\n   *\n   * @type {object}\n   */\n  #newProps;\n\n  /**\n   * @param {Annotation} annotation The annotation to update.\n   * @param {object} originaProps The original annotation properties.\n   * @param {object} newProps The new annotation properties.\n   * @param {DrawController} drawController The associated draw controller.\n   */\n  constructor(annotation, originaProps, newProps, drawController) {\n    this.#annotation = annotation;\n    this.#drawController = drawController;\n    this.#originalProps = originaProps;\n    this.#newProps = newProps;\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'UpdateAnnotation-' + this.#annotation.id;\n  }\n\n  /**\n   * Execute the command.\n   */\n  execute() {\n    const keys = Object.keys(this.#newProps);\n    for (const key of keys) {\n      this.#annotation[key] = this.#newProps[key];\n    }\n    this.#drawController.updateAnnotation(this.#annotation, keys);\n  }\n\n  /**\n   * Undo the command.\n   */\n  undo() {\n    const keys = Object.keys(this.#originalProps);\n    for (const key of keys) {\n      this.#annotation[key] = this.#originalProps[key];\n    }\n    this.#drawController.updateAnnotation(this.#annotation, keys);\n  }\n}\n/**\n * Draw group command.\n *\n * TODO: remove.\n */\nexport class DrawGroupCommand {\n\n  /**\n   * The group to draw.\n   *\n   * @type {Konva.Group}\n   */\n  #group;\n\n  /**\n   * The shape display name.\n   *\n   * @type {string}\n   */\n  #name;\n\n  /**\n   * The draw layer.\n   *\n   * @type {DrawLayer}\n   */\n  #layer;\n\n  /**\n   * Flag to send events.\n   *\n   * @type {boolean}\n   */\n  #isSilent;\n\n  /**\n   * The group parent.\n   *\n   * @type {object}\n   */\n  #parent;\n\n  /**\n   * @param {Konva.Group} group The group draw.\n   * @param {string} name The shape display name.\n   * @param {DrawLayer} layer The layer where to draw the group.\n   * @param {boolean} [silent] Whether to send a creation event or not.\n   */\n  constructor(group, name, layer, silent) {\n    this.#group = group;\n    this.#name = name;\n    this.#layer = layer;\n    this.#isSilent = (typeof silent === 'undefined') ? false : silent;\n    this.#parent = group.getParent();\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'Draw-' + this.#name;\n  }\n\n  /**\n   * Execute the command.\n   *\n   * @fires DrawGroupCommand#drawcreate\n   */\n  execute() {\n    // add the group to the parent (in case of undo/redo)\n    this.#parent.add(this.#group);\n    // draw\n    this.#layer.getKonvaLayer().draw();\n    // callback\n    if (!this.#isSilent) {\n      /**\n       * Draw create event.\n       *\n       * @event DrawGroupCommand#drawcreate\n       * @type {object}\n       * @property {string} id The id of the created draw.\n       * @property {string} srclayerid The id of the layer of the draw.\n       * @property {string} dataid The associated data id.\n       */\n      this.onExecute({\n        type: 'drawcreate',\n        id: this.#group.id(),\n        srclayerid: this.#layer.getId(),\n        dataid: this.#layer.getDataId()\n      });\n    }\n  }\n\n  /**\n   * Undo the command.\n   *\n   * @fires DeleteGroupCommand#drawdelete\n   */\n  undo() {\n    // remove the group from the parent layer\n    this.#group.remove();\n    // draw\n    this.#layer.getKonvaLayer().draw();\n    // callback\n    this.onUndo({\n      type: 'drawdelete',\n      id: this.#group.id(),\n      srclayerid: this.#layer.getId(),\n      dataid: this.#layer.getDataId()\n    });\n  }\n\n  /**\n   * Handle an execute event.\n   *\n   * @param {object} _event The execute event with type and id.\n   */\n  onExecute(_event) {\n    // default does nothing.\n  }\n\n  /**\n   * Handle an undo event.\n   *\n   * @param {object} _event The undo event with type and id.\n   */\n  onUndo(_event) {\n    // default does nothing.\n  }\n\n} // DrawGroupCommand class\n","import {getShadowColour} from '../utils/colour';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Scalar2D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Style class.\n */\nexport class Style {\n  /**\n   * Font size.\n   *\n   * @type {number}\n   */\n  #fontSize = 10;\n\n  /**\n   * Font family.\n   *\n   * @type {string}\n   */\n  #fontFamily = 'Verdana';\n\n  /**\n   * Text colour.\n   *\n   * @type {string}\n   */\n  #textColour = '#fff';\n\n  /**\n   * Line colour.\n   *\n   * @type {string}\n   */\n  #lineColour = '#ffff80';\n\n  /**\n   * Base scale.\n   *\n   * @type {Scalar2D}\n   */\n  #baseScale = {x: 1, y: 1};\n\n  /**\n   * Zoom scale.\n   *\n   * @type {Scalar2D}\n   */\n  #zoomScale = {x: 1, y: 1};\n\n  /**\n   * Stroke width.\n   *\n   * @type {number}\n   */\n  #strokeWidth = 2;\n\n  /**\n   * Shadow offset.\n   *\n   * @type {Scalar2D}\n   */\n  #shadowOffset = {x: 0.25, y: 0.25};\n\n  /**\n   * Tag opacity.\n   *\n   * @type {number}\n   */\n  #tagOpacity = 0.2;\n\n  /**\n   * Text padding.\n   *\n   * @type {number}\n   */\n  #textPadding = 3;\n\n  /**\n   * Get the font family.\n   *\n   * @returns {string} The font family.\n   */\n  getFontFamily() {\n    return this.#fontFamily;\n  }\n\n  /**\n   * Get the font size.\n   *\n   * @returns {number} The font size.\n   */\n  getFontSize() {\n    return this.#fontSize;\n  }\n\n  /**\n   * Get the stroke width.\n   *\n   * @returns {number} The stroke width.\n   */\n  getStrokeWidth() {\n    return this.#strokeWidth;\n  }\n\n  /**\n   * Get the text colour.\n   *\n   * @returns {string} The text colour.\n   */\n  getTextColour() {\n    return this.#textColour;\n  }\n\n  /**\n   * Get the line colour.\n   *\n   * @returns {string} The line colour.\n   */\n  getLineColour() {\n    return this.#lineColour;\n  }\n\n  /**\n   * Set the line colour.\n   *\n   * @param {string} colour The line colour.\n   */\n  setLineColour(colour) {\n    this.#lineColour = colour;\n  }\n\n  /**\n   * Set the base scale.\n   *\n   * @param {Scalar2D} scale The scale as {x,y}.\n   */\n  setBaseScale(scale) {\n    this.#baseScale = scale;\n  }\n\n  /**\n   * Set the zoom scale.\n   *\n   * @param {Scalar2D} scale The scale as {x,y}.\n   */\n  setZoomScale(scale) {\n    this.#zoomScale = scale;\n  }\n\n  /**\n   * Get the base scale.\n   *\n   * @returns {Scalar2D} The scale as {x,y}.\n   */\n  getBaseScale() {\n    return this.#baseScale;\n  }\n\n  /**\n   * Get the zoom scale.\n   *\n   * @returns {Scalar2D} The scale as {x,y}.\n   */\n  getZoomScale() {\n    return this.#zoomScale;\n  }\n\n  /**\n   * Scale an input value using the base scale.\n   *\n   * @param {number} value The value to scale.\n   * @returns {number} The scaled value.\n   */\n  scale(value) {\n    // TODO: 2D?\n    return value / this.#baseScale.x;\n  }\n\n  /**\n   * Apply zoom scale on an input value.\n   *\n   * @param {number} value The value to scale.\n   * @returns {Scalar2D} The scaled value as {x,y}.\n   */\n  applyZoomScale(value) {\n    return {\n      x: value / this.#zoomScale.x,\n      y: value / this.#zoomScale.y\n    };\n  }\n\n  /**\n   * Multiply an input value by the zoom ratio (zx/zy).\n   *\n   * @param {number} value The value to scale.\n   * @returns {number} The scaled value.\n   */\n  applyZoomRatio(value) {\n    return value * this.#zoomScale.x / this.#zoomScale.y;\n  }\n\n  /**\n   * Get the shadow offset.\n   *\n   * @returns {Scalar2D} The offset as {x,y}.\n   */\n  getShadowOffset() {\n    return this.#shadowOffset;\n  }\n\n  /**\n   * Get the tag opacity.\n   *\n   * @returns {number} The opacity.\n   */\n  getTagOpacity() {\n    return this.#tagOpacity;\n  }\n\n  /**\n   * Get the text padding.\n   *\n   * @returns {number} The padding.\n   */\n  getTextPadding() {\n    return this.#textPadding;\n  }\n\n  /**\n   * Get the font definition string.\n   *\n   * @returns {string} The font definition string.\n   */\n  getFontStr() {\n    return ('normal ' + this.getFontSize() + 'px sans-serif');\n  }\n\n  /**\n   * Get the line height.\n   *\n   * @returns {number} The line height.\n   */\n  getLineHeight() {\n    return (this.getFontSize() + this.getFontSize() / 5);\n  }\n\n  /**\n   * Get the font size scaled to the display.\n   *\n   * @returns {number} The scaled font size.\n   */\n  getScaledFontSize() {\n    return this.scale(this.getFontSize());\n  }\n\n  /**\n   * Get the stroke width scaled to the display.\n   *\n   * @returns {number} The scaled stroke width.\n   */\n  getScaledStrokeWidth() {\n    return this.scale(this.getStrokeWidth());\n  }\n\n  /**\n   * Get the shadow line colour.\n   *\n   * @returns {string} The shadow line colour.\n   */\n  getShadowLineColour() {\n    return getShadowColour(this.getLineColour());\n  }\n\n} // class Style\n","import {Point2D} from '../math/point';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Scalar2D} from '../math/scalar';\nimport {Style} from '../gui/style';\n// external\nimport Konva from 'konva';\n/* eslint-enable no-unused-vars */\n\n/**\n * List of default label texts.\n *\n * @type {Object.<string, Object.<string, string>>}\n */\nexport const defaultLabelTexts = {\n  arrow: {\n    '*': ''\n  },\n  circle: {\n    '*': '{surface}'\n  },\n  ellipse: {\n    '*': '{surface}'\n  },\n  protractor: {\n    '*': '{angle}'\n  },\n  rectangle: {\n    '*': '{surface}'\n  },\n  roi: {\n    '*': ''\n  },\n  ruler: {\n    '*': '{length}'\n  }\n};\n\n/**\n * Is an input node's name 'label'.\n *\n * @param {Konva.Node} node A Konva node.\n * @returns {boolean} True if the node's name is 'label'.\n */\nexport function isNodeNameLabel(node) {\n  return node.name() === 'label';\n}\n\n/**\n * Is an input node's name 'shape'.\n *\n * @param {Konva.Node} node A Konva node.\n * @returns {boolean} True if the node's name is 'shape'.\n */\nexport function isNodeNameShape(node) {\n  return node.name() === 'shape';\n}\n\n/**\n * Is an input node a position node.\n *\n * @param {Konva.Node} node A Konva node.\n * @returns {boolean} True if the node's name is 'position-group'.\n */\nexport function isPositionNode(node) {\n  return node.name() === 'position-group';\n}\n\n/**\n * Get a Konva.Line shape from a group.\n *\n * @param {Konva.Group} group The group to look into.\n * @returns {Konva.Line|undefined} The shape.\n */\nexport function getLineShape(group) {\n  const kshape = group.getChildren(isNodeNameShape)[0];\n  if (!(kshape instanceof Konva.Line)) {\n    return;\n  }\n  return kshape;\n}\n\n/**\n * Get a Konva.Ellipse anchor shape from a group.\n *\n * @param {Konva.Group} group The group to look into.\n * @param {number} index The anchor index.\n * @returns {Konva.Ellipse|undefined} The anchor shape.\n */\nexport function getAnchorShape(group, index) {\n  const kshape = group.getChildren(function (node) {\n    return node.id() === 'anchor' + index;\n  })[0];\n  if (!(kshape instanceof Konva.Ellipse)) {\n    return;\n  }\n  return kshape;\n}\n\n/**\n * @callback testFn\n * @param {Konva.Node} node The node.\n * @returns {boolean} True if the node passes the test.\n */\n\n/**\n * Get a lambda to check a node's id.\n *\n * @param {string} id The id to check.\n * @returns {testFn} A function to check a node's id.\n */\nexport function isNodeWithId(id) {\n  return function (node) {\n    return node.id() === id;\n  };\n}\n\n/**\n * Draw Debug flag.\n */\nexport const DRAW_DEBUG = false;\n\n/**\n * Get the default anchor shape.\n *\n * @param {number} x The X position.\n * @param {number} y The Y position.\n * @param {string} id The shape id.\n * @param {Style} style The application style.\n * @returns {Konva.Ellipse} The default anchor shape.\n */\nexport function getDefaultAnchor(x, y, id, style) {\n  const radius = style.applyZoomScale(6);\n  const absRadius = {\n    x: Math.abs(radius.x),\n    y: Math.abs(radius.y)\n  };\n  return new Konva.Ellipse({\n    x: x,\n    y: y,\n    stroke: '#999',\n    fill: 'rgba(100,100,100,0.7',\n    strokeWidth: style.getStrokeWidth(),\n    strokeScaleEnabled: false,\n    radius: absRadius,\n    radiusX: absRadius.x,\n    radiusY: absRadius.y,\n    name: 'anchor',\n    id: id.toString(),\n    dragOnTop: false,\n    draggable: true,\n    visible: false\n  });\n}\n\n/**\n * Get an anchor index from its id.\n *\n * @param {string} id The anchor id as 'anchor#'.\n * @returns {number} The anchor index.\n */\nexport function getAnchorIndex(id) {\n  // 'anchor'.length = 6\n  return parseInt(id.substring(6), 10);\n}\n\n/**\n * Bound a node position.\n *\n * @param {Konva.Node} node The node to bound the position.\n * @param {Point2D} min The minimum position.\n * @param {Point2D} max The maximum position.\n * @returns {boolean} True if the position was corrected.\n */\nfunction boundNodePosition(node, min, max) {\n  let changed = false;\n  if (node.x() < min.getX()) {\n    node.x(min.getX());\n    changed = true;\n  } else if (node.x() > max.getX()) {\n    node.x(max.getX());\n    changed = true;\n  }\n  if (node.y() < min.getY()) {\n    node.y(min.getY());\n    changed = true;\n  } else if (node.y() > max.getY()) {\n    node.y(max.getY());\n    changed = true;\n  }\n  return changed;\n}\n\n/**\n * Get a shape top left position range.\n *\n * @param {Scalar2D} stageSize The stage size as {x,y}.\n * @param {Konva.Shape} shape The shape to evaluate.\n * @returns {object} The range as {min, max}.\n */\nexport function getShapePositionRange(stageSize, shape) {\n  const min = new Point2D(0, 0);\n  const max = new Point2D(\n    stageSize.x - Math.abs(shape.width()),\n    stageSize.y - Math.abs(shape.height())\n  );\n\n  return {min: min, max: max};\n}\n\n/**\n * Is an input shape top left position in the input range.\n *\n * @param {Konva.Shape} shape The shape to evaluate.\n * @param {Point2D} min The minimum top left position.\n * @param {Point2D} max The maximum top left position.\n * @returns {boolean} True if in range.\n */\nexport function isShapeInRange(shape, min, max) {\n  // use client rect to get the shape's top left position\n  const boundRect = shape.getClientRect({relativeTo: shape.getParent()});\n  return boundRect.x > min.getX() &&\n    boundRect.x < max.getX() &&\n    boundRect.y > min.getY() &&\n    boundRect.y < max.getY();\n}\n\n/**\n * Validate an anchor position.\n *\n * @param {Scalar2D} stageSize The stage size {x,y}.\n * @param {Konva.Shape} anchor The anchor to evaluate.\n * @returns {boolean} True if the position was corrected.\n */\nexport function validateAnchorPosition(stageSize, anchor) {\n  const group = anchor.getParent();\n\n  const min = new Point2D(\n    -group.x(),\n    -group.y()\n  );\n  const max = new Point2D(\n    stageSize.x - group.x(),\n    stageSize.y - group.y()\n  );\n\n  return boundNodePosition(anchor, min, max);\n}\n","import {logger} from '../utils/logger';\nimport {UpdateAnnotationCommand} from './drawCommands';\nimport {validateAnchorPosition} from './drawBounds';\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {DrawLayer} from '../gui/drawLayer';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Draw shape editor.\n */\nexport class DrawShapeEditor {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Event callback.\n   *\n   * @type {Function}\n   */\n  #eventCallback;\n\n  /**\n   * @param {App} app The associated application.\n   * @param {Function} eventCallback Event callback.\n   */\n  constructor(app, eventCallback) {\n    this.#app = app;\n    this.#eventCallback = eventCallback;\n  }\n\n  /**\n   * Current shape factory.\n   *\n   * @type {object}\n   */\n  #currentFactory = null;\n\n  /**\n   * Edited shape.\n   *\n   * @type {Konva.Shape}\n   */\n  #shape = null;\n\n  /**\n   * Associated draw layer. Used to bound anchor move.\n   *\n   * @type {DrawLayer}\n   */\n  #drawLayer;\n\n  /**\n   * The associated annotation.\n   *\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * Active flag.\n   *\n   * @type {boolean}\n   */\n  #isActive = false;\n\n  /**\n   * @callback eventFn\n   * @param {object} event The event.\n   */\n\n  /**\n   * Set the shape to edit.\n   *\n   * @param {Konva.Shape} inshape The shape to edit.\n   * @param {DrawLayer} drawLayer The associated draw layer.\n   * @param {Annotation} annotation The associated annotation.\n   */\n  setShape(inshape, drawLayer, annotation) {\n    this.#shape = inshape;\n    this.#drawLayer = drawLayer;\n    this.#annotation = annotation;\n\n    if (this.#shape) {\n      // remove old anchors\n      this.#removeAnchors();\n\n      this.#currentFactory = annotation.getFactory();\n      if (this.#currentFactory === null) {\n        throw new Error('Could not find a factory to update shape.');\n      }\n\n      // add new anchors\n      this.#addAnchors();\n    }\n  }\n\n  /**\n   * Get the edited shape.\n   *\n   * @returns {Konva.Shape} The edited shape.\n   */\n  getShape() {\n    return this.#shape;\n  }\n\n  /**\n   * Get the edited annotation.\n   *\n   * @returns {Annotation} The annotation.\n   */\n  getAnnotation() {\n    return this.#annotation;\n  }\n\n  /**\n   * Get the active flag.\n   *\n   * @returns {boolean} The active flag.\n   */\n  isActive() {\n    return this.#isActive;\n  }\n\n  /**\n   * Enable the editor. Redraws the layer.\n   */\n  enable() {\n    this.#isActive = true;\n    if (this.#shape) {\n      this.#setAnchorsVisible(true);\n      if (this.#shape.getLayer()) {\n        this.#shape.getLayer().draw();\n      }\n    }\n  }\n\n  /**\n   * Disable the editor. Redraws the layer.\n   */\n  disable() {\n    this.#isActive = false;\n    if (this.#shape) {\n      this.#setAnchorsVisible(false);\n      if (this.#shape.getLayer()) {\n        this.#shape.getLayer().draw();\n      }\n    }\n  }\n\n  /**\n   * Reset the editor.\n   */\n  reset() {\n    this.#shape = undefined;\n    this.#drawLayer = undefined;\n    this.#annotation = undefined;\n  }\n\n  /**\n   * Reset the anchors.\n   */\n  resetAnchors() {\n    // remove previous controls\n    this.#removeAnchors();\n    // add anchors\n    this.#addAnchors();\n    // set them visible\n    this.#setAnchorsVisible(true);\n  }\n\n  /**\n   * Apply a function on all anchors.\n   *\n   * @param {object} func A f(shape) function.\n   */\n  #applyFuncToAnchors(func) {\n    if (this.#shape && this.#shape.getParent()) {\n      const anchors = this.#shape.getParent().find('.anchor');\n      anchors.forEach(func);\n    }\n  }\n\n  /**\n   * Set anchors visibility.\n   *\n   * @param {boolean} flag The visible flag.\n   */\n  #setAnchorsVisible(flag) {\n    this.#applyFuncToAnchors(function (anchor) {\n      anchor.visible(flag);\n    });\n  }\n\n  /**\n   * Set anchors active.\n   *\n   * @param {boolean} flag The active (on/off) flag.\n   */\n  setAnchorsActive(flag) {\n    let func = null;\n    if (flag) {\n      func = (anchor) => {\n        this.#setAnchorOn(anchor);\n      };\n    } else {\n      func = (anchor) => {\n        this.#setAnchorOff(anchor);\n      };\n    }\n    this.#applyFuncToAnchors(func);\n  }\n\n  /**\n   * Remove anchors.\n   */\n  #removeAnchors() {\n    this.#applyFuncToAnchors(function (anchor) {\n      anchor.remove();\n    });\n  }\n\n  /**\n   * Add the shape anchors.\n   */\n  #addAnchors() {\n    // exit if no shape or no layer\n    if (!this.#shape || !this.#shape.getLayer()) {\n      return;\n    }\n    // get shape group\n    const group = this.#shape.getParent();\n\n    // activate and add anchors to group\n    const anchors =\n      this.#currentFactory.getAnchors(this.#shape, this.#app.getStyle());\n    for (let i = 0; i < anchors.length; ++i) {\n      // set anchor on\n      this.#setAnchorOn(anchors[i]);\n      // add the anchor to the group\n      group.add(anchors[i]);\n    }\n  }\n\n  /**\n   * Set the anchor on listeners.\n   *\n   * @param {Konva.Ellipse} anchor The anchor to set on.\n   */\n  #setAnchorOn(anchor) {\n    let originalProps;\n\n    // drag start listener\n    anchor.on('dragstart.edit', (event) => {\n      // prevent bubbling upwards\n      event.cancelBubble = true;\n      // store original properties\n      originalProps = {\n        mathShape: this.#annotation.mathShape,\n        referencePoints: this.#annotation.referencePoints\n      };\n    });\n    // drag move listener\n    anchor.on('dragmove.edit', (event) => {\n      const anchor = event.target;\n      if (!(anchor instanceof Konva.Shape)) {\n        return;\n      }\n      // validate the anchor position\n      validateAnchorPosition(this.#drawLayer.getBaseSize(), anchor);\n      if (typeof this.#currentFactory.constrainAnchorMove !== 'undefined') {\n        this.#currentFactory.constrainAnchorMove(anchor);\n      }\n\n      // udpate annotation\n      this.#currentFactory.updateAnnotationOnAnchorMove(\n        this.#annotation, anchor);\n      // udpate shape\n      this.#currentFactory.updateShapeGroupOnAnchorMove(\n        this.#annotation, anchor, this.#app.getStyle());\n\n      // redraw\n      if (anchor.getLayer()) {\n        anchor.getLayer().draw();\n      } else {\n        logger.warn('No layer to draw the anchor!');\n      }\n      // prevent bubbling upwards\n      event.cancelBubble = true;\n    });\n    // drag end listener\n    anchor.on('dragend.edit', (event) => {\n      // update annotation command\n      const newProps = {\n        mathShape: this.#annotation.mathShape,\n        referencePoints: this.#annotation.referencePoints\n      };\n      const command = new UpdateAnnotationCommand(\n        this.#annotation,\n        originalProps,\n        newProps,\n        this.#drawLayer.getDrawController()\n      );\n      // add command to undo stack\n      this.#app.addToUndoStack(command);\n      // fire event manually since command is not executed\n      this.#eventCallback({\n        type: 'annotationupdate',\n        data: this.#annotation,\n        dataid: this.#drawLayer.getDataId(),\n        keys: Object.keys(newProps)\n      });\n      // update original properties\n      originalProps = {\n        mathShape: newProps.mathShape,\n        referencePoints: newProps.referencePoints\n      };\n\n      // prevent bubbling upwards\n      event.cancelBubble = true;\n    });\n    // mouse down listener\n    anchor.on('mousedown touchstart', (event) => {\n      const anchor = event.target;\n      anchor.moveToTop();\n    });\n    // mouse over styling\n    anchor.on('mouseover.edit', (event) => {\n      const anchor = event.target;\n      if (!(anchor instanceof Konva.Shape)) {\n        return;\n      }\n      // style is handled by the group\n      anchor.stroke('#ddd');\n      if (anchor.getLayer()) {\n        anchor.getLayer().draw();\n      } else {\n        logger.warn('No layer to draw the anchor!');\n      }\n    });\n    // mouse out styling\n    anchor.on('mouseout.edit', (event) => {\n      const anchor = event.target;\n      if (!(anchor instanceof Konva.Shape)) {\n        return;\n      }\n      // style is handled by the group\n      anchor.stroke('#999');\n      if (anchor.getLayer()) {\n        anchor.getLayer().draw();\n      } else {\n        logger.warn('No layer to draw the anchor!');\n      }\n    });\n  }\n\n  /**\n   * Set the anchor off listeners.\n   *\n   * @param {Konva.Ellipse} anchor The anchor to set off.\n   */\n  #setAnchorOff(anchor) {\n    anchor.off('dragstart.edit');\n    anchor.off('dragmove.edit');\n    anchor.off('dragend.edit');\n    anchor.off('mousedown touchstart');\n    anchor.off('mouseover.edit');\n    anchor.off('mouseout.edit');\n  }\n\n} // class Editor\n","import Konva from 'konva';\n\n/* eslint-disable no-unused-vars */\nimport {Scalar2D} from '../math/scalar';\nimport {DrawLayer} from '../gui/drawLayer';\n/* eslint-enable no-unused-vars */\n\nexport class DrawTrash {\n  /**\n   * Trash draw: a cross.\n   *\n   * @type {Konva.Group}\n   */\n  #trash;\n\n  constructor() {\n    this.createTrashIcon();\n\n  }\n\n  /**\n   * Creates the trash icon o positionates it.\n   */\n  createTrashIcon() {\n    this.#trash = new Konva.Group();\n    // first line of the cross\n    const trashLine1 = new Konva.Line({\n      points: [-10, -10, 10, 10],\n      stroke: 'red'\n    });\n    // second line of the cross\n    const trashLine2 = new Konva.Line({\n      points: [10, -10, -10, 10],\n      stroke: 'red'\n    });\n    this.#trash.width(20);\n    this.#trash.height(20);\n    this.#trash.add(trashLine1);\n    this.#trash.add(trashLine2);\n  }\n\n  /**\n   *\n   * Activates the trash, by showing the icon into the layer draw layer.\n   *\n   * @param {DrawLayer} drawLayer The draw layer where to draw.\n   */\n  activate(drawLayer) {\n    const stage = drawLayer.getKonvaStage();\n    const scale = stage.scale();\n    const konvaLayer = drawLayer.getKonvaLayer();\n    const invscale = {x: 1 / scale.x, y: 1 / scale.y};\n    this.#trash.x(stage.offset().x + (stage.width() / (2 * scale.x)));\n    this.#trash.y(stage.offset().y + (stage.height() / (15 * scale.y)));\n    this.#trash.scale(invscale);\n    konvaLayer.add(this.#trash);\n    // draw\n    konvaLayer.draw();\n  }\n\n  /**\n   *\n   * Change colour on trash over.\n   *\n   * @param {Scalar2D} eventPosition The event drag move position.\n   * @param {Konva.Group} shapeGroup The shape group whose colour\n   *   must be change.\n   * @param {string} originalShapeColour The original shape colour.\n   */\n  changeChildrenColourOnTrashHover(eventPosition,\n    shapeGroup, originalShapeColour) {\n    if (this.isOverTrash(eventPosition)) {\n      this.changeGroupChildrenColour(this.#trash, 'orange');\n      this.changeGroupChildrenColour(shapeGroup, 'red');\n      return;\n\n    }\n    this.changeGroupChildrenColour(this.#trash, 'red');\n    this.changeGroupChildrenColour(shapeGroup, originalShapeColour);\n  }\n\n  /**\n   * Change colour on trash out.\n   *\n   * @param {Konva.Group} group The group whose colour must be change.\n   * @param {string} colour The new colour to be set.\n   */\n  changeGroupChildrenColour(group, colour) {\n    group.getChildren().forEach(function (tshape) {\n      if (tshape instanceof Konva.Shape &&\n        typeof tshape.stroke !== 'undefined') {\n        tshape.stroke(colour);\n      }\n    });\n  }\n\n  /**\n   * Removes the trash from the draw layer.\n   */\n  remove() {\n    this.#trash.remove();\n  }\n\n  /**\n   * Determines if the event is over trash.\n   *\n   * @param {Scalar2D} eventPosition The event position.\n   * @returns {boolean} True if the event is over trash.\n   */\n  isOverTrash(eventPosition) {\n    const trashHalfWidth =\n        this.#trash.width() * Math.abs(this.#trash.scaleX()) / 2;\n    const trashHalfHeight =\n        this.#trash.height() * Math.abs(this.#trash.scaleY()) / 2;\n    return Math.abs(eventPosition.x - this.#trash.x()) < trashHalfWidth &&\n        Math.abs(eventPosition.y - this.#trash.y()) < trashHalfHeight;\n  }\n\n}","import {custom} from '../app/custom';\nimport {\n  getMousePoint,\n} from '../gui/generic';\nimport {\n  RemoveAnnotationCommand,\n  UpdateAnnotationCommand\n} from './drawCommands';\nimport {\n  isNodeNameShape,\n  isNodeNameLabel,\n  getShapePositionRange,\n  isShapeInRange\n} from './drawBounds';\nimport {DrawShapeEditor} from './drawShapeEditor';\nimport {DrawTrash} from './drawTrash';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {Scalar2D} from '../math/scalar';\nimport {DrawLayer} from '../gui/drawLayer';\nimport {Annotation} from '../image/annotation';\nimport {Point2D} from '../math/point';\n/* eslint-enable no-unused-vars */\n\n/**\n * Open a dialogue to edit roi data. Defaults to window.prompt.\n *\n * @param {Annotation} annotation The roi data.\n * @param {Function} callback The callback to launch on dialogue exit.\n */\nfunction defaultOpenRoiDialog(annotation, callback) {\n  const textExpr = prompt('Label', annotation.textExpr);\n  if (textExpr !== null) {\n    annotation.textExpr = textExpr;\n    callback(annotation);\n  }\n}\n\n/**\n * Draw shape handler: handle action on existing shapes.\n */\nexport class DrawShapeHandler {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Shape editor.\n   *\n   * @type {DrawShapeEditor}\n   */\n  #shapeEditor;\n\n  /**\n   * Trash draw: a cross.\n   *\n   * @type {DrawTrash}\n   */\n  #trash;\n\n  /**\n   * Mouse cursor.\n   *\n   * @type {string}\n   */\n  #mouseOverCursor = 'pointer';\n\n  /**\n   * Original mouse cursor.\n   *\n   * @type {string}\n   */\n  #originalCursor;\n\n  /**\n   * Shape with mouse over.\n   *\n   * @type {Konva.Group}\n   */\n  #mouseOverShapeGroup;\n\n  /**\n   * Event callback.\n   *\n   * @type {Function}\n   */\n  #eventCallback;\n\n  /**\n   * @callback eventFn\n   * @param {object} event The event.\n   */\n\n  /**\n   * @param {App} app The associated application.\n   * @param {Function} eventCallback Event callback.\n   */\n  constructor(app, eventCallback) {\n    this.#app = app;\n    this.#eventCallback = eventCallback;\n    this.#shapeEditor = new DrawShapeEditor(app, eventCallback);\n    this.#trash = new DrawTrash();\n  }\n\n  /**\n   * Set the draw editor shape.\n   *\n   * @param {Konva.Shape} shape The shape to edit.\n   * @param {DrawLayer} drawLayer The layer the shape belongs to.\n   */\n  setEditorShape(shape, drawLayer) {\n    const drawController = drawLayer.getDrawController();\n    if (shape &&\n      shape instanceof Konva.Shape &&\n      shape !== this.#shapeEditor.getShape() &&\n      drawController.isAnnotationGroupEditable()) {\n      // disable\n      this.#shapeEditor.disable();\n      // set shape\n      this.#shapeEditor.setShape(\n        shape,\n        drawLayer,\n        drawLayer.getDrawController().getAnnotation(shape.getParent().id()));\n      // enable\n      this.#shapeEditor.enable();\n    }\n  }\n\n  /**\n   * Get the currently edited shape group.\n   *\n   * @returns {Konva.Group|undefined} The edited group.\n   */\n  getEditorShapeGroup() {\n    let res;\n    if (this.#shapeEditor.isActive()) {\n      res = this.#shapeEditor.getShape().getParent();\n      if (!(res instanceof Konva.Group)) {\n        return;\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Get the currently edited annotation.\n   *\n   * @returns {Annotation|undefined} The edited annotation.\n   */\n  getEditorAnnotation() {\n    let res;\n    if (this.#shapeEditor.isActive()) {\n      res = this.#shapeEditor.getAnnotation();\n    }\n    return res;\n  }\n\n  /**\n   * Disable and reset the shape editor.\n   */\n  disableAndResetEditor() {\n    this.#shapeEditor.disable();\n    this.#shapeEditor.reset();\n  }\n\n  /**\n   * Get the real position from an event.\n   * TODO: use layer method?\n   *\n   * @param {Scalar2D} index The input index as {x,y}.\n   * @param {DrawLayer} drawLayer The origin draw layer.\n   * @returns {Scalar2D} The real position in the image as {x,y}.\n   */\n  #getRealPosition(index, drawLayer) {\n    const stage = drawLayer.getKonvaStage();\n    return {\n      x: stage.offset().x + index.x / stage.scale().x,\n      y: stage.offset().y + index.y / stage.scale().y\n    };\n  }\n\n  /**\n   * Store specific mouse over cursor.\n   *\n   * @param {string} cursor The cursor name.\n   */\n  storeMouseOverCursor(cursor) {\n    this.#mouseOverCursor = cursor;\n  }\n\n  /**\n   * Handle shape group mouseover.\n   */\n  #onMouseOverShapeGroup() {\n    // mouse cursor\n    this.#originalCursor = document.body.style.cursor;\n    document.body.style.cursor = this.#mouseOverCursor;\n    // shape opacity\n    this.#mouseOverShapeGroup.opacity(0.75);\n  }\n\n  /**\n   * Handle shape group mouseout.\n   */\n  onMouseOutShapeGroup() {\n    // mouse cursor\n    if (typeof this.#originalCursor !== 'undefined') {\n      document.body.style.cursor = this.#originalCursor;\n      this.#originalCursor = undefined;\n    }\n    // shape opacity\n    if (typeof this.#mouseOverShapeGroup !== 'undefined') {\n      this.#mouseOverShapeGroup.opacity(1);\n    }\n  }\n\n  /**\n   * Add shape group mouse over and out listeners: updates\n   *   shape group opacity and cursor.\n   *\n   * @param {Konva.Group} shapeGroup The shape group.\n   */\n  #addShapeOverListeners(shapeGroup) {\n    // handle mouse over\n    shapeGroup.on('mouseover', () => {\n      this.#mouseOverShapeGroup = shapeGroup;\n      this.#onMouseOverShapeGroup();\n    });\n\n    // handle mouse out\n    shapeGroup.on('mouseout', () => {\n      this.onMouseOutShapeGroup();\n      this.#mouseOverShapeGroup = undefined;\n    });\n  }\n\n  /**\n   * Remove shape group mouse over and out listeners.\n   *\n   * @param {Konva.Group} shapeGroup The shape group.\n   */\n  #removeShapeOverListeners(shapeGroup) {\n    shapeGroup.off('mouseover');\n    shapeGroup.off('mouseout');\n  }\n\n  /**\n   * Add shape group listeners.\n   *\n   * @param {Konva.Group} shapeGroup The shape group to set on.\n   * @param {Annotation} annotation The associated annotation.\n   * @param {DrawLayer} drawLayer The origin draw layer.\n   */\n  addShapeGroupListeners(shapeGroup, annotation, drawLayer) {\n    // shape mouse over\n    this.#addShapeOverListeners(shapeGroup);\n\n    // make shape draggable\n    this.#addShapeListeners(shapeGroup, annotation, drawLayer);\n\n    // make label draggable\n    this.#addLabelListeners(shapeGroup, annotation, drawLayer);\n\n    // double click handling: update annotation text\n    shapeGroup.on('dblclick', () => {\n      // original text expr\n      const originalTextExpr = annotation.textExpr;\n\n      const onSaveCallback = (annotation) => {\n        // new text expr\n        const newTextExpr = annotation.textExpr;\n        // create annotation update command\n        const command = new UpdateAnnotationCommand(\n          annotation,\n          {textExpr: originalTextExpr},\n          {textExpr: newTextExpr},\n          drawLayer.getDrawController()\n        );\n        // add command to undo stack\n        this.#app.addToUndoStack(command);\n        // execute command\n        command.execute();\n      };\n\n      // call roi dialog\n      if (typeof custom.openRoiDialog !== 'undefined') {\n        custom.openRoiDialog(annotation, onSaveCallback);\n      } else {\n        defaultOpenRoiDialog(annotation, onSaveCallback);\n      }\n    });\n  }\n\n  /**\n   * Add shape listeners.\n   *\n   * @param {Konva.Group} shapeGroup The shape group to get the shape from.\n   * @param {Annotation} annotation The associated annotation.\n   * @param {DrawLayer} drawLayer The origin draw layer.\n   */\n  #addShapeListeners(shapeGroup, annotation, drawLayer) {\n    const konvaLayer = drawLayer.getKonvaLayer();\n\n    const shape = shapeGroup.getChildren(isNodeNameShape)[0];\n    if (!(shape instanceof Konva.Shape)) {\n      return;\n    }\n    shape.draggable(true);\n\n    // cache vars\n    let dragStartPos;\n    let previousPos;\n    let originalProps;\n    let colour;\n\n    // drag start event handling\n    shape.on('dragstart.draw', (event) => {\n      // store colour\n      colour = shape.stroke();\n      // store pos\n      dragStartPos = {\n        x: shape.x(),\n        y: shape.y()\n      };\n      previousPos = {\n        x: event.target.x(),\n        y: event.target.y()\n      };\n      // store original properties\n      originalProps = {\n        mathShape: annotation.mathShape,\n        referencePoints: annotation.referencePoints\n      };\n\n      // display trash\n      this.#trash.activate(drawLayer);\n      // deactivate anchors to avoid events on null shape\n      this.#shapeEditor.setAnchorsActive(false);\n      // draw\n      konvaLayer.draw();\n    });\n\n    // drag move event handling\n    shape.on('dragmove.draw', (event) => {\n      // if out of range, reset shape position and exit\n      const range = getShapePositionRange(drawLayer.getBaseSize(), shape);\n      if (range && !isShapeInRange(shape, range.min, range.max)) {\n        shape.x(previousPos.x);\n        shape.y(previousPos.y);\n        return;\n      }\n\n      // move associated shapes (but not label)\n      const diff = {\n        x: event.target.x() - previousPos.x,\n        y: event.target.y() - previousPos.y\n      };\n      const children = shapeGroup.getChildren();\n      const labelWithDefaultPosition =\n        typeof annotation.labelPosition === 'undefined';\n      for (const child of children) {\n        // skip shape and label with defined position\n        if (child === event.target ||\n          (child.name() === 'label' && !labelWithDefaultPosition) ||\n          child.name() === 'connector'\n        ) {\n          continue;\n        }\n        // move other nodes\n        child.move(diff);\n      }\n\n      // store pos\n      previousPos = {\n        x: event.target.x(),\n        y: event.target.y()\n      };\n\n      // get appropriate factory\n      const factory = annotation.getFactory();\n      // update annotation\n      factory.updateAnnotationOnTranslation(annotation, diff);\n      // update label\n      factory.updateLabelContent(annotation, shapeGroup, this.#app.getStyle());\n      // update connector\n      factory.updateConnector(shapeGroup);\n      // highlight trash when on it\n      const mousePoint = getMousePoint(event.evt);\n      const offset = {\n        x: mousePoint.getX(),\n        y: mousePoint.getY()\n      };\n      const eventPos = this.#getRealPosition(offset, drawLayer);\n      this.#trash.changeChildrenColourOnTrashHover(eventPos,\n        shapeGroup, colour);\n      // draw\n      konvaLayer.draw();\n    });\n\n    // drag end event handling\n    shape.on('dragend.draw', (event) => {\n      // remove trash\n      this.#trash.remove();\n      // activate(false) will also trigger a dragend.draw\n      if (typeof event === 'undefined' ||\n        typeof event.evt === 'undefined') {\n        return;\n      }\n      const pos = {x: shape.x(), y: shape.y()};\n      // delete case\n      const mousePoint = getMousePoint(event.evt);\n      const offset = {\n        x: mousePoint.getX(),\n        y: mousePoint.getY()\n      };\n      const eventPos = this.#getRealPosition(offset, drawLayer);\n      if (this.#trash.isOverTrash(eventPos)) {\n        // compensate for the drag translation\n        shapeGroup.x(dragStartPos.x);\n        shapeGroup.y(dragStartPos.y);\n        // disable editor\n        this.#shapeEditor.disable();\n        this.#shapeEditor.reset();\n        this.#trash.changeGroupChildrenColour(shapeGroup, colour);\n        // reset math shape (for undo)\n        annotation.mathShape = originalProps.mathShape;\n        annotation.referencePoints = originalProps.referencePoints;\n\n        // create remove annotation command\n        const command = new RemoveAnnotationCommand(\n          annotation,\n          drawLayer.getDrawController()\n        );\n        // add command to undo stack\n        this.#app.addToUndoStack(command);\n        // execute command: triggers draw remove\n        command.execute();\n\n        // reset cursor\n        this.onMouseOutShapeGroup();\n      } else {\n        const translation = {\n          x: pos.x - dragStartPos.x,\n          y: pos.y - dragStartPos.y\n        };\n        if (translation.x !== 0 || translation.y !== 0) {\n          // update annotation command\n          const newProps = {\n            mathShape: annotation.mathShape,\n            referencePoints: annotation.referencePoints\n          };\n          const command = new UpdateAnnotationCommand(\n            annotation,\n            originalProps,\n            newProps,\n            drawLayer.getDrawController()\n          );\n          // add command to undo stack\n          this.#app.addToUndoStack(command);\n          // fire event manually since command is not executed\n          this.#eventCallback({\n            type: 'annotationupdate',\n            data: annotation,\n            dataid: drawLayer.getDataId(),\n            keys: Object.keys(newProps)\n          });\n          // update original shape\n          originalProps = {\n            mathShape: newProps.mathShape,\n            referencePoints: newProps.referencePoints\n          };\n        }\n        // reset anchors\n        this.#shapeEditor.setAnchorsActive(true);\n        this.#shapeEditor.resetAnchors();\n      }\n      // draw\n      konvaLayer.draw();\n      // reset start position\n      dragStartPos = {\n        x: shape.x(),\n        y: shape.y()\n      };\n    });\n  }\n\n  /**\n   * Add label listeners.\n   *\n   * @param {Konva.Group} shapeGroup The shape group to get the label from.\n   * @param {Annotation} annotation The associated annotation.\n   * @param {DrawLayer} drawLayer The origin draw layer.\n   */\n  #addLabelListeners(shapeGroup, annotation, drawLayer) {\n    const label = shapeGroup.getChildren(isNodeNameLabel)[0];\n    if (!(label instanceof Konva.Label)) {\n      return;\n    }\n    label.draggable(true);\n\n    // cache vars\n    let dragStartPos;\n    let originalLabelPosition;\n\n    // drag start event handling\n    label.on('dragstart.draw', (/*event*/) => {\n      // store pos\n      dragStartPos = {\n        x: label.x(),\n        y: label.y()\n      };\n      // store original position\n      originalLabelPosition = annotation.labelPosition;\n    });\n\n    // drag move event handling\n    label.on('dragmove.draw', (/*event*/) => {\n      // get factory\n      const factory = annotation.getFactory();\n      // update label\n      factory.updateConnector(shapeGroup);\n    });\n\n    // drag end event handling\n    label.on('dragend.draw', (/*event*/) => {\n      const translation = {\n        x: label.x() - dragStartPos.x,\n        y: label.y() - dragStartPos.y\n      };\n      if (translation.x !== 0 || translation.y !== 0) {\n        const newLabelPosition = new Point2D(label.x(), label.y());\n        // set label position\n        annotation.labelPosition = newLabelPosition;\n        // update annotation command\n        const command = new UpdateAnnotationCommand(\n          annotation,\n          {labelPosition: originalLabelPosition},\n          {labelPosition: newLabelPosition},\n          drawLayer.getDrawController()\n        );\n        // add command to undo stack\n        this.#app.addToUndoStack(command);\n        // fire event manually since command is not executed\n        this.#eventCallback({\n          type: 'annotationupdate',\n          data: annotation,\n          dataid: drawLayer.getDataId(),\n          keys: ['labelPosition']\n        });\n        // update original position\n        originalLabelPosition = newLabelPosition;\n      }\n      dragStartPos = {x: label.x(), y: label.y()};\n    });\n  }\n\n  /**\n   * Remove shape group listeners.\n   *\n   * @param {Konva.Group} shapeGroup The shape group to set off.\n   */\n  removeShapeListeners(shapeGroup) {\n    // mouse over\n    this.#removeShapeOverListeners(shapeGroup);\n    // double click\n    shapeGroup.off('dblclick');\n    // remove listeners from shape\n    const shape = shapeGroup.getChildren(isNodeNameShape)[0];\n    if (shape instanceof Konva.Shape) {\n      shape.draggable(false);\n      shape.off('dragstart.draw');\n      shape.off('dragmove.draw');\n      shape.off('dragend.draw');\n    }\n    // remove listeners from label\n    const label = shapeGroup.getChildren(isNodeNameLabel)[0];\n    if (label instanceof Konva.Label) {\n      label.draggable(false);\n      label.off('dragstart.draw');\n      label.off('dragend.draw');\n    }\n  }\n} // DrawShapeHandler class","import {Point2D} from '../math/point';\n\n/**\n * Region Of Interest shape.\n * Note: should be a closed path.\n */\nexport class ROI {\n\n  /**\n   * List of points.\n   *\n   * @type {Point2D[]}\n   */\n  #points = [];\n\n  /**\n   * @param {Point2D[]} [points] Optional initial point list.\n   */\n  constructor(points) {\n    if (typeof points !== 'undefined') {\n      this.#points = points;\n    }\n  }\n\n  /**\n   * Get a point of the list at a given index.\n   *\n   * @param {number} index The index of the point to get\n   *   (beware, no size check).\n   * @returns {Point2D|undefined} The Point2D at the given index.\n   */\n  getPoint(index) {\n    return this.#points[index];\n  }\n\n  /**\n   * Get the point list.\n   *\n   * @returns {Point2D[]} The list.\n   */\n  getPoints() {\n    return this.#points;\n  }\n\n  /**\n   * Get the length of the point list.\n   *\n   * @returns {number} The length of the point list.\n   */\n  getLength() {\n    return this.#points.length;\n  }\n\n  /**\n   * Add a point to the ROI.\n   *\n   * @param {Point2D} point The Point2D to add.\n   */\n  addPoint(point) {\n    this.#points.push(point);\n  }\n\n  /**\n   * Add points to the ROI.\n   *\n   * @param {Point2D[]} rhs The array of POints2D to add.\n   */\n  addPoints(rhs) {\n    this.#points = this.#points.concat(rhs);\n  }\n\n  /**\n   * Get the centroid of the roi. Only valid for\n   * a non-self-intersecting closed polygon.\n   * Ref: {@link https://en.wikipedia.org/wiki/Centroid#Of_a_polygon}.\n   *\n   * @returns {Point2D} The centroid point.\n   */\n  getCentroid() {\n    let a = 0;\n    let cx = 0;\n    let cy = 0;\n    for (let i = 0; i < this.#points.length; ++i) {\n      const pi = this.#points[i];\n      let pi1;\n      if (i === this.#points.length - 1) {\n        pi1 = this.#points[0];\n      } else {\n        pi1 = this.#points[i + 1];\n      }\n      const ai = pi.getX() * pi1.getY() - pi1.getX() * pi.getY();\n      a += ai;\n      cx += (pi.getX() + pi1.getX()) * ai;\n      cy += (pi.getY() + pi1.getY()) * ai;\n    }\n    a *= 0.5;\n    const a1 = 1 / (6 * a);\n    cx *= a1;\n    cy *= a1;\n\n    return new Point2D(cx, cy);\n  }\n\n} // ROI class\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D} from '../math/point';\n/* eslint-enable no-unused-vars */\n\n/**\n * Path shape.\n */\nexport class Path {\n\n  /**\n   * @param {Point2D[]} [inputPointArray] The list of Point2D that make\n   *   the path (optional).\n   * @param {number[]} [inputControlPointIndexArray] The list of control\n   *  point of path, as indexes (optional).\n   * Note: first and last point do not need to be equal.\n   */\n  constructor(inputPointArray, inputControlPointIndexArray) {\n    /**\n     * List of points.\n     *\n     * @type {Point2D[]}\n     */\n    this.pointArray = inputPointArray ? inputPointArray.slice() : [];\n    /**\n     * List of control points.\n     *\n     * @type {number[]}\n     */\n    this.controlPointIndexArray = inputControlPointIndexArray\n      ? inputControlPointIndexArray.slice() : [];\n  }\n\n  /**\n   * Get a point of the list.\n   *\n   * @param {number} index The index of the point\n   *   to get (beware, no size check).\n   * @returns {Point2D} The Point2D at the given index.\n   */\n  getPoint(index) {\n    return this.pointArray[index];\n  }\n\n  /**\n   * Is the given point a control point.\n   *\n   * @param {Point2D} point The Point2D to check.\n   * @returns {boolean} True if a control point.\n   */\n  isControlPoint(point) {\n    const index = this.pointArray.indexOf(point);\n    if (index !== -1) {\n      return this.controlPointIndexArray.indexOf(index) !== -1;\n    } else {\n      throw new Error('Error: isControlPoint called with not in list point.');\n    }\n  }\n\n  /**\n   * Get the length of the path.\n   *\n   * @returns {number} The length of the path.\n   */\n  getLength() {\n    return this.pointArray.length;\n  }\n\n  /**\n   * Add a point to the path.\n   *\n   * @param {Point2D} point The Point2D to add.\n   */\n  addPoint(point) {\n    this.pointArray.push(point);\n  }\n\n  /**\n   * Add a control point to the path.\n   *\n   * @param {Point2D} point The Point2D to make a control point.\n   */\n  addControlPoint(point) {\n    const index = this.pointArray.indexOf(point);\n    if (index !== -1) {\n      this.controlPointIndexArray.push(index);\n    } else {\n      throw new Error(\n        'Cannot mark a non registered point as control point.');\n    }\n  }\n\n  /**\n   * Add points to the path.\n   *\n   * @param {Point2D[]} newPointArray The list of Point2D to add.\n   */\n  addPoints(newPointArray) {\n    this.pointArray = this.pointArray.concat(newPointArray);\n  }\n\n  /**\n   * Append a Path to this one.\n   *\n   * @param {Path} other The Path to append.\n   */\n  appenPath(other) {\n    const oldSize = this.pointArray.length;\n    this.pointArray = this.pointArray.concat(other.pointArray);\n    const indexArray = [];\n    for (let i = 0; i < other.controlPointIndexArray.length; ++i) {\n      indexArray[i] = other.controlPointIndexArray[i] + oldSize;\n    }\n    this.controlPointIndexArray =\n      this.controlPointIndexArray.concat(indexArray);\n  }\n\n} // Path class\n","/**\n * Circular Bucket Queue.\n *\n * Returns input'd points in sorted order. All operations run in roughly O(1)\n * time (for input with small cost values), but it has a strict requirement:\n *\n * If the most recent point had a cost of c, any points added should have a cost\n * c' in the range c <= c' <= c + (capacity - 1).\n */\nexport class BucketQueue {\n\n  /**\n   * @param {number} bits Number of bits.\n   * @param {Function} cost_functor The cost functor.\n   */\n  constructor(bits, cost_functor) {\n    this.bucketCount = 1 << bits; // # of buckets = 2^bits\n    this.mask = this.bucketCount - 1; // 2^bits - 1 = index mask\n    this.size = 0;\n\n    this.loc = 0; // Current index in bucket list\n    // Cost defaults to item value\n    this.cost = (typeof (cost_functor) !== 'undefined')\n      ? cost_functor : function (item) {\n        return item;\n      };\n    this.buckets = this.buildArray(this.bucketCount);\n  }\n\n  push(item) {\n    // Prepend item to the list in the appropriate bucket\n    const bucket = this.getBucket(item);\n    item.next = this.buckets[bucket];\n    this.buckets[bucket] = item;\n\n    this.size++;\n  }\n\n  pop() {\n    if (this.size === 0) {\n      throw new Error('Cannot pop, bucketQueue is empty.');\n    }\n\n    // Find first empty bucket\n    while (this.buckets[this.loc] === null) {\n      this.loc = (this.loc + 1) % this.bucketCount;\n    }\n\n    // All items in bucket have same cost, return the first one\n    const ret = this.buckets[this.loc];\n    this.buckets[this.loc] = ret.next;\n    ret.next = null;\n\n    this.size--;\n    return ret;\n  }\n\n  // TODO: needs at least two items...\n  remove(item) {\n    // Tries to remove item from queue. Returns true on success, false otherwise\n    if (!item) {\n      return false;\n    }\n\n    // To find node, go to bucket and search through unsorted list.\n    const bucket = this.getBucket(item);\n    let node = this.buckets[bucket];\n\n    while (node !== null &&\n      !(node.next !== null &&\n      item.x === node.next.x &&\n      item.y === node.next.y)) {\n      node = node.next;\n    }\n\n    if (node === null) {\n      // Item not in list, ergo item not in queue\n      return false;\n    } else {\n      // Found item, do standard list node deletion\n      node.next = node.next.next;\n\n      this.size--;\n      return true;\n    }\n  }\n\n  isEmpty() {\n    return this.size === 0;\n  }\n\n  getBucket(item) {\n    // Bucket index is the masked cost\n    return this.cost(item) & this.mask;\n  }\n\n  buildArray(newSize) {\n    // Create array and initialze pointers to null\n    const buckets = new Array(newSize);\n\n    for (let i = 0; i < buckets.length; i++) {\n      buckets[i] = null;\n    }\n\n    return buckets;\n  }\n\n} // class BucketQueue\n","import {BucketQueue} from './bucketQueue';\n\n// Pre-created to reduce allocation in inner loops\nconst __twothirdpi = (2 / (3 * Math.PI));\n\n/**\n * Compute grey scale.\n *\n * @param {Array} data The input data.\n * @param {number} width The width of the output.\n * @param {number} height The height of the output.\n * @returns {object} A greyscale object.\n */\nfunction computeGreyscale(data, width, height) {\n  // Returns 2D augmented array containing greyscale data\n  // Greyscale values found by averaging colour channels\n  // Input should be in a flat RGBA array, with values between 0 and 255\n  const greyscale = {\n    data: []\n  };\n\n  // Compute actual values\n  for (let y = 0; y < height; y++) {\n    greyscale.data[y] = [];\n\n    for (let x = 0; x < width; x++) {\n      const p = (y * width + x) * 4;\n      greyscale.data[y][x] = (data[p] + data[p + 1] + data[p + 2]) / (3 * 255);\n    }\n  }\n\n  // Augment with convenience functions\n  greyscale.dx = function (x, y) {\n    if (x + 1 === this.data[y].length) {\n      // If we're at the end, back up one\n      x--;\n    }\n    return this.data[y][x + 1] - this.data[y][x];\n  };\n\n  greyscale.dy = function (x, y) {\n    if (y + 1 === this.data.length) {\n      // If we're at the end, back up one\n      y--;\n    }\n    return this.data[y][x] - this.data[y + 1][x];\n  };\n\n  greyscale.gradMagnitude = function (x, y) {\n    const dx = this.dx(x, y);\n    const dy = this.dy(x, y);\n    return Math.sqrt(dx * dx + dy * dy);\n  };\n\n  greyscale.laplace = function (x, y) {\n    // Laplacian of Gaussian\n    let lap = -16 * this.data[y][x];\n    lap += this.data[y - 2][x];\n    lap += this.data[y - 1][x - 1] +\n      2 * this.data[y - 1][x] +\n      this.data[y - 1][x + 1];\n    lap += this.data[y][x - 2] +\n      2 * this.data[y][x - 1] +\n      2 * this.data[y][x + 1] +\n      this.data[y][x + 2];\n    lap += this.data[y + 1][x - 1] +\n      2 * this.data[y + 1][x] +\n      this.data[y + 1][x + 1];\n    lap += this.data[y + 2][x];\n\n    return lap;\n  };\n\n  return greyscale;\n}\n\n/**\n * Compute gradient.\n *\n * @param {object} greyscale The input greyscale.\n * @returns {object} A gradient object.\n */\nfunction computeGradient(greyscale) {\n  // Returns a 2D array of gradient magnitude values for greyscale. The values\n  // are scaled between 0 and 1, and then flipped, so that it works as a cost\n  // function.\n  const gradient = [];\n\n  let max = 0; // Maximum gradient found, for scaling purposes\n\n  let x = 0;\n  let y = 0;\n\n  for (y = 0; y < greyscale.data.length - 1; y++) {\n    gradient[y] = [];\n\n    for (x = 0; x < greyscale.data[y].length - 1; x++) {\n      gradient[y][x] = greyscale.gradMagnitude(x, y);\n      max = Math.max(gradient[y][x], max);\n    }\n\n    gradient[y][greyscale.data[y].length - 1] =\n      gradient[y][greyscale.data.length - 2];\n  }\n\n  gradient[greyscale.data.length - 1] = [];\n  for (let i = 0; i < gradient[0].length; i++) {\n    gradient[greyscale.data.length - 1][i] =\n      gradient[greyscale.data.length - 2][i];\n  }\n\n  // Flip and scale.\n  for (y = 0; y < gradient.length; y++) {\n    for (x = 0; x < gradient[y].length; x++) {\n      // @ts-ignore\n      gradient[y][x] = 1 - (gradient[y][x] / max);\n    }\n  }\n\n  return gradient;\n}\n\n/**\n * @param {object} greyscale The input greyscale.\n * @returns {object} A laplace object.\n */\nfunction computeLaplace(greyscale) {\n  // Returns a 2D array of Laplacian of Gaussian values\n  const laplace = [];\n\n  // Make the edges low cost here.\n\n  laplace[0] = [];\n  laplace[1] = [];\n  for (let i = 1; i < greyscale.data.length; i++) {\n    // Pad top, since we can't compute Laplacian\n    laplace[0][i] = 1;\n    laplace[1][i] = 1;\n  }\n\n  for (let y = 2; y < greyscale.data.length - 2; y++) {\n    laplace[y] = [];\n    // Pad left, ditto\n    laplace[y][0] = 1;\n    laplace[y][1] = 1;\n\n    for (let x = 2; x < greyscale.data[y].length - 2; x++) {\n      // Threshold needed to get rid of clutter.\n      laplace[y][x] = (greyscale.laplace(x, y) > 0.33) ? 0 : 1;\n    }\n\n    // Pad right, ditto\n    laplace[y][greyscale.data[y].length - 2] = 1;\n    laplace[y][greyscale.data[y].length - 1] = 1;\n  }\n\n  laplace[greyscale.data.length - 2] = [];\n  laplace[greyscale.data.length - 1] = [];\n  for (let j = 1; j < greyscale.data.length; j++) {\n    // Pad bottom, ditto\n    laplace[greyscale.data.length - 2][j] = 1;\n    laplace[greyscale.data.length - 1][j] = 1;\n  }\n\n  return laplace;\n}\n\n/**\n * Compute the X gradient.\n *\n * @param {object} greyscale The values.\n * @returns {Array} The gradient.\n */\nfunction computeGradX(greyscale) {\n  // Returns 2D array of x-gradient values for greyscale\n  const gradX = [];\n\n  for (let y = 0; y < greyscale.data.length; y++) {\n    gradX[y] = [];\n\n    for (let x = 0; x < greyscale.data[y].length - 1; x++) {\n      gradX[y][x] = greyscale.dx(x, y);\n    }\n\n    gradX[y][greyscale.data[y].length - 1] =\n      gradX[y][greyscale.data[y].length - 2];\n  }\n\n  return gradX;\n}\n\n/**\n * Compute the Y gradient.\n *\n * @param {object} greyscale The values.\n * @returns {Array} The gradient.\n */\nfunction computeGradY(greyscale) {\n  // Returns 2D array of y-gradient values for greyscale\n  const gradY = [];\n\n  for (let y = 0; y < greyscale.data.length - 1; y++) {\n    gradY[y] = [];\n\n    for (let x = 0; x < greyscale.data[y].length; x++) {\n      gradY[y][x] = greyscale.dy(x, y);\n    }\n  }\n\n  gradY[greyscale.data.length - 1] = [];\n  for (let i = 0; i < greyscale.data[0].length; i++) {\n    gradY[greyscale.data.length - 1][i] = gradY[greyscale.data.length - 2][i];\n  }\n\n  return gradY;\n}\n\n/**\n * Compute the gradient unit vector.\n *\n * @param {Array} gradX The X gradient.\n * @param {Array} gradY The Y gradient.\n * @param {number} px The point X.\n * @param {number} py The point Y.\n * @param {object} out The result.\n */\nfunction gradUnitVector(gradX, gradY, px, py, out) {\n  // Returns the gradient vector at (px,py), scaled to a magnitude of 1\n  const ox = gradX[py][px];\n  const oy = gradY[py][px];\n\n  let gvm = Math.sqrt(ox * ox + oy * oy);\n  gvm = Math.max(gvm, 1e-100); // To avoid possible divide-by-0 errors\n\n  out.x = ox / gvm;\n  out.y = oy / gvm;\n}\n\n/**\n * Compute the gradient direction.\n *\n * @param {Array} gradX The X gradient.\n * @param {Array} gradY The Y gradient.\n * @param {number} px The point X.\n * @param {number} py The point Y.\n * @param {number} qx The q X.\n * @param {number} qy The q Y.\n * @returns {number} The direction.\n */\nfunction gradDirection(gradX, gradY, px, py, qx, qy) {\n  const __dgpuv = {x: -1, y: -1};\n  const __gdquv = {x: -1, y: -1};\n  // Compute the gradiant direction, in radians, between to points\n  gradUnitVector(gradX, gradY, px, py, __dgpuv);\n  gradUnitVector(gradX, gradY, qx, qy, __gdquv);\n\n  let dp = __dgpuv.y * (qx - px) - __dgpuv.x * (qy - py);\n  let dq = __gdquv.y * (qx - px) - __gdquv.x * (qy - py);\n\n  // Make sure dp is positive, to keep things consistant\n  if (dp < 0) {\n    dp = -dp;\n    dq = -dq;\n  }\n\n  if (px !== qx && py !== qy) {\n    // We're going diagonally between pixels\n    dp *= Math.SQRT1_2;\n    dq *= Math.SQRT1_2;\n  }\n\n  return __twothirdpi * (Math.acos(dp) + Math.acos(dq));\n}\n\n/**\n * Compute the sides.\n *\n * @param {number} dist The distance.\n * @param {Array} gradX The X gradient.\n * @param {Array} gradY The Y gradient.\n * @param {object} greyscale The value.\n * @returns {object} The sides.\n */\nfunction computeSides(dist, gradX, gradY, greyscale) {\n  // Returns 2 2D arrays, containing inside and outside greyscale values.\n  // These greyscale values are the intensity just a little bit along the\n  // gradient vector, in either direction, from the supplied point. These\n  // values are used when using active-learning Intelligent Scissors\n\n  const sides = {};\n  sides.inside = [];\n  sides.outside = [];\n\n  const guv = {x: -1, y: -1}; // Current gradient unit vector\n\n  for (let y = 0; y < gradX.length; y++) {\n    sides.inside[y] = [];\n    sides.outside[y] = [];\n\n    for (let x = 0; x < gradX[y].length; x++) {\n      gradUnitVector(gradX, gradY, x, y, guv);\n\n      //(x, y) rotated 90 = (y, -x)\n\n      let ix = Math.round(x + dist * guv.y);\n      let iy = Math.round(y - dist * guv.x);\n      let ox = Math.round(x - dist * guv.y);\n      let oy = Math.round(y + dist * guv.x);\n\n      ix = Math.max(Math.min(ix, gradX[y].length - 1), 0);\n      ox = Math.max(Math.min(ox, gradX[y].length - 1), 0);\n      iy = Math.max(Math.min(iy, gradX.length - 1), 0);\n      oy = Math.max(Math.min(oy, gradX.length - 1), 0);\n\n      sides.inside[y][x] = greyscale.data[iy][ix];\n      sides.outside[y][x] = greyscale.data[oy][ox];\n    }\n  }\n\n  return sides;\n}\n\n/**\n * Gaussian blur an input buffer.\n *\n * @param {Array} buffer The input buffer.\n * @param {Array} out The result.\n */\nfunction gaussianBlur(buffer, out) {\n  // Smooth values over to fill in gaps in the mapping\n  out[0] = 0.4 * buffer[0] + 0.5 * buffer[1] + 0.1 * buffer[1];\n  out[1] = 0.25 * buffer[0] + 0.4 * buffer[1] + 0.25 * buffer[2] +\n    0.1 * buffer[3];\n\n  for (let i = 2; i < buffer.length - 2; i++) {\n    out[i] = 0.05 * buffer[i - 2] + 0.25 * buffer[i - 1] +\n      0.4 * buffer[i] + 0.25 * buffer[i + 1] + 0.05 * buffer[i + 2];\n  }\n\n  const len = buffer.length;\n  out[len - 2] = 0.25 * buffer[len - 1] + 0.4 * buffer[len - 2] +\n    0.25 * buffer[len - 3] + 0.1 * buffer[len - 4];\n  out[len - 1] = 0.4 * buffer[len - 1] + 0.5 * buffer[len - 2] +\n    0.1 * buffer[len - 3];\n}\n\n/**\n * Scissors.\n *\n * Ref: Eric N. Mortensen, William A. Barrett, Interactive Segmentation with\n *   Intelligent Scissors, Graphical Models and Image Processing, Volume 60,\n *   Issue 5, September 1998, Pages 349-384, ISSN 1077-3169,\n *   DOI: 10.1006/gmip.1998.0480.\n *\n * See: {@link http://www.sciencedirect.com/science/article/B6WG4-45JB8WN-9/2/6fe59d8089fd1892c2bfb82283065579}.\n *\n * Highly inspired from: {@link http://code.google.com/p/livewire-javascript/}.\n */\nexport class Scissors {\n\n  constructor() {\n    this.width = -1;\n    this.height = -1;\n\n    this.curPoint = null; // Corrent point we're searching on.\n    this.searchGranBits = 8; // Bits of resolution for BucketQueue.\n    this.searchGran = 1 << this.searchGranBits; //bits.\n    this.pointsPerPost = 500;\n\n    // Precomputed image data. All in ranges 0 >= x >= 1 and\n    //   all inverted (1 - x).\n    this.greyscale = null; // Greyscale of image\n    this.laplace = null; // Laplace zero-crossings (either 0 or 1).\n    this.gradient = null; // Gradient magnitudes.\n    this.gradX = null; // X-differences.\n    this.gradY = null; // Y-differences.\n\n    // Matrix mapping point => parent along shortest-path to root.\n    this.parents = null;\n\n    this.working = false; // Currently computing shortest paths?\n\n    // Begin Training:\n    this.trained = false;\n    this.trainingPoints = null;\n\n    this.edgeWidth = 2;\n    this.trainingLength = 32;\n\n    this.edgeGran = 256;\n    this.edgeTraining = null;\n\n    this.gradPointsNeeded = 32;\n    this.gradGran = 1024;\n    this.gradTraining = null;\n\n    this.insideGran = 256;\n    this.insideTraining = null;\n\n    this.outsideGran = 256;\n    this.outsideTraining = null;\n  }\n  // End Training\n\n\n  // Begin training methods //\n  getTrainingIdx(granularity, value) {\n    return Math.round((granularity - 1) * value);\n  }\n\n  getTrainedEdge(edge) {\n    return this.edgeTraining[this.getTrainingIdx(this.edgeGran, edge)];\n  }\n\n  getTrainedGrad(grad) {\n    return this.gradTraining[this.getTrainingIdx(this.gradGran, grad)];\n  }\n\n  getTrainedInside(inside) {\n    return this.insideTraining[this.getTrainingIdx(this.insideGran, inside)];\n  }\n\n  getTrainedOutside(outside) {\n    return this.outsideTraining[this.getTrainingIdx(this.outsideGran, outside)];\n  }\n  // End training methods //\n\n  setWorking(working) {\n    // Sets working flag\n    this.working = working;\n  }\n\n  setDimensions(width, height) {\n    this.width = width;\n    this.height = height;\n  }\n\n  setData(data) {\n    if (this.width === -1 || this.height === -1) {\n      // The width and height should have already been set\n      throw new Error('Dimensions have not been set.');\n    }\n\n    this.greyscale = computeGreyscale(data, this.width, this.height);\n    this.laplace = computeLaplace(this.greyscale);\n    this.gradient = computeGradient(this.greyscale);\n    this.gradX = computeGradX(this.greyscale);\n    this.gradY = computeGradY(this.greyscale);\n\n    const sides = computeSides(\n      this.edgeWidth, this.gradX, this.gradY, this.greyscale);\n    this.inside = sides.inside;\n    this.outside = sides.outside;\n    this.edgeTraining = [];\n    this.gradTraining = [];\n    this.insideTraining = [];\n    this.outsideTraining = [];\n  }\n\n  findTrainingPoints(p) {\n    // Grab the last handful of points for training\n    const points = [];\n\n    if (this.parents !== null) {\n      for (let i = 0; i < this.trainingLength && p; i++) {\n        points.push(p);\n        p = this.parents[p.y][p.x];\n      }\n    }\n\n    return points;\n  }\n\n  resetTraining() {\n    this.trained = false; // Training is ignored with this flag set\n  }\n\n  doTraining(p) {\n    // Compute training weights and measures\n    this.trainingPoints = this.findTrainingPoints(p);\n\n    if (this.trainingPoints.length < 8) {\n      return; // Not enough points, I think. It might crash if length = 0.\n    }\n\n    const buffer = [];\n    this.calculateTraining(\n      buffer, this.edgeGran, this.greyscale, this.edgeTraining);\n    this.calculateTraining(\n      buffer, this.gradGran, this.gradient, this.gradTraining);\n    this.calculateTraining(\n      buffer, this.insideGran, this.inside, this.insideTraining);\n    this.calculateTraining(\n      buffer, this.outsideGran, this.outside, this.outsideTraining);\n\n    if (this.trainingPoints.length < this.gradPointsNeeded) {\n      // If we have two few training points, the gradient weight map might not\n      // be smooth enough, so average with normal weights.\n      this.addInStaticGrad(this.trainingPoints.length, this.gradPointsNeeded);\n    }\n\n    this.trained = true;\n  }\n\n  calculateTraining(\n    buffer, granularity, input, output) {\n    let i = 0;\n    // Build a map of raw-weights to trained-weights by favoring input values\n    buffer.length = granularity;\n    for (i = 0; i < granularity; i++) {\n      buffer[i] = 0;\n    }\n\n    let maxVal = 1;\n    for (i = 0; i < this.trainingPoints.length; i++) {\n      const p = this.trainingPoints[i];\n      const idx = this.getTrainingIdx(granularity, input[p.y][p.x]);\n      buffer[idx] += 1;\n\n      maxVal = Math.max(maxVal, buffer[idx]);\n    }\n\n    // Invert and scale.\n    for (i = 0; i < granularity; i++) {\n      buffer[i] = 1 - buffer[i] / maxVal;\n    }\n\n    // Blur it, as suggested. Gets rid of static.\n    gaussianBlur(buffer, output);\n  }\n\n  addInStaticGrad(have, need) {\n    // Average gradient raw-weights to trained-weights map with standard weight\n    // map so that we don't end up with something to spiky\n    for (let i = 0; i < this.gradGran; i++) {\n      this.gradTraining[i] = Math.min(\n        this.gradTraining[i],\n        1 - i * (need - have) / (need * this.gradGran)\n      );\n    }\n  }\n\n  gradDirection(px, py, qx, qy) {\n    return gradDirection(this.gradX, this.gradY, px, py, qx, qy);\n  }\n\n  dist(px, py, qx, qy) {\n    // The grand culmunation of most of the code: the weighted distance function\n    let grad = this.gradient[qy][qx];\n\n    if (px === qx || py === qy) {\n      // The distance is Euclidean-ish; non-diagonal edges should be shorter\n      grad *= Math.SQRT1_2;\n    }\n\n    const lap = this.laplace[qy][qx];\n    const dir = this.gradDirection(px, py, qx, qy);\n\n    if (this.trained) {\n      // Apply training magic\n      const gradT = this.getTrainedGrad(grad);\n      const edgeT = this.getTrainedEdge(this.greyscale.data[py][px]);\n      const insideT = this.getTrainedInside(this.inside[py][px]);\n      const outsideT = this.getTrainedOutside(this.outside[py][px]);\n\n      return 0.3 * gradT + 0.3 * lap + 0.1 * (dir + edgeT + insideT + outsideT);\n    } else {\n      // Normal weights\n      return 0.43 * grad + 0.43 * lap + 0.11 * dir;\n    }\n  }\n\n  adj(p) {\n    const list = [];\n\n    const sx = Math.max(p.x - 1, 0);\n    const sy = Math.max(p.y - 1, 0);\n    const ex = Math.min(p.x + 1, this.greyscale.data[0].length - 1);\n    const ey = Math.min(p.y + 1, this.greyscale.data.length - 1);\n\n    let idx = 0;\n    for (let y = sy; y <= ey; y++) {\n      for (let x = sx; x <= ex; x++) {\n        if (x !== p.x || y !== p.y) {\n          list[idx++] = {x: x, y: y};\n        }\n      }\n    }\n\n    return list;\n  }\n\n  #costFunction = (p) => {\n    return Math.round(this.searchGran * this.cost[p.y][p.x]);\n  };\n\n  setPoint(sp) {\n    this.setWorking(true);\n\n    this.curPoint = sp;\n\n    let x = 0;\n    let y = 0;\n\n    this.visited = [];\n    for (y = 0; y < this.height; y++) {\n      this.visited[y] = [];\n      for (x = 0; x < this.width; x++) {\n        this.visited[y][x] = false;\n      }\n    }\n\n    this.parents = [];\n    for (y = 0; y < this.height; y++) {\n      this.parents[y] = [];\n    }\n\n    this.cost = [];\n    for (y = 0; y < this.height; y++) {\n      this.cost[y] = [];\n      for (x = 0; x < this.width; x++) {\n        this.cost[y][x] = Number.MAX_VALUE;\n      }\n    }\n    this.cost[sp.y][sp.x] = 0;\n\n    this.pq = new BucketQueue(this.searchGranBits, this.#costFunction);\n    this.pq.push(sp);\n  }\n\n  doWork() {\n    if (!this.working) {\n      return;\n    }\n\n    this.timeout = null;\n\n    let pointCount = 0;\n    const newPoints = [];\n    while (!this.pq.isEmpty() && pointCount < this.pointsPerPost) {\n      const p = this.pq.pop();\n      newPoints.push(p);\n      newPoints.push(this.parents[p.y][p.x]);\n\n      this.visited[p.y][p.x] = true;\n\n      const adjList = this.adj(p);\n      for (let i = 0; i < adjList.length; i++) {\n        const q = adjList[i];\n\n        const pqCost = this.cost[p.y][p.x] + this.dist(p.x, p.y, q.x, q.y);\n\n        if (pqCost < this.cost[q.y][q.x]) {\n          if (this.cost[q.y][q.x] !== Number.MAX_VALUE) {\n            // Already in PQ, must remove it so we can re-add it.\n            this.pq.remove(q);\n          }\n\n          this.cost[q.y][q.x] = pqCost;\n          this.parents[q.y][q.x] = p;\n          this.pq.push(q);\n        }\n      }\n\n      pointCount++;\n    }\n\n    return newPoints;\n  }\n\n} // Scissors class\n","// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D} from '../math/point';\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Label factory to create and update shape label.\n */\nexport class LabelFactory {\n\n  /**\n   * Default position getter.\n   *\n   * @type {Function}\n   */\n  #defaultPositionGetter;\n\n  /**\n   * @param {Function} positionGetter Default position getter.\n   */\n  constructor(positionGetter) {\n    this.#defaultPositionGetter = positionGetter;\n  }\n\n  /**\n   * Get the annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  getPosition(annotation) {\n    let position = annotation.labelPosition;\n    if (typeof position === 'undefined') {\n      position = this.#defaultPositionGetter(annotation);\n    }\n    return position;\n  }\n\n  /**\n   * Creates the konva label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Label} The Konva label.\n   */\n  create(annotation, style) {\n    // konva text\n    const ktext = new Konva.Text({\n      fontSize: style.getFontSize(),\n      fontFamily: style.getFontFamily(),\n      fill: annotation.colour,\n      padding: style.getTextPadding(),\n      shadowColor: style.getShadowLineColour(),\n      shadowOffset: style.getShadowOffset(),\n      name: 'text'\n    });\n    const labelText = annotation.getText();\n    ktext.setText(labelText);\n\n    // times 2 so that the font size 10 looks like a 10...\n    // (same logic as in the DrawController::updateLabelScale)\n    const zoomScale = style.applyZoomScale(1);\n    const labelScale = {\n      x: 2 * zoomScale.x,\n      y: 2 * zoomScale.y\n    };\n\n    // konva label\n    const labelPosition = this.getPosition(annotation);\n    const klabel = new Konva.Label({\n      x: labelPosition.getX(),\n      y: labelPosition.getY(),\n      scale: labelScale,\n      visible: labelText.length !== 0,\n      name: 'label'\n    });\n    klabel.add(ktext);\n    klabel.add(new Konva.Tag({\n      fill: annotation.colour,\n      opacity: style.getTagOpacity()\n    }));\n\n    return klabel;\n  }\n\n  /**\n   * Update the shape label position.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   */\n  updatePosition(annotation, group) {\n    // associated label\n    const klabel = group.getChildren(function (node) {\n      return node.name() === 'label';\n    })[0];\n    if (!(klabel instanceof Konva.Label)) {\n      return;\n    }\n    // update position\n    const labelPosition = this.getPosition(annotation);\n    klabel.position({\n      x: labelPosition.getX(),\n      y: labelPosition.getY()\n    });\n  }\n\n  /**\n   * Get the anchors positions for the label.\n   *\n   * @param {Konva.Label} label The label.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  getLabelAnchorsPosition(label) {\n    const lx = label.x();\n    const ly = label.y();\n    const dx = label.width() * label.scale().x;\n    const dy = label.height() * label.scale().y;\n    return [\n      new Point2D(lx + dx / 2, ly),\n      new Point2D(lx, ly + dy / 2),\n      new Point2D(lx + dx / 2, ly + dy),\n      new Point2D(lx + dx, ly + dy / 2),\n    ];\n  }\n\n  /**\n   * Get the two closest points of two points lists.\n   *\n   * @param {Point2D[]} points1 The first point list.\n   * @param {Point2D[]} points2 The second point list.\n   * @returns {Point2D[]} The closests points.\n   */\n  getClosestPoints(points1, points2) {\n    let minDist = points1[0].getDistance(points2[0]);\n    let p1 = points1[0];\n    let p2 = points2[0];\n    for (const point1 of points1) {\n      for (const point2 of points2) {\n        const dist = point1.getDistance(point2);\n        if (dist < minDist) {\n          minDist = dist;\n          p1 = point1;\n          p2 = point2;\n        }\n      }\n    }\n    return [p1, p2];\n  }\n\n  /**\n   * Get the connector between this label and its shape.\n   *\n   * @param {Point2D[]} connectorsPos The shape connectors positions.\n   * @param {Konva.Label} label The label.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Line} The connector.\n   */\n  getConnector(connectorsPos, label, style) {\n    const labelAnchorsPos = this.getLabelAnchorsPosition(label);\n    const anchorPoints = this.getClosestPoints(\n      connectorsPos, labelAnchorsPos);\n    return new Konva.Line({\n      points: [\n        anchorPoints[0].getX(),\n        anchorPoints[0].getY(),\n        anchorPoints[1].getX(),\n        anchorPoints[1].getY()\n      ],\n      stroke: label.getText().fill(),\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      visible: label.visible(),\n      dash: [10, 7],\n      name: 'connector'\n    });\n  }\n\n  /**\n   * Update the connector between a label and its shape.\n   *\n   * @param {Konva.Group} group The associated shape group.\n   * @param {Point2D[]} connectorsPos The shape connectors positions.\n   */\n  updateConnector(group, connectorsPos) {\n    // associated label\n    const klabel = group.getChildren(function (node) {\n      return node.name() === 'label';\n    })[0];\n    if (!(klabel instanceof Konva.Label)) {\n      return;\n    }\n\n    const labelAnchorsPos = this.getLabelAnchorsPosition(klabel);\n\n    const anchors = this.getClosestPoints(connectorsPos, labelAnchorsPos);\n\n    const kconnect = group.getChildren(function (node) {\n      return node.name() === 'connector';\n    })[0];\n    if (!(kconnect instanceof Konva.Line)) {\n      return;\n    }\n\n    kconnect.points([\n      anchors[0].getX(),\n      anchors[0].getY(),\n      anchors[1].getX(),\n      anchors[1].getY()\n    ]);\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   */\n  updateContent(annotation, group) {\n    // associated label\n    const klabel = group.getChildren(function (node) {\n      return node.name() === 'label';\n    })[0];\n    if (!(klabel instanceof Konva.Label)) {\n      return;\n    }\n    // update text\n    const text = annotation.getText();\n    const ktext = klabel.getText();\n    ktext.setText(text);\n    // hide if visible and empty\n    if (klabel.visible()) {\n      klabel.visible(text.length !== 0);\n    }\n  }\n\n} // LabelFactory","import {getStats} from './stats';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Index} from './index';\nimport {Point2D} from '../math/point';\nimport {ViewController} from '../app/viewController';\nimport {Scalar2D} from './scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Mulitply the three inputs if the last two are not null.\n *\n * @param {number} a The first input.\n * @param {number} b The second input.\n * @param {number} c The third input.\n * @returns {number} The multiplication of the three inputs or\n *  null if one of the last two is null.\n */\nfunction mulABC(a, b, c) {\n  let res = null;\n  if (b !== null && c !== null) {\n    res = a * b * c;\n  }\n  return res;\n}\n\n/**\n * Circle shape.\n */\nexport class Circle {\n\n  /**\n   * Circle centre.\n   *\n   * @type {Point2D}\n   */\n  #centre;\n\n  /**\n   * Circle radius.\n   *\n   * @type {number}\n   */\n  #radius;\n\n  /**\n   * @param {Point2D} centre A Point2D representing the centre\n   *   of the circle.\n   * @param {number} radius The radius of the circle.\n   */\n  constructor(centre, radius) {\n    this.#centre = centre;\n    this.#radius = radius;\n  }\n\n  /**\n   * Get the centre (point) of the circle.\n   *\n   * @returns {Point2D} The center (point) of the circle.\n   */\n  getCenter() {\n    return this.#centre;\n  }\n\n  /**\n   * Get the centroid of the circle.\n   *\n   * @returns {Point2D} The centroid point.\n   */\n  getCentroid() {\n    return this.#centre;\n  }\n\n  /**\n   * Get the radius of the circle.\n   *\n   * @returns {number} The radius of the circle.\n   */\n  getRadius() {\n    return this.#radius;\n  }\n\n\n  /**\n   * Check for equality.\n   *\n   * @param {Circle} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.getCenter().equals(rhs.getCenter()) &&\n      this.getRadius() === rhs.getRadius();\n  }\n\n  /**\n   * Get the surface of the circle.\n   *\n   * @returns {number} The surface of the circle.\n   */\n  getSurface() {\n    return Math.PI * this.getRadius() * this.getRadius();\n  }\n\n  /**\n   * Get the surface of the circle according to a spacing.\n   *\n   * @param {Scalar2D} spacing2D The 2D spacing.\n   * @returns {number} The surface of the circle multiplied by the given\n   *  spacing or null for null spacings.\n   */\n  getWorldSurface(spacing2D) {\n    return mulABC(this.getSurface(), spacing2D.x, spacing2D.y);\n  }\n\n  /**\n   * Get the rounded limits of the circle.\n   *\n   * See: {@link https://en.wikipedia.org/wiki/Circle#Equations}.\n   *\n   * Circle formula: `x*x + y*y = r*r`.\n   *\n   * Implies: `y = (+-) sqrt(r*r - x*x)`.\n   *\n   * @returns {number[][][]} The rounded limits:\n   *  list of [x, y] pairs (min, max).\n   */\n  getRound() {\n    const centerX = this.getCenter().getX();\n    const centerY = this.getCenter().getY();\n    const radius = this.getRadius();\n    const rSquare = Math.pow(radius, 2);\n    // Y bounds\n    const minY = centerY - radius;\n    const maxY = centerY + radius;\n    const regions = [];\n    // loop through lines and store limits\n    for (let y = minY; y < maxY; ++y) {\n      const diff = rSquare - Math.pow(y - centerY, 2);\n      // remove small values (possibly negative)\n      if (Math.abs(diff) < 1e-7) {\n        continue;\n      }\n      const transX = Math.sqrt(diff);\n      // remove small values\n      if (transX < 0.5) {\n        continue;\n      }\n      regions.push([\n        [Math.round(centerX - transX), Math.round(y)],\n        [Math.round(centerX + transX), Math.round(y)]\n      ]);\n    }\n    return regions;\n  }\n\n  /**\n   * Quantify an circle according to view information.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   * @param {Index} index The index at which to get the\n   *   image values.\n   * @param {string[]} flags A list of stat values to calculate.\n   * @returns {object} A quantification object.\n   */\n  quantify(viewController, index, flags) {\n    const quant = {};\n    // shape quantification\n    const spacing2D = viewController.get2DSpacing();\n    quant.radius = {\n      value: this.getRadius() * spacing2D.x,\n      unit: 'unit.mm'\n    };\n    const surface = this.getWorldSurface(spacing2D);\n    if (surface !== null) {\n      quant.surface = {\n        value: surface / 100,\n        unit: 'unit.cm2'\n      };\n    }\n\n    // pixel values quantification\n    if (viewController.canQuantifyImage()) {\n      const regions = this.getRound();\n      if (regions.length !== 0) {\n        const values = viewController.getImageVariableRegionValues(\n          regions, index);\n        const unit = viewController.getPixelUnit();\n        const quantif = getStats(values, flags);\n        quant.min = {value: quantif.min, unit: unit};\n        quant.max = {value: quantif.max, unit: unit};\n        quant.mean = {value: quantif.mean, unit: unit};\n        quant.stdDev = {value: quantif.stdDev, unit: unit};\n        if (typeof quantif.median !== 'undefined') {\n          quant.median = {value: quantif.median, unit: unit};\n        }\n        if (typeof quantif.p25 !== 'undefined') {\n          quant.p25 = {value: quantif.p25, unit: unit};\n        }\n        if (typeof quantif.p75 !== 'undefined') {\n          quant.p75 = {value: quantif.p75, unit: unit};\n        }\n      }\n    }\n\n    // return\n    return quant;\n  }\n\n} // Circle class\n","import {getStats} from './stats';\nimport {Index} from './index';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D} from '../math/point';\nimport {ViewController} from '../app/viewController';\nimport {Scalar2D} from './scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Mulitply the three inputs if the last two are not null.\n *\n * @param {number} a The first input.\n * @param {number} b The second input.\n * @param {number} c The third input.\n * @returns {number} The multiplication of the three inputs or\n *  null if one of the last two is null.\n */\nfunction mulABC(a, b, c) {\n  let res = null;\n  if (b !== null && c !== null) {\n    res = a * b * c;\n  }\n  return res;\n}\n\n/**\n * Ellipse shape.\n */\nexport class Ellipse {\n\n  /**\n   * Ellipse centre.\n   *\n   * @type {Point2D}\n   */\n  #centre;\n\n  /**\n   * Ellipse horizontal radius.\n   *\n   * @type {number}\n   */\n  #a;\n\n  /**\n   * Ellipse vertical radius.\n   *\n   * @type {number}\n   */\n  #b;\n\n  /**\n   * @param {Point2D} centre A Point2D representing the centre\n   *   of the ellipse.\n   * @param {number} a The radius of the ellipse on the horizontal axe.\n   * @param {number} b The radius of the ellipse on the vertical axe.\n   */\n  constructor(centre, a, b) {\n    this.#centre = centre;\n    this.#a = a;\n    this.#b = b;\n  }\n\n  /**\n   * Get the centre (point) of the ellipse.\n   *\n   * @returns {Point2D} The center (point) of the ellipse.\n   */\n  getCenter() {\n    return this.#centre;\n  }\n\n  /**\n   * Get the centroid of the ellipse.\n   *\n   * @returns {Point2D} The centroid point.\n   */\n  getCentroid() {\n    return this.#centre;\n  }\n\n  /**\n   * Get the radius of the ellipse on the horizontal axe.\n   *\n   * @returns {number} The radius of the ellipse on the horizontal axe.\n   */\n  getA() {\n    return this.#a;\n  }\n\n  /**\n   * Get the radius of the ellipse on the vertical axe.\n   *\n   * @returns {number} The radius of the ellipse on the vertical axe.\n   */\n  getB() {\n    return this.#b;\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Ellipse} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.getCenter().equals(rhs.getCenter()) &&\n      this.getA() === rhs.getA() &&\n      this.getB() === rhs.getB();\n  }\n\n  /**\n   * Get the surface of the ellipse.\n   *\n   * @returns {number} The surface of the ellipse.\n   */\n  getSurface() {\n    return Math.PI * this.getA() * this.getB();\n  }\n\n  /**\n   * Get the surface of the ellipse according to a spacing.\n   *\n   * @param {Scalar2D} spacing2D The 2D spacing.\n   * @returns {number} The surface of the ellipse multiplied by the given\n   *  spacing or null for null spacings.\n   */\n  getWorldSurface(spacing2D) {\n    return mulABC(this.getSurface(), spacing2D.x, spacing2D.y);\n  }\n\n  /**\n   * Get the rounded limits of the ellipse.\n   *\n   * See: {@link https://en.wikipedia.org/wiki/Ellipse#Standard_equation}.\n   *\n   * Ellipse formula: `x*x / a*a + y*y / b*b = 1`.\n   *\n   * Implies: `y = (+-)(b/a) * sqrt(a*a - x*x)`.\n   *\n   * @returns {number[][][]} The rounded limits:\n   *  list of [x, y] pairs (min, max).\n   */\n  getRound() {\n    const centerX = this.getCenter().getX();\n    const centerY = this.getCenter().getY();\n    const radiusX = this.getA();\n    const radiusY = this.getB();\n    const radiusRatio = radiusX / radiusY;\n    const rySquare = Math.pow(radiusY, 2);\n    // Y bounds\n    const minY = centerY - radiusY;\n    const maxY = centerY + radiusY;\n    const regions = [];\n    // loop through lines and store limits\n    for (let y = minY; y < maxY; ++y) {\n      const diff = rySquare - Math.pow(y - centerY, 2);\n      // remove small values (possibly negative)\n      if (Math.abs(diff) < 1e-7) {\n        continue;\n      }\n      const transX = radiusRatio * Math.sqrt(diff);\n      // remove small values\n      if (transX < 0.5) {\n        continue;\n      }\n      regions.push([\n        [Math.round(centerX - transX), Math.round(y)],\n        [Math.round(centerX + transX), Math.round(y)]\n      ]);\n    }\n    return regions;\n  }\n\n  /**\n   * Quantify an ellipse according to view information.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   * @param {Index} index The index at which to get the\n   *   image values.\n   * @param {string[]} flags A list of stat values to calculate.\n   * @returns {object} A quantification object.\n   */\n  quantify(viewController, index, flags) {\n    const quant = {};\n    // shape quantification\n    const spacing2D = viewController.get2DSpacing();\n    quant.a = {\n      value: this.getA() * spacing2D.x,\n      unit: 'unit.mm'\n    };\n    quant.b = {\n      value: this.getB() * spacing2D.y,\n      unit: 'unit.mm'\n    };\n    const surface = this.getWorldSurface(spacing2D);\n    if (surface !== null) {\n      quant.surface = {\n        value: surface / 100,\n        unit: 'unit.cm2'\n      };\n    }\n\n    // pixel values quantification\n    if (viewController.canQuantifyImage()) {\n      const regions = this.getRound();\n      if (regions.length !== 0) {\n        const values = viewController.getImageVariableRegionValues(\n          regions, index);\n        const unit = viewController.getPixelUnit();\n        const quantif = getStats(values, flags);\n        quant.min = {value: quantif.min, unit: unit};\n        quant.max = {value: quantif.max, unit: unit};\n        quant.mean = {value: quantif.mean, unit: unit};\n        quant.stdDev = {value: quantif.stdDev, unit: unit};\n        if (typeof quantif.median !== 'undefined') {\n          quant.median = {value: quantif.median, unit: unit};\n        }\n        if (typeof quantif.p25 !== 'undefined') {\n          quant.p25 = {value: quantif.p25, unit: unit};\n        }\n        if (typeof quantif.p75 !== 'undefined') {\n          quant.p75 = {value: quantif.p75, unit: unit};\n        }\n      }\n    }\n\n    // return\n    return quant;\n  }\n\n} // Ellipse class\n\n/**\n * Get the indices that form a ellpise.\n *\n * @param {Index} center The ellipse center.\n * @param {number[]} radius The 2 ellipse radiuses.\n * @param {number[]} dir The 2 ellipse directions.\n * @returns {Index[]} The indices of the ellipse.\n */\nexport function getEllipseIndices(center, radius, dir) {\n  const centerValues = center.getValues();\n  // keep all values for possible extra dimensions\n  const values = centerValues.slice();\n  const indices = [];\n  const radiusI = radius[0];\n  const radiusJ = radius[1];\n  const radiusRatio = radiusI / radiusJ;\n  const radiusJ2 = Math.pow(radiusJ, 2);\n  const di = dir[0];\n  const dj = dir[1];\n  // deduce 4 positions from top right\n  for (let j = 0; j < radiusJ; ++j) {\n    // right triangle formed by radiuses, j and len\n    // ellipse: i*i / a*a + j*j / b*b = 1\n    // -> i = a/b * sqrt(b*b - j*j)\n    const len = Math.round(\n      radiusRatio * Math.sqrt(radiusJ2 - Math.pow(j, 2)));\n    const jmax = centerValues[dj] + j;\n    const jmin = centerValues[dj] - j;\n    for (let i = 0; i < len; ++i) {\n      const imax = centerValues[di] + i;\n      const imin = centerValues[di] - i;\n\n      // right\n      values[di] = imax;\n      // right - top\n      values[dj] = jmax;\n      indices.push(new Index(values.slice()));\n      // right - bottom\n      if (jmin !== jmax) {\n        values[dj] = jmin;\n        indices.push(new Index(values.slice()));\n      }\n\n      // left\n      if (imin !== imax) {\n        values[di] = imin;\n        // left - top\n        values[dj] = jmax;\n        indices.push(new Index(values.slice()));\n        // left - bottom\n        if (jmin !== jmax) {\n          values[dj] = jmin;\n          indices.push(new Index(values.slice()));\n        }\n      }\n    }\n  }\n  return indices;\n}\n","import {Line, getAngle} from './line';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D} from '../math/point';\nimport {ViewController} from '../app/viewController';\n/* eslint-enable no-unused-vars */\n\n/**\n * Protractor shape: 3 points from which to calculate an angle.\n */\nexport class Protractor {\n\n  /**\n   * List of points.\n   *\n   * @type {Point2D[]}\n   */\n  #points;\n\n  /**\n   * @param {Point2D[]} points The list of Point2D that make\n   *   the protractor.\n   */\n  constructor(points) {\n    if (points.length > 3) {\n      throw new Error('Too many points for a protractor');\n    }\n    this.#points = points.slice(0, 3);\n  }\n\n  /**\n   * Get a point of the list.\n   *\n   * @param {number} index The index of the point\n   *   to get (beware, no size check).\n   * @returns {Point2D|undefined} The Point2D at the given index.\n   */\n  getPoint(index) {\n    return this.#points[index];\n  }\n\n  /**\n   * Get the length of the path (should be 3).\n   *\n   * @returns {number} The length of the path.\n   */\n  getLength() {\n    return this.#points.length;\n  }\n\n  /**\n   * Get the centroid of the protractor.\n   *\n   * @returns {Point2D} THe centroid point.\n   */\n  getCentroid() {\n    return this.#points[1];\n  }\n\n  /**\n   * Quantify a path according to view information.\n   *\n   * @param {ViewController} _viewController The associated view controller.\n   * @param {string[]} _flags A list of stat values to calculate.\n   * @returns {object} A quantification object.\n   */\n  quantify(_viewController, _flags) {\n    const quant = {};\n    if (this.#points.length === 3) {\n      const line0 = new Line(this.#points[0], this.#points[1]);\n      const line1 = new Line(this.#points[1], this.#points[2]);\n      let angle = getAngle(line0, line1);\n      if (angle > 180) {\n        angle = 360 - angle;\n      }\n      quant.angle = {\n        value: angle,\n        unit: 'unit.degree'\n      };\n    }\n    return quant;\n  }\n\n} // Protractor class\n","import {Point2D} from './point';\nimport {getStats} from './stats';\nimport {Index} from './index';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {ViewController} from '../app/viewController';\nimport {Scalar2D} from './scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * Mulitply the three inputs if the last two are not null.\n *\n * @param {number} a The first input.\n * @param {number} b The second input.\n * @param {number} c The third input.\n * @returns {number} The multiplication of the three inputs or\n *  null if one of the last two is null.\n */\nfunction mulABC(a, b, c) {\n  let res = null;\n  if (b !== null && c !== null) {\n    res = a * b * c;\n  }\n  return res;\n}\n\n/**\n * Rectangle shape.\n */\nexport class Rectangle {\n\n  /**\n   * Rectangle begin point.\n   *\n   * @type {Point2D}\n   */\n  #begin;\n\n  /**\n   * Rectangle end point.\n   *\n   * @type {Point2D}\n   */\n  #end;\n\n  /**\n   * @param {Point2D} begin A Point2D representing the beginning\n   *   of the rectangle.\n   * @param {Point2D} end A Point2D representing the end\n   *   of the rectangle.\n   */\n  constructor(begin, end) {\n    this.#begin = new Point2D(\n      Math.min(begin.getX(), end.getX()),\n      Math.min(begin.getY(), end.getY())\n    );\n    this.#end = new Point2D(\n      Math.max(begin.getX(), end.getX()),\n      Math.max(begin.getY(), end.getY())\n    );\n  }\n\n  /**\n   * Get the begin point of the rectangle.\n   *\n   * @returns {Point2D} The begin point of the rectangle.\n   */\n  getBegin() {\n    return this.#begin;\n  }\n\n  /**\n   * Get the end point of the rectangle.\n   *\n   * @returns {Point2D} The end point of the rectangle.\n   */\n  getEnd() {\n    return this.#end;\n  }\n\n  /**\n   * Check for equality.\n   *\n   * @param {Rectangle} rhs The object to compare to.\n   * @returns {boolean} True if both objects are equal.\n   */\n  equals(rhs) {\n    return rhs !== null &&\n      this.getBegin().equals(rhs.getBegin()) &&\n      this.getEnd().equals(rhs.getEnd());\n  }\n\n  /**\n   * Get the surface of the rectangle.\n   *\n   * @returns {number} The surface of the rectangle.\n   */\n  getSurface() {\n    const begin = this.getBegin();\n    const end = this.getEnd();\n    return Math.abs(end.getX() - begin.getX()) *\n      Math.abs(end.getY() - begin.getY());\n  }\n\n  /**\n   * Get the surface of the rectangle according to a spacing.\n   *\n   * @param {Scalar2D} spacing2D The 2D spacing.\n   * @returns {number} The surface of the rectangle multiplied by the given\n   *  spacing or null for null spacings.\n   */\n  getWorldSurface(spacing2D) {\n    return mulABC(this.getSurface(), spacing2D.x, spacing2D.y);\n  }\n\n  /**\n   * Get the real width of the rectangle.\n   *\n   * @returns {number} The real width of the rectangle.\n   */\n  getRealWidth() {\n    return this.getEnd().getX() - this.getBegin().getX();\n  }\n\n  /**\n   * Get the real height of the rectangle.\n   *\n   * @returns {number} The real height of the rectangle.\n   */\n  getRealHeight() {\n    return this.getEnd().getY() - this.getBegin().getY();\n  }\n\n  /**\n   * Get the width of the rectangle.\n   *\n   * @returns {number} The width of the rectangle.\n   */\n  getWidth() {\n    return Math.abs(this.getRealWidth());\n  }\n\n  /**\n   * Get the height of the rectangle.\n   *\n   * @returns {number} The height of the rectangle.\n   */\n  getHeight() {\n    return Math.abs(this.getRealHeight());\n  }\n\n  /**\n   * Get the rounded limits of the rectangle.\n   *\n   * @returns {object} The rounded limits as {min, max} (Point2D).\n   */\n  getRound() {\n    const roundBegin = new Point2D(\n      Math.round(this.getBegin().getX()),\n      Math.round(this.getBegin().getY())\n    );\n    const roundEnd = new Point2D(\n      Math.round(this.getEnd().getX()),\n      Math.round(this.getEnd().getY())\n    );\n    return {\n      min: roundBegin,\n      max: roundEnd\n    };\n  }\n\n  /**\n   * Get the centroid of the rectangle.\n   *\n   * @returns {Point2D} The centroid point.\n   */\n  getCentroid() {\n    return new Point2D(\n      this.getBegin().getX() + this.getWidth() / 2,\n      this.getBegin().getY() + this.getHeight() / 2\n    );\n  }\n\n  /**\n   * Quantify a rectangle according to view information.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   * @param {Index} index The index at which to get the\n   *   image values.\n   * @param {string[]} flags A list of stat values to calculate.\n   * @returns {object} A quantification object.\n   */\n  quantify(viewController, index, flags) {\n    const quant = {};\n    // shape quantification\n    const spacing2D = viewController.get2DSpacing();\n    quant.width = {\n      value: this.getWidth() * spacing2D.x,\n      unit: 'unit.mm'\n    };\n    quant.height = {\n      value: this.getHeight() * spacing2D.y,\n      unit: 'unit.mm'\n    };\n    const surface = this.getWorldSurface(spacing2D);\n    if (surface !== null) {\n      quant.surface = {\n        value: surface / 100,\n        unit: 'unit.cm2'\n      };\n    }\n\n    // pixel values quantification\n    if (viewController.canQuantifyImage()) {\n      const round = this.getRound();\n      const values = viewController.getImageRegionValues(\n        round.min, round.max, index);\n      const unit = viewController.getPixelUnit();\n      const quantif = getStats(values, flags);\n      quant.min = {value: quantif.min, unit: unit};\n      quant.max = {value: quantif.max, unit: unit};\n      quant.mean = {value: quantif.mean, unit: unit};\n      quant.stdDev = {value: quantif.stdDev, unit: unit};\n      if (typeof quantif.median !== 'undefined') {\n        quant.median = {value: quantif.median, unit: unit};\n      }\n      if (typeof quantif.p25 !== 'undefined') {\n        quant.p25 = {value: quantif.p25, unit: unit};\n      }\n      if (typeof quantif.p75 !== 'undefined') {\n        quant.p75 = {value: quantif.p75, unit: unit};\n      }\n    }\n\n    // return\n    return quant;\n  }\n\n} // Rectangle class\n\n/**\n * Get the indices that form a rectangle.\n *\n * @param {Index} center The rectangle center.\n * @param {number[]} size The 2 rectangle sizes.\n * @param {number[]} dir The 2 rectangle directions.\n * @returns {Index[]} The indices of the rectangle.\n */\nexport function getRectangleIndices(center, size, dir) {\n  const centerValues = center.getValues();\n  // keep all values for possible extra dimensions\n  const values = centerValues.slice();\n  const indices = [];\n  const sizeI = size[0];\n  const halfSizeI = Math.floor(sizeI / 2);\n  const sizeJ = size[1];\n  const halfSizeJ = Math.floor(sizeJ / 2);\n  const di = dir[0];\n  const dj = dir[1];\n  for (let j = 0; j < sizeJ; ++j) {\n    values[dj] = centerValues[dj] - halfSizeJ + j;\n    for (let i = 0; i < sizeI; ++i) {\n      values[di] = centerValues[di] - halfSizeI + i;\n      indices.push(new Index(values.slice()));\n    }\n  }\n  return indices;\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\n/* eslint-enable no-unused-vars */\n\n/**\n * Threshold an image between an input minimum and maximum.\n */\nexport class ThresholdFilter {\n  /**\n   * Threshold minimum.\n   *\n   * @type {number}\n   */\n  #min = 0;\n\n  /**\n   * Threshold maximum.\n   *\n   * @type {number}\n   */\n  #max = 0;\n\n  /**\n   * Get the threshold minimum.\n   *\n   * @returns {number} The threshold minimum.\n   */\n  getMin() {\n    return this.#min;\n  }\n\n  /**\n   * Set the threshold minimum.\n   *\n   * @param {number} val The threshold minimum.\n   */\n  setMin(val) {\n    this.#min = val;\n  }\n\n  /**\n   * Get the threshold maximum.\n   *\n   * @returns {number} The threshold maximum.\n   */\n  getMax() {\n    return this.#max;\n  }\n\n  /**\n   * Set the threshold maximum.\n   *\n   * @param {number} val The threshold maximum.\n   */\n  setMax(val) {\n    this.#max = val;\n  }\n\n  /**\n   * Get the name of the filter.\n   *\n   * @returns {string} The name of the filter.\n   */\n  getName() {\n    return 'Threshold';\n  }\n\n  /**\n   * Original image.\n   *\n   * @type {Image}\n   */\n  #originalImage = null;\n\n  /**\n   * Set the original image.\n   *\n   * @param {Image} image The original image.\n   */\n  setOriginalImage(image) {\n    this.#originalImage = image;\n  }\n\n  /**\n   * Get the original image.\n   *\n   * @returns {Image} The original image.\n   */\n  getOriginalImage() {\n    return this.#originalImage;\n  }\n\n  /**\n   * Transform the main image using this filter.\n   *\n   * @returns {Image} The transformed image.\n   */\n  update() {\n    const image = this.getOriginalImage();\n    const imageMin = image.getDataRange().min;\n    const threshFunction = (value) => {\n      if (value < this.getMin() || value > this.getMax()) {\n        return imageMin;\n      } else {\n        return value;\n      }\n    };\n    return image.transform(threshFunction);\n  }\n\n} // class Threshold\n\n/**\n * Sharpen an image using a sharpen convolution matrix.\n */\nexport class SharpenFilter {\n  /**\n   * Get the name of the filter.\n   *\n   * @returns {string} The name of the filter.\n   */\n  getName() {\n    return 'Sharpen';\n  }\n\n  /**\n   * Original image.\n   *\n   * @type {Image}\n   */\n  #originalImage = null;\n\n  /**\n   * Set the original image.\n   *\n   * @param {Image} image The original image.\n   */\n  setOriginalImage(image) {\n    this.#originalImage = image;\n  }\n\n  /**\n   * Get the original image.\n   *\n   * @returns {Image} The original image.\n   */\n  getOriginalImage() {\n    return this.#originalImage;\n  }\n\n  /**\n   * Transform the main image using this filter.\n   *\n   * @returns {Image} The transformed image.\n   */\n  update() {\n    const image = this.getOriginalImage();\n    /* eslint-disable @stylistic/js/array-element-newline */\n    return image.convolute2D([\n      0, -1, 0,\n      -1, 5, -1,\n      0, -1, 0\n    ]);\n    /* eslint-enable @stylistic/js/array-element-newline */\n  }\n\n} // class Sharpen\n\n/**\n * Apply a Sobel filter to an image.\n */\nexport class SobelFilter {\n  /**\n   * Get the name of the filter.\n   *\n   * @returns {string} The name of the filter.\n   */\n  getName() {\n    return 'Sobel';\n  }\n\n  /**\n   * Original image.\n   *\n   * @type {Image}\n   */\n  #originalImage = null;\n\n  /**\n   * Set the original image.\n   *\n   * @param {Image} image The original image.\n   */\n  setOriginalImage(image) {\n    this.#originalImage = image;\n  }\n\n  /**\n   * Get the original image.\n   *\n   * @returns {Image} The original image.\n   */\n  getOriginalImage() {\n    return this.#originalImage;\n  }\n\n  /**\n   * Transform the main image using this filter.\n   *\n   * @returns {Image} The transformed image.\n   */\n  update() {\n    const image = this.getOriginalImage();\n    /* eslint-disable @stylistic/js/array-element-newline */\n    const gradX = image.convolute2D([\n      1, 0, -1,\n      2, 0, -2,\n      1, 0, -1\n    ]);\n    const gradY = image.convolute2D([\n      1, 2, 1,\n      0, 0, 0,\n      -1, -2, -1\n    ]);\n    /* eslint-enable @stylistic/js/array-element-newline */\n    return gradX.compose(gradY, function (x, y) {\n      return Math.sqrt(x * x + y * y);\n    });\n  }\n\n} // class Sobel\n","import {ListenerHandler} from '../utils/listen';\nimport {\n  ThresholdFilter,\n  SobelFilter,\n  SharpenFilter\n} from '../image/filter';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\n/* eslint-enable no-unused-vars */\n\n/**\n * Filter tool.\n */\nexport class Filter {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Filter list.\n   *\n   * @type {object}\n   */\n  #filterList = null;\n\n  /**\n   * Selected filter.\n   *\n   * @type {object}\n   */\n  #selectedFilter = 0;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} bool Flag to activate or not.\n   */\n  activate(bool) {\n    // setup event listening\n    for (const key in this.#filterList) {\n      if (bool) {\n        this.#filterList[key].addEventListener('filterrun', this.#fireEvent);\n        this.#filterList[key].addEventListener('filter-undo', this.#fireEvent);\n      } else {\n        this.#filterList[key].removeEventListener(\n          'filterrun', this.#fireEvent);\n        this.#filterList[key].removeEventListener(\n          'filter-undo', this.#fireEvent);\n      }\n    }\n  }\n\n  /**\n   * Set the tool options.\n   *\n   * @param {object} options The list of filter names amd classes.\n   */\n  setOptions(options) {\n    this.#filterList = {};\n    // try to instanciate filters from the options\n    for (const key in options) {\n      this.#filterList[key] = new options[key](this.#app);\n    }\n  }\n\n  /**\n   * Get the type of tool options: here 'instance' since the filter\n   * list contains instances of each possible filter.\n   *\n   * @returns {string} The type.\n   */\n  getOptionsType() {\n    return 'instance';\n  }\n\n  /**\n   * Initialise the filter. Called once the image is loaded.\n   */\n  init() {\n    // setup event listening\n    for (const key in this.#filterList) {\n      this.#filterList[key].init();\n    }\n  }\n\n  /**\n   * Handle keydown event.\n   *\n   * @param {object} event The keydown event.\n   */\n  keydown = (event) => {\n    event.context = 'Filter';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Get the list of event names that this tool can fire.\n   *\n   * @returns {string[]} The list of event names.\n   */\n  getEventNames() {\n    return ['filterrun', 'filterundo'];\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  /**\n   * Get the selected filter.\n   *\n   * @returns {object} The selected filter.\n   */\n  getSelectedFilter() {\n    return this.#selectedFilter;\n  }\n\n  /**\n   * Set the tool live features: filter name.\n   *\n   * @param {object} features The list of features.\n   */\n  setFeatures(features) {\n    if (typeof features.filterName !== 'undefined') {\n      // check if we have it\n      if (!this.hasFilter(features.filterName)) {\n        throw new Error('Unknown filter: \\'' + features.filterName + '\\'');\n      }\n      // de-activate last selected\n      if (this.#selectedFilter) {\n        this.#selectedFilter.activate(false);\n      }\n      // enable new one\n      this.#selectedFilter = this.#filterList[features.filterName];\n      // activate the selected filter\n      this.#selectedFilter.activate(true);\n    }\n    if (typeof features.run !== 'undefined' && features.run) {\n      let args = {};\n      if (typeof features.runArgs !== 'undefined') {\n        args = features.runArgs;\n      }\n      this.getSelectedFilter().run(args);\n    }\n  }\n\n  /**\n   * Get the list of filters.\n   *\n   * @returns {Array} The list of filter objects.\n   */\n  getFilterList() {\n    return this.#filterList;\n  }\n\n  /**\n   * Check if a filter is in the filter list.\n   *\n   * @param {string} name The name to check.\n   * @returns {string} The filter list element for the given name.\n   */\n  hasFilter(name) {\n    return this.#filterList[name];\n  }\n\n} // class Filter\n\n/**\n * Threshold filter tool.\n */\nexport class Threshold {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Associated filter.\n   *\n   * @type {object}\n   */\n  #filter = new ThresholdFilter();\n\n  /**\n   * Flag to know wether to reset the image or not.\n   *\n   * @type {boolean}\n   */\n  #resetImage = true;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Activate the filter.\n   *\n   * @param {boolean} bool Flag to activate or not.\n   */\n  activate(bool) {\n    // reset the image when the tool is activated\n    if (bool) {\n      this.#resetImage = true;\n    }\n  }\n\n  /**\n   * Initialise the filter. Called once the image is loaded.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Run the filter.\n   *\n   * @param {*} args The filter arguments.\n   */\n  run(args) {\n    if (typeof args.dataId === 'undefined') {\n      throw new Error('No dataId to run threshod filter on.');\n    }\n    this.#filter.setMin(args.min);\n    this.#filter.setMax(args.max);\n    // reset the image if asked\n    if (this.#resetImage) {\n      const image = this.#app.getData(args.dataId).image;\n      this.#filter.setOriginalImage(image);\n      this.#resetImage = false;\n    }\n    const command = new RunFilterCommand(this.#filter, args.dataId, this.#app);\n    command.onExecute = this.#fireEvent;\n    command.onUndo = this.#fireEvent;\n    command.execute();\n    // save command in undo stack\n    this.#app.addToUndoStack(command);\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *  event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n} // class Threshold\n\n/**\n * Sharpen filter tool.\n */\nexport class Sharpen {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Activate the filter.\n   *\n   * @param {boolean} _bool Flag to activate or not.\n   */\n  activate(_bool) {\n    // does nothing\n  }\n\n  /**\n   * Initialise the filter. Called once the image is loaded.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Run the filter.\n   *\n   * @param {*} args The filter arguments.\n   */\n  run(args) {\n    if (typeof args.dataId === 'undefined') {\n      throw new Error('No dataId to run sharpen filter on.');\n    }\n    const filter = new SharpenFilter();\n    const image = this.#app.getData(args.dataId).image;\n    filter.setOriginalImage(image);\n    const command = new RunFilterCommand(filter, args.dataId, this.#app);\n    command.onExecute = this.#fireEvent;\n    command.onUndo = this.#fireEvent;\n    command.execute();\n    // save command in undo stack\n    this.#app.addToUndoStack(command);\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *    event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n} // filter.Sharpen\n\n/**\n * Sobel filter tool.\n */\nexport class Sobel {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Activate the filter.\n   *\n   * @param {boolean} _bool Flag to activate or not.\n   */\n  activate(_bool) {\n    // does nothing\n  }\n\n  /**\n   * Initialise the filter. Called once the image is loaded.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Run the filter.\n   *\n   * @param {*} args The filter arguments.\n   */\n  run(args) {\n    if (typeof args.dataId === 'undefined') {\n      throw new Error('No dataId to run sobel filter on.');\n    }\n    const filter = new SobelFilter();\n    const image = this.#app.getData(args.dataId).image;\n    filter.setOriginalImage(image);\n    const command = new RunFilterCommand(filter, args.dataId, this.#app);\n    command.onExecute = this.#fireEvent;\n    command.onUndo = this.#fireEvent;\n    command.execute();\n    // save command in undo stack\n    this.#app.addToUndoStack(command);\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *  event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n} // class filter.Sobel\n\n/**\n * Run filter command.\n */\nexport class RunFilterCommand {\n\n  /**\n   * The filter to run.\n   *\n   * @type {object}\n   */\n  #filter;\n\n  /**\n   * Data id.\n   *\n   * @type {string}\n   */\n  #dataId;\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {object} filter The filter to run.\n   * @param {string} dataId The data to filter.\n   * @param {App} app The associated application.\n   */\n  constructor(filter, dataId, app) {\n    this.#filter = filter;\n    this.#dataId = dataId;\n    this.#app = app;\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'Filter-' + this.#filter.getName();\n  }\n\n  /**\n   * Execute the command.\n   *\n   * @fires RunFilterCommand#filterrun\n   */\n  execute() {\n    // run filter and set app image\n    this.#app.setImage(this.#dataId, this.#filter.update());\n    // update display\n    this.#app.render(this.#dataId);\n    /**\n     * Filter run event.\n     *\n     * @event RunFilterCommand#filterrun\n     * @type {object}\n     * @property {string} type The event type: filterrun.\n     * @property {number} id The id of the run command.\n     */\n    const event = {\n      type: 'filterrun',\n      id: this.getName(),\n      dataId: this.#dataId\n    };\n    // callback\n    this.onExecute(event);\n  }\n\n  /**\n   * Undo the command.\n   *\n   * @fires RunFilterCommand#filterundo\n   */\n  undo() {\n    // reset the image\n    this.#app.setImage(this.#dataId, this.#filter.getOriginalImage());\n    // update display\n    this.#app.render(this.#dataId);\n    /**\n     * Filter undo event.\n     *\n     * @event RunFilterCommand#filterundo\n     * @type {object}\n     * @property {string} type The event type: filterundo.\n     * @property {number} id The id of the undone run command.\n     */\n    const event = {\n      type: 'filterundo',\n      id: this.getName(),\n      dataid: this.#dataId\n    }; // callback\n    this.onUndo(event);\n  }\n\n  /**\n   * Handle an execute event.\n   *\n   * @param {object} _event The execute event with type and id.\n   */\n  onExecute(_event) {\n    // default does nothing.\n  }\n\n  /**\n   * Handle an undo event.\n   *\n   * @param {object} _event The undo event with type and id.\n   */\n  onUndo(_event) {\n    // default does nothing.\n  }\n\n} // RunFilterCommand class\n","import {WindowLevel} from './windowLevel';\nimport {Scroll} from './scroll';\nimport {ZoomAndPan} from './zoomPan';\nimport {Opacity} from './opacity';\nimport {Draw} from './draw';\nimport {Floodfill} from './floodfill';\nimport {Livewire} from './livewire';\n\nimport {ArrowFactory} from './arrow';\nimport {CircleFactory} from './circle';\nimport {EllipseFactory} from './ellipse';\nimport {ProtractorFactory} from './protractor';\nimport {RectangleFactory} from './rectangle';\nimport {RoiFactory} from './roi';\nimport {RulerFactory} from './ruler';\n\nimport {Filter, Threshold, Sobel, Sharpen} from './filter';\n\n/**\n * List of client provided tools to be added to\n * the default ones.\n *\n * @example\n * // custom tool\n * class AlertTool {\n *   mousedown() {alert('AlertTool mousedown');}\n *   init() {}\n *   activate() {}\n * }\n * // pass it to dwv tool list\n * dwv.toolList['Alert'] = AlertTool;\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {Alert: {}};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('Alert');\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n *\n * @type {Object<string, any>}\n */\nexport const toolList = {};\n\n/**\n * List of client provided tool options to be added to\n * the default ones.\n *\n * @example\n * // custom factory\n * class LoveFactory {\n *   getName() {return 'love';}\n *   static supports(mathShape) {return mathShape instanceof ROI;}\n *   getNPoints() {return 1;}\n *   getTimeout() {return 0;}\n *   setAnnotationMathShape(annotation, points) {\n *     const px = points[0].getX();\n *     const py = points[0].getY();\n *     annotation.mathShape = new dwv.ROI([\n *       new dwv.Point2D(px+15,py), new dwv.Point2D(px+10,py-10),\n *       new dwv.Point2D(px,py), new dwv.Point2D(px-10,py-10),\n *       new dwv.Point2D(px-15,py), new dwv.Point2D(px,py+20)\n *     ]);\n *     annotation.getFactory = function () {return new LoveFactory();}\n *   }\n *   createShapeGroup(annotation, style) {\n *     const roi = annotation.mathShape;\n *     // konva line\n *     const arr = [];\n *     for (let i = 0; i < roi.getLength(); ++i) {\n *       arr.push(roi.getPoint(i).getX());\n *       arr.push(roi.getPoint(i).getY());\n *     }\n *     const shape = new Konva.Line({\n *       name: 'shape', points: arr,\n *       stroke: 'red', strokeWidth: 2,\n *       closed: true\n *     });\n *     // konva group\n *     const group = new Konva.Group();\n *     group.name('love-group');\n *     group.visible(true);\n *     group.id(annotation.id);\n *     group.add(shape);\n *     return group;\n *   }\n * }\n * // pass it to dwv option list\n * dwv.toolOptions['draw'] = {LoveFactory};\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {Draw: {options: ['Love']}};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('Draw');\n *   app.setToolFeatures({shapeName: 'Love'});\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n *\n * @type {Object<string, Object<string, any>>}\n */\nexport const toolOptions = {};\n\n/**\n * Default tool list.\n *\n * @type {Object<string, any>}\n */\nexport const defaultToolList = {\n  WindowLevel,\n  Scroll,\n  ZoomAndPan,\n  Opacity,\n  Draw,\n  Filter,\n  Floodfill,\n  Livewire\n};\n\n/**\n * Default tool options.\n *\n * @type {Object<string, Object<string, any>>}\n */\nexport const defaultToolOptions = {\n  draw: {\n    ArrowFactory,\n    CircleFactory,\n    EllipseFactory,\n    ProtractorFactory,\n    RectangleFactory,\n    RoiFactory,\n    RulerFactory\n  },\n  filter: {\n    Threshold,\n    Sobel,\n    Sharpen\n  }\n};","import {ScrollWheel} from './scrollWheel';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {\n  validateWindowWidth,\n  WindowLevel as WindowLevelValues\n} from '../image/windowLevel';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {Point2D} from '../math/point';\n/* eslint-enable no-unused-vars */\n\n/**\n * WindowLevel tool: handle window/level related events.\n *\n * @example\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {WindowLevel: new dwv.ToolConfig()};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('WindowLevel');\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n */\nexport class WindowLevel {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Start point.\n   *\n   * @type {Point2D}\n   */\n  #startPoint;\n\n  /**\n   * Scroll wheel handler.\n   *\n   * @type {ScrollWheel}\n   */\n  #scrollWhell;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n    this.#scrollWhell = new ScrollWheel(app);\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   */\n  #start(point, divId) {\n    // check if possible\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer === 'undefined') {\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n    if (!viewController.isMonochrome()) {\n      return;\n    }\n\n    this.#started = true;\n    this.#startPoint = point;\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    // check start flag\n    if (!this.#started) {\n      return;\n    }\n\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer === 'undefined') {\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n\n    // difference to last position\n    const diffX = point.getX() - this.#startPoint.getX();\n    const diffY = this.#startPoint.getY() - point.getY();\n    // data range\n    const range = viewController.getImageRescaledDataRange();\n    // 1/1000 seems to give reasonable results...\n    const pixelToIntensity = (range.max - range.min) * 0.01;\n\n    // calculate new window level\n    const center = viewController.getWindowLevel().center;\n    const width = viewController.getWindowLevel().width;\n    const windowCenter = center + Math.round(diffY * pixelToIntensity);\n    let windowWidth = width + Math.round(diffX * pixelToIntensity);\n    // bound window width\n    windowWidth = validateWindowWidth(windowWidth);\n    // set\n    const wl = new WindowLevelValues(windowCenter, windowWidth);\n    viewController.setWindowLevel(wl);\n\n    // store position\n    this.#startPoint = point;\n  }\n\n  /**\n   * Finish tool interaction.\n   */\n  #finish() {\n    if (this.#started) {\n      this.#started = false;\n    }\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} _event The mouse up event.\n   */\n  mouseup = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} _event The touch end event.\n   */\n  touchend = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle double click event.\n   *\n   * @param {object} event The double click event.\n   */\n  dblclick = (event) => {\n    const layerDetails = getLayerDetailsFromEvent(event);\n    const mousePoint = getMousePoint(event);\n\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    const viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer === 'undefined') {\n      return;\n    }\n    const index = viewLayer.displayToPlaneIndex(mousePoint);\n    const viewController = viewLayer.getViewController();\n    // exit if not possible\n    if (!viewController.isMonochrome()) {\n      return;\n    }\n\n    // update view controller\n    const image = this.#app.getData(viewLayer.getDataId()).image;\n    const wl = new WindowLevelValues(\n      image.getRescaledValueAtIndex(\n        viewController.getCurrentIndex().getWithNew2D(\n          index.get(0),\n          index.get(1)\n        )\n      ),\n      viewController.getWindowLevel().width\n    );\n    viewController.setWindowLevel(wl);\n  };\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {WheelEvent} event The mouse wheel event.\n   */\n  wheel = (event) => {\n    this.#scrollWhell.wheel(event);\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'WindowLevel';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} _bool The flag to activate or not.\n   */\n  activate(_bool) {\n    // does nothing\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Set the tool live features: does nothing.\n   *\n   * @param {object} _features The list of features.\n   */\n  setFeatures(_features) {\n    // does nothing\n  }\n\n} // WindowLevel class\n","import {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {ScrollWheel} from './scrollWheel';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {Point2D} from '../math/point';\nimport {LayerGroup} from '../gui/layerGroup';\nimport {ViewLayer} from '../gui/viewLayer';\n/* eslint-enable no-unused-vars */\n\n/**\n * Scroll class.\n *\n * @example\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {Scroll: new dwv.ToolConfig()};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('Scroll');\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm',\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323707.dcm',\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323563.dcm'\n * ]);\n * @example <caption>Example with slider</caption>\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {Scroll: new dwv.ToolConfig()};\n * app.init(options);\n * // create range\n * const range = document.createElement('input');\n * range.type = 'range';\n * range.min = 0;\n * range.id = 'sliceRange';\n * document.body.appendChild(range);\n * // update app on slider change\n * range.oninput = function () {\n *   const lg = app.getLayerGroupByDivId('layerGroup0');\n *   const vl = lg.getBaseViewLayer();\n *   const vc = vl.getViewController();\n *   const index = vc.getCurrentIndex();\n *   const values = index.getValues();\n *   values[2] = this.value;\n *   vc.setCurrentIndex(new dwv.Index(values));\n * }\n * // activate tool and update range max on load\n * app.addEventListener('load', function () {\n *   app.setTool('Scroll');\n *   const size = app.getData(0).image.getGeometry().getSize();\n *   range.max = size.get(2) - 1;\n * });\n * // update slider on slice change (for ex via mouse wheel)\n * app.addEventListener('positionchange', function () {\n *   const lg = app.getLayerGroupByDivId('layerGroup0');\n *   const vl = lg.getBaseViewLayer();\n *   const vc = vl.getViewController();\n *   range.value = vc.getCurrentIndex().get(2);\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm',\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323707.dcm',\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323563.dcm'\n * ]);\n */\nexport class Scroll {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Start point.\n   *\n   * @type {Point2D}\n   */\n  #startPoint;\n\n  /**\n   * Scroll wheel handler.\n   *\n   * @type {ScrollWheel}\n   */\n  #scrollWhell;\n\n  /**\n   * Touch timer ID (created by setTimeout).\n   *\n   * @type {number}\n   */\n  #touchTimerID;\n\n  /**\n   * Option to show or not a value tooltip on mousemove.\n   *\n   * @type {boolean}\n   */\n  #displayTooltip = false;\n\n  /**\n   * Current layer group div id.\n   *\n   * @type {string}\n   */\n  #currentDivId;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n    this.#scrollWhell = new ScrollWheel(app);\n  }\n\n  /**\n   * Get the associated view layer.\n   *\n   * @param {LayerGroup} layerGroup The layer group to search.\n   * @returns {ViewLayer|undefined} The view layer.\n   */\n  #getViewLayer(layerGroup) {\n    let viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer === 'undefined') {\n      const drawLayer = layerGroup.getActiveDrawLayer();\n      if (typeof drawLayer === 'undefined') {\n        logger.warn('No draw layer to do scroll');\n        return;\n      }\n      viewLayer = layerGroup.getViewLayerById(\n        drawLayer.getReferenceLayerId());\n    }\n    return viewLayer;\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   */\n  #start(point, divId) {\n    // optional tooltip\n    this.#removeTooltipDiv();\n\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to start scroll');\n      return;\n    }\n\n    const viewController = viewLayer.getViewController();\n\n    // stop auto scroll if playing\n    if (viewController.isPlaying()) {\n      viewController.stop();\n    }\n    // update base controller position\n    const planePos = viewLayer.displayToPlanePos(point);\n    const position = viewController.getPositionFromPlanePoint(planePos);\n    viewController.setCurrentPosition(position);\n\n    // start flag\n    this.#started = true;\n    this.#startPoint = point;\n\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    if (!this.#started) {\n      // optional tooltip\n      if (this.#displayTooltip) {\n        this.#showTooltip(point, divId);\n      }\n      return;\n    }\n\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const positionHelper = layerGroup.getPositionHelper();\n\n    // difference to last Y position\n    const diffY = point.getY() - this.#startPoint.getY();\n    const yMove = (Math.abs(diffY) > 15);\n    // difference to last X position\n    const diffX = point.getX() - this.#startPoint.getX();\n    const xMove = (Math.abs(diffX) > 15);\n\n    // do not trigger for small moves\n    if (yMove && layerGroup.canScroll()) {\n      // update view controller\n      if (diffY > 0) {\n        positionHelper.decrementPositionAlongScroll();\n      } else {\n        positionHelper.incrementPositionAlongScroll();\n      }\n    } else if (xMove && layerGroup.moreThanOne(3)) {\n      // update view controller\n      if (diffX > 0) {\n        positionHelper.incrementPosition(3);\n      } else {\n        positionHelper.decrementPosition(3);\n      }\n    }\n\n    // reset origin point\n    if (xMove || yMove) {\n      this.#startPoint = point;\n    }\n  }\n\n  /**\n   * Finish tool interaction.\n   */\n  #finish() {\n    if (this.#started) {\n      this.#started = false;\n    }\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} _event The mouse up event.\n   */\n  mouseup = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    this.#finish();\n    // remove possible tooltip div\n    this.#removeTooltipDiv();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    // long touch triggers the dblclick\n    // @ts-ignore\n    this.#touchTimerID = setTimeout(() => {\n      this.dblclick(event);\n    }, 500);\n    // call start\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    // abort timer if move\n    if (this.#touchTimerID !== null) {\n      clearTimeout(this.#touchTimerID);\n      this.#touchTimerID = null;\n    }\n    // call update\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} _event The touch end event.\n   */\n  touchend = (_event) => {\n    // abort timer\n    if (this.#touchTimerID !== null) {\n      clearTimeout(this.#touchTimerID);\n      this.#touchTimerID = null;\n    }\n    // call mouse equivalent\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {WheelEvent} event The mouse wheel event.\n   */\n  wheel = (event) => {\n    this.#scrollWhell.wheel(event);\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'Scroll';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Handle double click.\n   *\n   * @param {object} event The key down event.\n   */\n  dblclick = (event) => {\n    const layerDetails = getLayerDetailsFromEvent(event);\n\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    const viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer !== 'undefined') {\n      const viewController = viewLayer.getViewController();\n      viewController.play();\n    }\n  };\n\n  /**\n   * Display a tooltip at the given point.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #showTooltip(point, divId) {\n    // get layer group\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    this.#currentDivId = divId;\n    // show new tooltip\n    layerGroup.showTooltip(point);\n  }\n\n  /**\n   * Remove the last tooltip html div.\n   */\n  #removeTooltipDiv() {\n    if (typeof this.#currentDivId !== 'undefined') {\n      const layerGroup = this.#app.getLayerGroupByDivId(this.#currentDivId);\n      layerGroup.removeTooltipDiv();\n      this.#currentDivId = undefined;\n    }\n  }\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} _bool The flag to activate or not.\n   */\n  activate(_bool) {\n    // remove tooltip html when deactivating\n    if (!_bool) {\n      this.#removeTooltipDiv();\n    }\n  }\n\n  /**\n   * Set the tool live features: disaply tooltip.\n   *\n   * @param {object} features The list of features.\n   */\n  setFeatures(features) {\n    if (typeof features.displayTooltip !== 'undefined') {\n      this.#displayTooltip = features.displayTooltip;\n    }\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n} // Scroll class\n","import {Point2D} from '../math/point';\nimport {Line} from '../math/line';\nimport {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {LayerGroup} from '../gui/layerGroup';\nimport {ViewLayer} from '../gui/viewLayer';\n/* eslint-enable no-unused-vars */\n\n/**\n * ZoomAndPan class.\n *\n * @example\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {ZoomAndPan: new dwv.ToolConfig()};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('ZoomAndPan');\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n */\nexport class ZoomAndPan {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Start point.\n   *\n   * @type {Point2D}\n   */\n  #startPoint;\n\n  /**\n   * Move flag: true if mouse or touch move.\n   *\n   * @type {boolean}\n   */\n  #hasMoved;\n\n  /**\n   * Line between input points.\n   *\n   * @type {Line}\n   */\n  #pointsLine;\n\n  /**\n   * PointsLine midpoint.\n   *\n   * @type {Point2D}\n   */\n  #midPoint;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Get the associated view layer.\n   *\n   * @param {LayerGroup} layerGroup The layer group to search.\n   * @returns {ViewLayer|undefined} The view layer.\n   */\n  #getViewLayer(layerGroup) {\n    let viewLayer = layerGroup.getActiveViewLayer();\n    if (typeof viewLayer === 'undefined') {\n      const drawLayer = layerGroup.getActiveDrawLayer();\n      if (typeof drawLayer === 'undefined') {\n        logger.warn('No draw layer to do zoom/pan');\n        return;\n      }\n      viewLayer = layerGroup.getViewLayerById(\n        drawLayer.getReferenceLayerId());\n    }\n    return viewLayer;\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   */\n  #start(point) {\n    this.#started = true;\n    this.#startPoint = point;\n    this.#hasMoved = false;\n  }\n\n  /**\n   * Two touch start.\n   *\n   * @param {Point2D[]} points The start points.\n   */\n  #twoTouchStart = (points) => {\n    this.#started = true;\n    this.#startPoint = points[0];\n    this.#hasMoved = false;\n    // points line\n    this.#pointsLine = new Line(points[0], points[1]);\n    this.#midPoint = this.#pointsLine.getMidpoint();\n  };\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    if (!this.#started) {\n      return;\n    }\n    this.#hasMoved = true;\n\n    // calculate translation\n    const tx = point.getX() - this.#startPoint.getX();\n    const ty = point.getY() - this.#startPoint.getY();\n    // apply translation\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to update zoom/pan');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n    const planeOffset = viewLayer.displayToPlaneScale(\n      new Point2D(tx, ty)\n    );\n    const offset3D = viewController.getOffset3DFromPlaneOffset({\n      x: planeOffset.getX(),\n      y: planeOffset.getY()\n    });\n    layerGroup.addTranslation({\n      x: offset3D.getX(),\n      y: offset3D.getY(),\n      z: offset3D.getZ()\n    });\n    layerGroup.draw();\n    // reset origin point\n    this.#startPoint = point;\n  }\n\n  /**\n   * Two touch update.\n   *\n   * @param {Point2D[]} points The update points.\n   * @param {string} divId The layer group divId.\n   */\n  #twoTouchUpdate = (points, divId) => {\n    if (!this.#started) {\n      return;\n    }\n    this.#hasMoved = true;\n\n    const newLine = new Line(points[0], points[1]);\n    const lineRatio = newLine.getLength() / this.#pointsLine.getLength();\n\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const positionHelper = layerGroup.getPositionHelper();\n\n    if (lineRatio === 1) {\n      // scroll mode\n      // difference  to last position\n      const diffY = points[0].getY() - this.#startPoint.getY();\n      // do not trigger for small moves\n      if (Math.abs(diffY) < 15) {\n        return;\n      }\n      // update view controller\n      if (layerGroup.canScroll()) {\n        if (diffY > 0) {\n          positionHelper.incrementPositionAlongScroll();\n        } else {\n          positionHelper.decrementPositionAlongScroll();\n        }\n      }\n    } else {\n      // zoom mode\n      const zoom = (lineRatio - 1) / 10;\n      if (Math.abs(zoom) % 0.1 <= 0.05 &&\n        typeof this.#midPoint !== 'undefined') {\n        const viewLayer = this.#getViewLayer(layerGroup);\n        if (typeof viewLayer === 'undefined') {\n          logger.warn('No view layer to do touch zoom/pan');\n          return;\n        }\n        const viewController = viewLayer.getViewController();\n        const planePos = viewLayer.displayToMainPlanePos(this.#midPoint);\n        const center = viewController.getPlanePositionFromPlanePoint(planePos);\n        layerGroup.addScale(zoom, center);\n        layerGroup.draw();\n      }\n    }\n  };\n\n  /**\n   * Set the current position.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #setCurrentPosition(point, divId) {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to set current position');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n    const planePos = viewLayer.displayToPlanePos(point);\n    const position = viewController.getPositionFromPlanePoint(planePos);\n    viewController.setCurrentPosition(position);\n  }\n\n  /**\n   * Finish tool interaction.\n   */\n  #finish() {\n    if (this.#started) {\n      this.#started = false;\n    }\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    this.#start(mousePoint);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} event The mouse up event.\n   */\n  mouseup = (event) => {\n    // update position if no move\n    if (!this.#hasMoved) {\n      const mousePoint = getMousePoint(event);\n      const layerDetails = getLayerDetailsFromEvent(event);\n      this.#setCurrentPosition(mousePoint, layerDetails.groupDivId);\n    }\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    const touchPoints = getTouchPoints(event);\n    if (touchPoints.length === 1) {\n      this.#start(touchPoints[0]);\n    } else if (touchPoints.length === 2) {\n      this.#twoTouchStart(touchPoints);\n    }\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    if (touchPoints.length === 1) {\n      this.#update(touchPoints[0], layerDetails.groupDivId);\n    } else if (touchPoints.length === 2) {\n      this.#twoTouchUpdate(touchPoints, layerDetails.groupDivId);\n    }\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} event The touch end event.\n   */\n  touchend = (event) => {\n    // update position if no move\n    if (!this.#hasMoved) {\n      const mousePoint = getMousePoint(event);\n      const layerDetails = getLayerDetailsFromEvent(event);\n      this.#setCurrentPosition(mousePoint, layerDetails.groupDivId);\n    }\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {object} event The mouse wheel event.\n   */\n  wheel = (event) => {\n    // prevent default page scroll\n    event.preventDefault();\n\n    const step = -event.deltaY / 500;\n\n    const layerDetails = getLayerDetailsFromEvent(event);\n    const mousePoint = getMousePoint(event);\n\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to do wheel zoom/pan');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n    const planePos = viewLayer.displayToMainPlanePos(mousePoint);\n    const center = viewController.getPlanePositionFromPlanePoint(planePos);\n    layerGroup.addScale(step, center);\n    layerGroup.draw();\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'ZoomAndPan';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} _bool The flag to activate or not.\n   */\n  activate(_bool) {\n    // does nothing\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Set the tool live features: does nothing.\n   *\n   * @param {object} _features The list of features.\n   */\n  setFeatures(_features) {\n    // does nothing\n  }\n\n} // ZoomAndPan class\n","import {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {ScrollWheel} from './scrollWheel';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {Point2D} from '../math/point';\n/* eslint-enable no-unused-vars */\n\n/**\n * Opacity class.\n *\n * @example\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * options.tools = {Opacity: new dwv.ToolConfig()};\n * app.init(options);\n * // activate tool\n * app.addEventListener('load', function () {\n *   app.setTool('Opacity');\n * });\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n */\nexport class Opacity {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Start point.\n   *\n   * @type {Point2D}\n   */\n  #startPoint;\n\n  /**\n   * Scroll wheel handler.\n   *\n   * @type {ScrollWheel}\n   */\n  #scrollWhell;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n    this.#scrollWhell = new ScrollWheel(app);\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   */\n  #start(point) {\n    this.#started = true;\n    this.#startPoint = point;\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    if (!this.#started) {\n      return;\n    }\n\n    // difference to last X position\n    const diffX = point.getX() - this.#startPoint.getX();\n    const xMove = (Math.abs(diffX) > 15);\n    // do not trigger for small moves\n    if (xMove) {\n      const layerGroup = this.#app.getLayerGroupByDivId(divId);\n      const layer = layerGroup.getActiveLayer();\n      const op = layer.getOpacity();\n      layer.setOpacity(op + (diffX / 200));\n      layer.draw();\n\n      // reset origin point\n      this.#startPoint = point;\n    }\n  }\n\n  /**\n   * Finish tool interaction.\n   */\n  #finish() {\n    if (this.#started) {\n      this.#started = false;\n    }\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    this.#start(mousePoint);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} _event The mouse up event.\n   */\n  mouseup = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    const touchPoints = getTouchPoints(event);\n    this.#start(touchPoints[0]);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} _event The touch end event.\n   */\n  touchend = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {object} event The mouse wheel event.\n   */\n  wheel = (event) => {\n    this.#scrollWhell.wheel(event);\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'Opacity';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} _bool The flag to activate or not.\n   */\n  activate(_bool) {\n    // does nothing\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Set the tool live features: does nothing.\n   *\n   * @param {object} _features The list of features.\n   */\n  setFeatures(_features) {\n    // does nothing\n  }\n\n} // Opacity class\n","import {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {guid} from '../math/stats';\nimport {logger} from '../utils/logger';\nimport {\n  AddAnnotationCommand,\n  RemoveAnnotationCommand\n} from './drawCommands';\nimport {\n  isNodeNameShape,\n} from './drawBounds';\nimport {Annotation} from '../image/annotation';\nimport {ScrollWheel} from './scrollWheel';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {Style} from '../gui/style';\nimport {LayerGroup} from '../gui/layerGroup';\nimport {Point2D} from '../math/point';\nimport {DrawLayer} from '../gui/drawLayer';\nimport {ViewLayer} from '../gui/viewLayer';\nimport {DrawShapeHandler} from './drawShapeHandler';\n/* eslint-enable no-unused-vars */\n\n/**\n * Drawing tool.\n *\n * This tool is responsible for the draw of layer group structure.\n *\n * ```\n * drawLayer\n * |_ positionGroup: {name=\"position-group\", id=\"#2-0#_#3-1\"}\n *    |_ shapeGroup: {name=\"{shape name}-group\", id=\"#\"}\n *       |_ shape: {name=\"shape\"},\n *       |_ label: {name=\"label\"},\n *       |_ extra: line tick, protractor arc...\n * ```\n *\n * Discussion:\n * - posGroup > shapeGroup:\n *   (pro) slice/frame display: 1 loop -\n *   (cons) multi-slice shape splitted in positionGroups.\n * - shapeGroup > posGroup:\n *   (pros) more logical -\n *   (cons) slice/frame display: 2 loops.\n */\nexport class Draw {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Scroll wheel handler.\n   *\n   * @type {ScrollWheel}\n   */\n  #scrollWhell;\n\n  /**\n   * Drawing style.\n   *\n   * @type {Style}\n   */\n  #style;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #isDrawing = false;\n\n  /**\n   * Shape factory list.\n   *\n   * @type {object}\n   */\n  #shapeFactoryList = null;\n\n  /**\n   * Current shape factory.\n   *\n   * @type {object}\n   */\n  #currentFactory = null;\n\n  /**\n   * Current shape group.\n   *\n   * @type {object}\n   */\n  #tmpShapeGroup = null;\n\n  /**\n   * Shape name.\n   *\n   * @type {string}\n   */\n  #shapeName;\n\n  /**\n   * List of points.\n   *\n   * @type {Point2D[]}\n   */\n  #points = [];\n\n  /**\n   * Last selected point.\n   *\n   * @type {Point2D}\n   */\n  #lastPoint = null;\n\n  /**\n   * With scroll flag.\n   *\n   * @type {boolean}\n   */\n  #withScroll = true;\n\n  /**\n   * Black list: list of dataIds for which draw layer creation\n   *   is forbidden.\n   */\n  #blacklist = [];\n\n  /**\n   * Shape handler: activate listeners on existing shape.\n   *\n   * @type {DrawShapeHandler}\n   */\n  #shapeHandler;\n\n  /**\n   * Auto shape colour: will use defaults colours and\n   * vary them according to the layer.\n   *\n   * @type {boolean}\n   */\n  #autoShapeColour = false;\n\n  /**\n   * Event listeners.\n   */\n  #listeners = {};\n\n  /**\n   * Flag to know if the last added point was made by mouse move.\n   *\n   * @type {boolean}\n   */\n  #lastIsMouseMovePoint = false;\n\n  /**\n   * Callback store to allow attach/detach.\n   *\n   * @type {Array}\n   */\n  #callbackStore = [];\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n    this.#scrollWhell = new ScrollWheel(app);\n    this.#shapeHandler = new DrawShapeHandler(app, this.#fireEvent);\n\n    this.#style = app.getStyle();\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   */\n  #switchEditOrCreateShapeGroup(point, divId) {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    let drawLayer = layerGroup.getActiveDrawLayer();\n\n    if (typeof drawLayer === 'undefined') {\n      const viewLayer = layerGroup.getActiveViewLayer();\n      const refDataId = viewLayer.getDataId();\n      const refData = this.#app.getData(refDataId);\n      const refMeta = refData.image.getMeta();\n      const seriesInstanceUID = refMeta.SeriesInstanceUID;\n      // check black list\n      if (this.#blacklist.includes(seriesInstanceUID)) {\n        /**\n         * Warn event.\n         *\n         * @event Draw#warn\n         * @type {object}\n         * @property {string} type The event type.\n         * @property {string} message The warning message.\n         */\n        this.#fireEvent({\n          type: 'warn',\n          message: 'Cannot create draw layer, data is in black list'\n        });\n        return;\n      }\n      // create new data\n      const data = this.#app.createAnnotationData(refDataId);\n      // render (will create draw layer)\n      this.#app.addAndRenderAnnotationData(data, divId, refDataId);\n      // get draw layer\n      drawLayer = layerGroup.getActiveDrawLayer();\n      // set the layer shape handler\n      drawLayer.setShapeHandler(this.#shapeHandler);\n      // set active to bind to toolboxController\n      layerGroup.setActiveLayerByDataId(drawLayer.getDataId());\n    }\n\n    // data should exist / be created\n    const data = drawLayer.getDrawController().getAnnotationGroup();\n\n    const stage = drawLayer.getKonvaStage();\n\n    // update scale\n    this.#style.setZoomScale(stage.scale());\n\n    if (data.isEditable()) {\n      // determine if the click happened on an existing shape or not\n      const kshape = stage.getIntersection({\n        x: point.getX(),\n        y: point.getY()\n      });\n      if (kshape) {\n        // select shape for edition\n        this.#selectShapeGroup(drawLayer, kshape);\n      } else {\n        // create new shape\n        this.#startShapeGroupCreation(layerGroup, point);\n      }\n    }\n  }\n\n  /**\n   * Get the associated view layer.\n   *\n   * @param {LayerGroup} layerGroup The layer group to search.\n   * @returns {ViewLayer|undefined} The view layer.\n   */\n  #getViewLayer(layerGroup) {\n    const drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      logger.warn('No draw layer to do draw');\n      return;\n    }\n    return layerGroup.getViewLayerById(\n      drawLayer.getReferenceLayerId());\n  }\n\n  /**\n   * Initializes the new shape creation:\n   * - Updates the started variable,\n   * - Gets the factory,\n   * - Initializes the points array.\n   *\n   * @param {LayerGroup} layerGroup The layer group where the user clicks.\n   * @param {Point2D} point The start point where the user clicks.\n   */\n  #startShapeGroupCreation(layerGroup, point) {\n    // disable edition\n    this.#shapeHandler.disableAndResetEditor();\n    this.#setToDrawingState();\n    // store point\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to start shape');\n      return;\n    }\n    this.#lastPoint = viewLayer.displayToPlanePos(point);\n    this.#points.push(this.#lastPoint);\n  }\n\n  /**\n   * Sets the variables to drawing state:\n   * - Updates is drawing variable,\n   * - Initializes the current factory,\n   * - Resets points.\n   */\n  #setToDrawingState() {\n    // start storing points\n    this.#isDrawing = true;\n    // set factory\n    this.#currentFactory = new this.#shapeFactoryList[this.#shapeName]();\n    // clear array\n    this.#points = [];\n  }\n\n  /**\n   * Resets the variables to not drawing state:\n   * - Destroys tmp shape group,\n   * - Updates is drawing variable,\n   * - Resets points.\n   */\n  #setToNotDrawingState() {\n    this.#isDrawing = false;\n    this.#points = [];\n  }\n\n  /**\n   * Selects a shape group.\n   *\n   * @param {DrawLayer} drawLayer The draw layer where to draw.\n   * @param {Konva.Shape} kshape The shape that has been selected.\n   */\n  #selectShapeGroup(drawLayer, kshape) {\n    let group = kshape.getParent();\n    // kshape: Konva.Tag -> parent: Konva.Label -> parent: Konva.Group\n    if (kshape instanceof Konva.Tag) {\n      group = group.getParent();\n    }\n    const selectedShape = group.find('.shape')[0];\n    if (!(selectedShape instanceof Konva.Shape)) {\n      return;\n    }\n    /**\n     * Annotation select event.\n     *\n     * @event Draw#annotationselect\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} annotationid The annotation id.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'annotationselect',\n      annotationid: group.id(),\n      dataid: drawLayer.getDataId()\n    });\n    this.#shapeHandler.setEditorShape(selectedShape, drawLayer);\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #updateShapeGroupCreation(point, divId) {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to update shape');\n      return;\n    }\n    const pos = viewLayer.displayToPlanePos(point);\n\n    // draw line to current pos\n    if (Math.abs(pos.getX() - this.#lastPoint.getX()) > 0 ||\n      Math.abs(pos.getY() - this.#lastPoint.getY()) > 0) {\n      // clear last mouse move point\n      if (this.#lastIsMouseMovePoint) {\n        this.#points.pop();\n      }\n      // current point\n      this.#lastPoint = pos;\n      // mark it as temporary\n      this.#lastIsMouseMovePoint = true;\n      // add it to the list\n      this.#points.push(this.#lastPoint);\n      // update points\n      this.#onNewPoints(this.#points, layerGroup);\n    }\n  }\n\n  /**\n   * Finish tool interaction.\n   *\n   * @param {string} divId The layer group divId.\n   */\n  #finishShapeGroupCreation(divId) {\n    // exit if no points\n    if (this.#points.length === 0) {\n      logger.warn('Draw mouseup but no points...');\n      return;\n    }\n\n    // do we have all the needed points\n    if (this.#points.length === this.#currentFactory.getNPoints()) {\n      // store points\n      const layerGroup =\n        this.#app.getLayerGroupByDivId(divId);\n      this.#onFinalPoints(this.#points, layerGroup);\n      this.#setToNotDrawingState();\n    }\n\n    // reset mouse move point flag\n    this.#lastIsMouseMovePoint = false;\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    // exit if not started draw\n    if (this.#isDrawing) {\n      return;\n    }\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#switchEditOrCreateShapeGroup(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    // exit if not started draw\n    if (!this.#isDrawing) {\n      return;\n    }\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#updateShapeGroupCreation(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} event The mouse up event.\n   */\n  mouseup = (event) => {\n    // exit if not started draw\n    if (!this.#isDrawing) {\n      return;\n    }\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#finishShapeGroupCreation(layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle double click event: some tools use it to finish interaction.\n   *\n   * @param {object} event The double click event.\n   */\n  dblclick = (event) => {\n    // only end by double click undefined NPoints\n    if (this.#currentFactory &&\n      typeof this.#currentFactory.getNPoints() !== 'undefined') {\n      return;\n    }\n    // exit if not started draw\n    if (!this.#isDrawing) {\n      return;\n    }\n    // exit if no points\n    if (this.#points.length === 0) {\n      logger.warn('Draw dblclick but no points...');\n      return;\n    }\n\n    // store points\n    const layerDetails = getLayerDetailsFromEvent(event);\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    this.#onFinalPoints(this.#points, layerGroup);\n    this.#setToNotDrawingState();\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} event The mouse out event.\n   */\n  mouseout = (event) => {\n    // exit if not started draw\n    if (!this.#isDrawing) {\n      return;\n    }\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#finishShapeGroupCreation(layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    // exit if not started draw\n    if (this.#isDrawing) {\n      return;\n    }\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#switchEditOrCreateShapeGroup(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    // exit if not started draw\n    if (!this.#isDrawing) {\n      return;\n    }\n\n    const layerDetails = getLayerDetailsFromEvent(event);\n    const touchPoints = getTouchPoints(event);\n\n    const layerGroup = this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to handle touch move');\n      return;\n    }\n    const pos = viewLayer.displayToPlanePos(touchPoints[0]);\n\n    if (Math.abs(pos.getX() - this.#lastPoint.getX()) > 0 ||\n      Math.abs(pos.getY() - this.#lastPoint.getY()) > 0) {\n      // clear last added point from the list (but not the first one)\n      if (this.#points.length !== 1) {\n        this.#points.pop();\n      }\n      // current point\n      this.#lastPoint = pos;\n      // add current one to the list\n      this.#points.push(this.#lastPoint);\n      // allow for anchor points\n      if (this.#points.length < this.#currentFactory.getNPoints()) {\n        clearTimeout(this.timer);\n        this.timer = setTimeout(() => {\n          this.#points.push(this.#lastPoint);\n        }, this.#currentFactory.getTimeout());\n      }\n      // update points\n      this.#onNewPoints(this.#points, layerGroup);\n    }\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} event The touch end event.\n   */\n  touchend = (event) => {\n    this.dblclick(event);\n  };\n\n  /**\n   * Handle mouse wheel event.\n   *\n   * @param {WheelEvent} event The mouse wheel event.\n   */\n  wheel = (event) => {\n    if (this.#withScroll) {\n      this.#scrollWhell.wheel(event);\n    }\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    // call app handler if we are not in the middle of a draw\n    if (!this.#isDrawing) {\n      event.context = 'Draw';\n      this.#app.onKeydown(event);\n    }\n\n    // press delete or backspace key\n    const annotation = this.#shapeHandler.getEditorAnnotation();\n    if ((event.key === 'Delete' ||\n      event.key === 'Backspace') &&\n      typeof annotation !== 'undefined') {\n      const layerGroup = this.#app.getActiveLayerGroup();\n      const drawLayer = layerGroup.getActiveDrawLayer();\n      if (typeof drawLayer === 'undefined') {\n        logger.warn('No draw layer to handle key down');\n        return;\n      }\n      const drawController = drawLayer.getDrawController();\n\n      // create remove annotation command\n      const command = new RemoveAnnotationCommand(annotation, drawController);\n      // add command to undo stack\n      this.#app.addToUndoStack(command);\n      // execute command: triggers draw remove\n      command.execute();\n\n      // reset cursor\n      this.#shapeHandler.onMouseOutShapeGroup();\n    }\n\n    // escape key: exit shape creation\n    if (event.key === 'Escape' && this.#tmpShapeGroup !== null) {\n      const konvaLayer = this.#tmpShapeGroup.getLayer();\n      // reset temporary shape group\n      this.#tmpShapeGroup.destroy();\n      this.#tmpShapeGroup = null;\n      // set state\n      this.#setToNotDrawingState();\n      // redraw\n      konvaLayer.draw();\n    }\n  };\n\n  /**\n   * Update the current draw with new points.\n   *\n   * @param {Point2D[]} tmpPoints The array of new points.\n   * @param {LayerGroup} layerGroup The origin layer group.\n   */\n  #onNewPoints(tmpPoints, layerGroup) {\n    // remove temporary shape draw\n    if (this.#tmpShapeGroup) {\n      this.#tmpShapeGroup.destroy();\n      this.#tmpShapeGroup = null;\n    }\n\n    const drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      logger.warn('No draw layer to handle new points');\n      return;\n    }\n    const drawController = drawLayer.getDrawController();\n    const konvaLayer = drawLayer.getKonvaLayer();\n    const viewLayer = layerGroup.getViewLayerById(\n      drawLayer.getReferenceLayerId());\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to handle new points');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n\n    // auto mode: vary shape colour with layer id\n    if (this.#autoShapeColour) {\n      const colours = [\n        '#ffff80', '#ff80ff', '#80ffff', '#80ff80', '8080ff', 'ff8080'\n      ];\n      // warning: depends on layer id nomenclature\n      const drawLayerId = drawLayer.getId();\n      const layerId = drawLayerId.substring(drawLayerId.length - 1);\n      const layerIndex = parseInt(layerId, 10) - 1;\n      const colour = colours[layerIndex];\n      if (typeof colour !== 'undefined') {\n        this.#style.setLineColour(colour);\n      }\n    }\n\n    // create tmp annotation\n    const annotation = new Annotation();\n    // use group colour if defined\n    const groupColour = drawController.getAnnotationGroup().getColour();\n    if (typeof groupColour !== 'undefined') {\n      annotation.colour = groupColour;\n    } else {\n      annotation.colour = this.#style.getLineColour();\n    }\n    annotation.init(viewController);\n    // set annotation shape\n    this.#currentFactory.setAnnotationMathShape(annotation, tmpPoints);\n    // create shape group\n    this.#tmpShapeGroup =\n      this.#currentFactory.createShapeGroup(annotation, this.#style);\n    // set the label visibility\n    drawLayer.setLabelVisibility(this.#tmpShapeGroup);\n\n    // do not listen during creation\n    const shape = this.#tmpShapeGroup.getChildren(isNodeNameShape)[0];\n    shape.listening(false);\n    konvaLayer.listening(false);\n    // draw shape\n    konvaLayer.add(this.#tmpShapeGroup);\n    konvaLayer.draw();\n  }\n\n  /**\n   * Create the final shape from a point list.\n   *\n   * @param {Point2D[]} finalPoints The array of points.\n   * @param {LayerGroup} layerGroup The origin layer group.\n   */\n  #onFinalPoints(finalPoints, layerGroup) {\n    // remove temporary shape draw\n    // (has to be done before sending add event)\n    if (this.#tmpShapeGroup) {\n      this.#tmpShapeGroup.destroy();\n      this.#tmpShapeGroup = null;\n    }\n\n    const drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      logger.warn('No draw layer to handle final points');\n      return;\n    }\n    const konvaLayer = drawLayer.getKonvaLayer();\n    const drawController = drawLayer.getDrawController();\n    const viewLayer = layerGroup.getViewLayerById(\n      drawLayer.getReferenceLayerId());\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to handle final points');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n\n    // create final annotation\n    const annotation = new Annotation();\n    // use group colour if defined\n    const groupColour = drawController.getAnnotationGroup().getColour();\n    if (typeof groupColour !== 'undefined') {\n      annotation.colour = groupColour;\n    } else {\n      annotation.colour = this.#style.getLineColour();\n    }\n    annotation.id = guid();\n    annotation.init(viewController);\n    // set annotation shape\n    this.#currentFactory.setAnnotationMathShape(annotation, finalPoints);\n\n    // create add annotation command\n    const command = new AddAnnotationCommand(annotation, drawController);\n    // add command to undo stack\n    this.#app.addToUndoStack(command);\n    // execute command: triggers draw creation\n    command.execute();\n\n    // re-activate layer\n    konvaLayer.listening(true);\n  }\n\n  /**\n   * Get a DrawLayer position callback.\n   *\n   * TODO: check need for store item removal.\n   *\n   * @param {DrawLayer} layer The layer to update.\n   * @returns {Function} The callback.\n   */\n  #getPositionCallback(layer) {\n    const layerId = layer.getId();\n    if (typeof this.#callbackStore[layerId] === 'undefined') {\n      this.#callbackStore[layerId] = () => {\n        layer.activateCurrentPositionShapes(true);\n      };\n    }\n    return this.#callbackStore[layerId];\n  }\n\n  /**\n   * Activate a draw layer.\n   *\n   * @param {DrawLayer} drawLayer The layer to update.\n   * @param {boolean} flag The flag to activate or not.\n   */\n  #activateLayer(drawLayer, flag) {\n    drawLayer.setShapeHandler(this.#shapeHandler);\n    drawLayer.activateCurrentPositionShapes(flag);\n    // update on position change\n    if (flag) {\n      this.#app.addEventListener('positionchange',\n        this.#getPositionCallback(drawLayer)\n      );\n    } else {\n      this.#app.removeEventListener('positionchange',\n        this.#getPositionCallback(drawLayer)\n      );\n    }\n  }\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} flag The flag to activate or not.\n   */\n  activate(flag) {\n    // force cursor if deactivate\n    if (!flag) {\n      this.#shapeHandler.onMouseOutShapeGroup();\n    }\n    // update draw layers\n    const drawLayers = this.#app.getDrawLayers();\n    for (const drawLayer of drawLayers) {\n      if (typeof drawLayer !== 'undefined') {\n        this.#activateLayer(drawLayer, flag);\n      }\n    }\n    // activate newly added layers\n    this.#app.addEventListener('drawlayeradd', (event) => {\n      const drawLayers = this.#app.getDrawLayers(function (item) {\n        return item.getId() === event.layerid;\n      });\n      // should be just one\n      if (drawLayers.length === 1) {\n        this.#activateLayer(drawLayers[0], flag);\n      }\n    });\n\n  }\n\n  /**\n   * Set the tool configuration options.\n   *\n   * @param {object} options The list of shape names amd classes.\n   */\n  setOptions(options) {\n    // save the options as the shape factory list\n    this.#shapeFactoryList = options;\n  }\n\n  /**\n   * Get the type of tool options: here 'factory' since the shape\n   * list contains factories to create each possible shape.\n   *\n   * @returns {string} The type.\n   */\n  getOptionsType() {\n    return 'factory';\n  }\n\n  /**\n   * Set the tool live features: shape colour and shape name.\n   *\n   * @param {object} features The list of features.\n   */\n  setFeatures(features) {\n    if (typeof features.autoShapeColour !== 'undefined') {\n      this.#autoShapeColour = features.autoShapeColour;\n    }\n    if (typeof features.shapeColour !== 'undefined') {\n      this.#style.setLineColour(features.shapeColour);\n      this.#autoShapeColour = false;\n    }\n    if (typeof features.shapeName !== 'undefined') {\n      // check if we have it\n      if (!this.hasShape(features.shapeName)) {\n        throw new Error('Unknown shape: \\'' + features.shapeName + '\\'');\n      }\n      this.#shapeName = features.shapeName;\n    }\n    if (typeof features.mouseOverCursor !== 'undefined') {\n      this.#shapeHandler.storeMouseOverCursor(features.mouseOverCursor);\n    }\n    if (typeof features.withScroll !== 'undefined') {\n      this.#withScroll = features.withScroll;\n    }\n    if (typeof features.blacklist !== 'undefined') {\n      this.#blacklist = features.blacklist;\n    }\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Get the list of event names that this tool can fire.\n   *\n   * @returns {string[]} The list of event names.\n   */\n  getEventNames() {\n    return [\n      'annotationupdate', 'annotationselect', 'warn'\n    ];\n  }\n\n  /**\n   * Add an event listener on the app.\n   *\n   * @param {string} type The event type.\n   * @param {Function} listener The function associated with the provided\n   *   event type.\n   */\n  addEventListener(type, listener) {\n    if (typeof this.#listeners[type] === 'undefined') {\n      this.#listeners[type] = [];\n    }\n    this.#listeners[type].push(listener);\n  }\n\n  /**\n   * Remove an event listener from the app.\n   *\n   * @param {string} type The event type.\n   * @param {Function} listener The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, listener) {\n    if (typeof this.#listeners[type] === 'undefined') {\n      return;\n    }\n    for (let i = 0; i < this.#listeners[type].length; ++i) {\n      if (this.#listeners[type][i] === listener) {\n        this.#listeners[type].splice(i, 1);\n      }\n    }\n  }\n\n  // Private Methods -----------------------------------------------------------\n\n  /**\n   * Fire an event: call all associated listeners.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    if (typeof this.#listeners[event.type] === 'undefined') {\n      return;\n    }\n    for (let i = 0; i < this.#listeners[event.type].length; ++i) {\n      this.#listeners[event.type][i](event);\n    }\n  };\n\n  /**\n   * Check if the shape is in the shape list.\n   *\n   * @param {string} name The name of the shape.\n   * @returns {boolean} True if there is a factory for the shape.\n   */\n  hasShape(name) {\n    return typeof this.#shapeFactoryList[name] !== 'undefined';\n  }\n\n} // Draw class\n","import {Annotation} from '../image/annotation';\nimport {\n  AddAnnotationCommand,\n  UpdateAnnotationCommand\n} from '../tools/drawCommands';\n//import {RoiFactory} from '../tools/roi';\nimport {ROI} from '../math/roi';\nimport {guid} from '../math/stats';\nimport {Point2D} from '../math/point';\nimport {Style} from '../gui/style';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {ListenerHandler} from '../utils/listen';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\nimport {LayerGroup} from '../gui/layerGroup';\nimport {ViewLayer} from '../gui/viewLayer';\nimport {Scalar2D} from '../math/scalar';\n/* eslint-enable no-unused-vars */\n\n/**\n * The magic wand namespace.\n *\n * Ref: {@link https://github.com/Tamersoul/magic-wand-js}.\n *\n * @external MagicWand\n */\nimport MagicWand from 'magic-wand-tool';\n\n/**\n * Floodfill painting tool.\n */\nexport class Floodfill {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Original variables from external library. Used as in the lib example.\n   *\n   * @type {number}\n   */\n  #blurRadius = 5;\n  /**\n   * Original variables from external library. Used as in the lib example.\n   *\n   * @type {number}\n   */\n  #simplifyTolerant = 0;\n\n  /**\n   * Original variables from external library. Used as in the lib example.\n   *\n   * @type {number}\n   */\n  #simplifyCount = 2000;\n\n  /**\n   * Canvas info.\n   *\n   * @type {object}\n   */\n  #imageInfo = null;\n\n  /**\n   * Object created by MagicWand lib containing border points.\n   *\n   * @type {object}\n   */\n  #mask = null;\n\n  /**\n   * Threshold default tolerance of the tool border.\n   *\n   * @type {number}\n   */\n  #initialthreshold = 10;\n\n  /**\n   * Threshold tolerance of the tool border.\n   *\n   * @type {number}\n   */\n  #currentthreshold = null;\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Current annotation.\n   *\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * Coordinates of the fist mousedown event.\n   *\n   * @type {object}\n   */\n  #initialpoint;\n\n  /**\n   * Floodfill border.\n   *\n   * @type {object}\n   */\n  #border = null;\n\n  /**\n   * List of parent points.\n   *\n   * @type {Point2D[]}\n   */\n  #parentPoints = [];\n\n  /**\n   * Assistant variable to paint border on all slices.\n   *\n   * @type {boolean}\n   */\n  #extender = false;\n\n  /**\n   * Drawing style.\n   *\n   * @type {Style}\n   */\n  #style = new Style();\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Set extend option for painting border on all slices.\n   *\n   * @param {boolean} bool The option to set.\n   */\n  setExtend(bool) {\n    this.#extender = bool;\n  }\n\n  /**\n   * Get extend option for painting border on all slices.\n   *\n   * @returns {boolean} The actual value of of the variable to use Floodfill\n   *   on museup.\n   */\n  getExtend() {\n    return this.#extender;\n  }\n\n  /**\n   * Get the associated view layer.\n   *\n   * @param {LayerGroup} layerGroup The layer group to search.\n   * @returns {ViewLayer|undefined} The view layer.\n   */\n  #getViewLayer(layerGroup) {\n    const drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      logger.warn('No draw layer to do floodfill');\n      return;\n    }\n    return layerGroup.getViewLayerById(\n      drawLayer.getReferenceLayerId());\n  }\n\n  /**\n   * Get (x, y) coordinates referenced to the canvas.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   * @returns {Scalar2D|undefined} The coordinates as a {x,y}.\n   */\n  #getIndex = (point, divId) => {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to get index');\n      return;\n    }\n    const index = viewLayer.displayToPlaneIndex(point);\n    return {\n      x: index.get(0),\n      y: index.get(1)\n    };\n  };\n\n  /**\n   * Calculate border.\n   *\n   * @param {object} points The input points.\n   * @param {number} threshold The threshold of the floodfill.\n   * @param {boolean} simple Return first points or a list.\n   * @returns {Point2D[]} The parent points.\n   */\n  #calcBorder(points, threshold, simple) {\n\n    this.#parentPoints = [];\n    const image = {\n      data: this.#imageInfo.data,\n      width: this.#imageInfo.width,\n      height: this.#imageInfo.height,\n      bytes: 4\n    };\n\n    this.#mask = MagicWand.floodFill(image, points.x, points.y, threshold);\n    this.#mask = MagicWand.gaussBlurOnlyBorder(this.#mask, this.#blurRadius);\n\n    let cs = MagicWand.traceContours(this.#mask);\n    cs = MagicWand.simplifyContours(\n      cs, this.#simplifyTolerant, this.#simplifyCount);\n\n    if (cs.length > 0 && cs[0].points[0].x) {\n      if (simple) {\n        return cs[0].points;\n      }\n      for (let j = 0, icsl = cs[0].points.length; j < icsl; j++) {\n        this.#parentPoints.push(new Point2D(\n          cs[0].points[j].x,\n          cs[0].points[j].y\n        ));\n      }\n      return this.#parentPoints;\n    } else {\n      return [];\n    }\n  }\n\n  /**\n   * Paint Floodfill.\n   *\n   * @param {object} point The start point.\n   * @param {number} threshold The border threshold.\n   * @param {LayerGroup} layerGroup The origin layer group.\n   * @returns {boolean} False if no border.\n   */\n  #paintBorder(point, threshold, layerGroup) {\n    // Calculate the border\n    this.#border = this.#calcBorder(point, threshold, false);\n    // Paint the border\n    if (this.#border.length !== 0) {\n      const drawLayer = layerGroup.getActiveDrawLayer();\n      if (typeof drawLayer === 'undefined') {\n        logger.warn('No draw layer to paint border');\n        return false;\n      }\n      const drawController = drawLayer.getDrawController();\n\n      const newMathShape = new ROI(this.#border);\n\n      let command;\n      if (typeof this.#annotation === 'undefined') {\n        // create annotation\n        this.#annotation = new Annotation();\n        this.#annotation.colour = this.#style.getLineColour();\n        this.#annotation.id = guid();\n\n        const viewLayer =\n          layerGroup.getViewLayerById(drawLayer.getReferenceLayerId());\n        if (typeof viewLayer === 'undefined') {\n          logger.warn('No view layer to paint border');\n          return false;\n        }\n        const viewController = viewLayer.getViewController();\n        this.#annotation.init(viewController);\n\n        this.#annotation.mathShape = newMathShape;\n        command = new AddAnnotationCommand(\n          this.#annotation,\n          drawController\n        );\n      } else {\n        // update annotation\n        const originalMathShape = this.#annotation.mathShape;\n        command = new UpdateAnnotationCommand(\n          this.#annotation,\n          {mathShape: originalMathShape},\n          {mathShape: newMathShape},\n          drawController\n        );\n      }\n\n      // add command to undo stack\n      this.#app.addToUndoStack(command);\n      // execute command: triggers draw creation\n      command.execute();\n    }\n\n    return this.#border.length !== 0;\n  }\n\n  /**\n   * Create Floodfill in all the prev and next slices while border is found.\n   *\n   * @param {number} ini The first slice to extend to.\n   * @param {number} end The last slice to extend to.\n   * @param {object} layerGroup The origin layer group.\n   */\n  extend(ini, end, layerGroup) {\n    //avoid errors\n    if (!this.#initialpoint) {\n      throw '\\'initialpoint\\' not found. User must click before use extend!';\n    }\n\n    const positionHelper = layerGroup.getPositionHelper();\n    const viewLayer = this.#getViewLayer(layerGroup);\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to extend floodfill');\n      return;\n    }\n    const viewController = viewLayer.getViewController();\n\n    const pos = viewController.getCurrentIndex();\n    const imageSize = viewController.getImageSize();\n    const threshold = this.#currentthreshold || this.#initialthreshold;\n\n    // Iterate over the next images and paint border on each slice.\n    for (let i = pos.get(2),\n      len = end\n        ? end : imageSize.get(2);\n      i < len; i++) {\n      if (!this.#paintBorder(this.#initialpoint, threshold, layerGroup)) {\n        break;\n      }\n      positionHelper.incrementPositionAlongScroll();\n    }\n    viewController.setCurrentIndex(pos);\n\n    // Iterate over the prev images and paint border on each slice.\n    for (let j = pos.get(2), jl = ini ? ini : 0; j > jl; j--) {\n      if (!this.#paintBorder(this.#initialpoint, threshold, layerGroup)) {\n        break;\n      }\n      positionHelper.decrementPositionAlongScroll();\n    }\n    viewController.setCurrentIndex(pos);\n  }\n\n  /**\n   * Event fired when threshold change.\n   *\n   * @param {number} _value Current threshold.\n   */\n  onThresholdChange(_value) {\n    // Defaults do nothing\n  }\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   */\n  #start(point, divId) {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    let viewLayer;\n    let drawLayer = layerGroup.getActiveDrawLayer();\n\n    if (typeof drawLayer === 'undefined') {\n      viewLayer = layerGroup.getActiveViewLayer();\n      const refDataId = viewLayer.getDataId();\n      // create new data\n      const data = this.#app.createAnnotationData(refDataId);\n      // render (will create draw layer)\n      this.#app.addAndRenderAnnotationData(data, divId, refDataId);\n      // get draw layer\n      drawLayer = layerGroup.getActiveDrawLayer();\n      // set active to bind to toolboxController\n      layerGroup.setActiveLayerByDataId(drawLayer.getDataId());\n    } else {\n      viewLayer = layerGroup.getViewLayerById(\n        drawLayer.getReferenceLayerId());\n      if (typeof viewLayer === 'undefined') {\n        logger.warn('No view layer to start floodfill');\n        return;\n      }\n    }\n\n    this.#imageInfo = viewLayer.getImageData();\n    if (!this.#imageInfo) {\n      logger.error('No image found');\n      return;\n    }\n\n    // update zoom scale\n    this.#style.setZoomScale(\n      drawLayer.getKonvaLayer().getAbsoluteScale());\n\n    this.#started = true;\n    this.#initialpoint = this.#getIndex(point, divId);\n    this.#paintBorder(this.#initialpoint, this.#initialthreshold, layerGroup);\n    this.onThresholdChange(this.#initialthreshold);\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    if (!this.#started) {\n      return;\n    }\n\n    const movedpoint = this.#getIndex(point, divId);\n    this.#currentthreshold = Math.round(Math.sqrt(\n      Math.pow((this.#initialpoint.x - movedpoint.x), 2) +\n      Math.pow((this.#initialpoint.y - movedpoint.y), 2)) / 2);\n    this.#currentthreshold = this.#currentthreshold < this.#initialthreshold\n      ? this.#initialthreshold\n      : this.#currentthreshold - this.#initialthreshold;\n\n    this.#paintBorder(\n      this.#initialpoint,\n      this.#currentthreshold,\n      this.#app.getLayerGroupByDivId(divId)\n    );\n\n    this.onThresholdChange(this.#currentthreshold);\n  }\n\n  /**\n   * Finish tool interaction.\n   */\n  #finish() {\n    if (this.#started) {\n      this.#started = false;\n    }\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} _event The mouse up event.\n   */\n  mouseup = (_event) => {\n    this.#finish();\n    // TODO: re-activate\n    // if (this.#extender) {\n    //   const layerDetails = getLayerDetailsFromEvent(event);\n    //   const layerGroup =\n    //     this.#app.getLayerGroupByDivId(layerDetails.groupDivId);\n    //   this.extend(layerGroup);\n    // }\n  };\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} _event The touch end event.\n   */\n  touchend = (_event) => {\n    this.#finish();\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'Floodfill';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} bool The flag to activate or not.\n   */\n  activate(bool) {\n    if (bool) {\n      // init with the app window scale\n      this.#style.setBaseScale(this.#app.getBaseScale());\n      // set the default to the first in the list\n      this.setFeatures({shapeColour: this.#style.getLineColour()});\n    }\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Get the list of event names that this tool can fire.\n   *\n   * @returns {Array} The list of event names.\n   */\n  getEventNames() {\n    return ['drawcreate', 'drawchange', 'drawmove', 'drawdelete'];\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  // #fireEvent = (event) => {\n  //   this.#listenerHandler.fireEvent(event);\n  // };\n\n  /**\n   * Set the tool live features: shape colour.\n   *\n   * @param {object} features The list of features.\n   */\n  setFeatures(features) {\n    if (typeof features.shapeColour !== 'undefined') {\n      this.#style.setLineColour(features.shapeColour);\n    }\n  }\n\n} // Floodfill class\n","import {Style} from '../gui/style';\nimport {\n  getMousePoint,\n  getTouchPoints\n} from '../gui/generic';\nimport {Point2D} from '../math/point';\nimport {Path} from '../math/path';\nimport {Scissors} from '../math/scissors';\nimport {guid} from '../math/stats';\nimport {getLayerDetailsFromEvent} from '../gui/layerGroup';\nimport {ListenerHandler} from '../utils/listen';\nimport {logger} from '../utils/logger';\nimport {ROI} from '../math/roi';\nimport {Annotation} from '../image/annotation';\nimport {\n  AddAnnotationCommand,\n  UpdateAnnotationCommand\n} from '../tools/drawCommands';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\n/* eslint-enable no-unused-vars */\n\n/**\n * Livewire painting tool.\n */\nexport class Livewire {\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * @param {App} app The associated application.\n   */\n  constructor(app) {\n    this.#app = app;\n  }\n\n  /**\n   * Interaction start flag.\n   *\n   * @type {boolean}\n   */\n  #started = false;\n\n  /**\n   * Start point.\n   *\n   * @type {Point2D}\n   */\n  #startPoint;\n\n  /**\n   * Current annotation.\n   *\n   * @type {Annotation}\n   */\n  #annotation;\n\n  /**\n   * Drawing style.\n   *\n   * @type {Style}\n   */\n  #style = new Style();\n\n  /**\n   * Path storage. Paths are stored in reverse order.\n   *\n   * @type {Path}\n   */\n  #path = new Path();\n\n  /**\n   * Current path storage. Paths are stored in reverse order.\n   *\n   * @type {Path}\n   */\n  #currentPath = new Path();\n\n  /**\n   * List of parent points.\n   *\n   * @type {Array}\n   */\n  #parentPoints = [];\n\n  /**\n   * Tolerance.\n   *\n   * @type {number}\n   */\n  #tolerance = 5;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Clear the parent points list.\n   *\n   * @param {object} imageSize The image size.\n   */\n  #clearParentPoints(imageSize) {\n    const nrows = imageSize.get(1);\n    for (let i = 0; i < nrows; ++i) {\n      this.#parentPoints[i] = [];\n    }\n  }\n\n  /**\n   * Clear the stored paths.\n   */\n  #clearPaths() {\n    this.#path = new Path();\n    this.#currentPath = new Path();\n  }\n\n  /**\n   * Scissor representation.\n   *\n   * @type {Scissors}\n   */\n  #scissors = new Scissors();\n\n  /**\n   * Start tool interaction.\n   *\n   * @param {Point2D} point The start point.\n   * @param {string} divId The layer group divId.\n   */\n  #start(point, divId) {\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n\n    let viewLayer;\n    let drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      viewLayer = layerGroup.getActiveViewLayer();\n    } else {\n      viewLayer =\n        layerGroup.getViewLayerById(drawLayer.getReferenceLayerId());\n    }\n\n    const imageSize = viewLayer.getViewController().getImageSize();\n\n    this.#scissors.setDimensions(\n      imageSize.get(0),\n      imageSize.get(1));\n    this.#scissors.setData(viewLayer.getImageData().data);\n\n    const index = viewLayer.displayToPlaneIndex(point);\n\n    // first time\n    if (!this.#started) {\n      this.#started = true;\n      this.#startPoint = new Point2D(index.get(0), index.get(1));\n      // clear vars\n      this.#clearPaths();\n      this.#clearParentPoints(imageSize);\n      // get draw layer\n      if (typeof drawLayer === 'undefined') {\n        const refDataId = viewLayer.getDataId();\n        // create new data\n        const data = this.#app.createAnnotationData(refDataId);\n        // render (will create draw layer)\n        this.#app.addAndRenderAnnotationData(data, divId, refDataId);\n        // get draw layer\n        drawLayer = layerGroup.getActiveDrawLayer();\n        // set active to bind to toolboxController\n        layerGroup.setActiveLayerByDataId(drawLayer.getDataId());\n      }\n      // update zoom scale\n      this.#style.setZoomScale(\n        drawLayer.getKonvaLayer().getAbsoluteScale());\n      // do the training from the first point\n      const p = {x: index.get(0), y: index.get(1)};\n      this.#scissors.doTraining(p);\n      // add the initial point to the path\n      const p0 = new Point2D(index.get(0), index.get(1));\n      this.#path.addPoint(p0);\n      this.#path.addControlPoint(p0);\n    } else {\n      const diffX = Math.abs(index.get(0) - this.#startPoint.getX());\n      const diffY = Math.abs(index.get(1) - this.#startPoint.getY());\n      // final point: at 'tolerance' of the initial point\n      if (diffX < this.#tolerance &&\n        diffY < this.#tolerance) {\n        // finish\n        this.#finishShape();\n      } else {\n        // anchor point\n        this.#path = this.#currentPath;\n        this.#clearParentPoints(imageSize);\n        const pn = {x: index.get(0), y: index.get(1)};\n        this.#scissors.doTraining(pn);\n        this.#path.addControlPoint(this.#currentPath.getPoint(0));\n      }\n    }\n  }\n\n  /**\n   * Update tool interaction.\n   *\n   * @param {Point2D} point The update point.\n   * @param {string} divId The layer group divId.\n   */\n  #update(point, divId) {\n    if (!this.#started) {\n      return;\n    }\n    const layerGroup = this.#app.getLayerGroupByDivId(divId);\n    const drawLayer = layerGroup.getActiveDrawLayer();\n    if (typeof drawLayer === 'undefined') {\n      logger.warn('No draw layer to update livewire');\n      return;\n    }\n    const viewLayer = layerGroup.getViewLayerById(\n      drawLayer.getReferenceLayerId());\n    if (typeof viewLayer === 'undefined') {\n      logger.warn('No view layer to update livewire');\n      return;\n    }\n    const index = viewLayer.displayToPlaneIndex(point);\n\n    // set the point to find the path to\n    let p = {x: index.get(0), y: index.get(1)};\n    this.#scissors.setPoint(p);\n    // do the work\n    let results = [];\n    let stop = false;\n    while (!this.#parentPoints[p.y][p.x] && !stop) {\n      results = this.#scissors.doWork();\n\n      if (results.length === 0) {\n        stop = true;\n      } else {\n        // fill parents\n        for (let i = 0; i < results.length - 1; i += 2) {\n          const _p = results[i];\n          const _q = results[i + 1];\n          this.#parentPoints[_p.y][_p.x] = _q;\n        }\n      }\n    }\n\n    // get the path\n    this.#currentPath = new Path();\n    stop = false;\n    while (p && !stop) {\n      this.#currentPath.addPoint(new Point2D(p.x, p.y));\n      if (!this.#parentPoints[p.y]) {\n        stop = true;\n      } else {\n        if (!this.#parentPoints[p.y][p.x]) {\n          stop = true;\n        } else {\n          p = this.#parentPoints[p.y][p.x];\n        }\n      }\n    }\n    this.#currentPath.appenPath(this.#path);\n\n    const drawController = drawLayer.getDrawController();\n\n    const newMathShape = new ROI(this.#currentPath.pointArray);\n\n    let command;\n    if (typeof this.#annotation === 'undefined') {\n      // create annotation\n      this.#annotation = new Annotation();\n      this.#annotation.colour = this.#style.getLineColour();\n      this.#annotation.id = guid();\n\n      const viewController = viewLayer.getViewController();\n      this.#annotation.init(viewController);\n\n      this.#annotation.mathShape = newMathShape;\n      command = new AddAnnotationCommand(\n        this.#annotation,\n        drawController\n      );\n    } else {\n      // update annotation\n      const originalMathShape = this.#annotation.mathShape;\n      command = new UpdateAnnotationCommand(\n        this.#annotation,\n        {mathShape: originalMathShape},\n        {mathShape: newMathShape},\n        drawController\n      );\n    }\n\n    // add command to undo stack\n    this.#app.addToUndoStack(command);\n    // execute command: triggers draw creation\n    command.execute();\n  }\n\n  /**\n   * Finish a livewire (roi) shape.\n   */\n  #finishShape() {\n    // set flag\n    this.#started = false;\n  }\n\n  /**\n   * Handle mouse down event.\n   *\n   * @param {object} event The mouse down event.\n   */\n  mousedown = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse move event.\n   *\n   * @param {object} event The mouse move event.\n   */\n  mousemove = (event) => {\n    const mousePoint = getMousePoint(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(mousePoint, layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle mouse up event.\n   *\n   * @param {object} _event The mouse up event.\n   */\n  mouseup(_event) {\n    // nothing to do\n  }\n\n  /**\n   * Handle mouse out event.\n   *\n   * @param {object} _event The mouse out event.\n   */\n  mouseout = (_event) => {\n    // nothing to do\n  };\n\n  /**\n   * Handle double click event.\n   *\n   * @param {object} _event The double click event.\n   */\n  dblclick = (_event) => {\n    this.#finishShape();\n  };\n\n  /**\n   * Handle touch start event.\n   *\n   * @param {object} event The touch start event.\n   */\n  touchstart = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#start(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch move event.\n   *\n   * @param {object} event The touch move event.\n   */\n  touchmove = (event) => {\n    const touchPoints = getTouchPoints(event);\n    const layerDetails = getLayerDetailsFromEvent(event);\n    this.#update(touchPoints[0], layerDetails.groupDivId);\n  };\n\n  /**\n   * Handle touch end event.\n   *\n   * @param {object} _event The touch end event.\n   */\n  touchend = (_event) => {\n    // nothing to do\n  };\n\n  /**\n   * Handle key down event.\n   *\n   * @param {object} event The key down event.\n   */\n  keydown = (event) => {\n    event.context = 'Livewire';\n    this.#app.onKeydown(event);\n  };\n\n  /**\n   * Activate the tool.\n   *\n   * @param {boolean} bool The flag to activate or not.\n   */\n  activate(bool) {\n    // start scissors if displayed\n    if (bool) {\n      // init with the app window scale\n      this.#style.setBaseScale(this.#app.getBaseScale());\n      // set the default to the first in the list\n      this.setFeatures({shapeColour: this.#style.getLineColour()});\n    }\n  }\n\n  /**\n   * Initialise the tool.\n   */\n  init() {\n    // does nothing\n  }\n\n  /**\n   * Get the list of event names that this tool can fire.\n   *\n   * @returns {Array} The list of event names.\n   */\n  getEventNames() {\n    return ['drawcreate', 'drawchange', 'drawmove', 'drawdelete'];\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *    event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  // #fireEvent = (event) => {\n  //   this.#listenerHandler.fireEvent(event);\n  // };\n\n  /**\n   * Set the tool live features: shape colour.\n   *\n   * @param {object} features The list of features.\n   */\n  setFeatures(features) {\n    if (typeof features.shapeColour !== 'undefined') {\n      this.#style.setLineColour(features.shapeColour);\n    }\n  }\n\n} // Livewire class\n","import {\n  Line,\n  getPerpendicularLine,\n  getPerpendicularLineAtDistance\n} from '../math/line';\nimport {Point2D} from '../math/point';\nimport {custom} from '../app/custom';\nimport {logger} from '../utils/logger';\nimport {\n  defaultLabelTexts,\n  getLineShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Arrow factory.\n */\nexport class ArrowFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'arrow';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Point2D;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 2;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 0;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.referencePoints = [points[1]];\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a line shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(shape);\n    // extras\n    const extras = this.#createShapeExtras(annotation, style);\n    for (const extra of extras) {\n      group.add(extra);\n    }\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(label);\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    const centerX = (points[0] + points[2]) / 2 + sx;\n    const centerY = (points[1] + points[3]) / 2 + sy;\n    return [new Point2D(centerX, centerY)];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    return [\n      new Point2D(points[0] + sx, points[1] + sy),\n      new Point2D(points[2] + sx, points[3] + sy)\n    ];\n  }\n\n  /**\n   * Get anchors to update a line shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} _anchor The active anchor.\n   */\n  constrainAnchorMove(_anchor) {\n    // no constraints\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n    // find anchors\n    const begin = getAnchorShape(group, 0);\n    const end = getAnchorShape(group, 1);\n\n    // math shape\n    // compensate for possible shape drag\n    const pointBegin = new Point2D(\n      begin.x() - kline.x(),\n      begin.y() - kline.y()\n    );\n    const pointEnd = new Point2D(\n      end.x() - kline.x(),\n      end.y() - kline.y()\n    );\n    annotation.mathShape = pointBegin;\n    annotation.referencePoints = [pointEnd];\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const point = annotation.mathShape;\n    const endPoint = annotation.referencePoints[0];\n    const line = new Line(point, endPoint);\n\n    const begin = line.getBegin();\n    const newBegin = new Point2D(\n      begin.getX() + translation.x,\n      begin.getY() + translation.y\n    );\n    const end = line.getEnd();\n    const newEnd = new Point2D(\n      end.getX() + translation.x,\n      end.getY() + translation.y\n    );\n    annotation.mathShape = newBegin;\n    annotation.referencePoints = [newEnd];\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Point2D} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    return points[0];\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Line} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const point = annotation.mathShape;\n    const endPoint = annotation.referencePoints[0];\n    const line = new Line(point, endPoint);\n\n    // konva line\n    const kshape = new Konva.Line({\n      points: [\n        point.getX(),\n        point.getY(),\n        endPoint.getX(),\n        endPoint.getY()\n      ],\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n\n    // larger hitfunc\n    const tickLen = 20;\n    const linePerp0 = getPerpendicularLine(\n      line, point, tickLen, style.getZoomScale());\n    const linePerp1 = getPerpendicularLine(\n      line, endPoint, tickLen, style.getZoomScale());\n    kshape.hitFunc(function (context) {\n      context.beginPath();\n      context.moveTo(linePerp0.getBegin().getX(), linePerp0.getBegin().getY());\n      context.lineTo(linePerp0.getEnd().getX(), linePerp0.getEnd().getY());\n      context.lineTo(linePerp1.getEnd().getX(), linePerp1.getEnd().getY());\n      context.lineTo(linePerp1.getBegin().getX(), linePerp1.getBegin().getY());\n      context.closePath();\n      context.fillStrokeShape(kshape);\n    });\n\n    return kshape;\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Line|undefined} The shape.\n   */\n  #getShape(group) {\n    return getLineShape(group);\n  }\n\n  /**\n   * Creates the konva shape extras.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Array} The konva shape extras.\n   */\n  #createShapeExtras(annotation, style) {\n    const point = annotation.mathShape;\n    const endPoint = annotation.referencePoints[0];\n    const line = new Line(point, endPoint);\n\n    const tickLen = 20;\n    // perpendicular line at 2*tickLen\n    const perpLine = getPerpendicularLineAtDistance(\n      line, 2 * tickLen, tickLen, style.getZoomScale());\n\n    // triangle\n    const ktriangle = new Konva.Line({\n      points: [\n        line.getBegin().getX(),\n        line.getBegin().getY(),\n        perpLine.getBegin().getX(),\n        perpLine.getBegin().getY(),\n        perpLine.getEnd().getX(),\n        perpLine.getEnd().getY(),\n      ],\n      fill: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      closed: true,\n      name: 'shape-triangle'\n    });\n\n    return [ktriangle];\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const point = annotation.mathShape;\n    return point;\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  #updateShape(annotation, anchor, style) {\n    const point = annotation.mathShape;\n    const endPoint = annotation.referencePoints[0];\n    const line = new Line(point, endPoint);\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n\n    // reset position after possible shape drag\n    kline.position({x: 0, y: 0});\n    // update shape\n    kline.points([\n      point.getX(),\n      point.getY(),\n      endPoint.getX(),\n      endPoint.getY(),\n    ]);\n\n    // associated triangle shape\n    const ktriangle = group.getChildren(function (node) {\n      return node.name() === 'shape-triangle';\n    })[0];\n    if (!(ktriangle instanceof Konva.Line)) {\n      return;\n    }\n    // find anchors\n    const begin = getAnchorShape(group, 0);\n    const end = getAnchorShape(group, 1);\n\n    // update 'self' (undo case)\n    switch (anchor.id()) {\n    case 'anchor0':\n      begin.x(anchor.x());\n      begin.y(anchor.y());\n      break;\n    case 'anchor1':\n      end.x(anchor.x());\n      end.y(anchor.y());\n      break;\n    default:\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n\n    const tickLen = 20;\n\n    // triangle\n    const perpLine = getPerpendicularLineAtDistance(\n      line, 2 * tickLen, tickLen, style.getZoomScale());\n    ktriangle.position({x: 0, y: 0});\n    ktriangle.points([\n      line.getBegin().getX(),\n      line.getBegin().getY(),\n      perpLine.getBegin().getX(),\n      perpLine.getBegin().getY(),\n      perpLine.getEnd().getX(),\n      perpLine.getEnd().getY(),\n    ]);\n\n    // larger hitfunc\n    const linePerp0 = getPerpendicularLine(\n      line, point, tickLen, style.getZoomScale());\n    const linePerp1 = getPerpendicularLine(\n      line, endPoint, tickLen, style.getZoomScale());\n    kline.hitFunc(function (context) {\n      context.beginPath();\n      context.moveTo(linePerp0.getBegin().getX(), linePerp0.getBegin().getY());\n      context.lineTo(linePerp0.getEnd().getX(), linePerp0.getEnd().getY());\n      context.lineTo(linePerp1.getEnd().getX(), linePerp1.getEnd().getY());\n      context.lineTo(linePerp1.getBegin().getX(), linePerp1.getBegin().getY());\n      context.closePath();\n      context.fillStrokeShape(kline);\n    });\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} [_group] The associated group.\n   * @returns {Konva.Group|undefined} The shadow konva group.\n   */\n  #getDebugShadow(_annotation, _group) {\n    return;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} _group The associated group.\n   */\n  #updateDebugShadow(_annotation, _group) {\n    // does nothing\n  }\n\n} // class ArrowFactory\n","import {Circle} from '../math/circle';\nimport {Point2D} from '../math/point';\nimport {logger} from '../utils/logger';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  isNodeNameShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Circle factory.\n */\nexport class CircleFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'circle';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Circle;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 2;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 0;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a circle shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(this.#createShape(annotation, style));\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(this.#labelFactory.create(annotation, style));\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Circle} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const centerX = shape.x();\n    const centerY = shape.y();\n    const radius = shape.radius() * Math.sqrt(2) / 2;\n    return [\n      new Point2D(centerX - radius, centerY - radius),\n      new Point2D(centerX + radius, centerY - radius),\n      new Point2D(centerX - radius, centerY + radius),\n      new Point2D(centerX + radius, centerY + radius),\n    ];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Circle} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const centerX = shape.x();\n    const centerY = shape.y();\n    const radius = shape.radius();\n    return [\n      new Point2D(centerX - radius, centerY),\n      new Point2D(centerX + radius, centerY),\n      new Point2D(centerX, centerY + radius),\n      new Point2D(centerX, centerY - radius),\n    ];\n  }\n\n  /**\n   * Get anchors to update a circle shape.\n   *\n   * @param {Konva.Circle} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} anchor The active anchor.\n   */\n  constrainAnchorMove(anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // find special points\n    const left = getAnchorShape(group, 0);\n    const right = getAnchorShape(group, 1);\n    const bottom = getAnchorShape(group, 2);\n    const top = getAnchorShape(group, 3);\n\n    // update 'self' (undo case) and special points\n    switch (anchor.id()) {\n    case 'anchor0':\n      // block y\n      left.y(right.y());\n      break;\n    case 'anchor1':\n      // block y\n      right.y(left.y());\n      break;\n    case 'anchor2':\n      // block x\n      bottom.x(top.x());\n      break;\n    case 'anchor3':\n      // block x\n      top.x(bottom.x());\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // math shape\n    const circle = annotation.mathShape;\n    const center = new Point2D(\n      circle.getCenter().getX(),\n      circle.getCenter().getY()\n    );\n    const anchorPoint = new Point2D(anchor.x(), anchor.y());\n    const newRadius = center.getDistance(anchorPoint);\n    annotation.mathShape = new Circle(center, newRadius);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const circle = annotation.mathShape;\n    const center = circle.getCenter();\n    const newCenter = new Point2D(\n      center.getX() + translation.x,\n      center.getY() + translation.y\n    );\n    annotation.mathShape = new Circle(newCenter, circle.getRadius());\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Circle} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    // calculate radius\n    const a = Math.abs(points[0].getX() - points[1].getX());\n    const b = Math.abs(points[0].getY() - points[1].getY());\n    const radius = Math.round(Math.sqrt(a * a + b * b));\n    // physical shape\n    return new Circle(points[0], radius);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Circle} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const circle = annotation.mathShape;\n    // konva circle\n    return new Konva.Circle({\n      x: circle.getCenter().getX(),\n      y: circle.getCenter().getY(),\n      radius: circle.getRadius(),\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Circle|undefined} The shape.\n   */\n  #getShape(group) {\n    const kshape = group.getChildren(isNodeNameShape)[0];\n    if (!(kshape instanceof Konva.Circle)) {\n      return;\n    }\n    return kshape;\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const circle = annotation.mathShape;\n    const center = circle.getCenter();\n    const radius = circle.getRadius();\n    return new Point2D(\n      center.getX() - radius,\n      center.getY() + radius,\n    );\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} _style The application style.\n   */\n  #updateShape(annotation, anchor, _style) {\n    const circle = annotation.mathShape;\n    const center = circle.getCenter();\n    const radius = circle.getRadius();\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kcircle = this.#getShape(group);\n    // update shape: just update the radius\n    kcircle.radius(radius);\n\n    // find anchors\n    const left = getAnchorShape(group, 0);\n    const right = getAnchorShape(group, 1);\n    const bottom = getAnchorShape(group, 2);\n    const top = getAnchorShape(group, 3);\n\n    const swapX = right.x() < left.x() ? -1 : 1;\n    const swapY = top.y() < bottom.y() ? 1 : -1;\n\n    // update 'self' (undo case) and other anchors\n    switch (anchor.id()) {\n    case 'anchor0':\n      // update self\n      left.x(anchor.x());\n      // update others\n      right.x(center.getX() + swapX * radius);\n      bottom.y(center.getY() + radius);\n      top.y(center.getY() - radius);\n      break;\n    case 'anchor1':\n      // update self\n      right.x(anchor.x());\n      // update others\n      left.x(center.getX() - swapX * radius);\n      bottom.y(center.getY() + radius);\n      top.y(center.getY() - radius);\n      break;\n    case 'anchor2':\n      // update self\n      bottom.y(anchor.y());\n      // update others\n      left.x(center.getX() - radius);\n      right.x(center.getX() + radius);\n      top.y(center.getY() - swapY * radius);\n      break;\n    case 'anchor3':\n      // update self\n      top.y(anchor.y());\n      // update others\n      left.x(center.getX() - radius);\n      right.x(center.getX() + radius);\n      bottom.y(center.getY() + swapY * radius);\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} annotation The annotation to shadow.\n   * @param {Konva.Group} [group] The associated group.\n   * @returns {Konva.Group|undefined} The shadow konva group.\n   */\n  #getDebugShadow(annotation, group) {\n    const circle = annotation.mathShape;\n\n    // possible group offset\n    let offsetX = 0;\n    let offsetY = 0;\n    if (typeof group !== 'undefined') {\n      offsetX = group.x();\n      offsetY = group.y();\n    }\n    const kshadow = new Konva.Group();\n    kshadow.name('shadow');\n    const regions = circle.getRound();\n    for (let i = 0; i < regions.length; ++i) {\n      const region = regions[i];\n      const minX = region[0][0];\n      const minY = region[0][1];\n      const maxX = region[1][0];\n      const pixelLine = new Konva.Rect({\n        x: minX - offsetX,\n        y: minY - offsetY,\n        width: maxX - minX,\n        height: 1,\n        fill: 'grey',\n        strokeWidth: 0,\n        strokeScaleEnabled: false,\n        opacity: 0.3,\n        name: 'shadow-element'\n      });\n      kshadow.add(pixelLine);\n    }\n    return kshadow;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} annotation The annotation to shadow.\n   * @param {Konva.Group} group The associated group.\n   */\n  #updateDebugShadow(annotation, group) {\n    const kshadow = group.getChildren(function (node) {\n      return node.name() === 'shadow';\n    })[0];\n    if (typeof kshadow !== 'undefined') {\n      // remove previous\n      kshadow.destroy();\n      // add new\n      group.add(this.#getDebugShadow(annotation, group));\n    }\n  }\n\n} // class CircleFactory\n","import {Ellipse} from '../math/ellipse';\nimport {Point2D} from '../math/point';\nimport {logger} from '../utils/logger';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  isNodeNameShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Ellipse factory.\n */\nexport class EllipseFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'ellipse';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Ellipse;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 2;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 0;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create an ellipse shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(this.#createShape(annotation, style));\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(this.#labelFactory.create(annotation, style));\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Ellipse} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const centerX = shape.x();\n    const centerY = shape.y();\n    const radiusX = shape.radiusX() * Math.sqrt(2) / 2;\n    const radiusY = shape.radiusY() * Math.sqrt(2) / 2;\n    return [\n      new Point2D(centerX - radiusX, centerY - radiusY),\n      new Point2D(centerX + radiusX, centerY - radiusY),\n      new Point2D(centerX - radiusX, centerY + radiusY),\n      new Point2D(centerX + radiusX, centerY + radiusY),\n    ];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Ellipse} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const centerX = shape.x();\n    const centerY = shape.y();\n    const radius = shape.radius();\n    return [\n      new Point2D(centerX - radius.x, centerY),\n      new Point2D(centerX + radius.x, centerY),\n      new Point2D(centerX, centerY + radius.y),\n      new Point2D(centerX, centerY - radius.y),\n    ];\n  }\n\n  /**\n   * Get anchors to update a ellipse shape.\n   *\n   * @param {Konva.Ellipse} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} anchor The active anchor.\n   */\n  constrainAnchorMove(anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // find special points\n    const left = getAnchorShape(group, 0);\n    const right = getAnchorShape(group, 1);\n    const bottom = getAnchorShape(group, 2);\n    const top = getAnchorShape(group, 3);\n\n    // update 'self' (undo case) and special points\n    switch (anchor.id()) {\n    case 'anchor0':\n      // block y\n      left.y(right.y());\n      break;\n    case 'anchor1':\n      // block y\n      right.y(left.y());\n      break;\n    case 'anchor2':\n      // block x\n      bottom.x(top.x());\n      break;\n    case 'anchor3':\n      // block x\n      top.x(bottom.x());\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // math shape\n    const ellipse = annotation.mathShape;\n    const center = ellipse.getCenter();\n    let radiusX = ellipse.getA();\n    let radiusY = ellipse.getB();\n\n    // update 'self' (undo case) and special points\n    switch (anchor.id()) {\n    case 'anchor0':\n      radiusX = center.getX() - anchor.x();\n      break;\n    case 'anchor1':\n      radiusX = anchor.x() - center.getX();\n      break;\n    case 'anchor2':\n      radiusY = anchor.y() - center.getY();\n      break;\n    case 'anchor3':\n      radiusY = center.getY() - anchor.y();\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n\n    annotation.mathShape = new Ellipse(\n      center, Math.abs(radiusX), Math.abs(radiusY));\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const ellipse = annotation.mathShape;\n    const center = ellipse.getCenter();\n    const newCenter = new Point2D(\n      center.getX() + translation.x,\n      center.getY() + translation.y\n    );\n    annotation.mathShape = new Ellipse(\n      newCenter, ellipse.getA(), ellipse.getB());\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Ellipse} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    // calculate radius\n    const a = Math.abs(points[0].getX() - points[1].getX());\n    const b = Math.abs(points[0].getY() - points[1].getY());\n    // physical shape\n    return new Ellipse(points[0], a, b);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Ellipse} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const ellipse = annotation.mathShape;\n    const center = ellipse.getCenter();\n    const radius = {\n      x: ellipse.getA(),\n      y: ellipse.getB()\n    };\n    // konva circle\n    return new Konva.Ellipse({\n      x: center.getX(),\n      y: center.getY(),\n      radius: radius,\n      radiusX: radius.x,\n      radiusY: radius.y,\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Ellipse|undefined} The shape.\n   */\n  #getShape(group) {\n    const kshape = group.getChildren(isNodeNameShape)[0];\n    if (!(kshape instanceof Konva.Ellipse)) {\n      return;\n    }\n    return kshape;\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const ellipse = annotation.mathShape;\n    const center = ellipse.getCenter();\n    return new Point2D(\n      center.getX() - ellipse.getA(),\n      center.getY() + ellipse.getB()\n    );\n  }\n\n  /**\n   * Update shape on anchor move.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} _style The application style.\n   */\n  #updateShape(annotation, anchor, _style) {\n    const ellipse = annotation.mathShape;\n    const center = ellipse.getCenter();\n    const radiusX = ellipse.getA();\n    const radiusY = ellipse.getB();\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kellipse = this.#getShape(group);\n    // update shape: just update radius\n    kellipse.radius({\n      x: radiusX,\n      y: radiusY\n    });\n\n    // find anchors\n    const left = getAnchorShape(group, 0);\n    const right = getAnchorShape(group, 1);\n    const bottom = getAnchorShape(group, 2);\n    const top = getAnchorShape(group, 3);\n\n    const swapX = right.x() < left.x() ? -1 : 1;\n    const swapY = top.y() < bottom.y() ? 1 : -1;\n\n    // update 'self' (undo case) and other anchors\n    switch (anchor.id()) {\n    case 'anchor0':\n      // update self\n      left.x(anchor.x());\n      // update others\n      right.x(center.getX() + swapX * radiusX);\n      bottom.y(center.getY() + radiusY);\n      top.y(center.getY() - radiusY);\n      break;\n    case 'anchor1':\n      // update self\n      right.x(anchor.x());\n      // update others\n      left.x(center.getX() - swapX * radiusX);\n      bottom.y(center.getY() + radiusY);\n      top.y(center.getY() - radiusY);\n      break;\n    case 'anchor2':\n      // update self\n      bottom.y(anchor.y());\n      // update others\n      left.x(center.getX() - radiusX);\n      right.x(center.getX() + radiusX);\n      top.y(center.getY() - swapY * radiusY);\n      break;\n    case 'anchor3':\n      // update self\n      top.y(anchor.y());\n      // update others\n      left.x(center.getX() - radiusX);\n      right.x(center.getX() + radiusX);\n      bottom.y(center.getY() + swapY * radiusY);\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} annotation The annotation to shadow.\n   * @param {Konva.Group} [group] The associated group.\n   * @returns {Konva.Group|undefined} The shadow konva group.\n   */\n  #getDebugShadow(annotation, group) {\n    const ellipse = annotation.mathShape;\n\n    // possible group offset\n    let offsetX = 0;\n    let offsetY = 0;\n    if (typeof group !== 'undefined') {\n      offsetX = group.x();\n      offsetY = group.y();\n    }\n    const kshadow = new Konva.Group();\n    kshadow.name('shadow');\n    const regions = ellipse.getRound();\n    for (let i = 0; i < regions.length; ++i) {\n      const region = regions[i];\n      const minX = region[0][0];\n      const minY = region[0][1];\n      const maxX = region[1][0];\n      const pixelLine = new Konva.Rect({\n        x: minX - offsetX,\n        y: minY - offsetY,\n        width: maxX - minX,\n        height: 1,\n        fill: 'grey',\n        strokeWidth: 0,\n        strokeScaleEnabled: false,\n        opacity: 0.3,\n        name: 'shadow-element'\n      });\n      kshadow.add(pixelLine);\n    }\n    return kshadow;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} annotation The annotation to shadow.\n   * @param {Konva.Group} group The associated group.\n   */\n  #updateDebugShadow(annotation, group) {\n    const kshadow = group.getChildren(function (node) {\n      return node.name() === 'shadow';\n    })[0];\n    if (typeof kshadow !== 'undefined') {\n      // remove previous\n      kshadow.destroy();\n      // add new\n      group.add(this.#getDebugShadow(annotation, group));\n    }\n  }\n\n} // class EllipseFactory\n","import {Line, getAngle} from '../math/line';\nimport {Protractor} from '../math/protractor';\nimport {Point2D} from '../math/point';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  getLineShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Protractor factory.\n */\nexport class ProtractorFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'protractor';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Protractor;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 3;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 500;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a line shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    const protractor = annotation.mathShape;\n\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(this.#createShape(annotation, style));\n\n    if (protractor.getLength() === this.getNPoints()) {\n      // extras\n      const extras = this.#createShapeExtras(annotation, style);\n      for (const extra of extras) {\n        group.add(extra);\n      }\n      // konva label\n      const label = this.#labelFactory.create(annotation, style);\n      group.add(this.#labelFactory.create(annotation, style));\n      // label-shape connector\n      const connectorsPos = this.#getConnectorsPositions(shape);\n      group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n      // konva shadow (if debug)\n      if (DRAW_DEBUG) {\n        group.add(this.#getDebugShadow(annotation));\n      }\n    }\n    return group;\n  }\n\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    return [\n      new Point2D(points[2] + sx, points[3] + sy)\n    ];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    return [\n      new Point2D(points[0] + sx, points[1] + sy),\n      new Point2D(points[2] + sx, points[3] + sy),\n      new Point2D(points[4] + sx, points[5] + sy)\n    ];\n  }\n\n  /**\n   * Get anchors to update a line shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} _anchor The active anchor.\n   */\n  constrainAnchorMove(_anchor) {\n    // no constraints\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n    // find special points\n    const begin = getAnchorShape(group, 0);\n    const mid = getAnchorShape(group, 1);\n    const end = getAnchorShape(group, 2);\n\n    // math shape\n    // compensate for possible shape drag\n    const pointBegin = new Point2D(\n      begin.x() - kline.x(),\n      begin.y() - kline.y()\n    );\n    const pointMid = new Point2D(\n      mid.x() - kline.x(),\n      mid.y() - kline.y()\n    );\n    const pointEnd = new Point2D(\n      end.x() - kline.x(),\n      end.y() - kline.y()\n    );\n    annotation.mathShape = new Protractor([pointBegin, pointMid, pointEnd]);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const protractor = annotation.mathShape;\n    const newPointList = [];\n    for (let i = 0; i < 3; ++i) {\n      newPointList.push(new Point2D(\n        protractor.getPoint(i).getX() + translation.x,\n        protractor.getPoint(i).getY() + translation.y\n      ));\n    }\n    annotation.mathShape = new Protractor(newPointList);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Protractor} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    return new Protractor(points);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Line} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const protractor = annotation.mathShape;\n    const points = [];\n    for (let i = 0; i < protractor.getLength(); ++i) {\n      points.push(protractor.getPoint(i).getX());\n      points.push(protractor.getPoint(i).getY());\n    }\n\n    // konva line\n    const kshape = new Konva.Line({\n      points: points,\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n\n    if (protractor.getLength() === this.getNPoints()) {\n      // larger hitfunc\n      kshape.hitFunc(function (context) {\n        context.beginPath();\n        context.moveTo(\n          protractor.getPoint(0).getX(), protractor.getPoint(0).getY());\n        context.lineTo(\n          protractor.getPoint(1).getX(), protractor.getPoint(1).getY());\n        context.lineTo(\n          protractor.getPoint(2).getX(), protractor.getPoint(2).getY());\n        context.closePath();\n        context.fillStrokeShape(kshape);\n      });\n    }\n\n    return kshape;\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Line|undefined} The shape.\n   */\n  #getShape(group) {\n    return getLineShape(group);\n  }\n\n  /**\n   * Creates the konva shape extras.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Array} The konva shape extras.\n   */\n  #createShapeExtras(annotation, style) {\n    const protractor = annotation.mathShape;\n    const line0 = new Line(\n      protractor.getPoint(0), protractor.getPoint(1));\n    const line1 = new Line(\n      protractor.getPoint(1), protractor.getPoint(2));\n\n    let angle = getAngle(line0, line1);\n    let inclination = line0.getInclination();\n    if (angle > 180) {\n      angle = 360 - angle;\n      inclination += angle;\n    }\n\n    const radius = Math.min(line0.getLength(), line1.getLength()) * 33 / 100;\n    const karc = new Konva.Arc({\n      innerRadius: radius,\n      outerRadius: radius,\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      angle: angle,\n      rotation: -inclination,\n      x: protractor.getPoint(1).getX(),\n      y: protractor.getPoint(1).getY(),\n      name: 'shape-arc'\n    });\n\n    return [karc];\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const protractor = annotation.mathShape;\n    const line0 = new Line(\n      protractor.getPoint(0), protractor.getPoint(1));\n    const line1 = new Line(\n      protractor.getPoint(1), protractor.getPoint(2));\n\n    const midX =\n      (line0.getMidpoint().getX() + line1.getMidpoint().getX()) / 2;\n    const midY =\n      (line0.getMidpoint().getY() + line1.getMidpoint().getY()) / 2;\n\n    return new Point2D(\n      midX,\n      midY\n    );\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} _style The application style.\n   */\n  #updateShape(annotation, anchor, _style) {\n    const protractor = annotation.mathShape;\n    const line0 = new Line(\n      protractor.getPoint(0), protractor.getPoint(1));\n    const line1 = new Line(\n      protractor.getPoint(1), protractor.getPoint(2));\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n\n    // reset position after possible shape drag\n    kline.position({x: 0, y: 0});\n    // update shape\n    kline.points([\n      protractor.getPoint(0).getX(),\n      protractor.getPoint(0).getY(),\n      protractor.getPoint(1).getX(),\n      protractor.getPoint(1).getY(),\n      protractor.getPoint(2).getX(),\n      protractor.getPoint(2).getY()\n    ]);\n\n    // associated arc\n    const karc = group.getChildren(function (node) {\n      return node.name() === 'shape-arc';\n    })[0];\n    if (!(karc instanceof Konva.Arc)) {\n      return;\n    }\n\n    // find special points\n    const begin = getAnchorShape(group, 0);\n    const mid = getAnchorShape(group, 1);\n    const end = getAnchorShape(group, 2);\n\n    // update special points\n    switch (anchor.id()) {\n    case 'anchor0':\n      begin.x(anchor.x());\n      begin.y(anchor.y());\n      break;\n    case 'anchor1':\n      mid.x(anchor.x());\n      mid.y(anchor.y());\n      break;\n    case 'anchor2':\n      end.x(anchor.x());\n      end.y(anchor.y());\n      break;\n    }\n\n    // angle\n    let angle = getAngle(line0, line1);\n    let inclination = line0.getInclination();\n    if (angle > 180) {\n      angle = 360 - angle;\n      inclination += angle;\n    }\n\n    // arc\n    const radius = Math.min(line0.getLength(), line1.getLength()) * 33 / 100;\n    karc.innerRadius(radius);\n    karc.outerRadius(radius);\n    karc.angle(angle);\n    karc.rotation(-inclination);\n    const arcPos = {x: mid.x(), y: mid.y()};\n    karc.position(arcPos);\n\n    // larger hitfunc\n    kline.hitFunc(function (context) {\n      context.beginPath();\n      context.moveTo(\n        protractor.getPoint(0).getX(), protractor.getPoint(0).getY());\n      context.lineTo(\n        protractor.getPoint(1).getX(), protractor.getPoint(1).getY());\n      context.lineTo(\n        protractor.getPoint(2).getX(), protractor.getPoint(2).getY());\n      context.closePath();\n      context.fillStrokeShape(kline);\n    });\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} [_group] The associated group.\n   * @returns {Konva.Group|undefined} The shadow konva group.\n   */\n  #getDebugShadow(_annotation, _group) {\n    return;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} _group The associated group.\n   */\n  #updateDebugShadow(_annotation, _group) {\n    // does nothing\n  }\n\n} // class ProtractorFactory\n","import {Rectangle} from '../math/rectangle';\nimport {Point2D} from '../math/point';\nimport {logger} from '../utils/logger';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  isNodeNameShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Rectangle factory.\n */\nexport class RectangleFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'rectangle';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Rectangle;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 2;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 0;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a rectangle shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(shape);\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(label);\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Rect} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const sx = shape.x();\n    const sy = shape.y();\n    const width = shape.width();\n    const height = shape.height();\n    return [\n      new Point2D(sx + width / 2, sy),\n      new Point2D(sx, sy + height / 2),\n      new Point2D(sx + width / 2, sy + height),\n      new Point2D(sx + width, sy + height / 2),\n    ];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Rect} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const sx = shape.x();\n    const sy = shape.y();\n    const width = shape.width();\n    const height = shape.height();\n    return [\n      new Point2D(sx, sy),\n      new Point2D(sx + width, sy),\n      new Point2D(sx + width, sy + height),\n      new Point2D(sx, sy + height),\n    ];\n  }\n\n  /**\n   * Get anchors to update a rectangle shape.\n   *\n   * @param {Konva.Rect} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} _anchor The active anchor.\n   */\n  constrainAnchorMove(_anchor) {\n    // no constraints\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // find anchors\n    const topLeft = getAnchorShape(group, 0);\n    const bottomRight = getAnchorShape(group, 2);\n\n    const pointTopLeft = new Point2D(\n      topLeft.x(),\n      topLeft.y()\n    );\n    const pointBottomRight = new Point2D(\n      bottomRight.x(),\n      bottomRight.y()\n    );\n    // new rect\n    annotation.mathShape = new Rectangle(pointTopLeft, pointBottomRight);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const rectangle = annotation.mathShape;\n    const begin = rectangle.getBegin();\n    const newBegin = new Point2D(\n      begin.getX() + translation.x,\n      begin.getY() + translation.y\n    );\n    const end = rectangle.getEnd();\n    const newEnd = new Point2D(\n      end.getX() + translation.x,\n      end.getY() + translation.y\n    );\n    annotation.mathShape = new Rectangle(newBegin, newEnd);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label content.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Rectangle} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    return new Rectangle(points[0], points[1]);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Rect} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const rectangle = annotation.mathShape;\n    // konva rect\n    return new Konva.Rect({\n      x: rectangle.getBegin().getX(),\n      y: rectangle.getBegin().getY(),\n      width: rectangle.getWidth(),\n      height: rectangle.getHeight(),\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Rect|undefined} The shape.\n   */\n  #getShape(group) {\n    const kshape = group.getChildren(isNodeNameShape)[0];\n    if (!(kshape instanceof Konva.Rect)) {\n      return;\n    }\n    return kshape;\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const rectangle = annotation.mathShape;\n    return new Point2D(\n      rectangle.getBegin().getX(),\n      rectangle.getEnd().getY(),\n    );\n  }\n\n  /**\n   * Update shape on anchor move.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} _style The application style.\n   */\n  #updateShape(annotation, anchor, _style) {\n    const rectangle = annotation.mathShape;\n    const begin = rectangle.getBegin();\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const krect = this.#getShape(group);\n    // update shape\n    krect.position({\n      x: begin.getX(),\n      y: begin.getY()\n    });\n    krect.size({\n      width: rectangle.getWidth(),\n      height: rectangle.getHeight()\n    });\n\n    // find anchors\n    const topLeft = getAnchorShape(group, 0);\n    const topRight = getAnchorShape(group, 1);\n    const bottomRight = getAnchorShape(group, 2);\n    const bottomLeft = getAnchorShape(group, 3);\n\n    // update 'self' (undo case) and other anchors\n    switch (anchor.id()) {\n    case 'anchor0':\n      // update self\n      topLeft.x(anchor.x());\n      topLeft.y(anchor.y());\n      // update others\n      topRight.y(anchor.y());\n      bottomLeft.x(anchor.x());\n      break;\n    case 'anchor1':\n      // update self\n      topRight.x(anchor.x());\n      topRight.y(anchor.y());\n      // update others\n      topLeft.y(anchor.y());\n      bottomRight.x(anchor.x());\n      break;\n    case 'anchor2':\n      // update self\n      bottomRight.x(anchor.x());\n      bottomRight.y(anchor.y());\n      // update others\n      bottomLeft.y(anchor.y());\n      topRight.x(anchor.x());\n      break;\n    case 'anchor3':\n      // update self\n      bottomLeft.x(anchor.x());\n      bottomLeft.y(anchor.y());\n      // update others\n      bottomRight.y(anchor.y());\n      topLeft.x(anchor.x());\n      break;\n    default :\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} annotation The anootation to shadow.\n   * @param {Konva.Group} [_group] The associated group.\n   * @returns {Konva.Rect} The shadow konva rect.\n   */\n  #getDebugShadow(annotation, _group) {\n    const rectangle = annotation.mathShape;\n    const round = rectangle.getRound();\n    const rWidth = round.max.getX() - round.min.getX();\n    const rHeight = round.max.getY() - round.min.getY();\n    return new Konva.Rect({\n      x: round.min.getX(),\n      y: round.min.getY(),\n      width: rWidth,\n      height: rHeight,\n      fill: 'grey',\n      strokeWidth: 0,\n      strokeScaleEnabled: false,\n      opacity: 0.3,\n      name: 'shadow'\n    });\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} annotation The annotation to shadow.\n   * @param {Konva.Group} group The associated group.\n   */\n  #updateDebugShadow(annotation, group) {\n    const kshadow = group.getChildren(function (node) {\n      return node.name() === 'shadow';\n    })[0];\n    if (typeof kshadow !== 'undefined') {\n      // remove previous\n      kshadow.destroy();\n      // add new\n      group.add(this.#getDebugShadow(annotation, group));\n    }\n  }\n\n} // class RectangleFactory\n","import {ROI} from '../math/roi';\nimport {Point2D} from '../math/point';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  getLineShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorIndex\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * ROI factory.\n */\nexport class RoiFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'roi';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof ROI;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number|undefined} The number of points.\n   */\n  getNPoints() {\n    // undefined to end with double click\n    return undefined;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 100;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a roi shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(this.#createShape(annotation, style));\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(this.#labelFactory.create(annotation, style));\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    const positions = [];\n    for (let i = 0; i < points.length; i = i + 2) {\n      positions.push(new Point2D(\n        points[i] + sx,\n        points[i + 1] + sy\n      ));\n    }\n    return positions;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    const positions = [];\n    for (let i = 0; i < points.length; i += 2) {\n      const nextIndex = (i + 2) % points.length;\n      const midX = (points[i] + points[nextIndex]) / 2 + sx;\n      const midY = (points[i + 1] + points[nextIndex + 1]) / 2 + sy;\n      positions.push(new Point2D(midX, midY));\n    }\n    return positions;\n  }\n\n  /**\n   * Get anchors to update a roi shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} _anchor The active anchor.\n   */\n  constrainAnchorMove(_anchor) {\n    // no constraints\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kroi = this.#getShape(group);\n\n    // update the roi point and compensate for possible drag\n    // (the anchor id is the index of the point in the main list)\n    const roi = annotation.mathShape;\n    const points = roi.getPoints().slice();\n    const newPoint = new Point2D(\n      anchor.x() - kroi.x(),\n      anchor.y() - kroi.y()\n    );\n    const index = getAnchorIndex(anchor.id());\n    points[index] = newPoint;\n\n    // new math shape\n    annotation.mathShape = new ROI(points);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const roi = annotation.mathShape;\n    const newPoints = [];\n    for (let i = 0; i < roi.getLength(); ++i) {\n      newPoints.push(new Point2D(\n        roi.getPoint(i).getX() + translation.x,\n        roi.getPoint(i).getY() + translation.y\n      ));\n    }\n    annotation.mathShape = new ROI(newPoints);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {ROI} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    return new ROI(points);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Line} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const roi = annotation.mathShape;\n    // konva line\n    const arr = [];\n    for (let i = 0; i < roi.getLength(); ++i) {\n      arr.push(roi.getPoint(i).getX());\n      arr.push(roi.getPoint(i).getY());\n    }\n    return new Konva.Line({\n      points: arr,\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape',\n      closed: true\n    });\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Line|undefined} The shape.\n   */\n  #getShape(group) {\n    return getLineShape(group);\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const roi = annotation.mathShape;\n    return new Point2D(\n      roi.getPoint(0).getX(),\n      roi.getPoint(0).getY()\n    );\n  }\n\n  /**\n   * Update shape on anchor move.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} _style The application style.\n   */\n  #updateShape(annotation, anchor, _style) {\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kroi = this.#getShape(group);\n    // update the roi point and compensate for possible drag\n    // (the anchor id is the index of the point in the main list)\n    const points = kroi.points();\n    const index = getAnchorIndex(anchor.id()) * 2;\n    points[index] = anchor.x() - kroi.x();\n    points[index + 1] = anchor.y() - kroi.y();\n    kroi.points(points);\n\n    // update self\n    const point = group.getChildren(function (node) {\n      return node.id() === anchor.id();\n    })[0];\n\n    point.x(anchor.x());\n    point.y(anchor.y());\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} _annotation The anootation to shadow.\n   * @param {Konva.Group} [_group] The associated group.\n   * @returns {Konva.Line} The shadow konva line.\n   */\n  #getDebugShadow(_annotation, _group) {\n    // does nothing\n    return undefined;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} _group The associated group.\n   */\n  #updateDebugShadow(_annotation, _group) {\n    // does nothing\n  }\n\n} // class RoiFactory\n","import {Line, getPerpendicularLine} from '../math/line';\nimport {Point2D} from '../math/point';\nimport {logger} from '../utils/logger';\nimport {custom} from '../app/custom';\nimport {\n  defaultLabelTexts,\n  getLineShape,\n  DRAW_DEBUG,\n  getDefaultAnchor,\n  getAnchorShape\n} from './drawBounds';\nimport {LabelFactory} from './labelFactory';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Style} from '../gui/style';\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Ruler factory.\n */\nexport class RulerFactory {\n\n  /**\n   * The name of the factory.\n   *\n   * @type {string}\n   */\n  #name = 'ruler';\n\n  /**\n   * The associated label factory.\n   *\n   * @type {LabelFactory}\n   */\n  #labelFactory = new LabelFactory(this.#getDefaultLabelPosition);\n\n  /**\n   * Does this factory support the input math shape.\n   *\n   * @param {object} mathShape The mathematical shape.\n   * @returns {boolean} True if supported.\n   */\n  static supports(mathShape) {\n    return mathShape instanceof Line;\n  }\n\n  /**\n   * Get the name of the factory.\n   *\n   * @returns {string} The name.\n   */\n  getName() {\n    return this.#name;\n  }\n\n  /**\n   * Get the name of the shape group.\n   *\n   * @returns {string} The name.\n   */\n  getGroupName() {\n    return this.#name + '-group';\n  }\n\n  /**\n   * Get the number of points needed to build the shape.\n   *\n   * @returns {number} The number of points.\n   */\n  getNPoints() {\n    return 2;\n  }\n\n  /**\n   * Get the timeout between point storage.\n   *\n   * @returns {number} The timeout in milliseconds.\n   */\n  getTimeout() {\n    return 0;\n  }\n\n  /**\n   * Set an annotation math shape from input points.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Point2D[]} points The points.\n   */\n  setAnnotationMathShape(annotation, points) {\n    annotation.mathShape = this.#calculateMathShape(points);\n    annotation.setTextExpr(this.#getDefaultLabel());\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Create a line shape to be displayed.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Group} The Konva group.\n   */\n  createShapeGroup(annotation, style) {\n    // konva group\n    const group = new Konva.Group();\n    group.name(this.getGroupName());\n    group.visible(true);\n    group.id(annotation.id);\n    // konva shape\n    const shape = this.#createShape(annotation, style);\n    group.add(this.#createShape(annotation, style));\n    // extras\n    const extras = this.#createShapeExtras(annotation, style);\n    for (const extra of extras) {\n      group.add(extra);\n    }\n    // konva label\n    const label = this.#labelFactory.create(annotation, style);\n    group.add(this.#labelFactory.create(annotation, style));\n    // label-shape connector\n    const connectorsPos = this.#getConnectorsPositions(shape);\n    group.add(this.#labelFactory.getConnector(connectorsPos, label, style));\n    // konva shadow (if debug)\n    if (DRAW_DEBUG) {\n      group.add(this.#getDebugShadow(annotation));\n    }\n    return group;\n  }\n\n  /**\n   * Get the connectors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The connectors positions.\n   */\n  #getConnectorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    const centerX = (points[0] + points[2]) / 2 + sx;\n    const centerY = (points[1] + points[3]) / 2 + sy;\n    return [new Point2D(centerX, centerY)];\n  }\n\n  /**\n   * Get the anchors positions for the shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @returns {Point2D[]} The anchor positions.\n   */\n  #getAnchorsPositions(shape) {\n    const points = shape.points();\n    const sx = shape.x();\n    const sy = shape.y();\n    return [\n      new Point2D(points[0] + sx, points[1] + sy),\n      new Point2D(points[2] + sx, points[3] + sy)\n    ];\n  }\n\n  /**\n   * Get anchors to update a line shape.\n   *\n   * @param {Konva.Line} shape The associated shape.\n   * @param {Style} style The application style.\n   * @returns {Konva.Ellipse[]} A list of anchors.\n   */\n  getAnchors(shape, style) {\n    const positions = this.#getAnchorsPositions(shape);\n    const anchors = [];\n    for (let i = 0; i < positions.length; ++i) {\n      anchors.push(getDefaultAnchor(\n        positions[i].getX(),\n        positions[i].getY(),\n        'anchor' + i,\n        style\n      ));\n    }\n    return anchors;\n  }\n\n  /**\n   * Constrain anchor movement.\n   *\n   * @param {Konva.Ellipse} _anchor The active anchor.\n   */\n  constrainAnchorMove(_anchor) {\n    // no constraints\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  updateShapeGroupOnAnchorMove(annotation, anchor, style) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n\n    // update shape and anchors\n    this.#updateShape(annotation, anchor, style);\n    // update label\n    this.updateLabelContent(annotation, group, style);\n    // label position\n    if (typeof annotation.labelPosition === 'undefined') {\n      // update label position if default position\n      this.#labelFactory.updatePosition(annotation, group);\n    } else {\n      // update connector if not default position\n      this.updateConnector(group);\n    }\n    // update shadow\n    if (DRAW_DEBUG) {\n      this.#updateDebugShadow(annotation, group);\n    }\n  }\n\n  /**\n   * Update an annotation on anchor move.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {Konva.Shape} anchor The anchor.\n   */\n  updateAnnotationOnAnchorMove(annotation, anchor) {\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n    // find anchors\n    const begin = getAnchorShape(group, 0);\n    const end = getAnchorShape(group, 1);\n\n    // math shape\n    // compensate for possible shape drag\n    const pointBegin = new Point2D(\n      begin.x() - kline.x(),\n      begin.y() - kline.y()\n    );\n    const pointEnd = new Point2D(\n      end.x() - kline.x(),\n      end.y() - kline.y()\n    );\n    annotation.mathShape = new Line(pointBegin, pointEnd);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update an annotation on translation (shape move).\n   *\n   * @param {Annotation} annotation The annotation.\n   * @param {object} translation The translation.\n   */\n  updateAnnotationOnTranslation(annotation, translation) {\n    // math shape\n    const line = annotation.mathShape;\n    const begin = line.getBegin();\n    const newBegin = new Point2D(\n      begin.getX() + translation.x,\n      begin.getY() + translation.y\n    );\n    const end = line.getEnd();\n    const newEnd = new Point2D(\n      end.getX() + translation.x,\n      end.getY() + translation.y\n    );\n    annotation.mathShape = new Line(newBegin, newEnd);\n    // quantification\n    annotation.updateQuantification();\n  }\n\n  /**\n   * Update the shape label.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Group} group The shape group.\n   * @param {Style} _style The application style.\n   */\n  updateLabelContent(annotation, group, _style) {\n    this.#labelFactory.updateContent(annotation, group);\n  }\n\n  /**\n   * Update the shape connector.\n   *\n   * @param {Konva.Group} group The shape group.\n   */\n  updateConnector(group) {\n    const kshape = this.#getShape(group);\n    const connectorsPos = this.#getConnectorsPositions(kshape);\n    this.#labelFactory.updateConnector(group, connectorsPos);\n  }\n\n  /**\n   * Calculate the mathematical shape from a list of points.\n   *\n   * @param {Point2D[]} points The points that define the shape.\n   * @returns {Line} The mathematical shape.\n   */\n  #calculateMathShape(points) {\n    return new Line(points[0], points[1]);\n  }\n\n  /**\n   * Get the default labels.\n   *\n   * @returns {object} The label list.\n   */\n  #getDefaultLabel() {\n    if (typeof custom.labelTexts !== 'undefined' &&\n      typeof custom.labelTexts[this.#name] !== 'undefined'\n    ) {\n      return custom.labelTexts[this.#name];\n    } else {\n      return defaultLabelTexts[this.#name];\n    }\n  }\n\n  /**\n   * Creates the konva shape.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Konva.Line} The konva shape.\n   */\n  #createShape(annotation, style) {\n    const line = annotation.mathShape;\n\n    // konva line\n    const kshape = new Konva.Line({\n      points: [\n        line.getBegin().getX(),\n        line.getBegin().getY(),\n        line.getEnd().getX(),\n        line.getEnd().getY()\n      ],\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape'\n    });\n\n    // larger hitfunc\n    const tickLen = 20;\n    const linePerp0 = getPerpendicularLine(\n      line, line.getBegin(), tickLen, style.getZoomScale());\n    const linePerp1 = getPerpendicularLine(\n      line, line.getEnd(), tickLen, style.getZoomScale());\n    kshape.hitFunc(function (context) {\n      context.beginPath();\n      context.moveTo(linePerp0.getBegin().getX(), linePerp0.getBegin().getY());\n      context.lineTo(linePerp0.getEnd().getX(), linePerp0.getEnd().getY());\n      context.lineTo(linePerp1.getEnd().getX(), linePerp1.getEnd().getY());\n      context.lineTo(linePerp1.getBegin().getX(), linePerp1.getBegin().getY());\n      context.closePath();\n      context.fillStrokeShape(kshape);\n    });\n\n    return kshape;\n  }\n\n  /**\n   * Get the associated shape from a group.\n   *\n   * @param {Konva.Group} group The group to look into.\n   * @returns {Konva.Line|undefined} The shape.\n   */\n  #getShape(group) {\n    return getLineShape(group);\n  }\n\n  /**\n   * Creates the konva shape extras.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Style} style The drawing style.\n   * @returns {Array} The konva shape extras.\n   */\n  #createShapeExtras(annotation, style) {\n    const line = annotation.mathShape;\n\n    const tickLen = 20;\n\n    // tick begin\n    const linePerp0 = getPerpendicularLine(\n      line, line.getBegin(), tickLen, style.getZoomScale());\n    const ktick0 = new Konva.Line({\n      points: [\n        linePerp0.getBegin().getX(),\n        linePerp0.getBegin().getY(),\n        linePerp0.getEnd().getX(),\n        linePerp0.getEnd().getY()\n      ],\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape-tick0'\n    });\n\n    // tick end\n    const linePerp1 = getPerpendicularLine(\n      line, line.getEnd(), tickLen, style.getZoomScale());\n    const ktick1 = new Konva.Line({\n      points: [\n        linePerp1.getBegin().getX(),\n        linePerp1.getBegin().getY(),\n        linePerp1.getEnd().getX(),\n        linePerp1.getEnd().getY()\n      ],\n      stroke: annotation.colour,\n      strokeWidth: style.getStrokeWidth(),\n      strokeScaleEnabled: false,\n      name: 'shape-tick1'\n    });\n\n    return [ktick0, ktick1];\n  }\n\n  /**\n   * Get the default annotation label position.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Point2D} The position.\n   */\n  #getDefaultLabelPosition(annotation) {\n    const line = annotation.mathShape;\n    const begin = line.getBegin();\n    const end = line.getEnd();\n    // lowest point\n    let res = begin;\n    if (begin.getY() < end.getY()) {\n      res = end;\n    }\n    return res;\n  }\n\n  /**\n   * Update shape and label on anchor move taking the updated\n   *   annotation as input.\n   *\n   * @param {Annotation} annotation The associated annotation.\n   * @param {Konva.Ellipse} anchor The active anchor.\n   * @param {Style} style The application style.\n   */\n  #updateShape(annotation, anchor, style) {\n    const line = annotation.mathShape;\n\n    // parent group\n    const group = anchor.getParent();\n    if (!(group instanceof Konva.Group)) {\n      return;\n    }\n    // associated shape\n    const kline = this.#getShape(group);\n\n    // reset position after possible shape drag\n    kline.position({x: 0, y: 0});\n    // update shape\n    kline.points([\n      line.getBegin().getX(),\n      line.getBegin().getY(),\n      line.getEnd().getX(),\n      line.getEnd().getY(),\n    ]);\n\n    // associated tick0\n    const ktick0 = group.getChildren(function (node) {\n      return node.name() === 'shape-tick0';\n    })[0];\n    if (!(ktick0 instanceof Konva.Line)) {\n      return;\n    }\n    // associated tick1\n    const ktick1 = group.getChildren(function (node) {\n      return node.name() === 'shape-tick1';\n    })[0];\n    if (!(ktick1 instanceof Konva.Line)) {\n      return;\n    }\n    // find anchors\n    const begin = getAnchorShape(group, 0);\n    const end = getAnchorShape(group, 1);\n\n    // update 'self' (undo case)\n    switch (anchor.id()) {\n    case 'anchor0':\n      begin.x(anchor.x());\n      begin.y(anchor.y());\n      break;\n    case 'anchor1':\n      end.x(anchor.x());\n      end.y(anchor.y());\n      break;\n    default:\n      logger.error('Unhandled anchor id: ' + anchor.id());\n      break;\n    }\n\n    // tick\n    const tickLen = 20;\n    const linePerp0 = getPerpendicularLine(\n      line, line.getBegin(), tickLen, style.getZoomScale());\n    ktick0.position({x: 0, y: 0});\n    ktick0.points([linePerp0.getBegin().getX(),\n      linePerp0.getBegin().getY(),\n      linePerp0.getEnd().getX(),\n      linePerp0.getEnd().getY()]);\n    const linePerp1 = getPerpendicularLine(\n      line, line.getEnd(), tickLen, style.getZoomScale());\n    ktick1.position({x: 0, y: 0});\n    ktick1.points([linePerp1.getBegin().getX(),\n      linePerp1.getBegin().getY(),\n      linePerp1.getEnd().getX(),\n      linePerp1.getEnd().getY()]);\n\n    // larger hitfunc\n    kline.hitFunc(function (context) {\n      context.beginPath();\n      context.moveTo(linePerp0.getBegin().getX(), linePerp0.getBegin().getY());\n      context.lineTo(linePerp0.getEnd().getX(), linePerp0.getEnd().getY());\n      context.lineTo(linePerp1.getEnd().getX(), linePerp1.getEnd().getY());\n      context.lineTo(linePerp1.getBegin().getX(), linePerp1.getBegin().getY());\n      context.closePath();\n      context.fillStrokeShape(kline);\n    });\n  }\n\n  /**\n   * Get the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} [_group] The associated group.\n   * @returns {Konva.Group|undefined} The shadow konva group.\n   */\n  #getDebugShadow(_annotation, _group) {\n    return;\n  }\n\n  /**\n   * Update the debug shadow.\n   *\n   * @param {Annotation} _annotation The annotation to shadow.\n   * @param {Konva.Group} _group The associated group.\n   */\n  #updateDebugShadow(_annotation, _group) {\n    // does nothing\n  }\n\n} // class RulerFactory\n","import {logger} from '../utils/logger';\nimport {getFlags, replaceFlags} from '../utils/string';\nimport {Point} from '../math/point';\nimport {getOrientationName} from '../math/orientation';\nimport {defaultToolOptions, toolOptions} from '../tools/index';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D, Point3D} from '../math/point';\nimport {Index} from '../math/index';\nimport {ViewController} from '../app/viewController';\nimport {PlaneHelper} from './planeHelper';\n/* eslint-enable no-unused-vars */\n\n/**\n * Image annotation.\n */\nexport class Annotation {\n  /**\n   * The ID.\n   *\n   * @type {string}\n   */\n  id;\n\n  /**\n   * The reference image SOP UID.\n   *\n   * @type {string}\n   */\n  referenceSopUID;\n\n  /**\n   * The mathematical shape.\n   *\n   * @type {object}\n   */\n  mathShape;\n\n  /**\n   * Additional points used to define the annotation.\n   *\n   * @type {Point2D[]|undefined}\n   */\n  referencePoints;\n\n  /**\n   * The color: for example 'green', '#00ff00' or 'rgb(0,255,0)'.\n   *\n   * @type {string|undefined}\n   */\n  colour;\n\n  /**\n   * Annotation quantification.\n   *\n   * @type {object|undefined}\n   */\n  quantification;\n\n  /**\n   * Text expression. Can contain variables surrounded with '{}' that will\n   * be extracted from the quantification object.\n   *\n   * @type {string|undefined}\n   */\n  textExpr;\n\n  /**\n   * Label position. If undefined, the default shape\n   *   label position will be used.\n   *\n   * @type {Point2D|undefined}\n   */\n  labelPosition;\n\n  /**\n   * The plane origin, the 3D position of index [0, 0, k].\n   *\n   * @type {Point3D|undefined}\n   */\n  planeOrigin;\n\n  /**\n   * A couple of points that help define the annotation plane.\n   *\n   * @type {Point3D[]|undefined}\n   */\n  planePoints;\n\n  /**\n   * Associated view controller: needed for quantification and label.\n   *\n   * @type {ViewController|undefined}\n   */\n  #viewController;\n\n  /**\n   * Get the orientation name for this annotation.\n   *\n   * @returns {string|undefined} The orientation name,\n   *   undefined if same as reference data.\n   */\n  getOrientationName() {\n    let res;\n    if (typeof this.planePoints !== 'undefined') {\n      const cosines = this.planePoints[1].getValues().concat(\n        this.planePoints[2].getValues()\n      );\n      res = getOrientationName(cosines);\n    }\n    return res;\n  }\n\n  /**\n   * Initialise the annotation.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   */\n  init(viewController) {\n    if (typeof this.referenceSopUID !== 'undefined') {\n      logger.debug('Cannot initialise annotation twice');\n      return;\n    }\n\n    this.#viewController = viewController;\n    // set UID\n    this.referenceSopUID = viewController.getCurrentImageUid();\n    // set plane origin (not saved with file)\n    this.planeOrigin =\n      viewController.getOriginForImageUid(this.referenceSopUID);\n    // set plane points if not aquisition orientation\n    // (planePoints are saved with file if present)\n    if (!viewController.isAquisitionOrientation()) {\n      this.planePoints = viewController.getPlanePoints(\n        viewController.getCurrentPosition()\n      );\n    }\n  }\n\n  /**\n   * Check if an input view is compatible with the annotation.\n   *\n   * @param {PlaneHelper} planeHelper The input view to check.\n   * @returns {boolean} True if compatible view.\n   */\n  isCompatibleView(planeHelper) {\n    let res = false;\n\n    // TODO: add check for referenceSopUID\n\n    if (typeof this.planePoints === 'undefined') {\n      // non oriented view\n      if (planeHelper.isAquisitionOrientation()) {\n        res = true;\n      }\n    } else {\n      // oriented view: compare cosines (independent of slice index)\n      const cosines = planeHelper.getCosines();\n      const cosine1 = new Point3D(cosines[0], cosines[1], cosines[2]);\n      const cosine2 = new Point3D(cosines[3], cosines[4], cosines[5]);\n\n      if (cosine1.equals(this.planePoints[1]) &&\n        cosine2.equals(this.planePoints[2])) {\n        res = true;\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Set the associated view controller if it is compatible.\n   *\n   * @param {ViewController} viewController The view controller.\n   */\n  setViewController(viewController) {\n    // check uid\n    if (!viewController.includesImageUid(this.referenceSopUID)) {\n      return;\n    }\n    // check if same view\n    if (!this.isCompatibleView(viewController.getPlaneHelper())) {\n      return;\n    }\n    this.#viewController = viewController;\n\n    // set plane origin (not saved with file)\n    this.planeOrigin =\n      viewController.getOriginForImageUid(this.referenceSopUID);\n  }\n\n  /**\n   * Get the index of the plane origin.\n   *\n   * @returns {Index|undefined} The index.\n   */\n  #getOriginIndex() {\n    let res;\n    if (typeof this.#viewController !== 'undefined') {\n      let origin = this.planeOrigin;\n      if (typeof this.planePoints !== 'undefined') {\n        origin = this.planePoints[0];\n      }\n      const originPoint =\n        new Point([origin.getX(), origin.getY(), origin.getZ()]);\n      res = this.#viewController.getIndexFromPosition(originPoint);\n    }\n    return res;\n  }\n\n  /**\n   * Get the centroid of the math shape.\n   *\n   * @returns {Point|undefined} The 3D centroid point.\n   */\n  getCentroid() {\n    let res;\n    if (typeof this.#viewController !== 'undefined' &&\n      typeof this.mathShape.getCentroid !== 'undefined') {\n      // find the slice index of the annotation origin\n      const originIndex = this.#getOriginIndex();\n      const scrollDimIndex = this.#viewController.getScrollDimIndex();\n      const k = originIndex.getValues()[scrollDimIndex];\n      // shape center converted to 3D\n      const planePoint = this.mathShape.getCentroid();\n      res = this.#viewController.getPositionFromPlanePoint(planePoint, k);\n    }\n    return res;\n  }\n\n  /**\n   * Set the annotation text expression.\n   *\n   * @param {Object.<string, string>} labelText The list of label\n   *   texts indexed by modality.\n   */\n  setTextExpr(labelText) {\n    if (typeof this.#viewController !== 'undefined') {\n      const modality = this.#viewController.getModality();\n\n      if (typeof labelText[modality] !== 'undefined') {\n        this.textExpr = labelText[modality];\n      } else {\n        this.textExpr = labelText['*'];\n      }\n    } else {\n      logger.warn('Cannot set text expr without a view controller');\n    }\n  }\n\n  /**\n   * Get the annotation label text by applying the\n   *   text expression on the current quantification.\n   *\n   * @returns {string} The resulting text.\n   */\n  getText() {\n    return replaceFlags(this.textExpr, this.quantification);\n  }\n\n  /**\n   * Update the annotation quantification.\n   */\n  updateQuantification() {\n    if (typeof this.#viewController !== 'undefined' &&\n      typeof this.mathShape.quantify !== 'undefined') {\n      this.quantification = this.mathShape.quantify(\n        this.#viewController,\n        this.#getOriginIndex(),\n        getFlags(this.textExpr)\n      );\n    }\n  }\n\n  /**\n   * Get the math shape associated draw factory.\n   *\n   * @returns {object} The factory.\n   */\n  getFactory() {\n    let fac;\n    // check in user provided factories\n    if (typeof toolOptions.draw !== 'undefined') {\n      for (const factoryName in toolOptions.draw) {\n        const factory = toolOptions.draw[factoryName];\n        if (factory.supports(this.mathShape)) {\n          fac = new factory();\n          break;\n        }\n      }\n    }\n    // check in default factories\n    if (typeof fac === 'undefined') {\n      for (const factoryName in defaultToolOptions.draw) {\n        const factory = defaultToolOptions.draw[factoryName];\n        if (factory.supports(this.mathShape)) {\n          fac = new factory();\n          break;\n        }\n      }\n    }\n    if (typeof fac === 'undefined') {\n      logger.warn('No shape factory found for math shape');\n    }\n    return fac;\n  }\n}\n","import {logger} from '../utils/logger';\nimport {ListenerHandler} from '../utils/listen';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Annotation} from './annotation';\nimport {ViewController} from '../app/viewController';\n/* eslint-enable no-unused-vars */\n\n/**\n * Annotation group.\n */\nexport class AnnotationGroup {\n  /**\n   * @type {Annotation[]}\n   */\n  #list;\n\n  /**\n   * Annotation meta data.\n   *\n   * @type {Object<string, any>}\n   */\n  #meta = {};\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Editable flag.\n   *\n   * @type {boolean}\n   */\n  #editable;\n\n  /**\n   * Group colour as hex string. If defined, it will be used as\n   *   default colour for new annotations in draw tool.\n   *\n   * @type {string|undefined}\n   */\n  #colour;\n\n  /**\n   * @param {Annotation[]} [list] Optional list, will\n   *   create new if not provided.\n   */\n  constructor(list) {\n    if (typeof list !== 'undefined') {\n      this.#list = list;\n    } else {\n      this.#list = [];\n    }\n    this.#editable = true;\n  }\n\n  /**\n   * Get the annotation group as an array.\n   *\n   * @returns {Annotation[]} The array.\n   */\n  getList() {\n    return this.#list;\n  }\n\n  /**\n   * Get the number of annotations of this list.\n   *\n   * @returns {number} The number of annotations.\n   */\n  getLength() {\n    return this.#list.length;\n  }\n\n  /**\n   * Check if the annotation group is editable.\n   *\n   * @returns {boolean} True if editable.\n   */\n  isEditable() {\n    return this.#editable;\n  }\n\n  /**\n   * Set the annotation group editability.\n   *\n   * @param {boolean} flag True to make the annotation group editable.\n   */\n  setEditable(flag) {\n    this.#editable = flag;\n    /**\n     * Annotation group editable flag change event.\n     *\n     * @event AnnotationGroup#annotationgroupeditablechange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {boolean} data The value of the editable flag.\n     */\n    this.#fireEvent({\n      type: 'annotationgroupeditablechange',\n      data: flag\n    });\n  }\n\n  /**\n   * Get the group colour.\n   *\n   * @returns {string} The colour as hex string.\n   */\n  getColour() {\n    return this.#colour;\n  }\n\n  /**\n   * Set the group colour.\n   *\n   * @param {string} colour The colour as hex string.\n   */\n  setColour(colour) {\n    this.#colour = colour;\n  }\n\n  /**\n   * Add a new annotation.\n   *\n   * @param {Annotation} annotation The annotation to add.\n   */\n  add(annotation) {\n    this.#list.push(annotation);\n    /**\n     * Annotation add event.\n     *\n     * @event AnnotationGroup#annotationadd\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Annotation} data The added annnotation.\n     */\n    this.#fireEvent({\n      type: 'annotationadd',\n      data: annotation\n    });\n  }\n\n  /**\n   * Update an existing annotation.\n   *\n   * @param {Annotation} annotation The annotation to update.\n   * @param {string[]} [propKeys] Optional properties that got updated.\n   */\n  update(annotation, propKeys) {\n    const index = this.#list.findIndex((item) => item.id === annotation.id);\n    if (index !== -1) {\n      // update quantification if needed\n      if (propKeys.includes('mathShape') ||\n        propKeys.includes('textExpr')) {\n        annotation.updateQuantification();\n      }\n      // update list\n      this.#list[index] = annotation;\n      /**\n       * Annotation update event.\n       *\n       * @event AnnotationGroup#annotationupdate\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {Annotation} data The added annnotation.\n       * @property {string[]} keys The properties that were updated.\n       */\n      this.#fireEvent({\n        type: 'annotationupdate',\n        data: annotation,\n        keys: propKeys\n      });\n    } else {\n      logger.warn('Cannot find annotation to update');\n    }\n  }\n\n  /**\n   * Remove an annotation.\n   *\n   * @param {string} id The id of the annotation to remove.\n   */\n  remove(id) {\n    const index = this.#list.findIndex((item) => item.id === id);\n    if (index !== -1) {\n      const annotation = this.#list.splice(index, 1)[0];\n      /**\n       * Annotation update event.\n       *\n       * @event AnnotationGroup#annotationremove\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {Annotation} data The added annnotation.\n       * @property {string[]} keys The properties that were updated.\n       */\n      this.#fireEvent({\n        type: 'annotationremove',\n        data: annotation\n      });\n    } else {\n      logger.warn('Cannot find annotation to remove');\n    }\n  }\n\n  /**\n   * Set the associated view controller.\n   *\n   * @param {ViewController} viewController The associated view controller.\n   */\n  setViewController(viewController) {\n    for (const item of this.#list) {\n      item.setViewController(viewController);\n      item.updateQuantification();\n    }\n  }\n\n  /**\n   * Find an annotation.\n   *\n   * @param {string} id The id of the annotation to find.\n   * @returns {Annotation|undefined} The found annotation.\n   */\n  find(id) {\n    return this.#list.find((item) => item.id === id);\n  }\n\n  /**\n   * Get the meta data.\n   *\n   * @returns {Object<string, any>} The meta data.\n   */\n  getMeta() {\n    return this.#meta;\n  }\n\n  /**\n   * Check if this list contains a meta data value.\n   *\n   * @param {string} key The key to check.\n   * @returns {boolean} True if the meta data is present.\n   */\n  hasMeta(key) {\n    return typeof this.#meta[key] !== 'undefined';\n  }\n\n  /**\n   * Get a meta data value.\n   *\n   * @param {string} key The meta data key.\n   * @returns {string|object} The meta data value.\n   */\n  getMetaValue(key) {\n    return this.#meta[key];\n  }\n\n  /**\n   * Set a meta data.\n   *\n   * @param {string} key The meta data key.\n   * @param {string|object} value The value of the meta data.\n   */\n  setMetaValue(key, value) {\n    this.#meta[key] = value;\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n}\n","import {AnnotationGroup} from '../image/annotationGroup';\nimport {\n  RemoveAnnotationCommand,\n  UpdateAnnotationCommand\n} from '../tools/drawCommands';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Annotation} from '../image/annotation';\n/* eslint-enable no-unused-vars */\n\n/**\n * Draw controller.\n */\nexport class DrawController {\n\n  /**\n   * The annotation group.\n   *\n   * @type {AnnotationGroup}\n   */\n  #annotationGroup;\n\n  /**\n   * Get an annotation.\n   *\n   * @param {string} id The annotation id.\n   * @returns {Annotation|undefined} The annotation.\n   */\n  getAnnotation(id) {\n    return this.#annotationGroup.find(id);\n  }\n\n  /**\n   * Get the annotation group.\n   *\n   * @returns {AnnotationGroup} The list.\n   */\n  getAnnotationGroup() {\n    return this.#annotationGroup;\n  }\n\n  /**\n   * Check if the annotation group is editable.\n   *\n   * @returns {boolean} True if editable.\n   */\n  isAnnotationGroupEditable() {\n    return this.#annotationGroup.isEditable();\n  }\n\n  /**\n   * Set the annotation group editability.\n   *\n   * @param {boolean} flag True to make the annotation group editable.\n   */\n  setAnnotationGroupEditable(flag) {\n    this.#annotationGroup.setEditable(flag);\n  }\n\n  /**\n   * Add an annotation.\n   *\n   * @param {Annotation} annotation The annotation to add.\n   */\n  addAnnotation(annotation) {\n    this.#annotationGroup.add(annotation);\n  }\n\n  /**\n   * Update an anotation from the list.\n   *\n   * @param {Annotation} annotation The annotation to update.\n   * @param {string[]} [propKeys] Optional properties that got updated.\n   */\n  updateAnnotation(annotation, propKeys) {\n    this.#annotationGroup.update(annotation, propKeys);\n  }\n\n  /**\n   * Remove an anotation for the list.\n   *\n   * @param {string} id The id of the annotation to remove.\n   */\n  removeAnnotation(id) {\n    this.#annotationGroup.remove(id);\n  }\n\n  /**\n   * Remove an annotation via a remove command (triggers draw actions).\n   *\n   * @param {string} id The annotation id.\n   * @param {Function} exeCallback The undo stack callback.\n   */\n  removeAnnotationWithCommand(id, exeCallback) {\n    const annotation = this.getAnnotation(id);\n    if (typeof annotation === 'undefined') {\n      logger.warn(\n        'Cannot create remove command for undefined annotation: ' + id);\n      return;\n    }\n    // create remove annotation command\n    const command = new RemoveAnnotationCommand(annotation, this);\n    // add command to undo stack\n    exeCallback(command);\n    // execute command: triggers draw remove\n    command.execute();\n  }\n\n  /**\n   * Update an annotation via an update command (triggers draw actions).\n   *\n   * @param {string} id The annotation id.\n   * @param {object} originalProps The original annotation properties\n   *   that will be updated.\n   * @param {object} newProps The new annotation properties\n   *   that will replace the original ones.\n   * @param {Function} exeCallback The undo stack callback.\n   */\n  updateAnnotationWithCommand(id, originalProps, newProps, exeCallback) {\n    const annotation = this.getAnnotation(id);\n    if (typeof annotation === 'undefined') {\n      logger.warn(\n        'Cannot create update command for undefined annotation: ' + id);\n      return;\n    }\n    // create remove annotation command\n    const command = new UpdateAnnotationCommand(\n      annotation, originalProps, newProps, this);\n    // add command to undo stack\n    exeCallback(command);\n    // execute command: triggers draw remove\n    command.execute();\n  }\n\n  /**\n   * Remove all annotations via remove commands (triggers draw actions).\n   *\n   * @param {Function} exeCallback The undo stack callback.\n   */\n  removeAllAnnotationsWithCommand(exeCallback) {\n    for (const annotation of this.#annotationGroup.getList()) {\n      this.removeAnnotationWithCommand(annotation.id, exeCallback);\n    }\n  }\n\n  /**\n   * @param {AnnotationGroup} [group] Optional annotation group.\n   */\n  constructor(group) {\n    if (typeof group !== 'undefined') {\n      this.#annotationGroup = group;\n    } else {\n      this.#annotationGroup = new AnnotationGroup();\n    }\n  }\n\n  /**\n   * Check if the annotation group contains a meta data value.\n   *\n   * @param {string} key The key to check.\n   * @returns {boolean} True if the meta data is present.\n   */\n  hasAnnotationMeta(key) {\n    return this.#annotationGroup.hasMeta(key);\n  }\n\n  /**\n   * Set an annotation meta data.\n   *\n   * @param {string} key The meta data to set.\n   * @param {string} value The value of the meta data.\n   */\n  setAnnotationMeta(key, value) {\n    this.#annotationGroup.setMetaValue(key, value);\n  }\n\n} // class DrawController\n","import {ListenerHandler} from '../utils/listen';\nimport {DrawController} from '../app/drawController';\nimport {getScaledOffset} from './layerGroup';\nimport {InteractionEventNames} from './generic';\nimport {logger} from '../utils/logger';\nimport {toStringId} from '../utils/array';\nimport {precisionRound} from '../utils/string';\nimport {AddAnnotationCommand} from '../tools/drawCommands';\nimport {\n  isNodeWithId,\n  isPositionNode,\n  isNodeNameShape,\n  isNodeNameLabel\n} from '../tools/drawBounds';\nimport {Style} from '../gui/style';\nimport {Line} from '../math/line';\nimport {Rectangle} from '../math/rectangle';\nimport {ROI} from '../math/roi';\nimport {Protractor} from '../math/protractor';\nimport {Ellipse} from '../math/ellipse';\nimport {Circle} from '../math/circle';\nimport {Point2D} from '../math/point';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point, Point3D} from '../math/point';\nimport {Index} from '../math/index';\nimport {Vector3D} from '../math/vector';\nimport {Scalar2D, Scalar3D} from '../math/scalar';\nimport {PlaneHelper} from '../image/planeHelper';\nimport {Annotation} from '../image/annotation';\nimport {AnnotationGroup} from '../image/annotationGroup';\nimport {DrawShapeHandler} from '../tools/drawShapeHandler';\n/* eslint-enable no-unused-vars */\n\n/**\n * Debug function to output the layer hierarchy as text.\n *\n * @param {object} layer The Konva layer.\n * @param {string} prefix A display prefix (used in recursion).\n * @returns {string} A text representation of the hierarchy.\n */\n// function getHierarchyLog(layer, prefix) {\n//   if (typeof prefix === 'undefined') {\n//     prefix = '';\n//   }\n//   const kids = layer.getChildren();\n//   let log = prefix + '|__ ' + layer.name() + ': ' + layer.id() + '\\n';\n//   for (let i = 0; i < kids.length; ++i) {\n//     log += getHierarchyLog(kids[i], prefix + '    ');\n//   }\n//   return log;\n// }\n\n/**\n * Draw layer.\n */\nexport class DrawLayer {\n\n  /**\n   * The container div.\n   *\n   * @type {HTMLDivElement}\n   */\n  #containerDiv;\n\n  /**\n   * Konva stage.\n   *\n   * @type {Konva.Stage}\n   */\n  #konvaStage = null;\n\n  /**\n   * The layer base size as {x,y}.\n   *\n   * @type {Scalar2D}\n   */\n  #baseSize;\n\n  /**\n   * The layer base spacing as {x,y}.\n   *\n   * @type {Scalar2D}\n   */\n  #baseSpacing;\n\n  /**\n   * The layer fit scale.\n   *\n   * @type {Scalar2D}\n   */\n  #fitScale = {x: 1, y: 1};\n\n  /**\n   * The layer flip scale.\n   *\n   * @type {Scalar3D}\n   */\n  #flipScale = {x: 1, y: 1, z: 1};\n\n  /**\n   * The base layer offset.\n   *\n   * @type {Scalar2D}\n   */\n  #baseOffset = {x: 0, y: 0};\n\n  /**\n   * The view offset.\n   *\n   * @type {Scalar2D}\n   */\n  #viewOffset = {x: 0, y: 0};\n\n  /**\n   * The zoom offset.\n   *\n   * @type {Scalar2D}\n   */\n  #zoomOffset = {x: 0, y: 0};\n\n  /**\n   * The flip offset.\n   *\n   * @type {Scalar2D}\n   */\n  #flipOffset = {x: 0, y: 0};\n\n  /**\n   * The draw controller.\n   *\n   * @type {DrawController}\n   */\n  #drawController;\n\n  /**\n   * The plane helper.\n   *\n   * @type {PlaneHelper}\n   */\n  #planeHelper;\n\n  /**\n   * The associated data id.\n   *\n   * @type {string}\n   */\n  #dataId;\n\n  /**\n   * The reference layer id.\n   *\n   * @type {string}\n   */\n  #referenceLayerId;\n\n  /**\n   * Current position group id.\n   *\n   * @type {string|undefined}\n   */\n  #currentPosGroupId;\n\n  /**\n   * Draw shape handler.\n   *\n   * @type {DrawShapeHandler|undefined}\n   */\n  #shapeHandler;\n\n  /**\n   * Visible labels flag.\n   *\n   * @type {boolean}\n   */\n  #visibleLabels = true;\n\n  /**\n   * @param {HTMLDivElement} containerDiv The layer div, its id will be used\n   *   as this layer id.\n   */\n  constructor(containerDiv) {\n    this.#containerDiv = containerDiv;\n    // specific css class name\n    this.#containerDiv.className += ' drawLayer';\n  }\n\n  /**\n   * Set the draw shape handler.\n   *\n   * @param {DrawShapeHandler|undefined} handler The shape handler.\n   */\n  setShapeHandler(handler) {\n    this.#shapeHandler = handler;\n  }\n\n  /**\n   * Get the associated data id.\n   *\n   * @returns {string} The id.\n   */\n  getDataId() {\n    return this.#dataId;\n  }\n\n  /**\n   * Get the reference layer id.\n   *\n   * @returns {string} The id.\n   */\n  getReferenceLayerId() {\n    return this.#referenceLayerId;\n  }\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Get the Konva stage.\n   *\n   * @returns {Konva.Stage} The stage.\n   */\n  getKonvaStage() {\n    return this.#konvaStage;\n  }\n\n  /**\n   * Get the Konva layer.\n   *\n   * @returns {Konva.Layer} The layer.\n   */\n  getKonvaLayer() {\n    // there should only be one layer\n    return this.#konvaStage.getLayers()[0];\n  }\n\n  /**\n   * Get the draw controller.\n   *\n   * @returns {DrawController} The controller.\n   */\n  getDrawController() {\n    return this.#drawController;\n  }\n\n  /**\n   * Set the plane helper.\n   *\n   * @param {PlaneHelper} helper The helper.\n   */\n  setPlaneHelper(helper) {\n    this.#planeHelper = helper;\n  }\n\n  // common layer methods [start] ---------------\n\n  /**\n   * Get the id of the layer.\n   *\n   * @returns {string} The string id.\n   */\n  getId() {\n    return this.#containerDiv.id;\n  }\n\n  /**\n   * Remove the HTML element from the DOM.\n   */\n  removeFromDOM() {\n    this.#containerDiv.remove();\n  }\n\n  /**\n   * Get the layer base size (without scale).\n   *\n   * @returns {Scalar2D} The size as {x,y}.\n   */\n  getBaseSize() {\n    return this.#baseSize;\n  }\n\n  /**\n   * Get the layer opacity.\n   *\n   * @returns {number} The opacity ([0:1] range).\n   */\n  getOpacity() {\n    return this.#konvaStage.opacity();\n  }\n\n  /**\n   * Set the layer opacity.\n   *\n   * @param {number} alpha The opacity ([0:1] range).\n   */\n  setOpacity(alpha) {\n    this.#konvaStage.opacity(Math.min(Math.max(alpha, 0), 1));\n  }\n\n  /**\n   * Add a flip offset along the layer X axis.\n   */\n  addFlipOffsetX() {\n    // flip offset\n    const scale = this.#konvaStage.scale();\n    const size = this.#konvaStage.size();\n    this.#flipOffset.x += size.width / scale.x;\n    // apply\n    const offset = this.#konvaStage.offset();\n    offset.x += this.#flipOffset.x;\n    this.#konvaStage.offset(offset);\n  }\n\n  /**\n   * Add a flip offset along the layer Y axis.\n   */\n  addFlipOffsetY() {\n    // flip offset\n    const scale = this.#konvaStage.scale();\n    const size = this.#konvaStage.size();\n    this.#flipOffset.y += size.height / scale.y;\n    // apply\n    const offset = this.#konvaStage.offset();\n    offset.y += this.#flipOffset.y;\n    this.#konvaStage.offset(offset);\n  }\n\n  /**\n   * Flip the scale along the layer X axis.\n   */\n  flipScaleX() {\n    this.#flipScale.x *= -1;\n  }\n\n  /**\n   * Flip the scale along the layer Y axis.\n   */\n  flipScaleY() {\n    this.#flipScale.y *= -1;\n  }\n\n  /**\n   * Flip the scale along the layer Z axis.\n   */\n  flipScaleZ() {\n    this.#flipScale.z *= -1;\n  }\n\n  /**\n   * Set the layer scale.\n   *\n   * @param {Scalar3D} newScale The scale as {x,y,z}.\n   * @param {Point3D} [center] The scale center.\n   */\n  setScale(newScale, center) {\n    const orientedNewScale =\n      this.#planeHelper.getTargetOrientedPositiveXYZ({\n        x: newScale.x * this.#flipScale.x,\n        y: newScale.y * this.#flipScale.y,\n        z: newScale.z * this.#flipScale.z,\n      });\n    const finalNewScale = {\n      x: this.#fitScale.x * orientedNewScale.x,\n      y: this.#fitScale.y * orientedNewScale.y\n    };\n\n    const offset = this.#konvaStage.offset();\n\n    if (Math.abs(newScale.x) === 1 &&\n      Math.abs(newScale.y) === 1 &&\n      Math.abs(newScale.z) === 1) {\n      // reset zoom offset for scale=1\n      const resetOffset = {\n        x: offset.x - this.#zoomOffset.x,\n        y: offset.y - this.#zoomOffset.y\n      };\n      // store new offset\n      this.#zoomOffset = {x: 0, y: 0};\n      this.#konvaStage.offset(resetOffset);\n    } else {\n      if (typeof center !== 'undefined') {\n        let worldCenter = this.#planeHelper.getPlaneOffsetFromOffset3D({\n          x: center.getX(),\n          y: center.getY(),\n          z: center.getZ()\n        });\n        // center was obtained with viewLayer.displayToMainPlanePos\n        // compensated for baseOffset\n        // TODO: justify...\n        worldCenter = {\n          x: worldCenter.x + this.#baseOffset.x,\n          y: worldCenter.y + this.#baseOffset.y\n        };\n\n        const newOffset = getScaledOffset(\n          offset, this.#konvaStage.scale(), finalNewScale, worldCenter);\n\n        const newZoomOffset = {\n          x: this.#zoomOffset.x + newOffset.x - offset.x,\n          y: this.#zoomOffset.y + newOffset.y - offset.y\n        };\n        // store new offset\n        this.#zoomOffset = newZoomOffset;\n        this.#konvaStage.offset(newOffset);\n      }\n    }\n\n    this.#konvaStage.scale(finalNewScale);\n    // update labels\n    this.#updateLabelScale(finalNewScale);\n  }\n\n  /**\n   * Initialise the layer scale.\n   *\n   * @param {Scalar3D} newScale The scale as {x,y,z}.\n   * @param {Scalar2D} absoluteZoomOffset The zoom offset as {x,y}\n   *   without the fit scale (as provided by getAbsoluteZoomOffset).\n   */\n  initScale(newScale, absoluteZoomOffset) {\n    const orientedNewScale = this.#planeHelper.getTargetOrientedPositiveXYZ({\n      x: newScale.x * this.#flipScale.x,\n      y: newScale.y * this.#flipScale.y,\n      z: newScale.z * this.#flipScale.z,\n    });\n    const finalNewScale = {\n      x: this.#fitScale.x * orientedNewScale.x,\n      y: this.#fitScale.y * orientedNewScale.y\n    };\n    this.#konvaStage.scale(finalNewScale);\n\n    this.#zoomOffset = {\n      x: absoluteZoomOffset.x / this.#fitScale.x,\n      y: absoluteZoomOffset.y / this.#fitScale.y\n    };\n    const offset = this.#konvaStage.offset();\n    this.#konvaStage.offset({\n      x: offset.x + this.#zoomOffset.x,\n      y: offset.y + this.#zoomOffset.y\n    });\n  }\n\n  /**\n   * Set the layer offset.\n   *\n   * @param {Scalar3D} newOffset The offset as {x,y,z}.\n   */\n  setOffset(newOffset) {\n    const planeNewOffset =\n      this.#planeHelper.getPlaneOffsetFromOffset3D(newOffset);\n    this.#konvaStage.offset({\n      x: planeNewOffset.x +\n        this.#viewOffset.x +\n        this.#baseOffset.x +\n        this.#zoomOffset.x +\n        this.#flipOffset.x,\n      y: planeNewOffset.y +\n        this.#viewOffset.y +\n        this.#baseOffset.y +\n        this.#zoomOffset.y +\n        this.#flipOffset.y\n    });\n  }\n\n  /**\n   * Set the base layer offset. Updates the layer offset.\n   *\n   * @param {Vector3D} scrollOffset The scroll offset vector.\n   * @param {Vector3D} planeOffset The plane offset vector.\n   * @returns {boolean} True if the offset was updated.\n   */\n  setBaseOffset(scrollOffset, planeOffset) {\n    const scrollDimIndex = this.#planeHelper.getNativeScrollDimIndex();\n    const newOffset = this.#planeHelper.getPlaneOffsetFromOffset3D({\n      x: scrollDimIndex === 0 ? scrollOffset.getX() : planeOffset.getX(),\n      y: scrollDimIndex === 1 ? scrollOffset.getY() : planeOffset.getY(),\n      z: scrollDimIndex === 2 ? scrollOffset.getZ() : planeOffset.getZ(),\n    });\n    const needsUpdate = this.#baseOffset.x !== newOffset.x ||\n      this.#baseOffset.y !== newOffset.y;\n    // reset offset if needed\n    if (needsUpdate) {\n      const offset = this.#konvaStage.offset();\n      this.#konvaStage.offset({\n        x: offset.x - this.#baseOffset.x + newOffset.x,\n        y: offset.y - this.#baseOffset.y + newOffset.y\n      });\n      this.#baseOffset = newOffset;\n    }\n    return needsUpdate;\n  }\n\n  /**\n   * Display the layer.\n   *\n   * @param {boolean} flag Whether to display the layer or not.\n   */\n  display(flag) {\n    this.#containerDiv.style.display = flag ? '' : 'none';\n  }\n\n  /**\n   * Check if the layer is visible.\n   *\n   * @returns {boolean} True if the layer is visible.\n   */\n  isVisible() {\n    return this.#containerDiv.style.display === '';\n  }\n\n  /**\n   * Draw the content (imageData) of the layer.\n   * The imageData variable needs to be set.\n   */\n  draw() {\n    this.#konvaStage.draw();\n  }\n\n  /**\n   * Initialise the layer: set the canvas and context.\n   *\n   * @param {Scalar2D} size The image size as {x,y}.\n   * @param {Scalar2D} spacing The image spacing as {x,y}.\n   * @param {string} refLayerId The reference image dataId.\n   */\n  initialise(size, spacing, refLayerId) {\n    // set locals\n    this.#baseSize = size;\n    this.#baseSpacing = spacing;\n    this.#referenceLayerId = refLayerId;\n\n    // create stage\n    this.#konvaStage = new Konva.Stage({\n      container: this.#containerDiv,\n      width: this.#baseSize.x,\n      height: this.#baseSize.y,\n      listening: false\n    });\n    // reset style\n    // (avoids a not needed vertical scrollbar)\n    this.#konvaStage.getContent().setAttribute('style', '');\n\n    // create layer\n    const konvaLayer = new Konva.Layer({\n      listening: false,\n      visible: true\n    });\n    this.#konvaStage.add(konvaLayer);\n  }\n\n  /**\n   * Set the annotation group.\n   *\n   * @param {AnnotationGroup} annotationGroup The annotation group.\n   * @param {string} dataId The associated data id.\n   * @param {object} exeCallback The undo stack callback.\n   */\n  setAnnotationGroup(annotationGroup, dataId, exeCallback) {\n    this.#dataId = dataId;\n    // local listeners\n    annotationGroup.addEventListener('annotationadd', (event) => {\n      // draw annotation\n      this.#addAnnotationDraw(event.data, true);\n      this.getKonvaLayer().draw();\n    });\n    annotationGroup.addEventListener('annotationupdate', (event) => {\n      // update annotation draw\n      this.#updateAnnotationDraw(event.data);\n      this.getKonvaLayer().draw();\n    });\n    annotationGroup.addEventListener('annotationremove', (event) => {\n      // remove annotation draw\n      this.#removeAnnotationDraw(event.data);\n      this.getKonvaLayer().draw();\n    });\n    annotationGroup.addEventListener(\n      'annotationgroupeditablechange',\n      (event) => {\n        this.activateCurrentPositionShapes(event.data);\n      }\n    );\n\n    // create draw controller\n    this.#drawController = new DrawController(annotationGroup);\n\n    // annotations are allready in the annotation list,\n    // -> no need to add them, just draw and save command\n    if (annotationGroup.getLength() !== 0) {\n      for (const annotation of annotationGroup.getList()) {\n        // draw annotation\n        this.#addAnnotationDraw(annotation, false);\n        // create the draw command\n        const command = new AddAnnotationCommand(\n          annotation, this.getDrawController());\n        // add command to undo stack\n        exeCallback(command);\n      }\n    }\n  }\n\n  /**\n   * Activate shapes at current position.\n   *\n   * @param {boolean} flag The flag to activate or not.\n   */\n  activateCurrentPositionShapes(flag) {\n    const konvaLayer = this.getKonvaLayer();\n\n    // stop stage listening\n    this.#konvaStage.listening(false);\n\n    if (typeof this.#shapeHandler !== 'undefined') {\n      // reset shape editor (remove anchors)\n      this.#shapeHandler.disableAndResetEditor();\n      // remove listeners for all position groups\n      const allPosGroups = konvaLayer.getChildren();\n      for (const posGroup of allPosGroups) {\n        if (posGroup instanceof Konva.Group) {\n          posGroup.getChildren().forEach((group) => {\n            if (group instanceof Konva.Group) {\n              this.#shapeHandler.removeShapeListeners(group);\n            }\n          });\n        }\n      }\n    }\n\n    // activate shape listeners if possible\n    const drawController = this.getDrawController();\n    if (flag &&\n      drawController.getAnnotationGroup().isEditable()) {\n      // start stage listening\n      this.#konvaStage.listening(true);\n      // shape groups at the current position\n      const shapeGroups =\n        this.#getCurrentPosGroup().getChildren();\n      // listen if we have shapes\n      if (shapeGroups.length !== 0) {\n        konvaLayer.listening(true);\n      }\n      // add listeners for position group\n      if (typeof this.#shapeHandler !== 'undefined') {\n        shapeGroups.forEach((group) => {\n          if (group instanceof Konva.Group) {\n            const annotation = drawController.getAnnotation(group.id());\n            this.#shapeHandler.addShapeGroupListeners(group, annotation, this);\n          }\n        });\n      }\n    }\n\n    konvaLayer.draw();\n  }\n\n  /**\n   * Get the position group id for an annotation.\n   *\n   * @param {Annotation} annotation The target annotation.\n   * @returns {string|undefined} The group id.\n   */\n  #getAnnotationPosGroupId(annotation) {\n    let points;\n    // annotation planePoints are only present\n    // for non aquisition plane\n    if (typeof annotation.planePoints !== 'undefined') {\n      // use plane points\n      points = annotation.planePoints;\n    } else {\n      // just use plane origin\n      points = [annotation.planeOrigin];\n    }\n    return this.#getPositionId(points);\n  }\n\n  /**\n   * Get a string id from input plane points.\n   *\n   * @param {Point3D[]} points A list of points that defined a plane.\n   * @returns {string} The string id.\n   */\n  #getPositionId(points) {\n    let res = '';\n    for (const point of points) {\n      if (res.length !== 0) {\n        res += '-';\n      }\n      const posValues = [\n        precisionRound(point.getX(), 2),\n        precisionRound(point.getY(), 2),\n        precisionRound(point.getZ(), 2),\n      ];\n      res += toStringId(posValues);\n    }\n    return res;\n  }\n\n  /**\n   * Find the shape group associated to an annotation.\n   *\n   * @param {Annotation} annotation The annotation.\n   * @returns {Konva.Group|undefined} The shape group.\n   */\n  #findShapeGroup(annotation) {\n    let res;\n\n    const posGroupId = this.#getAnnotationPosGroupId(annotation);\n    const layerChildren = this.getKonvaLayer().getChildren(\n      isNodeWithId(posGroupId));\n    if (layerChildren.length !== 0) {\n      const posGroup = layerChildren[0];\n      if (!(posGroup instanceof Konva.Group)) {\n        return;\n      }\n      const posChildren = posGroup.getChildren(\n        isNodeWithId(annotation.id));\n      if (posChildren.length !== 0 &&\n        posChildren[0] instanceof Konva.Group) {\n        res = posChildren[0];\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Draw an annotation: create the shape group and add it to\n   *   the Konva layer.\n   *\n   * @param {Annotation} annotation The annotation to draw.\n   * @param {boolean} visible The position group visibility.\n   */\n  #addAnnotationDraw(annotation, visible) {\n    // check for compatible view\n    if (!annotation.isCompatibleView(this.#planeHelper)) {\n      return;\n    }\n    const posGroupId = this.#getAnnotationPosGroupId(annotation);\n    // Get or create position-group if it does not exist and\n    // append it to konvaLayer\n    let posGroup = this.getKonvaLayer().getChildren(\n      isNodeWithId(posGroupId))[0];\n    if (typeof posGroup === 'undefined') {\n      posGroup = new Konva.Group({\n        id: posGroupId,\n        name: 'position-group',\n        visible: visible\n      });\n      this.getKonvaLayer().add(posGroup);\n    }\n    if (!(posGroup instanceof Konva.Group)) {\n      return;\n    };\n\n    const style = new Style();\n    const stage = this.getKonvaStage();\n    style.setZoomScale(stage.scale());\n\n    // shape group (use first one since it will be removed from\n    // the group when we change it)\n    const factory = annotation.getFactory();\n    const shapeGroup = factory.createShapeGroup(annotation, style);\n    // add group to posGroup (switches its parent)\n    posGroup.add(shapeGroup);\n\n    // activate shape if possible\n    if (visible &&\n      typeof this.#shapeHandler !== 'undefined'\n    ) {\n      this.#shapeHandler.addShapeGroupListeners(shapeGroup, annotation, this);\n    }\n    // set label visibility\n    this.setLabelVisibility(shapeGroup);\n  }\n\n  /**\n   * Remove an annotation draw.\n   *\n   * @param {Annotation} annotation The annotation to remove.\n   * @returns {boolean} True if the shape group has been found and removed.\n   */\n  #removeAnnotationDraw(annotation) {\n    const shapeGroup = this.#findShapeGroup(annotation);\n    if (!(shapeGroup instanceof Konva.Group)) {\n      logger.debug('No shape group to remove');\n      return false;\n    };\n    shapeGroup.remove();\n    return true;\n  }\n\n  /**\n   * Update an annotation draw.\n   *\n   * @param {Annotation} annotation The annotation to update.\n   */\n  #updateAnnotationDraw(annotation) {\n    if (this.#removeAnnotationDraw(annotation)) {\n      this.#addAnnotationDraw(annotation, true);\n    }\n  }\n\n  /**\n   * Fit the layer to its parent container.\n   *\n   * @param {Scalar2D} containerSize The container size as {x,y}.\n   * @param {number} divToWorldSizeRatio The div to world size ratio.\n   * @param {Scalar2D} fitOffset The fit offset as {x,y}.\n   */\n  fitToContainer(containerSize, divToWorldSizeRatio, fitOffset) {\n    // update konva\n    this.#konvaStage.width(containerSize.x);\n    this.#konvaStage.height(containerSize.y);\n\n    // fit scale\n    const divToImageSizeRatio = {\n      x: divToWorldSizeRatio * this.#baseSpacing.x,\n      y: divToWorldSizeRatio * this.#baseSpacing.y\n    };\n    // #scale = inputScale * fitScale * flipScale\n    // flipScale does not change here, we can omit it\n    // newScale = (#scale / fitScale) * newFitScale\n    const newScale = {\n      x: this.#konvaStage.scale().x * divToImageSizeRatio.x / this.#fitScale.x,\n      y: this.#konvaStage.scale().y * divToImageSizeRatio.y / this.#fitScale.y\n    };\n\n    // set scales if different from previous\n    if (this.#konvaStage.scale().x !== newScale.x ||\n      this.#konvaStage.scale().y !== newScale.y) {\n      this.#fitScale = divToImageSizeRatio;\n      this.#konvaStage.scale(newScale);\n    }\n\n    // view offset\n    const newViewOffset = {\n      x: fitOffset.x / divToImageSizeRatio.x,\n      y: fitOffset.y / divToImageSizeRatio.y\n    };\n    // flip offset\n    const scaledImageSize = {\n      x: containerSize.x / divToImageSizeRatio.x,\n      y: containerSize.y / divToImageSizeRatio.y\n    };\n    const newFlipOffset = {\n      x: this.#flipOffset.x !== 0 ? scaledImageSize.x : 0,\n      y: this.#flipOffset.y !== 0 ? scaledImageSize.y : 0,\n    };\n\n    // set offsets if different from previous\n    if (this.#viewOffset.x !== newViewOffset.x ||\n      this.#viewOffset.y !== newViewOffset.y ||\n      this.#flipOffset.x !== newFlipOffset.x ||\n      this.#flipOffset.y !== newFlipOffset.y) {\n      // update global offset\n      this.#konvaStage.offset({\n        x: this.#konvaStage.offset().x +\n          newViewOffset.x - this.#viewOffset.x +\n          newFlipOffset.x - this.#flipOffset.x,\n        y: this.#konvaStage.offset().y +\n          newViewOffset.y - this.#viewOffset.y +\n          newFlipOffset.y - this.#flipOffset.y,\n      });\n      // update private local offsets\n      this.#flipOffset = newFlipOffset;\n      this.#viewOffset = newViewOffset;\n    }\n  }\n\n  /**\n   * Check the visibility of an annotation.\n   *\n   * @param {string} id The id of the annotation.\n   * @returns {boolean} True if the annotation is visible.\n   */\n  isAnnotationVisible(id) {\n    // get the group (annotation and group have same id)\n    const group = this.#getGroup(id);\n    if (typeof group === 'undefined') {\n      return false;\n    }\n    // get visibility\n    return group.isVisible();\n  }\n\n  /**\n   * Set the visibility of an annotation.\n   *\n   * @param {string} id The id of the annotation.\n   * @param {boolean} [visible] True to set to visible,\n   *   will toggle visibility if not defined.\n   * @returns {boolean} False if the annotation shape cannot be found.\n   */\n  setAnnotationVisibility(id, visible) {\n    // get the group (annotation and group have same id)\n    const group = this.#getGroup(id);\n    if (typeof group === 'undefined') {\n      return false;\n    }\n    // if not set, toggle visibility\n    if (typeof visible === 'undefined') {\n      visible = !group.isVisible();\n    }\n    group.visible(visible);\n\n    // udpate\n    this.draw();\n\n    return true;\n  }\n\n  /**\n   * Set the visibility of all labels.\n   *\n   * @param {boolean} [visible] True to set to visible,\n   *   will toggle visibility if not defined.\n   */\n  setLabelsVisibility(visible) {\n    this.#visibleLabels = visible;\n\n    const posGroups = this.getKonvaLayer().getChildren();\n    for (const posGroup of posGroups) {\n      if (posGroup instanceof Konva.Group) {\n        const shapeGroups = posGroup.getChildren();\n        for (const shapeGroup of shapeGroups) {\n          if (shapeGroup instanceof Konva.Group) {\n            this.#setLabelVisibility(shapeGroup, visible);\n          }\n        }\n      }\n    }\n  }\n\n  /**\n   * Set a shape group label visibility.\n   *\n   * @param {Konva.Group} shapeGroup The shape group.\n   * @param {boolean} [visible] True to set to visible,\n   *   will toggle visibility if not defined.\n   */\n  #setLabelVisibility(shapeGroup, visible) {\n    const label = shapeGroup.getChildren(isNodeNameLabel)[0];\n    if (!(label instanceof Konva.Label)) {\n      return;\n    }\n    // if not set, toggle visibility\n    if (typeof visible === 'undefined') {\n      visible = !label.isVisible();\n    }\n    // set visible only for non empty text\n    if (typeof label.getText() !== 'undefined' &&\n      label.getText().text().length !== 0) {\n      label.visible(visible);\n      const connector = shapeGroup.getChildren(node =>\n        (node.className === 'Line') && node.name() === 'connector')[0];\n      if (connector) {\n        connector.visible(visible);\n      }\n    }\n  }\n\n  /**\n   * Set a shape group label visibility according to\n   *  this layer setting.\n   *\n   * @param {Konva.Group} shapeGroup The shape group.\n   */\n  setLabelVisibility(shapeGroup) {\n    this.#setLabelVisibility(shapeGroup, this.#visibleLabels);\n  }\n\n  /**\n   * Delete a Draw from the stage.\n   *\n   * @deprecated Since v0.34, please switch to `annotationGroup.remove`.\n   * @param {string} _id The id of the group to delete.\n   * @param {Function} _exeCallback The callback to call once the\n   *  DeleteCommand has been executed.\n   */\n  deleteDraw(_id, _exeCallback) {\n    // does nothing\n  }\n\n  /**\n   * Delete all Draws from the stage.\n   *\n   * @deprecated Since v0.34, please switch to `annotationGroup.remove`.\n   * @param {Function} _exeCallback The callback to call once the\n   *  DeleteCommand has been executed.\n   */\n  deleteDraws(_exeCallback) {\n    // does nothing\n  }\n\n  /**\n   * Get the total number of draws of this layer\n   * (at all positions).\n   *\n   * @returns {number|undefined} The total number of draws.\n   */\n  getNumberOfDraws() {\n    const posGroups = this.getKonvaLayer().getChildren();\n    let count = 0;\n    for (const posGroup of posGroups) {\n      if (posGroup instanceof Konva.Group) {\n        count += posGroup.getChildren().length;\n      }\n    }\n    return count;\n  }\n\n  /**\n   * Enable and listen to container interaction events.\n   */\n  bindInteraction() {\n    this.#konvaStage.listening(true);\n    // allow pointer events\n    this.#containerDiv.style.pointerEvents = 'auto';\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      this.#containerDiv.addEventListener(names[i], this.#fireEvent);\n    }\n  }\n\n  /**\n   * Disable and stop listening to container interaction events.\n   */\n  unbindInteraction() {\n    this.#konvaStage.listening(false);\n    // disable pointer events\n    this.#containerDiv.style.pointerEvents = 'none';\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      this.#containerDiv.removeEventListener(names[i], this.#fireEvent);\n    }\n  }\n\n  /**\n   * Set the current position.\n   *\n   * @param {Point} position The new position.\n   * @param {Index} [index] Optional coresponding index.\n   * @returns {boolean} True if the position was updated.\n   */\n  setCurrentPosition(position, index) {\n    if (typeof index === 'undefined') {\n      index = this.#planeHelper.worldToIndex(position);\n    }\n    const planePoints = this.#planeHelper.getPlanePoints(position);\n    let points;\n    if (this.#planeHelper.isAquisitionOrientation()) {\n      // just use plane origin\n      points = [planePoints[0]];\n    } else {\n      // use plane points\n      points = planePoints;\n    }\n    const posGroupId = this.#getPositionId(points);\n\n    this.#activateDrawLayer(posGroupId);\n    // TODO: add check\n    this.#fireEvent({\n      type: 'positionchange',\n      value: [\n        index.getValues(),\n        position.getValues(),\n      ],\n      valid: true\n    });\n\n    return true;\n  }\n\n  /**\n   * Activate the current draw layer.\n   *\n   * @param {string} posGroupId The position group ID.\n   */\n  #activateDrawLayer(posGroupId) {\n    this.#currentPosGroupId = posGroupId;\n\n    // get all position groups\n    const posGroups = this.getKonvaLayer().getChildren(isPositionNode);\n    // reset or set the visible property\n    let visible;\n    for (let i = 0, leni = posGroups.length; i < leni; ++i) {\n      visible = false;\n      if (typeof posGroupId !== 'undefined' &&\n        posGroups[i].id() === posGroupId) {\n        visible = true;\n      }\n      // group members inherit the visible property\n      posGroups[i].visible(visible);\n    }\n\n    // show current draw layer\n    this.getKonvaLayer().draw();\n  }\n\n  /**\n   * Get the current position group.\n   *\n   * @returns {Konva.Group|undefined} The Konva group.\n   */\n  #getCurrentPosGroup() {\n    if (typeof this.#currentPosGroupId === 'undefined') {\n      return;\n    }\n    // get position groups\n    const posGroups = this.getKonvaLayer().getChildren((node) => {\n      return node.id() === this.#currentPosGroupId;\n    });\n    // if one group, use it\n    // if no group, create one\n    let posGroup;\n    if (posGroups.length === 1) {\n      if (posGroups[0] instanceof Konva.Group) {\n        posGroup = posGroups[0];\n      }\n    } else if (posGroups.length === 0) {\n      posGroup = new Konva.Group();\n      posGroup.name('position-group');\n      posGroup.id(this.#currentPosGroupId);\n      posGroup.visible(true); // dont inherit\n      // add new group to layer\n      this.getKonvaLayer().add(posGroup);\n    } else {\n      logger.warn('Unexpected number of draw position groups');\n    }\n    // return\n    return posGroup;\n  }\n\n  /**\n   * Get a Konva group using its id.\n   *\n   * @param {string} id The group id.\n   * @returns {Konva.Group|undefined} The Konva group.\n   */\n  #getGroup(id) {\n    return this.getKonvaLayer().findOne('#' + id);\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    event.srclayerid = this.getId();\n    event.dataid = this.#dataId;\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  // common layer methods [end] ---------------\n\n  /**\n   * Update label scale: compensate for it so\n   *   that label size stays visually the same.\n   *\n   * @param {Scalar2D} scale The scale to compensate for as {x,y}.\n   */\n  #updateLabelScale(scale) {\n    // same formula as in labelFactory::create\n    // compensate for scale and times 2 so that font 10 looks like a 10\n    const ratioX = 2 / scale.x;\n    const ratioY = 2 / scale.y;\n    // compensate scale for labels\n    const labels = this.#konvaStage.find('Label');\n    for (let i = 0; i < labels.length; ++i) {\n      labels[i].scale({x: ratioX, y: ratioY});\n    }\n  }\n\n} // DrawLayer class\n\n// *************************\n// legacy code to allow to convert old state into annotation\n// *************************\n\n/**\n * Draw meta data.\n */\nexport class DrawMeta {\n  /**\n   * Draw quantification.\n   *\n   * @type {object}\n   */\n  quantification;\n\n  /**\n   * Draw text expression. Can contain variables surrounded with '{}' that will\n   * be extracted from the quantification object.\n   *\n   * @type {string}\n   */\n  textExpr;\n}\n\n/**\n * Draw details.\n */\nexport class DrawDetails {\n  /**\n   * The draw ID.\n   *\n   * @type {number}\n   */\n  id;\n\n  /**\n   * The draw position: an Index converted to string.\n   *\n   * @type {string}\n   */\n  position;\n\n  /**\n   * The draw type.\n   *\n   * @type {string}\n   */\n  type;\n\n  /**\n   * The draw color: for example 'green', '#00ff00' or 'rgb(0,255,0)'.\n   *\n   * @type {string}\n   */\n  color;\n\n  /**\n   * The draw meta.\n   *\n   * @type {DrawMeta}\n   */\n  meta;\n}\n\n/**\n * Convert a KonvaLayer object to a list of annotations.\n *\n * @param {Array} drawings An array of drawings stored\n *   with 'KonvaLayer().toObject()'.\n * @param {DrawDetails[]} drawingsDetails An array of drawings details.\n * @returns {Annotation[]} The associated list of annotations.\n */\nexport function konvaToAnnotation(drawings, drawingsDetails) {\n  const annotations = [];\n\n  // regular Konva deserialize\n  const stateLayer = Konva.Node.create(drawings);\n\n  // get all position groups\n  const statePosGroups = stateLayer.getChildren(isPositionNode);\n\n  for (let i = 0, leni = statePosGroups.length; i < leni; ++i) {\n    const statePosGroup = statePosGroups[i];\n    const statePosKids = statePosGroup.getChildren();\n    for (let j = 0, lenj = statePosKids.length; j < lenj; ++j) {\n      const annotation = new Annotation();\n\n      // shape group (use first one since it will be removed from\n      // the group when we change it)\n      const stateGroup = statePosKids[0];\n      // annotation id\n      annotation.id = stateGroup.id();\n\n      // shape\n      const shape = stateGroup.getChildren(isNodeNameShape)[0];\n      // annotation colour\n      annotation.colour = shape.stroke();\n\n      if (stateGroup.name() === 'line-group') {\n        const points = shape.points();\n        annotation.mathShape = new Point2D(points[0], points[1]);\n        annotation.referencePoints = [\n          new Point2D(points[2], points[3])\n        ];\n      } else if (stateGroup.name() === 'ruler-group') {\n        const points = shape.points();\n        annotation.mathShape = new Line(\n          new Point2D(points[0], points[1]),\n          new Point2D(points[2], points[3])\n        );\n      } else if (stateGroup.name() === 'rectangle-group') {\n        annotation.mathShape = new Rectangle(\n          new Point2D(shape.x(), shape.y()),\n          new Point2D(shape.x() + shape.width(), shape.y() + shape.height())\n        );\n      } else if (stateGroup.name() === 'roi-group') {\n        const points = shape.points();\n        const pointsArray = [];\n        for (let i = 0; i < points.length; i = i + 2) {\n          pointsArray.push(new Point2D(points[i], points[i + 1]));\n        }\n        annotation.mathShape = new ROI(pointsArray);\n      } else if (stateGroup.name() === 'freeHand-group') {\n        logger.warn('Converting freehand into ROI shape');\n        const points = shape.points();\n        const pointsArray = [];\n        for (let i = 0; i < points.length; i = i + 2) {\n          pointsArray.push(new Point2D(points[i], points[i + 1]));\n        }\n        annotation.mathShape = new ROI(pointsArray);\n      } else if (stateGroup.name() === 'protractor-group') {\n        const points = shape.points();\n        annotation.mathShape = new Protractor([\n          new Point2D(points[0], points[1]),\n          new Point2D(points[2], points[3]),\n          new Point2D(points[4], points[5])\n        ]);\n      } else if (stateGroup.name() === 'ellipse-group') {\n        const absPosition = shape.absolutePosition();\n        annotation.mathShape = new Ellipse(\n          new Point2D(absPosition.x, absPosition.y),\n          shape.radiusX(),\n          shape.radiusY()\n        );\n      } else if (stateGroup.name() === 'circle-group') {\n        const absPosition = shape.absolutePosition();\n        annotation.mathShape = new Circle(\n          new Point2D(absPosition.x, absPosition.y),\n          shape.radius()\n        );\n      }\n\n      // details\n      if (drawingsDetails) {\n        const details = drawingsDetails[stateGroup.id()];\n        annotation.textExpr = details.meta.textExpr;\n        annotation.quantification = details.meta.quantification;\n      }\n\n      annotations.push(annotation);\n    }\n  }\n\n  return annotations;\n}\n","import {Index} from '../math/index';\nimport {Point} from '../math/point';\nimport {Vector3D} from '../math/vector';\nimport {viewEventNames} from '../image/view';\nimport {ListenerHandler} from '../utils/listen';\nimport {logger} from '../utils/logger';\nimport {precisionRound} from '../utils/string';\nimport {ViewLayer} from './viewLayer';\nimport {DrawLayer} from './drawLayer';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Point2D, Point3D} from '../math/point';\nimport {Scalar2D, Scalar3D} from '../math/scalar';\nimport {PositionHelper} from '../image/positionHelper';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get the layer div id.\n *\n * @param {string} groupDivId The layer group div id.\n * @param {number} layerIndex The layer index.\n * @returns {string} A string id.\n */\nexport function getLayerDivId(groupDivId, layerIndex) {\n  return groupDivId + '-layer-' + layerIndex;\n}\n\n/**\n * Get the layer details from a div id.\n *\n * @param {string} idString The layer div id.\n * @returns {object} The layer details as {groupDivId, layerIndex, layerId}.\n */\nexport function getLayerDetailsFromLayerDivId(idString) {\n  const split = idString.split('-layer-');\n  if (split.length !== 2) {\n    logger.warn('Not the expected layer div id format...');\n  }\n  return {\n    groupDivId: split[0],\n    layerIndex: split[1],\n    layerId: idString,\n  };\n}\n\n/**\n * Get the layer details from a mouse event.\n *\n * @param {object} event The event to get the layer div id from. Expecting\n * an event origininating from a canvas inside a layer HTML div\n * with the 'layer' class and id generated with `getLayerDivId`.\n * @returns {object} The layer details as {groupDivId, layerIndex, layerId}.\n */\nexport function getLayerDetailsFromEvent(event) {\n  let res = null;\n  // get the closest element from the event target and with the 'layer' class\n  const layerDiv = event.target.closest('.layer');\n  if (layerDiv && typeof layerDiv.id !== 'undefined') {\n    res = getLayerDetailsFromLayerDivId(layerDiv.id);\n  }\n  return res;\n}\n\n/**\n * Get a scaled offset to adapt to new scale and such as the input center\n * stays at the same position.\n *\n * @param {Scalar2D} offset The previous offset as {x,y}.\n * @param {Scalar2D} scale The previous scale as {x,y}.\n * @param {Scalar2D} newScale The new scale as {x,y}.\n * @param {Scalar2D} center The scale center as {x,y}.\n * @returns {Scalar2D} The scaled offset as {x,y}.\n */\nexport function getScaledOffset(offset, scale, newScale, center) {\n  // worldPoint = indexPoint / scale + offset\n  //=> indexPoint = (worldPoint - offset ) * scale\n\n  // plane center should stay the same:\n  // indexCenter / newScale + newOffset =\n  //   indexCenter / oldScale + oldOffset\n  //=> newOffset = indexCenter / oldScale + oldOffset -\n  //     indexCenter / newScale\n  //=> newOffset = worldCenter - indexCenter / newScale\n  const indexCenter = {\n    x: (center.x - offset.x) * scale.x,\n    y: (center.y - offset.y) * scale.y\n  };\n  return {\n    x: center.x - (indexCenter.x / newScale.x),\n    y: center.y - (indexCenter.y / newScale.y)\n  };\n}\n\n/**\n * Layer group.\n *\n * - Display position: {x,y},\n * - Plane position: Index (access: get(i)),\n * - (world) Position: Point3D (access: getX, getY, getZ).\n *\n * Display -> World:\n * - planePos = viewLayer.displayToPlanePos(displayPos)\n *   -> compensate for layer scale and offset,\n * - pos = viewController.getPositionFromPlanePoint(planePos).\n *\n * World -> Display:\n * - planePos = viewController.getOffset3DFromPlaneOffset(pos)\n *   no need yet for a planePos to displayPos...\n */\nexport class LayerGroup {\n\n  /**\n   * The container div.\n   *\n   * @type {HTMLElement}\n   */\n  #containerDiv;\n\n  // jsdoc does not like\n  // @type {(ViewLayer|DrawLayer)[]}\n\n  /**\n   * List of layers.\n   *\n   * @type {Array<ViewLayer|DrawLayer>}\n   */\n  #layers = [];\n\n  /**\n   * The layer scale as {x,y,z}.\n   *\n   * @type {Scalar3D}\n   */\n  #scale = {x: 1, y: 1, z: 1};\n\n  /**\n   * The base scale as {x,y,z}: all posterior scale will be on top of this one.\n   *\n   * @type {Scalar3D}\n   */\n  #baseScale = {x: 1, y: 1, z: 1};\n\n  /**\n   * The layer offset as {x,y,z}.\n   *\n   * @type {Scalar3D}\n   */\n  #offset = {x: 0, y: 0, z: 0};\n\n  /**\n   * Active layer index.\n   *\n   * @type {number}\n   */\n  #activeLayerIndex = undefined;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Flag to activate crosshair or not.\n   *\n   * @type {boolean}\n   */\n  #showCrosshair = false;\n\n  /**\n   * Crosshair HTML elements.\n   *\n   * @type {HTMLElement[]}\n   */\n  #crosshairHtmlElements = [];\n\n  /**\n   * Tooltip HTML element.\n   *\n   * @type {HTMLElement}\n   */\n  #tooltipHtmlElement;\n\n  /**\n   * The current position used for the crosshair.\n   *\n   * @type {Point}\n   */\n  #currentPosition;\n\n  /**\n   * Image smoothing flag.\n   *\n   * @type {boolean}\n   */\n  #imageSmoothing = false;\n\n  /**\n   * Position helper.\n   *\n   * @type {PositionHelper}\n   */\n  #positionHelper;\n\n  /**\n   * Get the position helper.\n   *\n   * @returns {PositionHelper} The position helper.\n   */\n  getPositionHelper() {\n    if (typeof this.#positionHelper === 'undefined') {\n      for (const layer of this.#layers) {\n        if (layer instanceof ViewLayer) {\n          const controller = layer.getViewController();\n          const helper = controller.getPositionHelper();\n          if (typeof this.#positionHelper === 'undefined') {\n            this.#positionHelper = helper;\n          } else {\n            this.#positionHelper.merge(helper);\n          }\n        }\n      }\n    }\n    return this.#positionHelper;\n  }\n\n  /**\n   * @param {HTMLElement} containerDiv The associated HTML div.\n   */\n  constructor(containerDiv) {\n    this.#containerDiv = containerDiv;\n  }\n\n  /**\n   * Get the showCrosshair flag.\n   *\n   * @returns {boolean} True to display the crosshair.\n   */\n  getShowCrosshair() {\n    return this.#showCrosshair;\n  }\n\n  /**\n   * Set the showCrosshair flag.\n   *\n   * @param {boolean} flag True to display the crosshair.\n   */\n  setShowCrosshair(flag) {\n    this.#showCrosshair = flag;\n    if (flag) {\n      // listen to offset and zoom change\n      this.addEventListener('offsetchange', this.#updateCrosshairOnChange);\n      this.addEventListener('zoomchange', this.#updateCrosshairOnChange);\n      // show crosshair div\n      this.#showCrosshairDiv();\n    } else {\n      // listen to offset and zoom change\n      this.removeEventListener('offsetchange', this.#updateCrosshairOnChange);\n      this.removeEventListener('zoomchange', this.#updateCrosshairOnChange);\n      // remove crosshair div\n      this.#removeCrosshairDiv();\n    }\n  }\n\n  /**\n   * Set the imageSmoothing flag value.\n   *\n   * @param {boolean} flag True to enable smoothing.\n   */\n  setImageSmoothing(flag) {\n    this.#imageSmoothing = flag;\n    // set for existing layers\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        layer.setImageSmoothing(flag);\n      }\n    }\n  }\n\n  /**\n   * Update crosshair on offset or zoom change.\n   *\n   * @param {object} _event The change event.\n   */\n  #updateCrosshairOnChange = (_event) => {\n    this.#showCrosshairDiv();\n  };\n\n  /**\n   * Get the Id of the container div.\n   *\n   * @returns {string|undefined} The id of the div.\n   */\n  getDivId() {\n    let divId;\n    // could be null if html changed\n    if (this.#containerDiv !== null) {\n      divId = this.#containerDiv.id;\n    }\n    return divId;\n  }\n\n  /**\n   * Get the layer scale.\n   *\n   * @returns {Scalar3D} The scale as {x,y,z}.\n   */\n  getScale() {\n    return this.#scale;\n  }\n\n  /**\n   * Get the base scale.\n   *\n   * @returns {Scalar3D} The scale as {x,y,z}.\n   */\n  getBaseScale() {\n    return this.#baseScale;\n  }\n\n\n  /**\n   * Get the added scale: the scale added to the base scale.\n   *\n   * @returns {Scalar3D} The scale as {x,y,z}.\n   */\n  getAddedScale() {\n    return {\n      x: this.#scale.x / this.#baseScale.x,\n      y: this.#scale.y / this.#baseScale.y,\n      z: this.#scale.z / this.#baseScale.z\n    };\n  }\n\n  /**\n   * Get the layer offset.\n   *\n   * @returns {Scalar3D} The offset as {x,y,z}.\n   */\n  getOffset() {\n    return this.#offset;\n  }\n\n  /**\n   * Get the number of layers handled by this class.\n   *\n   * @returns {number} The number of layers.\n   */\n  getNumberOfLayers() {\n    let count = 0;\n    this.#layers.forEach(item => {\n      if (typeof item !== 'undefined') {\n        count++;\n      }\n    });\n    return count;\n  }\n\n  /**\n   * Check if this layerGroup contains a layer with the input id.\n   *\n   * @param {string} id The layer id to look for.\n   * @returns {boolean} True if this group contains\n   *   a layer with the input id.\n   */\n  includes(id) {\n    if (typeof id === 'undefined') {\n      return false;\n    }\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined' &&\n        layer.getId() === id) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Get a list of view layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a ViewLayer as input and returns a boolean. If undefined,\n   *   returns all view layers.\n   * @returns {ViewLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getViewLayers(callbackFn) {\n    if (typeof callbackFn === 'undefined') {\n      callbackFn = function () {\n        return true;\n      };\n    }\n    const res = [];\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer &&\n        callbackFn(layer)) {\n        res.push(layer);\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Test if one of the view layers satisfies an input callbackFn.\n   *\n   * @param {Function} callbackFn A function that takes\n   *   a ViewLayer as input and returns a boolean.\n   * @returns {boolean} True if one of the ViewLayers\n   *   satisfies the callbackFn.\n   */\n  someViewLayer(callbackFn) {\n    let hasOne = false;\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer &&\n        callbackFn(layer)) {\n        hasOne = true;\n        break;\n      }\n    }\n    return hasOne;\n  }\n\n  /**\n   * Get a list of draw layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a DrawLayer as input and returns a boolean. If undefined,\n   *   returns all draw layers.\n   * @returns {DrawLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getDrawLayers(callbackFn) {\n    if (typeof callbackFn === 'undefined') {\n      callbackFn = function () {\n        return true;\n      };\n    }\n    const res = [];\n    for (const layer of this.#layers) {\n      if (layer instanceof DrawLayer &&\n        callbackFn(layer)) {\n        res.push(layer);\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Get the number of view layers handled by this class.\n   *\n   * @returns {number} The number of layers.\n   */\n  getNumberOfViewLayers() {\n    let count = 0;\n    this.#layers.forEach(item => {\n      if (typeof item !== 'undefined' &&\n        item instanceof ViewLayer) {\n        count++;\n      }\n    });\n    return count;\n  }\n\n  /**\n   * Get the active image layer.\n   *\n   * @returns {ViewLayer|DrawLayer|undefined} The layer.\n   */\n  getActiveLayer() {\n    let layer;\n    if (typeof this.#activeLayerIndex !== 'undefined') {\n      layer = this.#layers[this.#activeLayerIndex];\n    }\n    return layer;\n  }\n\n  /**\n   * Get the active image layer.\n   *\n   * @returns {ViewLayer|undefined} The layer.\n   */\n  getActiveViewLayer() {\n    let layer;\n    const activeLayer = this.getActiveLayer();\n    if (typeof activeLayer !== 'undefined' &&\n      activeLayer instanceof ViewLayer) {\n      layer = activeLayer;\n    }\n    return layer;\n  }\n\n  /**\n   * Get the base view layer.\n   *\n   * @returns {ViewLayer|undefined} The layer.\n   */\n  getBaseViewLayer() {\n    // use first layer as base for calculating position and\n    // line sizes\n    let baseLayer;\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        baseLayer = layer;\n        break;\n      }\n    }\n    if (typeof baseLayer === 'undefined') {\n      logger.warn('No layer found');\n      return;\n    }\n    return baseLayer;\n  }\n\n  /**\n   * Get a view layer associated to a data id.\n   *\n   * @param {string} id The layer id.\n   * @returns {ViewLayer|undefined} The layer.\n   */\n  getViewLayerById(id) {\n    const callbackFn = function (layer) {\n      return layer.getId() === id;\n    };\n    const layers = this.getViewLayers(callbackFn);\n    let layer;\n    if (layers.length === 1) {\n      layer = layers[0];\n    }\n    return layer;\n  }\n\n  /**\n   * Get the view layers associated to a data id.\n   *\n   * @param {string} dataId The data id.\n   * @returns {ViewLayer[]} The layers.\n   */\n  getViewLayersByDataId(dataId) {\n    const callbackFn = function (layer) {\n      return layer.getDataId() === dataId;\n    };\n    return this.getViewLayers(callbackFn);\n  }\n\n  /**\n   * Search view layers for equal imae meta data.\n   *\n   * @param {object} meta The meta data to find.\n   * @returns {ViewLayer[]} The list of view layers that contain matched data.\n   */\n  searchViewLayers(meta) {\n    const res = [];\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        if (layer.getViewController().equalImageMeta(meta)) {\n          res.push(layer);\n        }\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Get the view layers data indices.\n   *\n   * @returns {string[]} The list of indices.\n   */\n  getViewDataIndices() {\n    const res = [];\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        res.push(layer.getDataId());\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Get the active draw layer.\n   *\n   * @returns {DrawLayer|undefined} The layer.\n   */\n  getActiveDrawLayer() {\n    let layer;\n    const activeLayer = this.getActiveLayer();\n    if (typeof activeLayer !== 'undefined' &&\n      activeLayer instanceof DrawLayer) {\n      layer = activeLayer;\n    }\n    return layer;\n  }\n\n  /**\n   * Get a draw layer associated to a data id.\n   *\n   * @param {string} id The layer id.\n   * @returns {DrawLayer|undefined} The layer.\n   */\n  getDrawLayerById(id) {\n    const callbackFn = function (layer) {\n      return layer.getId() === id;\n    };\n    const layers = this.getDrawLayers(callbackFn);\n    let layer;\n    if (layers.length === 1) {\n      layer = layers[0];\n    }\n    return layer;\n  }\n\n  /**\n   * Get the draw layers associated to a data id.\n   *\n   * @param {string} dataId The data id.\n   * @returns {DrawLayer[]} The layers.\n   */\n  getDrawLayersByDataId(dataId) {\n    const callbackFn = function (layer) {\n      return layer.getDataId() === dataId;\n    };\n    return this.getDrawLayers(callbackFn);\n  }\n\n  /**\n   * Set the active layer.\n   *\n   * @param {number} index The index of the layer to set as active.\n   */\n  setActiveLayer(index) {\n    this.#activeLayerIndex = index;\n    /**\n     * Active layer change event.\n     *\n     * @event LayerGroup#activelayerchange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} value The changed value.\n     */\n    this.#fireEvent({\n      type: 'activelayerchange',\n      value: [this.#layers[index]]\n    });\n  }\n\n  /**\n   * Set the active layer with a data id.\n   *\n   * @param {string} dataId The data id.\n   */\n  setActiveLayerByDataId(dataId) {\n    let index;\n    for (let i = 0; i < this.#layers.length; ++i) {\n      if (typeof this.#layers[i] !== 'undefined' &&\n        this.#layers[i].getDataId() === dataId) {\n        // stop at first one\n        index = i;\n        break;\n      }\n    }\n    if (typeof index !== 'undefined') {\n      this.setActiveLayer(index);\n    } else {\n      logger.warn('No layer to set as active with dataId: ' +\n        dataId);\n    }\n  }\n\n  /**\n   * Add a view layer.\n   *\n   * The new layer will be marked as the active view layer.\n   *\n   * @returns {ViewLayer} The created layer.\n   */\n  addViewLayer() {\n    // layer index\n    const viewLayerIndex = this.#layers.length;\n    // create div\n    const div = this.#getNextLayerDiv();\n    // prepend to container\n    this.#containerDiv.append(div);\n    // view layer\n    const layer = new ViewLayer(div);\n    layer.setImageSmoothing(this.#imageSmoothing);\n    // add layer\n    this.#layers.push(layer);\n    // mark it as active\n    this.setActiveLayer(viewLayerIndex);\n    // bind view layer events\n    this.#bindViewLayer(layer);\n\n    // force helper update\n    this.#positionHelper = undefined;\n\n    // return\n    return layer;\n  }\n\n  /**\n   * Add a draw layer.\n   *\n   * The new layer will be marked as the active draw layer.\n   *\n   * @returns {DrawLayer} The created layer.\n   */\n  addDrawLayer() {\n    // store active index\n    this.#activeLayerIndex = this.#layers.length;\n    // create div\n    const div = this.#getNextLayerDiv();\n    // prepend to container\n    this.#containerDiv.append(div);\n    // draw layer\n    const layer = new DrawLayer(div);\n    // add layer\n    this.#layers.push(layer);\n    // bind draw layer events\n    this.#bindDrawLayer(layer);\n    // return\n    return layer;\n  }\n\n  /**\n   * Bind view layer events to this.\n   *\n   * @param {ViewLayer} viewLayer The view layer to bind.\n   */\n  #bindViewLayer(viewLayer) {\n    // listen to position change to update other group layers\n    viewLayer.addEventListener(\n      'positionchange', this.updateLayersToPositionChange);\n    // propagate view viewLayer-layer events\n    for (const eventName of viewEventNames) {\n      viewLayer.addEventListener(eventName, this.#fireEvent);\n    }\n    // propagate viewLayer events\n    viewLayer.addEventListener('renderstart', this.#fireEvent);\n    viewLayer.addEventListener('renderend', this.#fireEvent);\n  }\n\n  /**\n   * Un-bind a view layer events to this.\n   *\n   * @param {ViewLayer} viewLayer The view layer to unbind.\n   */\n  #unbindViewLayer(viewLayer) {\n    // stop listening to position change to update other group layers\n    viewLayer.removeEventListener(\n      'positionchange', this.updateLayersToPositionChange);\n    // stop propagating view viewLayer-layer events\n    for (const eventName of viewEventNames) {\n      viewLayer.removeEventListener(eventName, this.#fireEvent);\n    }\n    // stop propagating viewLayer events\n    viewLayer.removeEventListener('renderstart', this.#fireEvent);\n    viewLayer.removeEventListener('renderend', this.#fireEvent);\n\n    // stop view layer - image binding\n    // (binding is done in layer.setView)\n    viewLayer.unbindImage();\n  }\n\n  /**\n   * Bind draw layer events to this.\n   *\n   * @param {DrawLayer} drawLayer The draw layer to bind.\n   */\n  #bindDrawLayer(drawLayer) {\n    // listen to position change to update other group layers\n    drawLayer.addEventListener(\n      'positionchange', this.updateLayersToPositionChange);\n    drawLayer.addEventListener(\n      'positionchange', this.#fireEvent);\n    // propagate drawLayer events\n    drawLayer.addEventListener('drawcreate', this.#fireEvent);\n    drawLayer.addEventListener('drawdelete', this.#fireEvent);\n  }\n\n  /**\n   * Un-bind a draw layer events to this.\n   *\n   * @param {DrawLayer} drawLayer The draw layer to unbind.\n   */\n  #unbindDrawLayer(drawLayer) {\n    // stop listening to position change to update other group layers\n    drawLayer.removeEventListener(\n      'positionchange', this.updateLayersToPositionChange);\n    drawLayer.removeEventListener(\n      'positionchange', this.#fireEvent);\n    // propagate drawLayer events\n    drawLayer.removeEventListener('drawcreate', this.#fireEvent);\n    drawLayer.removeEventListener('drawdelete', this.#fireEvent);\n  }\n\n  /**\n   * Get the next layer DOM div.\n   *\n   * @returns {HTMLDivElement} A DOM div.\n   */\n  #getNextLayerDiv() {\n    const div = document.createElement('div');\n    div.id = getLayerDivId(this.getDivId(), this.#layers.length);\n    div.className = 'layer';\n    div.style.pointerEvents = 'none';\n    return div;\n  }\n\n  /**\n   * Empty the layer list.\n   */\n  empty() {\n    this.#layers = [];\n    // reset active indices\n    this.#activeLayerIndex = undefined;\n    // remove possible crosshair\n    this.#removeCrosshairDiv();\n    // clean container div\n    const previous = this.#containerDiv.getElementsByClassName('layer');\n    if (previous) {\n      while (previous.length > 0) {\n        previous[0].remove();\n      }\n    }\n  }\n\n  /**\n   * Remove all layers for a specific data.\n   *\n   * @param {string} dataId The data to remove its layers.\n   */\n  removeLayersByDataId(dataId) {\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined' &&\n        layer.getDataId() === dataId) {\n        this.removeLayer(layer);\n      }\n    }\n  }\n\n  /**\n   * Remove a layer from this layer group.\n   * Warning: if current active layer, the index will\n   *   be set to `undefined`. Call one of the setActive\n   *   methods to define the active index.\n   *\n   * @param {ViewLayer | DrawLayer} layer The layer to remove.\n   */\n  removeLayer(layer) {\n    // find layer\n    const index = this.#layers.findIndex((item) => item === layer);\n    if (index === -1) {\n      throw new Error('Cannot find layer to remove');\n    }\n    // update active index\n    if (this.#activeLayerIndex === index) {\n      this.#activeLayerIndex = undefined;\n    }\n    // unbind and update active index\n    if (layer instanceof ViewLayer) {\n      this.#unbindViewLayer(layer);\n    } else {\n      this.#unbindDrawLayer(layer);\n    }\n    // reset in storage\n    this.#layers[index] = undefined;\n    // update html\n    layer.removeFromDOM();\n  }\n\n  /**\n   * Show a crosshair at a given position.\n   *\n   * @param {Point} [position] The position where to show the crosshair,\n   *   defaults to current position.\n   */\n  #showCrosshairDiv(position) {\n    if (typeof position === 'undefined') {\n      position = this.#currentPosition;\n    }\n\n    // remove previous\n    this.#removeCrosshairDiv();\n\n    // use first layer as base for calculating position and\n    // line sizes\n    let baseLayer;\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        baseLayer = layer;\n        break;\n      }\n    }\n    if (typeof baseLayer === 'undefined') {\n      logger.warn('No layer to show crosshair');\n      return;\n    }\n\n    const vc = baseLayer.getViewController();\n    const planePos = vc.getPlanePositionFromPosition(position);\n    const displayPos = baseLayer.planePosToDisplay(planePos);\n\n    // horizontal line\n    if (typeof displayPos.getY() !== 'undefined') {\n      const lineH = document.createElement('hr');\n      lineH.id = this.getDivId() + '-scroll-crosshair-horizontal';\n      lineH.className = 'horizontal';\n      lineH.style.width = this.#containerDiv.offsetWidth + 'px';\n      lineH.style.left = '0px';\n      lineH.style.top = displayPos.getY() + 'px';\n      // add to local array\n      this.#crosshairHtmlElements.push(lineH);\n      // add to html\n      this.#containerDiv.appendChild(lineH);\n    }\n\n    // vertical line\n    if (typeof displayPos.getX() !== 'undefined') {\n      const lineV = document.createElement('hr');\n      lineV.id = this.getDivId() + '-scroll-crosshair-vertical';\n      lineV.className = 'vertical';\n      lineV.style.width = this.#containerDiv.offsetHeight + 'px';\n      lineV.style.left = (displayPos.getX()) + 'px';\n      lineV.style.top = '0px';\n      // add to local array\n      this.#crosshairHtmlElements.push(lineV);\n      // add to html\n      this.#containerDiv.appendChild(lineV);\n    }\n  }\n\n  /**\n   * Remove crosshair divs.\n   */\n  #removeCrosshairDiv() {\n    for (const element of this.#crosshairHtmlElements) {\n      element.remove();\n    }\n    this.#crosshairHtmlElements = [];\n  }\n\n  /**\n   * Displays a tooltip in a temporary `span`.\n   * Works with css to hide/show the span only on mouse hover.\n   *\n   * @param {Point2D} point The update point.\n   */\n  showTooltip(point) {\n    // remove previous div\n    this.removeTooltipDiv();\n\n    const viewLayer = this.getBaseViewLayer();\n    const viewController = viewLayer.getViewController();\n    const planePos = viewLayer.displayToPlanePos(point);\n    const position = viewController.getPositionFromPlanePoint(planePos);\n    const value = viewController.getRescaledImageValue(position);\n\n    // create\n    if (typeof value !== 'undefined') {\n      const span = document.createElement('span');\n      span.id = 'scroll-tooltip';\n      // tooltip position\n      span.style.left = (point.getX() + 10) + 'px';\n      span.style.top = (point.getY() + 10) + 'px';\n      let text = precisionRound(value, 3).toString();\n      if (typeof viewController.getPixelUnit() !== 'undefined') {\n        text += ' ' + viewController.getPixelUnit();\n      }\n      span.appendChild(document.createTextNode(text));\n      // add to local var\n      this.#tooltipHtmlElement = span;\n      // add to html\n      this.#containerDiv.appendChild(span);\n    }\n  }\n\n  /**\n   * Remove the tooltip html div.\n   */\n  removeTooltipDiv() {\n    if (typeof this.#tooltipHtmlElement !== 'undefined') {\n      this.#tooltipHtmlElement.remove();\n      this.#tooltipHtmlElement = undefined;\n    }\n  }\n\n  /**\n   * Can the input position be set on one of the view layers.\n   *\n   * @param {Point} position The input position.\n   * @returns {boolean} True if one view layer accepts the input position.\n   */\n  isPositionInBounds(position) {\n    return this.someViewLayer(function (layer) {\n      return layer.getViewController().isPositionInBounds(position);\n    });\n  }\n\n  /**\n   * Can one of the view layers be scrolled.\n   *\n   * @returns {boolean} True if one view layer can be scrolled.\n   */\n  canScroll() {\n    return this.someViewLayer(function (layer) {\n      return layer.getViewController().canScroll();\n    });\n  }\n\n  /**\n   * Does one of the view layer have more than one slice in the\n   *   given dimension.\n   *\n   * @param {number} dim The input dimension.\n   * @returns {boolean} True if one view layer has more than one slice.\n   */\n  moreThanOne(dim) {\n    return this.someViewLayer(function (layer) {\n      return layer.getViewController().moreThanOne(dim);\n    });\n  }\n\n  /**\n   * Update layers (but not the event source layer) to a position change.\n   *\n   * @param {object} event The position change event.\n   * @function\n   */\n  updateLayersToPositionChange = (event) => {\n    // pause positionchange listeners\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.removeEventListener(\n          'positionchange', this.updateLayersToPositionChange);\n        layer.removeEventListener('positionchange', this.#fireEvent);\n      }\n    }\n\n    const index = new Index(event.value[0]);\n    const position = new Point(event.value[1]);\n\n    // store current position\n    this.#currentPosition = position;\n\n    if (this.#showCrosshair) {\n      this.#showCrosshairDiv(position);\n    }\n\n    // origin of the first view layer\n    const viewLayerOffsets = {};\n    let baseViewLayerOrigin0;\n    let baseViewLayerOrigin;\n    // update position for all layers except the source one\n    for (const layer of this.#layers) {\n      if (typeof layer === 'undefined') {\n        continue;\n      }\n      let hasSetOffset = false;\n\n      // view layer case: define and set offsets\n      if (layer instanceof ViewLayer) {\n        const vc = layer.getViewController();\n        // origin0 should always be there\n        const origin0 = vc.getOrigin();\n        // depending on position, origin could be undefined\n        const origin = vc.getOrigin(position);\n\n        let scrollOffset;\n        let planeOffset;\n\n        if (typeof baseViewLayerOrigin === 'undefined') {\n          // first view layer, store origins\n          baseViewLayerOrigin0 = origin0;\n          baseViewLayerOrigin = origin;\n          // no offset\n          scrollOffset = new Vector3D(0, 0, 0);\n          planeOffset = new Vector3D(0, 0, 0);\n        } else {\n          if (vc.isPositionInBounds(position) &&\n            typeof origin !== 'undefined') {\n            // TODO: compensate for possible different orientation between views\n            const scrollDiff = baseViewLayerOrigin0.minus(origin0);\n            scrollOffset = new Vector3D(\n              scrollDiff.getX(), scrollDiff.getY(), scrollDiff.getZ());\n            const planeDiff = baseViewLayerOrigin.minus(origin);\n            planeOffset = new Vector3D(\n              planeDiff.getX(), planeDiff.getY(), planeDiff.getZ());\n          }\n        }\n\n        // set and store offsets\n        if (typeof scrollOffset !== 'undefined' &&\n          typeof planeOffset !== 'undefined') {\n          hasSetOffset =\n            layer.setBaseOffset(\n              scrollOffset, planeOffset,\n              baseViewLayerOrigin, baseViewLayerOrigin0\n            );\n          // store\n          viewLayerOffsets[layer.getId()] = {\n            scroll: scrollOffset,\n            plane: planeOffset\n          };\n        }\n      }\n\n      // draw layer case: use associated view layer offsets\n      if (layer instanceof DrawLayer) {\n        const refOffsets = viewLayerOffsets[layer.getReferenceLayerId()];\n        if (typeof refOffsets !== 'undefined') {\n          hasSetOffset =\n            layer.setBaseOffset(refOffsets.scroll, refOffsets.plane);\n        }\n      }\n\n      // update position (triggers redraw)\n      let hasSetPos = false;\n      if (layer.getId() !== event.srclayerid) {\n        hasSetPos = layer.setCurrentPosition(position, index);\n      }\n\n      // force redraw if needed\n      if (!hasSetPos && hasSetOffset) {\n        layer.draw();\n      }\n    }\n\n    // re-start positionchange listeners\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.addEventListener(\n          'positionchange', this.updateLayersToPositionChange);\n        layer.addEventListener('positionchange', this.#fireEvent);\n      }\n    }\n  };\n\n  /**\n   * Calculate the div to world size ratio needed to fit\n   *   the largest data.\n   *\n   * @returns {number|undefined} The ratio.\n   */\n  getDivToWorldSizeRatio() {\n    // check container\n    if (this.#containerDiv.offsetWidth === 0 &&\n      this.#containerDiv.offsetHeight === 0) {\n      throw new Error('Cannot fit to zero sized container.');\n    }\n    // get max world size\n    const maxWorldSize = this.getMaxWorldSize();\n    if (typeof maxWorldSize === 'undefined') {\n      return undefined;\n    }\n    // if the container has a width but no height,\n    // resize it to follow the same ratio to completely\n    // fill the div with the image\n    if (this.#containerDiv.offsetHeight === 0) {\n      const ratioX = this.#containerDiv.offsetWidth / maxWorldSize.x;\n      const height = maxWorldSize.y * ratioX;\n      this.#containerDiv.style.height = height + 'px';\n    }\n    // return best fit\n    return Math.min(\n      this.#containerDiv.offsetWidth / maxWorldSize.x,\n      this.#containerDiv.offsetHeight / maxWorldSize.y\n    );\n  }\n\n  /**\n   * Fit to container: set the layers div to world size ratio.\n   *\n   * @param {number} divToWorldSizeRatio The ratio.\n   */\n  fitToContainer(divToWorldSizeRatio) {\n    // get maximum world size\n    const maxWorldSize = this.getMaxWorldSize();\n    // exit if none\n    if (typeof maxWorldSize === 'undefined') {\n      return;\n    }\n\n    const containerSize = {\n      x: this.#containerDiv.offsetWidth,\n      y: this.#containerDiv.offsetHeight\n    };\n    // offset to keep data centered\n    const fitOffset = {\n      x: -0.5 *\n        (containerSize.x - Math.floor(maxWorldSize.x * divToWorldSizeRatio)),\n      y: -0.5 *\n        (containerSize.y - Math.floor(maxWorldSize.y * divToWorldSizeRatio))\n    };\n\n    // apply to layers\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.fitToContainer(containerSize, divToWorldSizeRatio, fitOffset);\n      }\n    }\n\n    // update crosshair\n    if (this.#showCrosshair) {\n      this.#showCrosshairDiv();\n    }\n  }\n\n  /**\n   * Get the largest data world (mm) size.\n   *\n   * @returns {Scalar2D|undefined} The largest size as {x,y}.\n   */\n  getMaxWorldSize() {\n    let maxSize = {x: 0, y: 0};\n    for (const layer of this.#layers) {\n      if (layer instanceof ViewLayer) {\n        const size = layer.getImageWorldSize();\n        if (size.x > maxSize.x) {\n          maxSize.x = size.x;\n        }\n        if (size.y > maxSize.y) {\n          maxSize.y = size.y;\n        }\n      }\n    }\n    if (maxSize.x === 0 && maxSize.y === 0) {\n      maxSize = undefined;\n    }\n    return maxSize;\n  }\n\n  /**\n   * Flip all layers along the Z axis without offset compensation.\n   */\n  flipScaleZ() {\n    this.#baseScale.z *= -1;\n    this.setScale(this.#baseScale);\n  }\n\n  /**\n   * Add scale to the layers. Scale cannot go lower than 0.1.\n   *\n   * @param {number} scaleStep The scale to add.\n   * @param {Point3D} center The scale center Point3D.\n   */\n  addScale(scaleStep, center) {\n    const newScale = {\n      x: this.#scale.x * (1 + scaleStep),\n      y: this.#scale.y * (1 + scaleStep),\n      z: this.#scale.z * (1 + scaleStep)\n    };\n    this.setScale(newScale, center);\n  }\n\n  /**\n   * Set the layers' scale.\n   *\n   * @param {Scalar3D} newScale The scale to apply as {x,y,z}.\n   * @param {Point3D} [center] The scale center Point3D.\n   * @fires LayerGroup#zoomchange\n   */\n  setScale(newScale, center) {\n    this.#scale = newScale;\n    // apply to layers\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.setScale(this.#scale, center);\n      }\n    }\n\n    // event value\n    const value = [\n      newScale.x,\n      newScale.y,\n      newScale.z\n    ];\n    if (typeof center !== 'undefined') {\n      value.push(center.getX());\n      value.push(center.getY());\n      value.push(center.getZ());\n    }\n\n    /**\n     * Zoom change event.\n     *\n     * @event LayerGroup#zoomchange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} value The changed value.\n     */\n    this.#fireEvent({\n      type: 'zoomchange',\n      value: value\n    });\n  }\n\n  /**\n   * Add translation to the layers.\n   *\n   * @param {Scalar3D} translation The translation as {x,y,z}.\n   */\n  addTranslation(translation) {\n    this.setOffset({\n      x: this.#offset.x - translation.x,\n      y: this.#offset.y - translation.y,\n      z: this.#offset.z - translation.z\n    });\n  }\n\n  /**\n   * Set the layers' offset.\n   *\n   * @param {Scalar3D} newOffset The offset as {x,y,z}.\n   * @fires LayerGroup#offsetchange\n   */\n  setOffset(newOffset) {\n    // store\n    this.#offset = newOffset;\n    // apply to layers\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.setOffset(this.#offset);\n      }\n    }\n\n    /**\n     * Offset change event.\n     *\n     * @event LayerGroup#offsetchange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} value The changed value.\n     */\n    this.#fireEvent({\n      type: 'offsetchange',\n      value: [\n        this.#offset.x,\n        this.#offset.y,\n        this.#offset.z\n      ]\n    });\n  }\n\n  /**\n   * Reset the stage to its initial scale and no offset.\n   */\n  reset() {\n    this.setScale(this.#baseScale);\n    this.setOffset({x: 0, y: 0, z: 0});\n  }\n\n  /**\n   * Draw the layer.\n   */\n  draw() {\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.draw();\n      }\n    }\n  }\n\n  /**\n   * Display the layer.\n   *\n   * @param {boolean} flag Whether to display the layer or not.\n   */\n  display(flag) {\n    for (const layer of this.#layers) {\n      if (typeof layer !== 'undefined') {\n        layer.display(flag);\n      }\n    }\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n} // LayerGroup class\n","import {Point, Point3D} from '../math/point';\nimport {WindowLevel} from '../image/windowLevel';\nimport {LayerGroup} from './layerGroup';\nimport {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {ViewLayer} from '../gui/viewLayer';\nimport {DrawLayer} from '../gui/drawLayer';\n/* eslint-enable no-unused-vars */\n\n/**\n * Window/level binder.\n */\nexport class WindowLevelBinder {\n  getEventType = function () {\n    return 'wlchange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      const viewLayers = layerGroup.getViewLayersByDataId(event.dataid);\n      if (viewLayers.length !== 0) {\n        const vc = viewLayers[0].getViewController();\n        if (event.value.length === 2) {\n          const wl = new WindowLevel(event.value[0], event.value[1]);\n          vc.setWindowLevel(wl);\n        }\n        if (event.value.length === 3) {\n          vc.setWindowLevelPreset(event.value[2]);\n        }\n      }\n    };\n  };\n}\n\n/**\n * Colour map binder.\n */\nexport class ColourMapBinder {\n  getEventType = function () {\n    return 'colourmapchange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      const viewLayers = layerGroup.getViewLayersByDataId(event.dataid);\n      if (viewLayers.length !== 0) {\n        const vc = viewLayers[0].getViewController();\n        vc.setColourMap(event.value[0]);\n      }\n    };\n  };\n}\n\n/**\n * Position binder.\n */\nexport class PositionBinder {\n  getEventType = function () {\n    return 'positionchange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      const pointValues = event.value[1];\n      const vl = layerGroup.getBaseViewLayer();\n      const vc = vl.getViewController();\n      // handle different number of dimensions\n      const currentPos = vc.getCurrentPosition();\n      const currentDims = currentPos.length();\n      const inputDims = pointValues.length;\n      if (inputDims !== currentDims) {\n        if (inputDims === currentDims - 1) {\n          // add missing dim, for ex: input 3D -> current 4D\n          pointValues.push(currentPos.get(currentDims - 1));\n        } else if (inputDims === currentDims + 1) {\n          // remove extra dim, for ex: input 4D -> current 3D\n          pointValues.pop();\n        }\n      }\n      vc.setCurrentPosition(new Point(pointValues));\n    };\n  };\n}\n\n/**\n * Zoom binder.\n */\nexport class ZoomBinder {\n  getEventType = function () {\n    return 'zoomchange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      const scale = {\n        x: event.value[0],\n        y: event.value[1],\n        z: event.value[2]\n      };\n      let center;\n      if (event.value.length === 6) {\n        center = new Point3D(\n          event.value[3],\n          event.value[4],\n          event.value[5]\n        );\n      }\n      layerGroup.setScale(scale, center);\n      layerGroup.draw();\n    };\n  };\n}\n\n/**\n * Offset binder.\n */\nexport class OffsetBinder {\n  getEventType = function () {\n    return 'offsetchange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      layerGroup.setOffset({\n        x: event.value[0],\n        y: event.value[1],\n        z: event.value[2]\n      });\n      layerGroup.draw();\n    };\n  };\n}\n\n/**\n * Opacity binder. Only propagates to view layers of the same data.\n */\nexport class OpacityBinder {\n  getEventType = function () {\n    return 'opacitychange';\n  };\n  getCallback = function (layerGroup) {\n    return function (event) {\n      // exit if no data id\n      if (typeof event.dataid === 'undefined') {\n        return;\n      }\n      // propagate to first view layer if it is not base layer\n      const viewLayers = layerGroup.getViewLayersByDataId(event.dataid);\n      const baseLayer = layerGroup.getBaseViewLayer();\n      if (viewLayers.length !== 0 && baseLayer !== viewLayers[0]) {\n        viewLayers[0].setOpacity(event.value);\n        viewLayers[0].draw();\n      }\n    };\n  };\n}\n\n/**\n * List of binders.\n */\nexport const binderList = {\n  WindowLevelBinder,\n  PositionBinder,\n  ZoomBinder,\n  OffsetBinder,\n  OpacityBinder,\n  ColourMapBinder\n};\n\n/**\n * Stage: controls a list of layer groups and their\n * synchronisation.\n */\nexport class Stage {\n\n  /**\n   * Associated layer groups.\n   *\n   * @type {LayerGroup[]}\n   */\n  #layerGroups = [];\n\n  /**\n   * Active layer group index.\n   *\n   * @type {number|undefined}\n   */\n  #activeLayerGroupIndex;\n\n  /**\n   * Image smoothing flag.\n   *\n   * @type {boolean}\n   */\n  #imageSmoothing = false;\n\n  // layer group binders\n  #binders = [];\n  // binder callbacks\n  #callbackStore = null;\n\n  /**\n   * Get the layer group at the given index.\n   *\n   * @param {number} index The index.\n   * @returns {LayerGroup|undefined} The layer group.\n   */\n  getLayerGroup(index) {\n    return this.#layerGroups[index];\n  }\n\n  /**\n   * Get the number of layer groups that form the stage.\n   *\n   * @returns {number} The number of layer groups.\n   */\n  getNumberOfLayerGroups() {\n    return this.#layerGroups.length;\n  }\n\n  /**\n   * Get the active layer group.\n   *\n   * @returns {LayerGroup|undefined} The layer group.\n   */\n  getActiveLayerGroup() {\n    return this.getLayerGroup(this.#activeLayerGroupIndex);\n  }\n\n  /**\n   * Set the active layer group.\n   *\n   * @param {number} index The layer group index.\n   */\n  setActiveLayerGroup(index) {\n    if (typeof this.getLayerGroup(index) !== 'undefined') {\n      this.#activeLayerGroupIndex = index;\n    } else {\n      logger.warn('No layer group to set as active with index: ' +\n        index);\n    }\n  }\n\n  /**\n   * Get the view layers associated to a data id.\n   *\n   * @param {string} dataId The data id.\n   * @returns {ViewLayer[]} The layers.\n   */\n  getViewLayersByDataId(dataId) {\n    let res = [];\n    for (const layerGroup of this.#layerGroups) {\n      res = res.concat(layerGroup.getViewLayersByDataId(dataId));\n    }\n    return res;\n  }\n\n  /**\n   * Get a list of view layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a ViewLayer as input and returns a boolean. If undefined,\n   *   returns all view layers.\n   * @returns {ViewLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getViewLayers(callbackFn) {\n    let res = [];\n    for (const layerGroup of this.#layerGroups) {\n      res = res.concat(layerGroup.getViewLayers(callbackFn));\n    }\n    return res;\n  }\n\n  /**\n   * Get the draw layers associated to a data id.\n   *\n   * @param {string} dataId The data id.\n   * @returns {DrawLayer[]} The layers.\n   */\n  getDrawLayersByDataId(dataId) {\n    let res = [];\n    for (const layerGroup of this.#layerGroups) {\n      res = res.concat(layerGroup.getDrawLayersByDataId(dataId));\n    }\n    return res;\n  }\n\n  /**\n   * Get a list of draw layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a DrawLayer as input and returns a boolean. If undefined,\n   *   returns all draw layers.\n   * @returns {DrawLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getDrawLayers(callbackFn) {\n    let res = [];\n    for (const layerGroup of this.#layerGroups) {\n      res = res.concat(layerGroup.getDrawLayers(callbackFn));\n    }\n    return res;\n  }\n\n  /**\n   * Add a layer group to the list.\n   *\n   * The new layer group will be marked as the active layer group.\n   *\n   * @param {object} htmlElement The HTML element of the layer group.\n   * @returns {LayerGroup} The newly created layer group.\n   */\n  addLayerGroup(htmlElement) {\n    this.#activeLayerGroupIndex = this.#layerGroups.length;\n    const layerGroup = new LayerGroup(htmlElement);\n    layerGroup.setImageSmoothing(this.#imageSmoothing);\n    // add to storage\n    const isBound = this.#callbackStore && this.#callbackStore.length !== 0;\n    if (isBound) {\n      this.unbindLayerGroups();\n    }\n    this.#layerGroups.push(layerGroup);\n    if (isBound) {\n      this.bindLayerGroups();\n    }\n    // return created group\n    return layerGroup;\n  }\n\n  /**\n   * Get a layer group from an HTML element id.\n   *\n   * @param {string} id The element id to find.\n   * @returns {LayerGroup|undefined} The layer group.\n   */\n  getLayerGroupByDivId(id) {\n    return this.#layerGroups.find(function (item) {\n      return item.getDivId() === id;\n    });\n  }\n\n  /**\n   * Set the layer groups binders.\n   *\n   * @param {Array} list The list of binder objects.\n   */\n  setBinders(list) {\n    if (typeof list === 'undefined' || list === null) {\n      throw new Error('Cannot set null or undefined binders');\n    }\n    if (this.#binders.length !== 0) {\n      this.unbindLayerGroups();\n    }\n    this.#binders = list.slice();\n    this.bindLayerGroups();\n  }\n\n  /**\n   * Empty the layer group list.\n   */\n  empty() {\n    this.unbindLayerGroups();\n    for (const layerGroup of this.#layerGroups) {\n      layerGroup.empty();\n    }\n    this.#layerGroups = [];\n    this.#activeLayerGroupIndex = undefined;\n  }\n\n  /**\n   * Remove all layers for a specific data.\n   *\n   * @param {string} dataId The data to remove its layers.\n   */\n  removeLayersByDataId(dataId) {\n    for (const layerGroup of this.#layerGroups) {\n      layerGroup.removeLayersByDataId(dataId);\n    }\n  }\n\n  /**\n   * Remove a layer group from this stage.\n   *\n   * @param {LayerGroup} layerGroup The layer group to remove.\n   */\n  removeLayerGroup(layerGroup) {\n    // find layer\n    const index = this.#layerGroups.findIndex((item) => item === layerGroup);\n    if (index === -1) {\n      throw new Error('Cannot find layerGroup to remove');\n    }\n    // unbind\n    this.unbindLayerGroups();\n    // empty layer group\n    layerGroup.empty();\n    // remove from storage\n    this.#layerGroups.splice(index, 1);\n    // update active index\n    if (this.#activeLayerGroupIndex === index) {\n      this.#activeLayerGroupIndex = undefined;\n    }\n    // bind\n    this.bindLayerGroups();\n  }\n\n  /**\n   * Reset the stage: calls reset on all layer groups.\n   */\n  reset() {\n    for (const layerGroup of this.#layerGroups) {\n      layerGroup.reset();\n    }\n  }\n\n  /**\n   * Draw the stage: calls draw on all layer groups.\n   */\n  draw() {\n    for (const layerGroup of this.#layerGroups) {\n      layerGroup.draw();\n    }\n  }\n\n  /**\n   * Fit to container: synchronise the div to world size ratio\n   *   of the group layers.\n   */\n  fitToContainer() {\n    // find the minimum ratio\n    let minRatio;\n    const hasRatio = [];\n    for (let i = 0; i < this.#layerGroups.length; ++i) {\n      const ratio = this.#layerGroups[i].getDivToWorldSizeRatio();\n      if (typeof ratio !== 'undefined') {\n        hasRatio.push(i);\n        if (typeof minRatio === 'undefined' || ratio < minRatio) {\n          minRatio = ratio;\n        }\n      }\n    }\n    // exit if no ratio\n    if (typeof minRatio === 'undefined') {\n      return;\n    }\n    // apply min ratio to layers\n    for (let j = 0; j < this.#layerGroups.length; ++j) {\n      if (hasRatio.includes(j)) {\n        this.#layerGroups[j].fitToContainer(minRatio);\n      }\n    }\n  }\n\n  /**\n   * Bind the layer groups of the stage.\n   */\n  bindLayerGroups() {\n    if (this.#layerGroups.length === 0 ||\n      this.#layerGroups.length === 1 ||\n      this.#binders.length === 0) {\n      return;\n    }\n    // create callback store\n    this.#callbackStore = new Array(this.#layerGroups.length);\n    // add listeners\n    for (let i = 0; i < this.#layerGroups.length; ++i) {\n      for (let j = 0; j < this.#binders.length; ++j) {\n        this.#addEventListeners(i, this.#binders[j]);\n      }\n    }\n  }\n\n  /**\n   * Unbind the layer groups of the stage.\n   */\n  unbindLayerGroups() {\n    if (this.#layerGroups.length === 0 ||\n      this.#layerGroups.length === 1 ||\n      this.#binders.length === 0 ||\n      !this.#callbackStore) {\n      return;\n    }\n    // remove listeners\n    for (let i = 0; i < this.#layerGroups.length; ++i) {\n      for (let j = 0; j < this.#binders.length; ++j) {\n        this.#removeEventListeners(i, this.#binders[j]);\n      }\n    }\n    // clear callback store\n    this.#callbackStore = null;\n  }\n\n  /**\n   * Set the imageSmoothing flag value.\n   *\n   * @param {boolean} flag True to enable smoothing.\n   */\n  setImageSmoothing(flag) {\n    this.#imageSmoothing = flag;\n    // set for existing layer groups\n    for (const layerGroup of this.#layerGroups) {\n      layerGroup.setImageSmoothing(flag);\n    }\n  }\n\n  /**\n   * Get the binder callback function for a given layer group index.\n   * The function is created if not yet stored.\n   *\n   * @param {object} binder The layer binder.\n   * @param {number} index The index of the associated layer group.\n   * @returns {Function} The binder function.\n   */\n  #getBinderCallback(binder, index) {\n    if (typeof this.#callbackStore[index] === 'undefined') {\n      this.#callbackStore[index] = [];\n    }\n    const store = this.#callbackStore[index];\n    let binderObj = store.find(function (elem) {\n      return elem.binder === binder;\n    });\n    if (typeof binderObj === 'undefined') {\n      // create new callback object\n      binderObj = {\n        binder: binder,\n        callback: (event) => {\n          // stop listeners\n          this.#removeEventListeners(index, binder);\n          // apply binder\n          binder.getCallback(this.#layerGroups[index])(event);\n          // re-start listeners\n          this.#addEventListeners(index, binder);\n        }\n      };\n      this.#callbackStore[index].push(binderObj);\n    }\n    return binderObj.callback;\n  }\n\n  /**\n   * Add event listeners for a given layer group index and binder.\n   *\n   * @param {number} index The index of the associated layer group.\n   * @param {object} binder The layer binder.\n   */\n  #addEventListeners(index, binder) {\n    for (let i = 0; i < this.#layerGroups.length; ++i) {\n      if (i !== index) {\n        this.#layerGroups[index].addEventListener(\n          binder.getEventType(),\n          this.#getBinderCallback(binder, i)\n        );\n      }\n    }\n  }\n\n  /**\n   * Remove event listeners for a given layer group index and binder.\n   *\n   * @param {number} index The index of the associated layer group.\n   * @param {object} binder The layer binder.\n   */\n  #removeEventListeners(index, binder) {\n    for (let i = 0; i < this.#layerGroups.length; ++i) {\n      if (i !== index) {\n        this.#layerGroups[index].removeEventListener(\n          binder.getEventType(),\n          this.#getBinderCallback(binder, i)\n        );\n      }\n    }\n  }\n\n} // class Stage\n","import {Index} from '../math/index';\nimport {colourNameToHex} from '../utils/colour';\nimport {WindowLevel} from '../image/windowLevel';\n\n// external\nimport Konva from 'konva';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\n/* eslint-enable no-unused-vars */\n\n/**\n * State class.\n * Saves: data url/path, display info.\n *\n * History:\n * - v0.5 (dwv 0.30.0, 12/2021):\n *   - store position as array,\n *   - new draw position group key.\n * - v0.4 (dwv 0.29.0, 06/2021):\n *   - move drawing details into meta property,\n *   - remove scale center and translation, add offset.\n * - v0.3 (dwv v0.23.0, 03/2018):\n *   - new drawing structure, drawings are now the full layer object and\n *     using toObject to avoid saving a string representation,\n *   - new details structure: simple array of objects referenced by draw ids.\n * - v0.2 (dwv v0.17.0, 12/2016):\n *   - adds draw details: array [nslices][nframes] of detail objects.\n * - v0.1 (dwv v0.15.0, 07/2016):\n *   - adds version,\n *   - drawings: array [nslices][nframes] with all groups.\n * - initial release (dwv v0.10.0, 05/2015), no version number:\n *   - content: window-center, window-width, position, scale,\n *       scaleCenter, translation, drawings,\n *   - drawings: array [nslices] with all groups.\n */\nexport class State {\n  /**\n   * The state data id.\n   *\n   * @type {string}\n   */\n  #dataId;\n\n  /**\n   * @param {string} dataId The associated data id.\n   */\n  constructor(dataId) {\n    this.#dataId = dataId;\n  }\n\n  /**\n   * Load an application state from JSON.\n   *\n   * @param {string} json The state as a JSON string.\n   * @returns {object} The state object.\n   */\n  fromJSON(json) {\n    const data = JSON.parse(json);\n    let res = null;\n    if (data.version === '0.1') {\n      res = this.#readV01(data);\n    } else if (data.version === '0.2') {\n      res = this.#readV02(data);\n    } else if (data.version === '0.3') {\n      res = this.#readV03(data);\n    } else if (data.version === '0.4') {\n      res = this.#readV04(data);\n    } else if (data.version === '0.5') {\n      res = this.#readV05(data);\n    } else {\n      throw new Error('Unknown state file format version: \\'' +\n        data.version + '\\'.');\n    }\n    return res;\n  }\n\n  /**\n   * Load an application state from JSON.\n   *\n   * @param {App} app The app to apply the state to.\n   * @param {object} data The state data.\n   */\n  apply(app, data) {\n    const layerGroup = app.getActiveLayerGroup();\n    const viewLayer = layerGroup.getBaseViewLayer();\n    const viewController = viewLayer.getViewController();\n    // display\n    const wl = new WindowLevel(data['window-center'], data['window-width']);\n    viewController.setWindowLevel(wl);\n    // position is index...\n    viewController.setCurrentIndex(new Index(data.position));\n    // apply saved scale on top of current base one\n    const baseScale = app.getActiveLayerGroup().getBaseScale();\n    let scale = null;\n    let offset = null;\n    if (typeof data.scaleCenter !== 'undefined') {\n      scale = {\n        x: data.scale * baseScale.x,\n        y: data.scale * baseScale.y,\n        z: 1\n      };\n      // ---- transform translation (now) ----\n      // Tx = -offset.x * scale.x\n      // => offset.x = -Tx / scale.x\n      // ---- transform translation (before) ----\n      // origin.x = centerX - (centerX - origin.x) * (newZoomX / zoom.x);\n      // (zoom.x -> initial zoom = base scale, origin.x = 0)\n      // Tx = origin.x + (trans.x * zoom.x)\n      const originX = data.scaleCenter.x - data.scaleCenter.x * data.scale;\n      const originY = data.scaleCenter.y - data.scaleCenter.y * data.scale;\n      const oldTx = originX + data.translation.x * scale.x;\n      const oldTy = originY + data.translation.y * scale.y;\n      offset = {\n        x: -oldTx / scale.x,\n        y: -oldTy / scale.y,\n        z: 0\n      };\n    } else {\n      scale = {\n        x: data.scale.x * baseScale.x,\n        y: data.scale.y * baseScale.y,\n        z: baseScale.z\n      };\n      offset = {\n        x: data.offset.x,\n        y: data.offset.y,\n        z: 0\n      };\n    }\n    app.getActiveLayerGroup().setScale(scale);\n    app.getActiveLayerGroup().setOffset(offset);\n    // drawings (will draw the draw layer)\n    app.setDrawings(data.drawings, data.drawingsDetails, this.#dataId);\n  }\n\n  /**\n   * Read an application state from an Object in v0.1 format.\n   *\n   * @param {object} data The Object representation of the state.\n   * @returns {object} The state object.\n   */\n  #readV01(data) {\n    // v0.1 -> v0.2\n    const v02DAndD = v01Tov02DrawingsAndDetails(data.drawings);\n    // v0.2 -> v0.3, v0.4\n    data.drawings = v02Tov03Drawings(v02DAndD.drawings).toObject();\n    data.drawingsDetails = v03Tov04DrawingsDetails(\n      v02DAndD.drawingsDetails);\n    // v0.4 -> v0.5\n    data = v04Tov05Data(data);\n    data.drawings = v04Tov05Drawings(data.drawings);\n    return data;\n  }\n\n  /**\n   * Read an application state from an Object in v0.2 format.\n   *\n   * @param {object} data The Object representation of the state.\n   * @returns {object} The state object.\n   */\n  #readV02(data) {\n    // v0.2 -> v0.3, v0.4\n    data.drawings = v02Tov03Drawings(data.drawings).toObject();\n    data.drawingsDetails = v03Tov04DrawingsDetails(\n      v02Tov03DrawingsDetails(data.drawingsDetails));\n    // v0.4 -> v0.5\n    data = v04Tov05Data(data);\n    data.drawings = v04Tov05Drawings(data.drawings);\n    return data;\n  }\n\n  /**\n   * Read an application state from an Object in v0.3 format.\n   *\n   * @param {object} data The Object representation of the state.\n   * @returns {object} The state object.\n   */\n  #readV03(data) {\n    // v0.3 -> v0.4\n    data.drawingsDetails = v03Tov04DrawingsDetails(data.drawingsDetails);\n    // v0.4 -> v0.5\n    data = v04Tov05Data(data);\n    data.drawings = v04Tov05Drawings(data.drawings);\n    return data;\n  }\n\n  /**\n   * Read an application state from an Object in v0.4 format.\n   *\n   * @param {object} data The Object representation of the state.\n   * @returns {object} The state object.\n   */\n  #readV04(data) {\n    // v0.4 -> v0.5\n    data = v04Tov05Data(data);\n    data.drawings = v04Tov05Drawings(data.drawings);\n    return data;\n  }\n  /**\n   * Read an application state from an Object in v0.5 format.\n   *\n   * @param {object} data The Object representation of the state.\n   * @returns {object} The state object.\n   */\n  #readV05(data) {\n    return data;\n  }\n\n} // State class\n\n/**\n * Convert drawings from v0.2 to v0.3:\n * - v0.2: one layer per slice/frame,\n * - v0.3: one layer, one group per slice. `setDrawing` expects the full stage.\n *\n * @param {Array} drawings An array of drawings.\n * @returns {object} The layer with the converted drawings.\n */\nfunction v02Tov03Drawings(drawings) {\n  // Auxiliar variables\n  let group, groupShapes, parentGroup;\n  // Avoid errors when dropping multiple states\n  //drawLayer.getChildren().each(function(node){\n  //    node.visible(false);\n  //});\n\n  /**\n   * Get the draw group id for a given position.\n   *\n   * @param {Index} currentPosition The current position.\n   * @returns {string} The group id.\n   */\n  function getDrawPositionGroupId(currentPosition) {\n    const sliceNumber = currentPosition.get(2);\n    const frameNumber = currentPosition.length() === 4\n      ? currentPosition.get(3) : 0;\n    return 'slice-' + sliceNumber + '_frame-' + frameNumber;\n  }\n\n  const drawLayer = new Konva.Layer({\n    listening: false,\n    visible: true\n  });\n\n  // Get the positions-groups data\n  const groupDrawings = typeof drawings === 'string'\n    ? JSON.parse(drawings) : drawings;\n  // Iterate over each position-groups\n  for (let k = 0, lenk = groupDrawings.length; k < lenk; ++k) {\n    // Iterate over each frame\n    for (let f = 0, lenf = groupDrawings[k].length; f < lenf; ++f) {\n      groupShapes = groupDrawings[k][f];\n      if (groupShapes.length !== 0) {\n        // Create position-group set as visible and append it to drawLayer\n        parentGroup = new Konva.Group({\n          id: getDrawPositionGroupId(new Index([1, 1, k, f])),\n          name: 'position-group',\n          visible: false\n        });\n\n        // Iterate over shapes-group\n        for (let g = 0, leng = groupShapes.length; g < leng; ++g) {\n          // create the konva group\n          group = Konva.Node.create(groupShapes[g]);\n          // enforce draggable: only the shape was draggable in v0.2,\n          // now the whole group is.\n          group.draggable(true);\n          group.getChildren().forEach(function (gnode) {\n            gnode.draggable(false);\n          });\n          // add to position group\n          parentGroup.add(group);\n        }\n        // add to layer\n        drawLayer.add(parentGroup);\n      }\n    }\n  }\n\n  return drawLayer;\n}\n\n/**\n * Convert drawings from v0.1 to v0.2:\n * - v0.1: text on its own,\n * - v0.2: text as part of label.\n *\n * @param {Array} inputDrawings An array of drawings.\n * @returns {object} The converted drawings.\n */\nfunction v01Tov02DrawingsAndDetails(inputDrawings) {\n  const newDrawings = [];\n  const drawingsDetails = {};\n\n  let drawGroups;\n  let drawGroup;\n  // loop over each slice\n  for (let k = 0, lenk = inputDrawings.length; k < lenk; ++k) {\n    // loop over each frame\n    newDrawings[k] = [];\n    for (let f = 0, lenf = inputDrawings[k].length; f < lenf; ++f) {\n      // draw group\n      drawGroups = inputDrawings[k][f];\n      const newFrameDrawings = [];\n      // Iterate over shapes-group\n      for (let g = 0, leng = drawGroups.length; g < leng; ++g) {\n        // create konva group from input\n        drawGroup = Konva.Node.create(drawGroups[g]);\n        // force visible (not set in state)\n        drawGroup.visible(true);\n        // label position\n        let pos = {x: 0, y: 0};\n        // update shape colour\n        const kshape = drawGroup.getChildren(function (node) {\n          return node.name() === 'shape';\n        })[0];\n        kshape.stroke(colourNameToHex(kshape.stroke()));\n        // special line case\n        if (drawGroup.name() === 'line-group') {\n          // update name\n          drawGroup.name('ruler-group');\n          // add ticks\n          const ktick0 = new Konva.Line({\n            points: [kshape.points()[0],\n              kshape.points()[1],\n              kshape.points()[0],\n              kshape.points()[1]],\n            name: 'shape-tick0'\n          });\n          drawGroup.add(ktick0);\n          const ktick1 = new Konva.Line({\n            points: [kshape.points()[2],\n              kshape.points()[3],\n              kshape.points()[2],\n              kshape.points()[3]],\n            name: 'shape-tick1'\n          });\n          drawGroup.add(ktick1);\n        }\n        // special protractor case: update arc name\n        const karcs = drawGroup.getChildren(function (node) {\n          return node.name() === 'arc';\n        });\n        if (karcs.length === 1) {\n          karcs[0].name('shape-arc');\n        }\n        // get its text\n        const ktexts = drawGroup.getChildren(function (node) {\n          return node.name() === 'text';\n        });\n        // update text: move it into a label\n        let ktext = new Konva.Text({\n          name: 'text',\n          text: ''\n        });\n        if (ktexts.length === 1) {\n          pos.x = ktexts[0].x();\n          pos.y = ktexts[0].y();\n          // remove it from the group\n          ktexts[0].remove();\n          // use it\n          ktext = ktexts[0];\n        } else {\n          // use shape position if no text\n          if (kshape.points().length !== 0) {\n            pos = {x: kshape.points()[0],\n              y: kshape.points()[1]};\n          }\n        }\n        // create new label with text and tag\n        const klabel = new Konva.Label({\n          x: pos.x,\n          y: pos.y,\n          name: 'label'\n        });\n        klabel.add(ktext);\n        klabel.add(new Konva.Tag());\n        // add label to group\n        drawGroup.add(klabel);\n        // add group to list\n        newFrameDrawings.push(JSON.stringify(drawGroup.toObject()));\n\n        // create details (v0.3 format)\n        let textExpr = ktext.text();\n        const txtLen = textExpr.length;\n        let quant = null;\n        // adapt to text with flag\n        if (drawGroup.name() === 'ruler-group') {\n          quant = {\n            length: {\n              value: parseFloat(textExpr.substring(0, txtLen - 2)),\n              unit: textExpr.substring(-2)\n            }\n          };\n          textExpr = '{length}';\n        } else if (drawGroup.name() === 'ellipse-group' ||\n                    drawGroup.name() === 'rectangle-group') {\n          quant = {\n            surface: {\n              value: parseFloat(textExpr.substring(0, txtLen - 3)),\n              unit: textExpr.substring(-3)\n            }\n          };\n          textExpr = '{surface}';\n        } else if (drawGroup.name() === 'protractor-group' ||\n                    drawGroup.name() === 'rectangle-group') {\n          quant = {\n            angle: {\n              value: parseFloat(textExpr.substring(0, txtLen - 1)),\n              unit: textExpr.substring(-1)\n            }\n          };\n          textExpr = '{angle}';\n        }\n        // set details\n        drawingsDetails[drawGroup.id()] = {\n          textExpr: textExpr,\n          longText: '',\n          quant: quant\n        };\n\n      }\n      newDrawings[k].push(newFrameDrawings);\n    }\n  }\n\n  return {drawings: newDrawings, drawingsDetails: drawingsDetails};\n}\n\n/**\n * Convert drawing details from v0.2 to v0.3:\n * - v0.2: array [nslices][nframes] with all,\n * - v0.3: simple array of objects referenced by draw ids.\n *\n * @param {Array} details An array of drawing details.\n * @returns {object} The converted drawings.\n */\nfunction v02Tov03DrawingsDetails(details) {\n  const res = {};\n  // Get the positions-groups data\n  const groupDetails = typeof details === 'string'\n    ? JSON.parse(details) : details;\n  // Iterate over each position-groups\n  for (let k = 0, lenk = groupDetails.length; k < lenk; ++k) {\n    // Iterate over each frame\n    for (let f = 0, lenf = groupDetails[k].length; f < lenf; ++f) {\n      // Iterate over shapes-group\n      for (let g = 0, leng = groupDetails[k][f].length; g < leng; ++g) {\n        const group = groupDetails[k][f][g];\n        res[group.id] = {\n          textExpr: group.textExpr,\n          longText: group.longText,\n          quant: group.quant\n        };\n      }\n    }\n  }\n  return res;\n}\n\n/**\n * Convert drawing details from v0.3 to v0.4:\n * - v0.3: properties at group root,\n * - v0.4: properties in group meta object.\n *\n * @param {Array} details An array of drawing details.\n * @returns {object} The converted drawings.\n */\nfunction v03Tov04DrawingsDetails(details) {\n  const res = {};\n  const keys = Object.keys(details);\n  // Iterate over each position-groups\n  for (let k = 0, lenk = keys.length; k < lenk; ++k) {\n    const detail = details[keys[k]];\n    res[keys[k]] = {\n      meta: {\n        textExpr: detail.textExpr,\n        longText: detail.longText,\n        quantification: detail.quant\n      }\n    };\n  }\n  return res;\n}\n\n/**\n * Convert drawing from v0.4 to v0.5:\n * - v0.4: position as object,\n * - v0.5: position as array.\n *\n * @param {object} data An array of drawing.\n * @returns {object} The converted drawings.\n */\nfunction v04Tov05Data(data) {\n  const pos = data.position;\n  data.position = [pos.i, pos.j, pos.k];\n  return data;\n}\n\n/**\n * Convert drawing from v0.4 to v0.5:\n * - v0.4: draw id as 'slice-0_frame-1',\n * - v0.5: draw id as '#2-0_#3-1'.\n *\n * @param {object} inputDrawings An array of drawing.\n * @returns {object} The converted drawings.\n */\nfunction v04Tov05Drawings(inputDrawings) {\n  // Iterate over each position-groups\n  const posGroups = inputDrawings.children;\n  for (let k = 0, lenk = posGroups.length; k < lenk; ++k) {\n    const posGroup = posGroups[k];\n    const id = posGroup.attrs.id;\n    const ids = id.split('_');\n    const sliceNumber = parseInt(ids[0].substring(6), 10); // 'slice-0'\n    const frameNumber = parseInt(ids[1].substring(6), 10); // 'frame-0'\n    let newId = '#2-';\n    if (sliceNumber === 0 && frameNumber !== 0) {\n      newId += frameNumber;\n    } else {\n      newId += sliceNumber;\n    }\n    posGroup.attrs.id = newId;\n  }\n  return inputDrawings;\n}\n","import {logger} from './logger';\nimport {splitKeyValueString} from './string';\n\n/**\n * Get an full object URL from a string uri.\n *\n * @param {string} uri A string representing the url.\n * @returns {URL} A URL object.\n */\nexport function getUrlFromUri(uri) {\n  // add base to allow for relative urls\n  // (base is not used for absolute urls)\n  let base;\n  if (window.location.origin !== 'null') {\n    base = window.location.origin;\n  }\n  return new URL(uri, base);\n}\n\n/**\n * Split an input URI:\n * 'root?key0=val00&key0=val01&key1=val10' returns\n * { base : root, query : [ key0 : [val00, val01], key1 : val1 ] }\n * Returns an empty object if the input string is not correct (null, empty...)\n * or if it is not a query string (no question mark).\n *\n * @param {string} uri The string to split.\n * @returns {object} The split string.\n */\nexport function splitUri(uri) {\n  // result\n  const result = {};\n  // check if query string\n  let sepIndex = null;\n  if (uri && (sepIndex = uri.indexOf('?')) !== -1) {\n    // base: before the '?'\n    result.base = uri.substring(0, sepIndex);\n    // query : after the '?' and until possible '#'\n    let hashIndex = uri.indexOf('#');\n    if (hashIndex === -1) {\n      hashIndex = uri.length;\n    }\n    const query = uri.substring(sepIndex + 1, hashIndex);\n    // split key/value pairs of the query\n    result.query = splitKeyValueString(query);\n  }\n  // return\n  return result;\n}\n\n/**\n * Get the query part, split into an array, of an input URI.\n * The URI scheme is: `base?query#fragment`.\n *\n * @param {string} uri The input URI.\n * @returns {object} The query part, split into an array, of the input URI.\n */\nexport function getUriQuery(uri) {\n  // split\n  const parts = splitUri(uri);\n  // check not empty\n  if (Object.keys(parts).length === 0) {\n    return null;\n  }\n  // return query\n  return parts.query;\n}\n\n/**\n * Generic URI query decoder.\n * Supports manifest:\n *   `[dwv root]?input=encodeURIComponent('[manifest file]')&type=manifest`.\n * Or encoded URI with base and key value/pairs:\n *   `[dwv root]?input=encodeURIComponent([root]?key0=value0&key1=value1)`.\n *\n * @param {object} query The query part to the input URI.\n * @param {Function} callback The function to call with the decoded file urls.\n * @param {object} options Optional url request options.\n */\nexport function decodeQuery(query, callback, options) {\n  // manifest\n  if (query.type && query.type === 'manifest') {\n    decodeManifestQuery(query, callback);\n  } else {\n    // default case: encoded URI with base and key/value pairs\n    callback(\n      decodeKeyValueUri(query.input, query.dwvReplaceMode),\n      options);\n  }\n}\n\n/**\n * Decode a Key/Value pair URI. If a key is repeated, the result\n *   be an array of base + each key.\n *\n * @param {string} uri The URI to decode.\n * @param {string} replaceMode The key replace mode. Can be:\n * - key (default): keep the key\n * - other than key: do not use the key\n *   'file' is a special case where the '?' of the query is not kept.\n * @returns {string[]} The list of input file urls.\n */\nexport function decodeKeyValueUri(uri, replaceMode) {\n  const result = [];\n\n  // repeat key replace mode (default to keep key)\n  let repeatKeyReplaceMode = 'key';\n  if (replaceMode) {\n    repeatKeyReplaceMode = replaceMode;\n  }\n\n  // decode input URI\n  const queryUri = decodeURIComponent(uri);\n  // get key/value pairs from input URI\n  const inputQueryPairs = splitUri(queryUri);\n  if (Object.keys(inputQueryPairs).length === 0) {\n    result.push(queryUri);\n  } else {\n    const keys = Object.keys(inputQueryPairs.query);\n    // find repeat key\n    let repeatKey = null;\n    for (let i = 0; i < keys.length; ++i) {\n      if (inputQueryPairs.query[keys[i]] instanceof Array) {\n        repeatKey = keys[i];\n        break;\n      }\n    }\n\n    if (!repeatKey) {\n      result.push(queryUri);\n    } else {\n      const repeatList = inputQueryPairs.query[repeatKey];\n      // build base uri\n      let baseUrl = inputQueryPairs.base;\n      // add '?' when:\n      // - base is not empty\n      // - the repeatKey is not 'file'\n      // root/path/to/?file=0.jpg&file=1.jpg\n      if (baseUrl !== '' && repeatKey !== 'file') {\n        baseUrl += '?';\n      }\n      let gotOneArg = false;\n      for (let j = 0; j < keys.length; ++j) {\n        if (keys[j] !== repeatKey) {\n          if (gotOneArg) {\n            baseUrl += '&';\n          }\n          baseUrl += keys[j] + '=' + inputQueryPairs.query[keys[j]];\n          gotOneArg = true;\n        }\n      }\n      // append built urls to result\n      let url;\n      for (let k = 0; k < repeatList.length; ++k) {\n        url = baseUrl;\n        if (gotOneArg) {\n          url += '&';\n        }\n        if (repeatKeyReplaceMode === 'key') {\n          url += repeatKey + '=';\n        }\n        // other than 'key' mode: do nothing\n        url += repeatList[k];\n        result.push(url);\n      }\n    }\n  }\n  // return\n  return result;\n}\n\n/**\n * Decode a manifest query.\n *\n * @external XMLHttpRequest\n * @param {object} query The manifest query: {input, nslices},\n * with input the input URI and nslices the number of slices.\n * @param {Function} callback The function to call with the decoded urls.\n */\nfunction decodeManifestQuery(query, callback) {\n  let uri = '';\n  if (query.input[0] === '/') {\n    uri = window.location.protocol + '//' + window.location.host;\n  }\n  // TODO: needs to be decoded (decodeURIComponent?\n  uri += query.input;\n\n  /**\n   * Handle error.\n   *\n   * @param {object} event The error event.\n   */\n  function onError(event) {\n    logger.warn('RequestError while receiving manifest: ' +\n      event.target.status);\n  }\n\n  /**\n   * Handle load.\n   *\n   * @param {object} event The load event.\n   */\n  function onLoad(event) {\n    callback(decodeManifest(event.target.responseXML, query.nslices));\n  }\n\n  const request = new XMLHttpRequest();\n  request.open('GET', decodeURIComponent(uri), true);\n  request.responseType = 'document';\n  request.onload = onLoad;\n  request.onerror = onError;\n  request.send(null);\n}\n\n/**\n * Decode an XML manifest.\n *\n * @param {object} manifest The manifest to decode.\n * @param {number} nslices The number of slices to load.\n * @returns {string[]} The decoded manifest.\n */\nexport function decodeManifest(manifest, nslices) {\n  const result = [];\n  // wado url\n  const wadoElement = manifest.getElementsByTagName('wado_query');\n  const wadoURL = wadoElement[0].getAttribute('wadoURL');\n  const rootURL = wadoURL + '?requestType=WADO&contentType=application/dicom&';\n  // patient list\n  const patientList = manifest.getElementsByTagName('Patient');\n  if (patientList.length > 1) {\n    logger.warn('More than one patient, loading first one.');\n  }\n  // study list\n  const studyList = patientList[0].getElementsByTagName('Study');\n  if (studyList.length > 1) {\n    logger.warn('More than one study, loading first one.');\n  }\n  const studyUID = studyList[0].getAttribute('StudyInstanceUID');\n  // series list\n  const seriesList = studyList[0].getElementsByTagName('Series');\n  if (seriesList.length > 1) {\n    logger.warn('More than one series, loading first one.');\n  }\n  const seriesUID = seriesList[0].getAttribute('SeriesInstanceUID');\n  // instance list\n  const instanceList = seriesList[0].getElementsByTagName('Instance');\n  // loop on instances and push links\n  let max = instanceList.length;\n  if (nslices < max) {\n    max = nslices;\n  }\n  for (let i = 0; i < max; ++i) {\n    const sopInstanceUID = instanceList[i].getAttribute('SOPInstanceUID');\n    const link = rootURL +\n        '&studyUID=' + studyUID +\n        '&seriesUID=' + seriesUID +\n        '&objectUID=' + sopInstanceUID;\n    result.push(link);\n  }\n  // return\n  return result;\n}\n","import {ListenerHandler} from './listen';\n\n/**\n * UndoStack class.\n */\nexport class UndoStack {\n  /**\n   * Array of commands.\n   *\n   * @type {Array}\n   */\n  #stack = [];\n\n  /**\n   * Current command index.\n   *\n   * @type {number}\n   */\n  #curCmdIndex = 0;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Get the stack size.\n   *\n   * @returns {number} The size of the stack.\n   */\n  getStackSize() {\n    return this.#stack.length;\n  }\n\n  /**\n   * Get the current stack index.\n   *\n   * @returns {number} The stack index.\n   */\n  getCurrentStackIndex() {\n    return this.#curCmdIndex;\n  }\n\n  /**\n   * Add a command to the stack.\n   *\n   * @param {object} cmd The command to add.\n   * @fires UndoStack#undoadd\n   */\n  add(cmd) {\n    // clear commands after current index\n    this.#stack = this.#stack.slice(0, this.#curCmdIndex);\n    // store command\n    this.#stack.push(cmd);\n    // increment index\n    ++this.#curCmdIndex;\n    /**\n     * Command add to undo stack event.\n     *\n     * @event UndoStack#undoadd\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} command The name of the command added to the\n     *   undo stack.\n     */\n    this.#fireEvent({\n      type: 'undoadd',\n      command: cmd.getName()\n    });\n  }\n\n  /**\n   * Remove a command to the stack.\n   *\n   * @param {string} name The name of the command to remove.\n   * @returns {boolean} True if the command was found and removed.\n   * @fires UndoStack#undoremove\n   */\n  remove(name) {\n    let res = false;\n    const hasInputName = function (element) {\n      return element.getName() === name;\n    };\n    const index = this.#stack.findIndex(hasInputName);\n    if (index !== -1) {\n      // remove command\n      this.#stack.splice(index, 1);\n      // decrement index\n      --this.#curCmdIndex;\n      // result\n      res = true;\n      /**\n       * Command remove from undo stack event.\n       *\n       * @event UndoStack#undoremove\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {string} command The name of the command added to the\n       *   undo stack.\n       */\n      this.#fireEvent({\n        type: 'undoremove',\n        command: name\n      });\n    }\n    return res;\n  }\n\n  /**\n   * Undo the last command.\n   *\n   * @fires UndoStack#undo\n   */\n  undo() {\n    // a bit inefficient...\n    if (this.#curCmdIndex > 0) {\n      // decrement command index\n      --this.#curCmdIndex;\n      // undo last command\n      this.#stack[this.#curCmdIndex].undo();\n      /**\n       * Command undo event.\n       *\n       * @event UndoStack#undo\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {string} command The name of the undone command.\n       */\n      this.#fireEvent({\n        type: 'undo',\n        command: this.#stack[this.#curCmdIndex].getName()\n      });\n    }\n  }\n\n  /**\n   * Redo the last command.\n   *\n   * @fires UndoStack#redo\n   */\n  redo() {\n    if (this.#curCmdIndex < this.#stack.length) {\n      // run last command\n      this.#stack[this.#curCmdIndex].execute();\n      /**\n       * Command redo event.\n       *\n       * @event UndoStack#redo\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {string} command The name of the redone command.\n       */\n      this.#fireEvent({\n        type: 'redo',\n        command: this.#stack[this.#curCmdIndex].getName()\n      });\n      // increment command index\n      ++this.#curCmdIndex;\n    }\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *    event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n} // UndoStack class\n","import {InteractionEventNames} from '../gui/generic';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {LayerGroup} from '../gui/layerGroup';\nimport {ViewLayer} from '../gui/viewLayer';\nimport {DrawLayer} from '../gui/drawLayer';\n/* eslint-enable no-unused-vars */\n\n/**\n * Toolbox controller.\n */\nexport class ToolboxController {\n\n  /**\n   * List of tools to control.\n   *\n   * @type {object}\n   */\n  #toolList;\n\n  /**\n   * Selected tool.\n   *\n   * @type {object}\n   */\n  #selectedTool = null;\n\n  /**\n   * Callback store to allow attach/detach.\n   *\n   * @type {Array}\n   */\n  #callbackStore = [];\n\n  /**\n   * Current layers bound to tool.\n   *\n   * @type {object}\n   */\n  #boundLayers = {};\n\n  /**\n   * @param {object} toolList The list of tool objects.\n   */\n  constructor(toolList) {\n    this.#toolList = toolList;\n  }\n\n  /**\n   * Initialise.\n   */\n  init() {\n    for (const key in this.#toolList) {\n      this.#toolList[key].init();\n    }\n    // enable shortcuts\n    this.enableShortcuts(true);\n  }\n\n  /**\n   * Enable or disable shortcuts. The 'init' methods enables shortcuts\n   *  by default. Call this method after init to disable shortcuts.\n   *\n   * @param {boolean} flag True to enable shortcuts.\n   */\n  enableShortcuts(flag) {\n    if (flag) {\n      window.addEventListener('keydown',\n        this.#getCallback('window', 'keydown'), true);\n    } else {\n      window.removeEventListener('keydown',\n        this.#getCallback('window', 'keydown'), true);\n    }\n  }\n\n  /**\n   * Get the tool list.\n   *\n   * @returns {Array} The list of tool objects.\n   */\n  getToolList() {\n    return this.#toolList;\n  }\n\n  /**\n   * Check if a tool is in the tool list.\n   *\n   * @param {string} name The name to check.\n   * @returns {boolean} The tool list element for the given name.\n   */\n  hasTool(name) {\n    return typeof this.getToolList()[name] !== 'undefined';\n  }\n\n  /**\n   * Get the selected tool.\n   *\n   * @returns {object} The selected tool.\n   */\n  getSelectedTool() {\n    return this.#selectedTool;\n  }\n\n  /**\n   * Get the selected tool event handler.\n   *\n   * @param {string} eventType The event type, for example\n   *   mousedown, touchstart...\n   * @returns {Function} The event handler.\n   */\n  getSelectedToolEventHandler(eventType) {\n    return this.getSelectedTool()[eventType];\n  }\n\n  /**\n   * Set the selected tool.\n   *\n   * @param {string} name The name of the tool.\n   */\n  setSelectedTool(name) {\n    // check if we have it\n    if (!this.hasTool(name)) {\n      throw new Error('Unknown tool: \\'' + name + '\\'');\n    }\n    // de-activate previous\n    if (this.#selectedTool) {\n      this.#selectedTool.activate(false);\n    }\n    // set internal var\n    this.#selectedTool = this.#toolList[name];\n    // activate new tool\n    this.#selectedTool.activate(true);\n  }\n\n  /**\n   * Set the selected tool live features.\n   *\n   * @param {object} list The list of features.\n   */\n  setToolFeatures(list) {\n    if (this.getSelectedTool()) {\n      this.getSelectedTool().setFeatures(list);\n    }\n  }\n\n  /**\n   * Listen to layer interaction events.\n   *\n   * @param {LayerGroup} layerGroup The associated layer group.\n   * @param {ViewLayer|DrawLayer} layer The layer to listen to.\n   */\n  bindLayerGroup(layerGroup, layer) {\n    const divId = layerGroup.getDivId();\n    // listen to active layer changes\n    layerGroup.addEventListener(\n      'activelayerchange', this.#getActiveLayerChangeHandler(divId));\n    // bind the layer\n    this.#internalBindLayerGroup(divId, layer);\n  }\n\n  /**\n   * Bind a layer group to this controller.\n   *\n   * @param {string} layerGroupDivId The layer group div id.\n   * @param {ViewLayer|DrawLayer} layer The layer.\n   */\n  #internalBindLayerGroup(layerGroupDivId, layer) {\n    // remove from local list if preset\n    if (typeof this.#boundLayers[layerGroupDivId] !== 'undefined') {\n      this.#unbindLayer(this.#boundLayers[layerGroupDivId]);\n    }\n    // replace layer in local list\n    this.#boundLayers[layerGroupDivId] = layer;\n    // bind layer\n    this.#bindLayer(layer);\n  }\n\n  /**\n   * Get an active layer change handler.\n   *\n   * @param {string} divId The associated layer group div id.\n   * @returns {Function} The event handler.\n   */\n  #getActiveLayerChangeHandler(divId) {\n    return (event) => {\n      const layer = event.value[0];\n      if (typeof layer !== 'undefined') {\n        this.#internalBindLayerGroup(divId, layer);\n      }\n    };\n  }\n\n  /**\n   * Add canvas mouse and touch listeners to a layer.\n   *\n   * @param {ViewLayer|DrawLayer} layer The layer to start listening to.\n   */\n  #bindLayer(layer) {\n    layer.bindInteraction();\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      layer.addEventListener(names[i],\n        this.#getCallback(layer.getId(), names[i]));\n    }\n  }\n\n  /**\n   * Remove canvas mouse and touch listeners to a layer.\n   *\n   * @param {ViewLayer|DrawLayer} layer The layer to stop listening to.\n   */\n  #unbindLayer(layer) {\n    layer.unbindInteraction();\n    // interaction events\n    const names = InteractionEventNames;\n    for (let i = 0; i < names.length; ++i) {\n      layer.removeEventListener(names[i],\n        this.#getCallback(layer.getId(), names[i]));\n    }\n  }\n\n  /**\n   * Mou(se) and (T)ouch event handler. This function just determines\n   * the mouse/touch position relative to the canvas element.\n   * It then passes it to the current tool.\n   *\n   * @param {string} layerId The layer id.\n   * @param {string} eventType The event type.\n   * @returns {object} A callback for the provided layer and event.\n   */\n  #getCallback(layerId, eventType) {\n    if (typeof this.#callbackStore[layerId] === 'undefined') {\n      this.#callbackStore[layerId] = [];\n    }\n\n    if (typeof this.#callbackStore[layerId][eventType] === 'undefined') {\n      const applySelectedTool = (event) => {\n        // make sure we have a tool\n        if (this.#selectedTool) {\n          const func = this.#selectedTool[event.type];\n          if (func) {\n            func(event);\n          }\n        }\n      };\n      // store callback\n      this.#callbackStore[layerId][eventType] = applySelectedTool;\n    }\n\n    return this.#callbackStore[layerId][eventType];\n  }\n\n} // class ToolboxController\n","/**\n * Multiple progresses handler.\n * Stores a multi dimensional list of progresses to allow to\n * calculate a global progress.\n *\n */\nexport class MultiProgressHandler {\n\n  /**\n   * List of progresses.\n   * First dimension is a list of item for which the progress is recorded,\n   *   for example file names.\n   * Second dimension is a list of possible progresses, for example\n   *   the progress of the download and the progress of the decoding.\n   *\n   * @type {Array}\n   */\n  #progresses = [];\n\n  /**\n   * Number of dimensions.\n   *\n   * @type {number}\n   */\n  #numberOfDimensions = 2;\n\n  /**\n   * Progress callback.\n   *\n   * @type {Function}\n   */\n  #callback;\n\n  /**\n   * @param {Function} callback The function to pass the global progress to.\n   */\n  constructor(callback) {\n    this.#callback = callback;\n  }\n\n  /**\n   * Set the number of dimensions.\n   *\n   * @param {number} num The number.\n   */\n  setNumberOfDimensions(num) {\n    this.#numberOfDimensions = num;\n  }\n\n  /**\n   * Set the number of data to load.\n   *\n   * @param {number} n The number of data to load.\n   */\n  setNToLoad(n) {\n    for (let i = 0; i < n; ++i) {\n      this.#progresses[i] = [];\n      for (let j = 0; j < this.#numberOfDimensions; ++j) {\n        this.#progresses[i][j] = 0;\n      }\n    }\n  }\n\n  /**\n   * Handle a load progress.\n   * Call the member callback with a global event.\n   *\n   * @param {object} event The progress event.\n   */\n  onprogress = (event) => {\n    // check event\n    if (!event.lengthComputable) {\n      return;\n    }\n    if (typeof event.subindex === 'undefined') {\n      return;\n    }\n    if (typeof event.index === 'undefined') {\n      return;\n    }\n    // calculate percent\n    const percent = (event.loaded * 100) / event.total;\n    // set percent for index\n    this.#progresses[event.index][event.subindex] = percent;\n\n    // item progress\n    let item = null;\n    if (typeof event.item !== 'undefined') {\n      item = event.item;\n    } else {\n      item = {\n        loaded: this.#getItemProgress(event.index),\n        total: 100,\n        source: event.source\n      };\n    }\n\n    // call callback with a global event\n    this.#callback({\n      lengthComputable: true,\n      loaded: this.#getGlobalPercent(),\n      total: 100,\n      item: item\n    });\n  };\n\n  /**\n   * Get the item load percent.\n   *\n   * @param {number} index The index of the item.\n   * @returns {number} The load percentage.\n   */\n  #getItemProgress(index) {\n    let sum = 0;\n    for (let j = 0; j < this.#numberOfDimensions; ++j) {\n      sum += this.#progresses[index][j];\n    }\n    return sum / this.#numberOfDimensions;\n  }\n\n  /**\n   * Get the global load percent including the provided one.\n   *\n   * @returns {number} The accumulated percentage.\n   */\n  #getGlobalPercent() {\n    let sum = 0;\n    const lenprog = this.#progresses.length;\n    for (let i = 0; i < lenprog; ++i) {\n      sum += this.#getItemProgress(i);\n    }\n    return Math.round(sum / lenprog);\n  }\n\n\n  /**\n   * @callback eventFn\n   * @param {object} event The event.\n   */\n\n  /**\n   * Create a mono progress event handler.\n   *\n   * @param {number} index The index of the data.\n   * @param {number} subindex The sub-index of the data.\n   * @returns {eventFn} A progress handler function.\n   */\n  getMonoProgressHandler(index, subindex) {\n    return (event) => {\n      event.index = index;\n      event.subindex = subindex;\n      this.onprogress(event);\n    };\n  }\n\n  /**\n   * Create a mono progress event handler with an undefined index.\n   * Warning: The caller handles the progress index.\n   *\n   * @param {number} subindex The sub-index of the data.\n   * @returns {eventFn} A progress handler function.\n   */\n  getUndefinedMonoProgressHandler(subindex) {\n    return (event) => {\n      event.subindex = subindex;\n      this.onprogress(event);\n    };\n  }\n}\n","import {endsWith, getRootPath} from '../utils/string';\nimport {MultiProgressHandler} from '../utils/progress';\nimport {getFileListFromDicomDir} from '../dicom/dicomElementsWrapper';\nimport {loaderList} from './loaderList';\n\n// url content types\nexport const urlContentTypes = {\n  Text: 0,\n  ArrayBuffer: 1\n};\n\n/**\n * Urls loader.\n */\nexport class UrlsLoader {\n\n  /**\n   * Input data.\n   *\n   * @type {string[]}\n   */\n  #inputData = null;\n\n  /**\n   * Array of launched requests.\n   *\n   * @type {XMLHttpRequest[]}\n   */\n  #requests = [];\n\n  /**\n   * Data loader.\n   *\n   * @type {object}\n   */\n  #runningLoader = null;\n\n  /**\n   * Number of loaded data.\n   *\n   * @type {number}\n   */\n  #nLoad = 0;\n\n  /**\n   * Number of load end events.\n   *\n   * @type {number}\n   */\n  #nLoadend = 0;\n\n  /**\n   * Flag to know if the load is aborting.\n   *\n   * @type {boolean}\n   */\n  #aborting;\n\n  /**\n   * The default character set (optional).\n   *\n   * @type {string}\n   */\n  #defaultCharacterSet;\n\n  /**\n   * Get the default character set.\n   *\n   * @returns {string} The default character set.\n   */\n  getDefaultCharacterSet() {\n    return this.#defaultCharacterSet;\n  }\n\n  /**\n   * Set the default character set.\n   *\n   * @param {string} characterSet The character set.\n   */\n  setDefaultCharacterSet(characterSet) {\n    this.#defaultCharacterSet = characterSet;\n  }\n\n  /**\n   * Store the current input.\n   *\n   * @param {string[]} data The input data.\n   */\n  #storeInputData(data) {\n    this.#inputData = data;\n    // reset counters\n    this.#nLoad = 0;\n    this.#nLoadend = 0;\n    // reset flag\n    this.#aborting = false;\n    // clear storage\n    this.#clearStoredRequests();\n    this.#clearStoredLoader();\n  }\n\n  /**\n   * Store a launched request.\n   *\n   * @param {XMLHttpRequest} request The launched request.\n   */\n  #storeRequest(request) {\n    this.#requests.push(request);\n  }\n\n  /**\n   * Clear the stored requests.\n   *\n   */\n  #clearStoredRequests() {\n    this.#requests = [];\n  }\n\n  /**\n   * Store the launched loader.\n   *\n   * @param {object} loader The launched loader.\n   */\n  #storeLoader(loader) {\n    this.#runningLoader = loader;\n  }\n\n  /**\n   * Clear the stored loader.\n   *\n   */\n  #clearStoredLoader() {\n    this.#runningLoader = null;\n  }\n\n  /**\n   * Increment the number of loaded data\n   *   and call onload if loaded all data.\n   *\n   * @param {object} _event The load data event.\n   */\n  #addLoad = (_event) => {\n    this.#nLoad++;\n    // call onload when all is loaded\n    // (not using the input event since it is\n    //   an individual load)\n    if (this.#nLoad === this.#inputData.length) {\n      this.onload({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * Increment the counter of load end events\n   *   and run callbacks when all done, erroneus or not.\n   *\n   * @param {object} _event The load end event.\n   */\n  #addLoadend = (_event) => {\n    this.#nLoadend++;\n    // call onloadend when all is run\n    // (not using the input event since it is\n    //   an individual load end)\n    if (this.#nLoadend === this.#inputData.length) {\n      this.onloadend({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * @callback eventFn\n   * @param {object} event The event.\n   */\n\n  /**\n   * Augment a callback event with a srouce.\n   *\n   * @param {object} callback The callback to augment its event.\n   * @param {object} source The source to add to the event.\n   * @returns {eventFn} The augmented callback.\n   */\n  #augmentCallbackEvent(callback, source) {\n    return (event) => {\n      event.source = source;\n      callback(event);\n    };\n  }\n\n  /**\n   * Load a list of URLs or a DICOMDIR.\n   *\n   * @param {string[]} data The list of urls to load.\n   * @param {object} [options] Load options.\n   */\n  load(data, options) {\n    // send start event\n    this.onloadstart({\n      source: data\n    });\n\n    // check if DICOMDIR case\n    if (data.length === 1 &&\n      (endsWith(data[0], 'DICOMDIR') ||\n      endsWith(data[0], '.dcmdir'))) {\n      this.#loadDicomDir(data[0], options);\n    } else {\n      this.#loadUrls(data, options);\n    }\n  }\n\n  /**\n   * Get a load handler for a data element.\n   *\n   * @param {object} loader The associated loader.\n   * @param {string} dataElement The data element.\n   * @param {number} i The index of the element.\n   * @returns {eventFn} A load handler.\n   */\n  #getLoadHandler(loader, dataElement, i) {\n    return (event) => {\n      // check response status\n      // https://developer.mozilla.org/en-US/docs/Web/HTTP/Response_codes\n      // status 200: \"OK\"; status 0: \"debug\"\n      const status = event.target.status;\n      if (status !== 200 && status !== 0) {\n        this.onerror({\n          source: dataElement,\n          error: 'GET ' + event.target.responseURL +\n            ' ' + event.target.status +\n            ' (' + event.target.statusText + ')',\n          target: event.target\n        });\n        this.#addLoadend();\n      } else {\n        loader.load(event.target.response, dataElement, i);\n      }\n    };\n  }\n\n  /**\n   * Load a list of urls.\n   *\n   * @param {string[]} data The list of urls to load.\n   * @param {object} [options] The options object, can contain:\n   * - requestHeaders: an array of {name, value} to use as request headers,\n   * - withCredentials: boolean xhr.withCredentials flag to pass\n   *   to the request,\n   * - batchSize: the size of the request url batch.\n   */\n  #loadUrls(data, options) {\n    // check input\n    if (typeof data === 'undefined' || data.length === 0) {\n      return;\n    }\n    this.#storeInputData(data);\n\n    // create prgress handler\n    const mproghandler = new MultiProgressHandler(this.onprogress);\n    mproghandler.setNToLoad(data.length);\n\n    // create loaders\n    const loaders = [];\n    for (let m = 0; m < loaderList.length; ++m) {\n      loaders.push(new loaderList[m]());\n    }\n\n    // find an appropriate loader\n    let dataElement = data[0];\n    let loader = null;\n    let foundLoader = false;\n    for (let l = 0; l < loaders.length; ++l) {\n      loader = loaders[l];\n      if (loader.canLoadUrl(dataElement, options)) {\n        foundLoader = true;\n        // load options\n        loader.setOptions({\n          numberOfFiles: data.length,\n          defaultCharacterSet: this.getDefaultCharacterSet()\n        });\n        // set loader callbacks\n        // loader.onloadstart: nothing to do\n        loader.onprogress = mproghandler.getUndefinedMonoProgressHandler(1);\n        loader.onloaditem = this.onloaditem;\n        loader.onload = this.#addLoad;\n        loader.onloadend = this.#addLoadend;\n        loader.onerror = this.onerror;\n        loader.onabort = this.onabort;\n\n        // store loader\n        this.#storeLoader(loader);\n        // exit\n        break;\n      }\n    }\n    if (!foundLoader) {\n      throw new Error('No loader found for url: ' + dataElement);\n    }\n\n    // store last run request index\n    let lastRunRequestIndex = 0;\n    const requestOnLoadEnd = () => {\n      // launch next in queue\n      if (lastRunRequestIndex < this.#requests.length - 1 && !this.#aborting) {\n        ++lastRunRequestIndex;\n        this.#requests[lastRunRequestIndex].send(null);\n      }\n    };\n\n    // loop on I/O elements\n    for (let i = 0; i < data.length; ++i) {\n      dataElement = data[i];\n\n      // check loader\n      if (!loader.canLoadUrl(dataElement, options)) {\n        throw new Error('Input url of different type: ' + dataElement);\n      }\n      /**\n       * The http request.\n       *\n       * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest}.\n       *\n       * @external XMLHttpRequest\n       */\n      const request = new XMLHttpRequest();\n      request.open('GET', dataElement, true);\n\n      // request options\n      if (typeof options !== 'undefined') {\n        // optional request headers\n        if (typeof options.requestHeaders !== 'undefined') {\n          const requestHeaders = options.requestHeaders;\n          for (let j = 0; j < requestHeaders.length; ++j) {\n            if (typeof requestHeaders[j].name !== 'undefined' &&\n              typeof requestHeaders[j].value !== 'undefined') {\n              request.setRequestHeader(\n                requestHeaders[j].name, requestHeaders[j].value);\n            }\n          }\n        }\n        // optional withCredentials\n        // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials\n        if (typeof options.withCredentials !== 'undefined') {\n          request.withCredentials = options.withCredentials;\n        }\n      }\n\n      // set request callbacks\n      // request.onloadstart: nothing to do\n      request.onprogress = this.#augmentCallbackEvent(\n        mproghandler.getMonoProgressHandler(i, 0), dataElement);\n      request.onload = this.#getLoadHandler(loader, dataElement, i);\n      request.onloadend = requestOnLoadEnd;\n      const errorCallback =\n        this.#augmentCallbackEvent(this.onerror, dataElement);\n      request.onerror = (event) => {\n        this.#addLoadend();\n        errorCallback(event);\n      };\n      const timeoutCallback =\n        this.#augmentCallbackEvent(this.ontimeout, dataElement);\n      request.ontimeout = (event) => {\n        this.#addLoadend();\n        timeoutCallback(event);\n      };\n      const abortCallback =\n        this.#augmentCallbackEvent(this.onabort, dataElement);\n      request.onabort = (event) => {\n        this.#addLoadend();\n        abortCallback(event);\n      };\n      // response type (default is 'text')\n      if (loader.loadUrlAs() === urlContentTypes.ArrayBuffer) {\n        request.responseType = 'arraybuffer';\n      }\n\n      // store request\n      this.#storeRequest(request);\n    }\n\n    // launch requests in batch\n    let batchSize = this.#requests.length;\n    if (typeof options !== 'undefined') {\n      // optional request batch size\n      if (typeof options.batchSize !== 'undefined' && batchSize !== 0) {\n        batchSize = Math.min(options.batchSize, this.#requests.length);\n      }\n    }\n    for (let r = 0; r < batchSize; ++r) {\n      if (!this.#aborting) {\n        lastRunRequestIndex = r;\n        this.#requests[lastRunRequestIndex].send(null);\n      }\n    }\n  }\n\n  /**\n   * Load a DICOMDIR.\n   *\n   * @param {string} dicomDirUrl The DICOMDIR url.\n   * @param {object} [options] Load options.\n   */\n  #loadDicomDir(dicomDirUrl, options) {\n    // read DICOMDIR\n    const request = new XMLHttpRequest();\n    request.open('GET', dicomDirUrl, true);\n    request.responseType = 'arraybuffer';\n    // request.onloadstart: nothing to do\n    /**\n     * @param {object} event The load event.\n     */\n    request.onload = (event) => {\n      // check status\n      const status = event.target.status;\n      if (status !== 200 && status !== 0) {\n        this.onerror({\n          source: dicomDirUrl,\n          error: 'GET ' + event.target.responseURL +\n            ' ' + event.target.status +\n            ' (' + event.target.statusText + ')',\n          target: event.target\n        });\n        this.onloadend({});\n      } else {\n        // get the file list\n        const list = getFileListFromDicomDir(event.target.response);\n        // use the first list\n        const urls = list[0][0];\n        // append root url\n        const rootUrl = getRootPath(dicomDirUrl);\n        const fullUrls = [];\n        for (let i = 0; i < urls.length; ++i) {\n          fullUrls.push(rootUrl + '/' + urls[i]);\n        }\n        // load urls\n        this.#loadUrls(fullUrls, options);\n      }\n    };\n    request.onerror = (event) => {\n      this.#augmentCallbackEvent(this.onerror, dicomDirUrl)(event);\n      this.onloadend({});\n    };\n    request.onabort = (event) => {\n      this.#augmentCallbackEvent(this.onabort, dicomDirUrl)(event);\n      this.onloadend({});\n    };\n    // request.onloadend: nothing to do\n    // send request\n    request.send(null);\n  }\n\n  /**\n   * Abort a load.\n   */\n  abort() {\n    this.#aborting = true;\n    // abort non finished requests\n    for (let i = 0; i < this.#requests.length; ++i) {\n      // 0: UNSENT, 1: OPENED, 2: HEADERS_RECEIVED (send()), 3: LOADING, 4: DONE\n      if (this.#requests[i].readyState !== 4) {\n        this.#requests[i].abort();\n      }\n    }\n    // abort loader\n    if (this.#runningLoader && this.#runningLoader.isLoading()) {\n      this.#runningLoader.abort();\n    }\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle a load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle a timeout event.\n   * Default does nothing.\n   *\n   * @param {object} _event The timeout event.\n   */\n  ontimeout(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class UrlsLoader\n","/**\n * Thread Pool.\n *\n * Highly inspired from {@link http://www.smartjava.org/content/html5-easily-parallelize-jobs-using-web-workers-and-threadpool}.\n */\nexport class ThreadPool {\n\n  /**\n   * @param {number} poolSize The size of the pool.\n   */\n  constructor(poolSize) {\n    this.poolSize = poolSize;\n    // task queue\n    this.taskQueue = [];\n    // lsit of available threads\n    this.freeThreads = [];\n    // create 'poolSize' number of worker threads\n    for (let i = 0; i < poolSize; ++i) {\n      this.freeThreads.push(new WorkerThread(this));\n    }\n    // list of running threads (unsed in abort)\n    this.runningThreads = [];\n  }\n\n  /**\n   * Add a worker task to the queue.\n   * Will be run when a thread is made available.\n   *\n   * @param {object} workerTask The task to add to the queue.\n   */\n  addWorkerTask(workerTask) {\n    // send work start if first task\n    if (this.freeThreads.length === this.poolSize) {\n      this.onworkstart({type: 'work-start'});\n    }\n    // launch task or queue\n    if (this.freeThreads.length > 0) {\n      // get the first free worker thread\n      const workerThread = this.freeThreads.shift();\n      // add the thread to the runnning list\n      this.runningThreads.push(workerThread);\n      // run the input task\n      workerThread.run(workerTask);\n    } else {\n      // no free thread, add task to queue\n      this.taskQueue.push(workerTask);\n    }\n  }\n\n  /**\n   * Abort all threads.\n   */\n  abort() {\n    // stop all threads\n    this.#stop();\n    // callback\n    this.onabort({type: 'work-abort'});\n    this.onworkend({type: 'work-end'});\n  }\n\n  /**\n   * Handle a task end.\n   *\n   * @param {object} workerThread The thread to free.\n   */\n  onTaskEnd(workerThread) {\n    // launch next task in queue or finish\n    if (this.taskQueue.length > 0) {\n      // get waiting task\n      const workerTask = this.taskQueue.shift();\n      // use input thread to run the waiting task\n      workerThread.run(workerTask);\n    } else {\n      // stop the worker\n      workerThread.stop();\n      // no task to run, add to free list\n      this.freeThreads.push(workerThread);\n      // remove from running list\n      for (let i = 0; i < this.runningThreads.length; ++i) {\n        if (this.runningThreads[i].getId() === workerThread.getId()) {\n          this.runningThreads.splice(i, 1);\n        }\n      }\n      // the work is done when the queue is back to its initial size\n      if (this.freeThreads.length === this.poolSize) {\n        this.onwork({type: 'work'});\n        this.onworkend({type: 'work-end'});\n      }\n    }\n  }\n\n  /**\n   * Handle an error message from a worker.\n   *\n   * @param {object} event The error event.\n   */\n  handleWorkerError = (event) => {\n    // stop all threads\n    this.#stop();\n    // callback\n    this.onerror({error: event});\n    this.onworkend({type: 'work-end'});\n  };\n\n  // private ----------------------------------------------------------------\n\n  /**\n   * Stop the pool: stop all running threads.\n   *\n   */\n  #stop() {\n    // clear tasks\n    this.taskQueue = [];\n    // cancel running workers\n    for (let i = 0; i < this.runningThreads.length; ++i) {\n      this.runningThreads[i].stop();\n    }\n    this.runningThreads = [];\n  }\n\n\n  /**\n   * Handle a work start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The work start event.\n   */\n  onworkstart(_event) {}\n\n  /**\n   * Handle a work item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The work item event fired\n   *   when a work item ended successfully.\n   */\n  onworkitem(_event) {}\n\n  /**\n   * Handle a work event.\n   * Default does nothing.\n   *\n   * @param {object} _event The work event fired\n   *   when a work ended successfully.\n   */\n  onwork(_event) {}\n\n  /**\n   * Handle a work end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The work end event fired\n   *  when a work has completed, successfully or not.\n   */\n  onworkend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // ThreadPool\n\n/**\n * Worker background task.\n *\n * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/Worker}.\n *\n * @external Worker\n */\n\n/**\n * Worker thread.\n */\nclass WorkerThread {\n\n  /**\n   * @param {object} parentPool The parent pool.\n   */\n  constructor(parentPool) {\n    this.parentPool = parentPool;\n    // thread ID\n    this.id = Math.random().toString(36).substring(2, 15);\n    // running task\n    this.runningTask = null;\n    // worker used to run task\n    this.worker;\n  }\n\n  /**\n   * Get the thread ID.\n   *\n   * @returns {string} The thread ID (alphanumeric).\n   */\n  getId() {\n    return this.id;\n  }\n\n  /**\n   * Run a worker task.\n   *\n   * @param {object} workerTask The task to run.\n   */\n  run(workerTask) {\n    // store task\n    this.runningTask = workerTask;\n    // create a new web worker if not done yet\n    if (typeof this.worker === 'undefined') {\n      this.worker = new Worker(this.runningTask.script);\n      // set callbacks\n      this.worker.onmessage = this.onmessage;\n      this.worker.onerror = this.onerror;\n    }\n    // launch the worker\n    this.worker.postMessage(this.runningTask.startMessage);\n  }\n\n  /**\n   * Finish a task and tell the parent.\n   */\n  stop() {\n    // stop the worker\n    if (typeof this.worker !== 'undefined') {\n      this.worker.terminate();\n      // force create at next run\n      this.worker = undefined;\n    }\n  }\n\n  /**\n   * Message event handler.\n   * For now assume we only get a single callback from a worker\n   * which also indicates the end of this worker.\n   *\n   * @param {object} event The message event.\n   */\n  onmessage = (event) => {\n    // augment event\n    event.itemNumber = this.runningTask.info.itemNumber;\n    event.numberOfItems = this.runningTask.info.numberOfItems;\n    event.index = this.runningTask.info.index;\n    // send event\n    this.parentPool.onworkitem(event);\n    // tell the parent pool the task is done\n    this.parentPool.onTaskEnd(this);\n  };\n\n  /**\n   * Error event handler.\n   *\n   * @param {object} event The error event.\n   */\n  onerror = (event) => {\n    // augment event\n    event.itemNumber = this.runningTask.info.itemNumber;\n    event.numberOfItems = this.runningTask.info.numberOfItems;\n    event.index = this.runningTask.info.index;\n    // pass to parent\n    this.parentPool.handleWorkerError(event);\n    // stop the worker and free the thread\n    this.stop();\n  };\n} // class WorkerThread\n\n/**\n * Worker task.\n */\nexport class WorkerTask {\n  /**\n   * @param {string} script The worker script.\n   * @param {object} message The data to pass to the worker.\n   * @param {object} info Information object about the input data.\n   */\n  constructor(script, message, info) {\n    // worker script\n    this.script = script;\n    // worker start message\n    this.startMessage = message;\n    // information about the work data\n    this.info = info;\n  }\n}\n","import {ThreadPool, WorkerTask} from '../utils/thread';\n\n/**\n * The JPEG baseline decoder.\n *\n * Ref: {@link https://github.com/mozilla/pdf.js/blob/master/src/core/jpg.js}.\n *\n * @external JpegImage\n */\n/* global JpegImage */\n// @ts-ignore\nconst hasJpegBaselineDecoder = (typeof JpegImage !== 'undefined');\n\n/**\n * The JPEG decoder namespace.\n *\n * Ref: {@link https://github.com/rii-mango/JPEGLosslessDecoderJS}.\n *\n * @external jpeg\n */\n/* global jpeg */\nconst hasJpegLosslessDecoder =\n  // @ts-ignore\n  (typeof jpeg !== 'undefined') && (typeof jpeg.lossless !== 'undefined');\n\n/**\n * The JPEG 2000 decoder.\n *\n * Ref: {@link https://github.com/jpambrun/jpx-medical/blob/master/jpx.js}.\n *\n * @external JpxImage\n */\n/* global JpxImage */\n// @ts-ignore\nconst hasJpeg2000Decoder = (typeof JpxImage !== 'undefined');\n\n/* global dwvdecoder */\n\n/**\n * Decoder scripts to be passed to web workers for image decoding.\n */\nexport const decoderScripts = {\n  jpeg2000: '',\n  'jpeg-lossless': '',\n  'jpeg-baseline': '',\n  rle: ''\n};\n\n/**\n * Asynchronous pixel buffer decoder.\n */\nclass AsynchPixelBufferDecoder {\n\n  /**\n   * The associated worker script.\n   *\n   * @type {string}\n   */\n  #script;\n\n  /**\n   * Associated thread pool.\n   *\n   * @type {ThreadPool}\n   */\n  #pool = new ThreadPool(10);\n\n  /**\n   * Flag to know if callbacks are set.\n   *\n   * @type {boolean}\n   */\n  #areCallbacksSet = false;\n\n  /**\n   * @param {string} script The path to the decoder script to be used\n   *   by the web worker.\n   * @param {number} _numberOfData The anticipated number of data to decode.\n   */\n  constructor(script, _numberOfData) {\n    this.#script = script;\n  }\n\n  /**\n   * Decode a pixel buffer.\n   *\n   * @param {Array} pixelBuffer The pixel buffer.\n   * @param {object} pixelMeta The input meta data.\n   * @param {object} info Information object about the input data.\n   */\n  decode(pixelBuffer, pixelMeta, info) {\n    if (!this.#areCallbacksSet) {\n      this.#areCallbacksSet = true;\n      // set event handlers\n      this.#pool.onworkstart = this.ondecodestart;\n      this.#pool.onworkitem = this.ondecodeditem;\n      this.#pool.onwork = this.ondecoded;\n      this.#pool.onworkend = this.ondecodeend;\n      this.#pool.onerror = this.onerror;\n      this.#pool.onabort = this.onabort;\n    }\n    // create worker task\n    const workerTask = new WorkerTask(\n      this.#script,\n      {\n        buffer: pixelBuffer,\n        meta: pixelMeta\n      },\n      info\n    );\n    // add it the queue and run it\n    this.#pool.addWorkerTask(workerTask);\n  }\n\n  /**\n   * Abort decoding.\n   */\n  abort() {\n    // abort the thread pool, will trigger pool.onabort\n    this.#pool.abort();\n  }\n\n  /**\n   * Handle a decode start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode start event.\n   */\n  ondecodestart(_event) {}\n\n  /**\n   * Handle a decode item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode item event fired\n   *   when a decode item ended successfully.\n   */\n  ondecodeditem(_event) {}\n\n  /**\n   * Handle a decode event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode event fired\n   *   when a file has been decoded successfully.\n   */\n  ondecoded(_event) {}\n\n  /**\n   * Handle a decode end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode end event fired\n   *  when a file decoding has completed, successfully or not.\n   */\n  ondecodeend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class AsynchPixelBufferDecoder\n\n/**\n * Synchronous pixel buffer decoder.\n */\nclass SynchPixelBufferDecoder {\n\n  /**\n   * Name of the compression algorithm.\n   *\n   * @type {string}\n   */\n  #algoName;\n\n  /**\n   * Number of data.\n   *\n   * @type {number}\n   */\n  #numberOfData;\n\n  /**\n   * @param {string} algoName The decompression algorithm name.\n   * @param {number} numberOfData The anticipated number of data to decode.\n   */\n  constructor(algoName, numberOfData) {\n    this.#algoName = algoName;\n    this.#numberOfData = numberOfData;\n  }\n\n  // decode count\n  #decodeCount = 0;\n\n  /**\n   * Decode a pixel buffer.\n   *\n   * @param {Array} pixelBuffer The pixel buffer.\n   * @param {object} pixelMeta The input meta data.\n   * @param {object} info Information object about the input data.\n   * @external jpeg\n   * @external JpegImage\n   * @external JpxImage\n   */\n  decode(pixelBuffer, pixelMeta, info) {\n    ++this.#decodeCount;\n\n    let decoder = null;\n    let decodedBuffer = null;\n    if (this.#algoName === 'jpeg-lossless') {\n      if (!hasJpegLosslessDecoder) {\n        throw new Error('No JPEG Lossless decoder provided');\n      }\n      // bytes per element\n      const bpe = pixelMeta.bitsAllocated / 8;\n      const buf = new Uint8Array(pixelBuffer);\n      // @ts-ignore\n      decoder = new jpeg.lossless.Decoder();\n      const decoded = decoder.decode(buf.buffer, 0, buf.buffer.byteLength, bpe);\n      if (pixelMeta.bitsAllocated === 8) {\n        if (pixelMeta.isSigned) {\n          decodedBuffer = new Int8Array(decoded.buffer);\n        } else {\n          decodedBuffer = new Uint8Array(decoded.buffer);\n        }\n      } else if (pixelMeta.bitsAllocated === 16) {\n        if (pixelMeta.isSigned) {\n          decodedBuffer = new Int16Array(decoded.buffer);\n        } else {\n          decodedBuffer = new Uint16Array(decoded.buffer);\n        }\n      }\n    } else if (this.#algoName === 'jpeg-baseline') {\n      if (!hasJpegBaselineDecoder) {\n        throw new Error('No JPEG Baseline decoder provided');\n      }\n      // @ts-ignore\n      decoder = new JpegImage();\n      decoder.parse(pixelBuffer);\n      decodedBuffer = decoder.getData(decoder.width, decoder.height);\n    } else if (this.#algoName === 'jpeg2000') {\n      if (!hasJpeg2000Decoder) {\n        throw new Error('No JPEG 2000 decoder provided');\n      }\n      // decompress pixel buffer into Int16 image\n      // @ts-ignore\n      decoder = new JpxImage();\n      decoder.parse(pixelBuffer);\n      // set the pixel buffer\n      decodedBuffer = decoder.tiles[0].items;\n    } else if (this.#algoName === 'rle') {\n      // decode DICOM buffer\n      // @ts-ignore\n      decoder = new dwvdecoder.RleDecoder();\n      // set the pixel buffer\n      decodedBuffer = decoder.decode(\n        pixelBuffer,\n        pixelMeta.bitsAllocated,\n        pixelMeta.isSigned,\n        pixelMeta.sliceSize,\n        pixelMeta.samplesPerPixel,\n        pixelMeta.planarConfiguration);\n    }\n    // send decode events\n    this.ondecodeditem({\n      data: [decodedBuffer],\n      index: info.index,\n      numberOfItems: info.numberOfItems,\n      itemNumber: info.itemNumber\n    });\n    // decode end?\n    if (this.#decodeCount === this.#numberOfData) {\n      this.ondecoded({});\n      this.ondecodeend({});\n    }\n  }\n\n  /**\n   * Abort decoding.\n   */\n  abort() {\n    // nothing to do in the synchronous case.\n    // callback\n    this.onabort({});\n    this.ondecodeend({});\n  }\n\n  /**\n   * Handle a decode start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode start event.\n   */\n  ondecodestart(_event) {}\n\n  /**\n   * Handle a decode item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode item event fired\n   *   when a decode item ended successfully.\n   */\n  ondecodeditem(_event) {}\n\n  /**\n   * Handle a decode event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode event fired\n   *   when a file has been decoded successfully.\n   */\n  ondecoded(_event) {}\n\n  /**\n   * Handle a decode end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode end event fired\n   *  when a file decoding has completed, successfully or not.\n   */\n  ondecodeend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class SynchPixelBufferDecoder\n\n/**\n * Decode a pixel buffer.\n *\n * If the 'decoderScripts' variable does not contain the desired,\n * algorythm the decoder will switch to the synchronous mode.\n */\nexport class PixelBufferDecoder {\n\n  /**\n   * Flag to know if callbacks are set.\n   *\n   * @type {boolean}\n   */\n  #areCallbacksSet = false;\n\n  /**\n   * Pixel decoder.\n   * Defined only once.\n   *\n   * @type {object}\n   */\n  #pixelDecoder = null;\n\n  /**\n   * @param {string} algoName The decompression algorithm name.\n   * @param {number} numberOfData The anticipated number of data to decode.\n   */\n  constructor(algoName, numberOfData) {\n    // initialise the asynch decoder (if possible)\n    if (typeof decoderScripts !== 'undefined' &&\n      typeof decoderScripts[algoName] !== 'undefined') {\n      this.#pixelDecoder = new AsynchPixelBufferDecoder(\n        decoderScripts[algoName], numberOfData);\n    } else {\n      this.#pixelDecoder = new SynchPixelBufferDecoder(\n        algoName, numberOfData);\n    }\n  }\n\n  /**\n   * Get data from an input buffer using a DICOM parser.\n   *\n   * @param {Array} pixelBuffer The input data buffer.\n   * @param {object} pixelMeta The input meta data.\n   * @param {object} info Information object about the input data.\n   */\n  decode(pixelBuffer, pixelMeta, info) {\n    if (!this.#areCallbacksSet) {\n      this.#areCallbacksSet = true;\n      // set callbacks\n      this.#pixelDecoder.ondecodestart = this.ondecodestart;\n      this.#pixelDecoder.ondecodeditem = this.ondecodeditem;\n      this.#pixelDecoder.ondecoded = this.ondecoded;\n      this.#pixelDecoder.ondecodeend = this.ondecodeend;\n      this.#pixelDecoder.onerror = this.onerror;\n      this.#pixelDecoder.onabort = this.onabort;\n    }\n    // decode and call the callback\n    this.#pixelDecoder.decode(pixelBuffer, pixelMeta, info);\n  }\n\n  /**\n   * Abort decoding.\n   */\n  abort() {\n    // decoder classes should define an abort\n    this.#pixelDecoder.abort();\n  }\n\n  /**\n   * Handle a decode start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode start event.\n   */\n  ondecodestart(_event) {}\n\n  /**\n   * Handle a decode item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode item event fired\n   *   when a decode item ended successfully.\n   */\n  ondecodeditem(_event) {}\n\n  /**\n   * Handle a decode event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode event fired\n   *   when a file has been decoded successfully.\n   */\n  ondecoded(_event) {}\n\n  /**\n   * Handle a decode end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The decode end event fired\n   *  when a file decoding has completed, successfully or not.\n   */\n  ondecodeend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class PixelBufferDecoder\n","import {\n  getCode,\n  getDicomCodeItem\n} from './dicomCode';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\nimport {DicomCode} from './dicomCode';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  NumericValue: '0040A30A',\n  FloatingPointValue: '0040A161',\n  RationalNumeratorValue: '0040A162',\n  RationalDenominatorValue: '0040A163',\n  MeasurementUnitsCodeSequence: '004008EA'\n};\n\n/**\n * DICOM measured value: property of a numeric measurement.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.18.html#table_C.18.1-1}.\n */\nexport class MeasuredValue {\n  /**\n   * @type {number}\n   */\n  numericValue;\n\n  /**\n   * @type {number}\n   */\n  floatingPointValue;\n\n  /**\n   * @type {number}\n   */\n  rationalNumeratorValue;\n\n  /**\n   * @type {number}\n   */\n  rationalDenominatorValue;\n\n  /**\n   * @type {DicomCode}\n   */\n  measurementUnitsCode;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    return this.numericValue + ' ' +\n      this.measurementUnitsCode.toString();\n  };\n\n};\n\n/**\n * Get a measured value object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {MeasuredValue} A measured value object.\n */\nexport function getMeasuredValue(dataElements) {\n  const value = new MeasuredValue();\n\n  if (typeof dataElements[TagKeys.NumericValue] !== 'undefined') {\n    value.numericValue = dataElements[TagKeys.NumericValue].value[0];\n  }\n  if (typeof dataElements[TagKeys.FloatingPointValue] !== 'undefined') {\n    value.floatingPointValue =\n      dataElements[TagKeys.FloatingPointValue].value[0];\n  }\n  if (typeof dataElements[TagKeys.RationalNumeratorValue] !== 'undefined') {\n    value.rationalNumeratorValue =\n      dataElements[TagKeys.RationalNumeratorValue].value[0];\n  }\n  if (typeof dataElements[TagKeys.RationalDenominatorValue] !== 'undefined') {\n    value.rationalDenominatorValue =\n      dataElements[TagKeys.RationalDenominatorValue].value[0];\n  }\n  if (typeof dataElements[TagKeys.MeasurementUnitsCodeSequence] !==\n    'undefined') {\n    value.measurementUnitsCode = getCode(\n      dataElements[TagKeys.MeasurementUnitsCodeSequence].value[0]);\n  }\n\n  return value;\n};\n\n/**\n * Get a simple dicom element item from a measured value object.\n *\n * @param {MeasuredValue} value The measured value object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomMeasuredValueItem(value) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof value.measurementUnitsCode !== 'undefined') {\n    item.MeasurementUnitsCodeSequence = {\n      value: [getDicomCodeItem(value.measurementUnitsCode)]\n    };\n  }\n  if (typeof value.floatingPointValue !== 'undefined') {\n    item.FloatingPointValue = value.floatingPointValue;\n  }\n  if (typeof value.rationalNumeratorValue !== 'undefined') {\n    item.RationalNumeratorValue = value.rationalNumeratorValue;\n  }\n  if (typeof value.rationalDenominatorValue !== 'undefined') {\n    item.RationalDenominatorValue = value.rationalDenominatorValue;\n  }\n  if (typeof value.numericValue !== 'undefined') {\n    item.NumericValue = value.numericValue;\n  }\n\n  // return\n  return item;\n}\n","import {\n  getCode,\n  getDicomCodeItem\n} from './dicomCode';\nimport {\n  getMeasuredValue,\n  getDicomMeasuredValueItem\n} from './dicomMeasuredValue';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\nimport {MeasuredValue} from './dicomMeasuredValue';\nimport {DicomCode} from './dicomCode';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  MeasuredValueSequence: '0040A300',\n  NumericValueQualifierCodeSequence: '0040A301'\n};\n\n/**\n * DICOM numeric measurement: item of a SR content sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.18.html#table_C.18.1-1}.\n */\nexport class NumericMeasurement {\n  /**\n   * @type {MeasuredValue}\n   */\n  measuredValue;\n\n  /**\n   * @type {DicomCode}\n   */\n  numericValueQualifierCode;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    let res = this.measuredValue.toString();\n    if (typeof this.numericValueQualifierCode !== 'undefined') {\n      res += ' ' + this.numericValueQualifierCode.toString();\n    }\n    return res;\n  }\n};\n\n/**\n * Get a measurement object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {NumericMeasurement} A measurement object.\n */\nexport function getNumericMeasurement(dataElements) {\n  const measurement = new NumericMeasurement();\n\n  if (typeof dataElements[TagKeys.MeasuredValueSequence] !== 'undefined') {\n    measurement.measuredValue = getMeasuredValue(\n      dataElements[TagKeys.MeasuredValueSequence].value[0]);\n  }\n  if (typeof dataElements[TagKeys.NumericValueQualifierCodeSequence] !==\n    'undefined') {\n    measurement.numericValueQualifierCode = getCode(\n      dataElements[TagKeys.NumericValueQualifierCodeSequence].value[0]);\n  }\n\n  return measurement;\n};\n\n/**\n * Get a simple dicom element item from a measurement object.\n *\n * @param {NumericMeasurement} measurement The measurement object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomNumericMeasurementItem(measurement) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof measurement.measuredValue !== 'undefined') {\n    item.MeasuredValueSequence = {\n      value: [getDicomMeasuredValueItem(measurement.measuredValue)]\n    };\n  }\n  if (typeof measurement.numericValueQualifierCode !== 'undefined') {\n    item.NumericValueQualifierCodeSequence = {\n      value: [getDicomCodeItem(measurement.numericValueQualifierCode)]\n    };\n  }\n\n  // return\n  return item;\n}\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  ReferencedSOPClassUID: '00081150',\n  ReferencedSOPInstanceUID: '00081155'\n};\n\n/**\n * DICOM sop instance reference.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_10.8.html#table_10-11}.\n */\nexport class SopInstanceReference {\n  /**\n   * @type {string}\n   */\n  referencedSOPClassUID;\n\n  /**\n   * @type {string}\n   */\n  referencedSOPInstanceUID;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    return this.referencedSOPInstanceUID + ' (class: ' +\n      this.referencedSOPClassUID + ')';\n  };\n};\n\n/**\n * Get a SOP reference object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {SopInstanceReference} A SOP reference object.\n */\nexport function getSopInstanceReference(dataElements) {\n  const ref = new SopInstanceReference();\n\n  if (typeof dataElements[TagKeys.ReferencedSOPClassUID] !== 'undefined') {\n    ref.referencedSOPClassUID =\n      dataElements[TagKeys.ReferencedSOPClassUID].value[0];\n  }\n  if (typeof dataElements[TagKeys.ReferencedSOPInstanceUID] !== 'undefined') {\n    ref.referencedSOPInstanceUID =\n      dataElements[TagKeys.ReferencedSOPInstanceUID].value[0];\n  }\n\n  return ref;\n};\n\n/**\n * Get a simple dicom element item from a SOP reference object.\n *\n * @param {SopInstanceReference} ref The SOP reference object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSopInstanceReferenceItem(ref) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof ref.referencedSOPClassUID !== 'undefined') {\n    item.ReferencedSOPClassUID = ref.referencedSOPClassUID;\n  }\n  if (typeof ref.referencedSOPInstanceUID !== 'undefined') {\n    item.ReferencedSOPInstanceUID = ref.referencedSOPInstanceUID;\n  }\n\n  // return\n  return item;\n}\n","import {\n  getSopInstanceReference,\n  getDicomSopInstanceReferenceItem\n} from './dicomSopInstanceReference';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  ReferencedFrameNumber: '00081160',\n  ReferencedSOPSequence: '00081199',\n  ReferencedSegmentNumber: '0062000B'\n};\n\n/**\n * DICOM image reference: item of a SR content sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.18.4.html#table_C.18.4-1}.\n */\nexport class ImageReference {\n  /**\n   * @type {object}\n   */\n  referencedSOPSequence;\n\n  /**\n   * @type {object}\n   */\n  referencedFrameNumber;\n\n  /**\n   * @type {string}\n   */\n  referencedSegmentNumber;\n\n  /**\n   * @type {string}\n   */\n  fiducialUID;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    return this.referencedSOPSequence.toString();\n  };\n};\n\n/**\n * Get a reference object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {ImageReference} A reference object.\n */\nexport function getImageReference(dataElements) {\n  const ref = new ImageReference();\n\n  if (typeof dataElements[TagKeys.ReferencedFrameNumber] !== 'undefined') {\n    ref.referencedFrameNumber =\n      dataElements[TagKeys.ReferencedFrameNumber].value[0];\n  }\n  if (typeof dataElements[TagKeys.ReferencedSOPSequence] !== 'undefined') {\n    ref.referencedSOPSequence = getSopInstanceReference(\n      dataElements[TagKeys.ReferencedSOPSequence].value[0]);\n  }\n  if (typeof dataElements[TagKeys.ReferencedSegmentNumber] !== 'undefined') {\n    ref.referencedSegmentNumber =\n      dataElements[TagKeys.ReferencedSegmentNumber].value[0];\n  }\n\n  return ref;\n};\n\n/**\n * Get a simple dicom element item from a reference object.\n *\n * @param {ImageReference} ref The reference object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomImageReferenceItem(ref) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof ref.referencedFrameNumber !== 'undefined') {\n    item.ReferencedFrameNumber = ref.referencedFrameNumber;\n  }\n  if (typeof ref.referencedSOPSequence !== 'undefined') {\n    item.ReferencedSOPSequence = {\n      value: [getDicomSopInstanceReferenceItem(ref.referencedSOPSequence)]\n    };\n  }\n  if (typeof ref.referencedSegmentNumber !== 'undefined') {\n    item.ReferencedSegmentNumber =\n      ref.referencedSegmentNumber;\n  }\n\n  // return\n  return item;\n}\n","import {Point2D} from '../math/point';\nimport {Line, areOrthogonal} from '../math/line';\nimport {Protractor} from '../math/protractor';\nimport {ROI} from '../math/roi';\nimport {Circle} from '../math/circle';\nimport {Ellipse} from '../math/ellipse';\nimport {Rectangle} from '../math/rectangle';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  PixelOriginInterpretation: '00480301',\n  GraphicData: '00700022',\n  GraphicType: '00700023',\n  FiducialUID: '0070031A'\n};\n\n/**\n * DICOM graphic types.\n */\nexport const GraphicTypes = {\n  point: 'POINT',\n  multipoint: 'MULTIPOINT',\n  polyline: 'POLYLINE',\n  circle: 'CIRCLE',\n  ellipse: 'ELLIPSE'\n};\n\n/**\n * DICOM spatial coordinate (SCOORD): item of a SR content sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.18.6.html#table_C.18.6-1}.\n */\nexport class SpatialCoordinate {\n  /**\n   * @type {string[]}\n   */\n  graphicData;\n\n  /**\n   * @type {string}\n   */\n  graphicType;\n\n  /**\n   * @type {string}\n   */\n  pixelOriginInterpretation;\n\n  /**\n   * @type {string}\n   */\n  fiducialUID;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    return this.graphicType +\n      ' {' + this.graphicData + '}';\n  };\n};\n\n/**\n * Get a scoord object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {SpatialCoordinate} A scoord object.\n */\nexport function getSpatialCoordinate(dataElements) {\n  const scoord = new SpatialCoordinate();\n\n  if (typeof dataElements[TagKeys.GraphicData] !== 'undefined') {\n    scoord.graphicData = dataElements[TagKeys.GraphicData].value;\n  }\n  if (typeof dataElements[TagKeys.GraphicType] !== 'undefined') {\n    scoord.graphicType = dataElements[TagKeys.GraphicType].value[0];\n  }\n  if (typeof dataElements[TagKeys.PixelOriginInterpretation] !== 'undefined') {\n    scoord.pixelOriginInterpretation =\n      dataElements[TagKeys.PixelOriginInterpretation].value[0];\n  }\n  if (typeof dataElements[TagKeys.FiducialUID] !== 'undefined') {\n    scoord.fiducialUID = dataElements[TagKeys.FiducialUID].value[0];\n  }\n  return scoord;\n};\n\n/**\n * Get a simple dicom element item from a scoord object.\n *\n * @param {SpatialCoordinate} scoord The scoord object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSpatialCoordinateItem(scoord) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof scoord.pixelOriginInterpretation !== 'undefined') {\n    item.PixelOriginInterpretation = scoord.pixelOriginInterpretation;\n  }\n  if (typeof scoord.graphicData !== 'undefined') {\n    item.GraphicData = scoord.graphicData;\n  }\n  if (typeof scoord.graphicType !== 'undefined') {\n    item.GraphicType = scoord.graphicType;\n  }\n  if (typeof scoord.fiducialUID !== 'undefined') {\n    item.FiducialUID = scoord.fiducialUID;\n  }\n\n  // return\n  return item;\n}\n\n/**\n * Get a DICOM spatial coordinate (SCOORD) from a mathematical shape.\n *\n * @param {Point2D|Line|Protractor|ROI|Circle|Ellipse|Rectangle} shape\n *   The math shape.\n * @returns {SpatialCoordinate} The DICOM scoord.\n */\nexport function getScoordFromShape(shape) {\n  const scoord = new SpatialCoordinate();\n\n  if (shape instanceof Point2D) {\n    scoord.graphicData = [\n      shape.getX().toString(),\n      shape.getY().toString(),\n    ];\n    scoord.graphicType = GraphicTypes.point;\n  } else if (shape instanceof Line) {\n    scoord.graphicData = [\n      shape.getBegin().getX().toString(),\n      shape.getBegin().getY().toString(),\n      shape.getEnd().getX().toString(),\n      shape.getEnd().getY().toString(),\n    ];\n    scoord.graphicType = GraphicTypes.polyline;\n  } else if (shape instanceof Protractor) {\n    scoord.graphicData = [];\n    for (let i = 0; i < 3; ++i) {\n      scoord.graphicData.push(shape.getPoint(i).getX().toString());\n      scoord.graphicData.push(shape.getPoint(i).getY().toString());\n    }\n    scoord.graphicType = GraphicTypes.polyline;\n  } else if (shape instanceof ROI) {\n    scoord.graphicData = [];\n    for (let i = 0; i < shape.getLength(); ++i) {\n      scoord.graphicData.push(shape.getPoint(i).getX().toString());\n      scoord.graphicData.push(shape.getPoint(i).getY().toString());\n    }\n    // repeat first point to close shape\n    const firstPoint = shape.getPoint(0);\n    scoord.graphicData.push(firstPoint.getX().toString());\n    scoord.graphicData.push(firstPoint.getY().toString());\n\n    scoord.graphicType = GraphicTypes.polyline;\n  } else if (shape instanceof Circle) {\n    const center = shape.getCenter();\n    const pointPerimeter = new Point2D(\n      center.getX() + shape.getRadius(), center.getY()\n    );\n    scoord.graphicData = [\n      center.getX().toString(),\n      center.getY().toString(),\n      pointPerimeter.getX().toString(),\n      pointPerimeter.getY().toString(),\n    ];\n    scoord.graphicType = GraphicTypes.circle;\n  } else if (shape instanceof Ellipse) {\n    const center = shape.getCenter();\n    const radiusX = shape.getA();\n    const radiusY = shape.getB();\n    scoord.graphicData = [\n      (center.getX() - radiusX).toString(),\n      center.getY().toString(),\n      (center.getX() + radiusX).toString(),\n      center.getY().toString(),\n      center.getX().toString(),\n      (center.getY() - radiusY).toString(),\n      center.getX().toString(),\n      (center.getY() + radiusY).toString()\n    ];\n    scoord.graphicType = GraphicTypes.ellipse;\n  } else if (shape instanceof Rectangle) {\n    const begin = shape.getBegin();\n    const end = shape.getEnd();\n    // begin as first and last point to close shape\n    scoord.graphicData = [\n      begin.getX().toString(),\n      begin.getY().toString(),\n      begin.getX().toString(),\n      end.getY().toString(),\n      end.getX().toString(),\n      end.getY().toString(),\n      end.getX().toString(),\n      begin.getY().toString(),\n      begin.getX().toString(),\n      begin.getY().toString()\n    ];\n    scoord.graphicType = GraphicTypes.polyline;\n  }\n\n  return scoord;\n};\n\n/**\n * Get a mathematical shape from a DICOM spatial coordinate (SCOORD).\n *\n * @param {SpatialCoordinate} scoord The DICOM scoord.\n * @returns {Point2D|Line|Protractor|ROI|Circle|Ellipse|Rectangle}\n *   The math shape.\n */\nexport function getShapeFromScoord(scoord) {\n  // extract points\n  const dataLength = scoord.graphicData.length;\n  if (dataLength % 2 !== 0) {\n    throw new Error('Expecting even number of coordinates in scroord data');\n  }\n  const points = [];\n  for (let i = 0; i < dataLength; i += 2) {\n    points.push(new Point2D(\n      parseFloat(scoord.graphicData[i]),\n      parseFloat(scoord.graphicData[i + 1])\n    ));\n  }\n  let isClosed = false;\n  const numberOfPoints = points.length;\n  if (numberOfPoints > 2) {\n    const firstPoint = points[0];\n    const lastPoint = points[numberOfPoints - 1];\n    isClosed = firstPoint.equals(lastPoint);\n  }\n\n  // create math shape\n  let shape;\n  if (scoord.graphicType === GraphicTypes.point) {\n    if (points.length !== 1) {\n      throw new Error('Expecting 1 point for point');\n    }\n    shape = points[0];\n  } else if (scoord.graphicType === GraphicTypes.circle) {\n    if (points.length !== 2) {\n      throw new Error('Expecting 2 points for circles');\n    }\n    const center = points[0];\n    const pointPerimeter = points[1];\n    const radius = pointPerimeter.getDistance(center);\n    shape = new Circle(center, radius);\n  } else if (scoord.graphicType === GraphicTypes.ellipse) {\n    if (points.length !== 4) {\n      throw new Error('Expecting 4 points for ellipses');\n    }\n    // TODO: make more generic\n    const radiusX = points[0].getDistance(points[1]) / 2;\n    const radiusY = points[2].getDistance(points[3]) / 2;\n    const center = new Point2D(\n      points[0].getX() + radiusX,\n      points[0].getY()\n    );\n    shape = new Ellipse(center, radiusX, radiusY);\n  } else if (scoord.graphicType === GraphicTypes.polyline) {\n    if (!isClosed) {\n      if (points.length === 2) {\n        shape = new Line(points[0], points[1]);\n      } else if (points.length === 3) {\n        shape = new Protractor([points[0], points[1], points[2]]);\n      }\n    } else {\n      if (points.length === 5) {\n        const line0 = new Line(points[0], points[1]);\n        const line1 = new Line(points[1], points[2]);\n        const line2 = new Line(points[2], points[3]);\n        const line3 = new Line(points[3], points[4]);\n        if (areOrthogonal(line0, line1) &&\n          areOrthogonal(line1, line2) &&\n          areOrthogonal(line2, line3)) {\n          shape = new Rectangle(points[0], points[2]);\n        } else {\n          // remove last=first point for closed shape\n          shape = new ROI(points.slice(0, -1));\n        }\n      } else {\n        // remove last=first point for closed shape\n        shape = new ROI(points.slice(0, -1));\n      }\n    }\n  }\n\n  return shape;\n};","// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  GraphicData: '00700022',\n  GraphicType: '00700023',\n  ReferencedFrameofReferenceUID: '30060024',\n  FiducialUID: '0070031A'\n};\n\n/**\n * DICOM spatial coordinate 3D (SCOORD3D): item of a SR content sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.18.9.html#table_C.18.9-1}.\n */\nexport class SpatialCoordinate3D {\n  /**\n   * @type {string[]}\n   */\n  graphicData;\n\n  /**\n   * @type {string}\n   */\n  graphicType;\n\n  /**\n   * @type {string}\n   */\n  referencedFrameofReferenceUID;\n\n  /**\n   * @type {string}\n   */\n  fiducialUID;\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @returns {string} The object as string.\n   */\n  toString() {\n    return this.graphicType +\n      '{' + this.graphicData + '}';\n  };\n};\n\n/**\n * Get a scoord3d object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {SpatialCoordinate3D} A scoord3d object.\n */\nexport function getSpatialCoordinate3D(dataElements) {\n  const scoord = new SpatialCoordinate3D();\n\n  if (typeof dataElements[TagKeys.GraphicData] !== 'undefined') {\n    scoord.graphicData = dataElements[TagKeys.GraphicData].value;\n  }\n  if (typeof dataElements[TagKeys.GraphicType] !== 'undefined') {\n    scoord.graphicType = dataElements[TagKeys.GraphicType].value[0];\n  }\n  if (typeof dataElements[TagKeys.ReferencedFrameofReferenceUID] !==\n    'undefined') {\n    scoord.referencedFrameofReferenceUID =\n      dataElements[TagKeys.ReferencedFrameofReferenceUID].value[0];\n  }\n  if (typeof dataElements[TagKeys.FiducialUID] !== 'undefined') {\n    scoord.fiducialUID = dataElements[TagKeys.FiducialUID].value[0];\n  }\n  return scoord;\n};\n\n/**\n * Get a simple dicom element item from a scoord3d object.\n *\n * @param {SpatialCoordinate3D} scoord The scoord3d object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSpatialCoordinate3DItem(scoord) {\n  // dicom item (tags are in group/element order)\n  const item = {};\n\n  if (typeof scoord.graphicData !== 'undefined') {\n    item.GraphicData = scoord.graphicData;\n  }\n  if (typeof scoord.graphicType !== 'undefined') {\n    item.GraphicType = scoord.graphicType;\n  }\n  if (typeof scoord.referencedFrameofReferenceUID !== 'undefined') {\n    item.ReferencedFrameofReferenceUID =\n      scoord.referencedFrameofReferenceUID;\n  }\n  if (typeof scoord.fiducialUID !== 'undefined') {\n    item.FiducialUID = scoord.fiducialUID;\n  }\n\n  // return\n  return item;\n}","import {\n  NumericMeasurement,\n  getNumericMeasurement,\n  getDicomNumericMeasurementItem\n} from './dicomNumericMeasurement';\nimport {\n  getCode,\n  getDicomCodeItem,\n  getConceptNameCode,\n  getMeasurementUnitsCode\n} from './dicomCode';\nimport {\n  getImageReference,\n  getDicomImageReferenceItem\n} from './dicomImageReference';\nimport {\n  getSopInstanceReference,\n  getDicomSopInstanceReferenceItem\n} from './dicomSopInstanceReference';\nimport {\n  getSpatialCoordinate,\n  getDicomSpatialCoordinateItem\n} from './dicomSpatialCoordinate';\nimport {\n  getSpatialCoordinate3D,\n  getDicomSpatialCoordinate3DItem\n} from './dicomSpatialCoordinate3D';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from './dataElement';\nimport {DicomCode} from './dicomCode';\nimport {MeasuredValue} from './dicomMeasuredValue';\n/* eslint-enable no-unused-vars */\n\n/**\n * Related DICOM tag keys.\n */\nconst TagKeys = {\n  ReferencedSOPSequence: '00081199',\n  RelationshipType: '0040A010',\n  ValueType: '0040A040',\n  ConceptNameCodeSequence: '0040A043',\n  ConceptCodeSequence: '0040A168',\n  ContentSequence: '0040A730',\n  DateTime: '0040A120',\n  Date: '0040A121',\n  Time: '0040A122',\n  UID: '0040A124',\n  PersonName: '0040A123',\n  TextValue: '0040A160',\n  ContinuityOfContent: '0040A050'\n};\n\n/**\n * DICOM relationship types.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.17.3.2.4.html#sect_C.17.3.2.4}.\n */\nexport const RelationshipTypes = {\n  contains: 'CONTAINS',\n  hasProperties: 'HAS PROPERTIES',\n  hasObsContext: 'HAS OBS CONTEXT',\n  hasAcqContext: 'HAS ACQ CONTEXT',\n  inferredFrom: 'INFERRED FROM',\n  selectedFrom: 'SELECTED FROM',\n  hasConceptMod: 'HAS CONCEPT MOD'\n};\n\n/**\n * DICOM value types.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/current/output/chtml/part03/sect_C.17.3.2.html#sect_C.17.3.2.1}.\n */\nexport const ValueTypes = {\n  text: 'TEXT',\n  num: 'NUM',\n  code: 'CODE',\n  date: 'DATE',\n  time: 'TIME',\n  datetime: 'DATETIME',\n  uidref: 'UIDREF',\n  pname: 'PNAME',\n  composite: 'COMPOSITE',\n  image: 'IMAGE',\n  waveform: 'WAVEFORM',\n  scoord: 'SCOORD',\n  scoord3d: 'SCOORD3D',\n  tcoord: 'TCOORD',\n  container: 'CONTAINER',\n  table: 'TABLE',\n};\n\n/**\n * DICOM value type to associated tag name.\n */\nexport const ValueTypeValueTagName = {\n  TEXT: 'TextValue',\n  DATE: 'Date',\n  TIME: 'Time',\n  DATETIME: 'DateTime',\n  UIDREF: 'UID',\n  PNAME: 'PersonName',\n  CONTAINER: 'ContinuityOfContent',\n};\n\n/**\n * DICOM SR content: item of a SR content sequence.\n *\n * Ref: {@link https://dicom.nema.org/medical/dicom/2022a/output/chtml/part03/sect_C.17.3.html}.\n */\nexport class DicomSRContent {\n  /**\n   * Value type.\n   *\n   * @type {string}\n   */\n  valueType;\n  /**\n   * Concept name code.\n   *\n   * @type {DicomCode|undefined}\n   */\n  conceptNameCode;\n  /**\n   * Relationship Type.\n   *\n   * @type {string}\n   */\n  relationshipType;\n\n  /**\n   * Content sequence (0040,A730).\n   *\n   * @type {DicomSRContent[]|undefined}\n   */\n  contentSequence;\n\n  /**\n   * Value.\n   *\n   * @type {object}\n   */\n  value;\n\n  /**\n   * @param {string} valueType The content item value type.\n   */\n  constructor(valueType) {\n    this.valueType = valueType;\n  }\n\n  /**\n   * Get a string representation of this object.\n   *\n   * @param {string} [prefix] An optional prefix for recursive content.\n   * @returns {string} The object as string.\n   */\n  toString(prefix) {\n    if (typeof prefix === 'undefined') {\n      prefix = '';\n    }\n\n    let res = '';\n\n    if (typeof this.relationshipType !== 'undefined') {\n      res += '(' + this.relationshipType + ') ';\n    }\n\n    res += this.valueType + ': ';\n\n    if (typeof this.conceptNameCode !== 'undefined') {\n      res += this.conceptNameCode.toString();\n    }\n\n    res += ' = ' + this.value.toString();\n\n    if (typeof this.contentSequence !== 'undefined') {\n      for (const item of this.contentSequence) {\n        res += '\\n' + prefix + '- ' + item.toString(prefix + '  ');\n      }\n    }\n\n    return res;\n  }\n}\n\n/**\n * Check if two content item objects are equal.\n *\n * @param {DicomCode} item1 The first content item.\n * @param {DicomCode} item2 The second content item.\n * @returns {boolean} True if both content items are equal.\n */\nexport function isEqualContentItem(item1, item2) {\n  return Object.keys(item1).length === Object.keys(item2).length &&\n  Object.keys(item1).every(key =>\n    Object.prototype.hasOwnProperty.call(item2, key) &&\n    item1[key] === item2[key]\n  );\n}\n\n/**\n * Get a content item object from a dicom element.\n *\n * @param {Object<string, DataElement>} dataElements The dicom element.\n * @returns {DicomSRContent} A content item object.\n */\nexport function getSRContent(dataElements) {\n  // valueType -> ValueType (type1)\n  let valueType = '';\n  if (typeof dataElements[TagKeys.ValueType] !== 'undefined') {\n    valueType = dataElements[TagKeys.ValueType].value[0];\n  }\n\n  const content = new DicomSRContent(valueType);\n\n  // relationshipType -> RelationType (type1)\n  if (typeof dataElements[TagKeys.RelationshipType] !== 'undefined') {\n    content.relationshipType =\n      dataElements[TagKeys.RelationshipType].value[0];\n  }\n\n  if (typeof dataElements[TagKeys.ConceptNameCodeSequence] !== 'undefined') {\n    content.conceptNameCode =\n      getCode(dataElements[TagKeys.ConceptNameCodeSequence].value[0]);\n  }\n\n  // set value acording to valueType\n  // (date and time are stored as string)\n  if (valueType === ValueTypes.code) {\n    content.value = getCode(\n      dataElements[TagKeys.ConceptCodeSequence].value[0]);\n  } else if (valueType === ValueTypes.num) {\n    content.value = getNumericMeasurement(dataElements);\n  } else if (valueType === ValueTypes.image) {\n    content.value = getImageReference(dataElements);\n  } else if (valueType === ValueTypes.composite) {\n    content.value = getSopInstanceReference(\n      dataElements[TagKeys.ReferencedSOPSequence].value[0]\n    );\n  } else if (valueType === ValueTypes.scoord) {\n    content.value = getSpatialCoordinate(dataElements);\n  } else if (valueType === ValueTypes.scoord3d) {\n    content.value = getSpatialCoordinate3D(dataElements);\n  } else {\n    const valueTagName = ValueTypeValueTagName[valueType];\n    if (typeof valueTagName !== 'undefined') {\n      content.value = dataElements[TagKeys[valueTagName]].value[0];\n    } else {\n      console.warn('Unsupported input ValueType: ' + valueType);\n    }\n  }\n\n  const contentSqEl = dataElements[TagKeys.ContentSequence];\n  if (typeof contentSqEl !== 'undefined') {\n    content.contentSequence = [];\n    for (const item of dataElements[TagKeys.ContentSequence].value) {\n      content.contentSequence.push(getSRContent(item));\n    }\n  }\n\n  return content;\n}\n\n/**\n * Get a simple dicom element item from a content item object.\n *\n * @param {DicomSRContent} content The content item object.\n * @returns {Object<string, any>} The item as a list of (key, value) pairs.\n */\nexport function getDicomSRContentItem(content) {\n  // dicom item (tags are in ~group/element order)\n  let contentItem = {};\n\n  if (typeof content.relationshipType !== 'undefined') {\n    contentItem.RelationshipType = content.relationshipType;\n  }\n  if (typeof content.valueType !== 'undefined') {\n    contentItem.ValueType = content.valueType;\n  }\n  if (typeof content.conceptNameCode !== 'undefined') {\n    contentItem.ConceptNameCodeSequence = {\n      value: [getDicomCodeItem(content.conceptNameCode)]\n    };\n  }\n\n  // set appropriate value tag (data and time are stored as string)\n  if (content.valueType === 'CODE') {\n    contentItem.ConceptCodeSequence = {\n      value: [getDicomCodeItem(content.value)]\n    };\n  } else if (content.valueType === ValueTypes.num) {\n    contentItem = {\n      ...contentItem,\n      ...getDicomNumericMeasurementItem(content.value)\n    };\n  } else if (content.valueType === ValueTypes.image) {\n    contentItem = {\n      ...contentItem,\n      ...getDicomImageReferenceItem(content.value)\n    };\n  } else if (content.valueType === ValueTypes.composite) {\n    contentItem = {\n      ...contentItem,\n      ...getDicomSopInstanceReferenceItem(content.value)\n    };\n  } else if (content.valueType === ValueTypes.scoord) {\n    contentItem = {\n      ...contentItem,\n      ...getDicomSpatialCoordinateItem(content.value)\n    };\n  } else if (content.valueType === ValueTypes.scoord3d) {\n    contentItem = {\n      ...contentItem,\n      ...getDicomSpatialCoordinate3DItem(content.value)\n    };\n  } else {\n    const valueTagName = ValueTypeValueTagName[content.valueType];\n    if (typeof valueTagName !== 'undefined') {\n      contentItem[valueTagName] = content.value;\n    } else {\n      console.warn('Unsupported output ValueType: ' + content.valueType);\n    }\n  }\n\n  if (typeof content.contentSequence !== 'undefined') {\n    contentItem.ContentSequence = {\n      value: []\n    };\n    for (const item of content.contentSequence) {\n      contentItem.ContentSequence.value.push(getDicomSRContentItem(item));\n    }\n  }\n\n  return contentItem;\n}\n\n/**\n * Get a DicomSRContent from a value.\n *\n * @param {string} name The value name.\n * @param {object} value The value.\n * @param {string} unit The values' unit.\n * @returns {DicomSRContent|undefined} The SR content.\n */\nexport function getSRContentFromValue(name, value, unit) {\n  const conceptNameCode = getConceptNameCode(name);\n\n  if (typeof conceptNameCode === 'undefined') {\n    return undefined;\n  }\n\n  const content = new DicomSRContent(ValueTypes.num);\n  content.relationshipType = RelationshipTypes.contains;\n  content.conceptNameCode = conceptNameCode;\n\n  const measure = new MeasuredValue();\n  measure.numericValue = value;\n  measure.measurementUnitsCode = getMeasurementUnitsCode(unit);\n  const numMeasure = new NumericMeasurement();\n  numMeasure.measuredValue = measure;\n\n  content.value = numMeasure;\n\n  return content;\n}","import {\n  dateToDateObj,\n  getDicomDate,\n  dateToTimeObj,\n  getDicomTime,\n} from '../dicom/dicomDate';\nimport {safeGet} from '../dicom/dataElement';\nimport {\n  ValueTypes,\n  RelationshipTypes,\n  getSRContent,\n  getDicomSRContentItem,\n  DicomSRContent,\n  getSRContentFromValue\n} from '../dicom/dicomSRContent';\nimport {\n  isEqualCode,\n  getPathCode,\n  getMeasurementGroupCode,\n  getImageRegionCode,\n  getReferenceGeometryCode,\n  getSourceImageCode,\n  getTrackingIdentifierCode,\n  getShortLabelCode,\n  getReferencePointsCode,\n  getColourCode,\n  getQuantificationName,\n  getQuantificationUnit\n} from '../dicom/dicomCode';\nimport {getElementsFromJSONTags} from '../dicom/dicomWriter';\nimport {ImageReference} from '../dicom/dicomImageReference';\nimport {SopInstanceReference} from '../dicom/dicomSopInstanceReference';\nimport {\n  GraphicTypes,\n  getScoordFromShape,\n  getShapeFromScoord,\n  SpatialCoordinate\n} from '../dicom/dicomSpatialCoordinate';\nimport {SpatialCoordinate3D} from '../dicom/dicomSpatialCoordinate3D';\nimport {guid} from '../math/stats';\nimport {logger} from '../utils/logger';\nimport {Annotation} from './annotation';\nimport {AnnotationGroup} from './annotationGroup';\nimport {Line} from '../math/line';\nimport {Point2D, Point3D} from '../math/point';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from '../dicom/dataElement';\n/* eslint-enable no-unused-vars */\n\n/**\n * Merge two tag lists.\n *\n * @param {object} tags1 Base list, will be modified.\n * @param {object} tags2 List to merge.\n */\nfunction mergeTags(tags1, tags2) {\n  const keys2 = Object.keys(tags2);\n  for (const tagName2 of keys2) {\n    if (tags1[tagName2] !== undefined) {\n      logger.trace('Overwritting tag: ' + tagName2);\n    }\n    tags1[tagName2] = tags2[tagName2];\n  }\n}\n\n/**\n * {@link AnnotationGroup} factory.\n */\nexport class AnnotationGroupFactory {\n\n  /**\n   * Possible warning created by checkElements.\n   *\n   * @type {string|undefined}\n   */\n  #warning;\n\n  /**\n   * Get a warning string if elements are not as expected.\n   * Created by checkElements.\n   *\n   * @returns {string|undefined} The warning.\n   */\n  getWarning() {\n    return this.#warning;\n  }\n\n  /**\n   * Check dicom elements.\n   *\n   * @param {Object<string, DataElement>} dataElements The DICOM data elements.\n   * @returns {string|undefined} A possible warning.\n   * @throws Error for missing or wrong data.\n   */\n  checkElements(dataElements) {\n    // reset\n    this.#warning = undefined;\n\n    const srContent = getSRContent(dataElements);\n    if (typeof srContent.conceptNameCode !== 'undefined') {\n      if (srContent.conceptNameCode.value !== getMeasurementGroupCode().value) {\n        this.#warning = 'Not a measurement group';\n      }\n    } else {\n      this.#warning = 'No root concept name code';\n    }\n\n    return this.#warning;\n  }\n\n  /**\n   * Convert a DICOM SR content of type SCOORD into an annotation.\n   *\n   * @param {DicomSRContent} item The input SCOORD.\n   * @returns {Annotation} The annotation.\n   */\n  #scoordToAnnotation(item) {\n    const annotation = new Annotation();\n    annotation.mathShape = getShapeFromScoord(item.value);\n    // default\n    annotation.id = guid();\n    annotation.textExpr = '';\n\n    for (const subItem of item.contentSequence) {\n      // reference image UID\n      if (subItem.valueType === ValueTypes.image &&\n        subItem.relationshipType === RelationshipTypes.selectedFrom &&\n        isEqualCode(subItem.conceptNameCode, getSourceImageCode())) {\n        annotation.referenceSopUID =\n          subItem.value.referencedSOPSequence.referencedSOPInstanceUID;\n      }\n      // annotation id\n      if (subItem.valueType === ValueTypes.uidref &&\n        subItem.relationshipType === RelationshipTypes.hasProperties &&\n        isEqualCode(subItem.conceptNameCode, getTrackingIdentifierCode())) {\n        annotation.id = subItem.value;\n      }\n      // text expr\n      if (subItem.valueType === ValueTypes.text &&\n        subItem.relationshipType === RelationshipTypes.hasProperties &&\n        isEqualCode(subItem.conceptNameCode, getShortLabelCode())) {\n        annotation.textExpr = subItem.value;\n        if (typeof subItem.contentSequence !== 'undefined') {\n          for (const subsubItem of subItem.contentSequence) {\n            if (subsubItem.valueType === ValueTypes.scoord &&\n              subsubItem.relationshipType === RelationshipTypes.hasProperties &&\n              isEqualCode(\n                subsubItem.conceptNameCode, getReferencePointsCode())) {\n              annotation.labelPosition = new Point2D(\n                subsubItem.value.graphicData[0],\n                subsubItem.value.graphicData[1]\n              );\n            }\n          }\n        }\n      }\n      // color\n      if (subItem.valueType === ValueTypes.text &&\n        subItem.relationshipType === RelationshipTypes.hasProperties &&\n        isEqualCode(subItem.conceptNameCode, getColourCode())) {\n        annotation.colour = subItem.value;\n      }\n      // reference points\n      if (subItem.valueType === ValueTypes.scoord &&\n        subItem.relationshipType === RelationshipTypes.hasProperties &&\n        isEqualCode(subItem.conceptNameCode, getReferencePointsCode()) &&\n        subItem.value.graphicType === GraphicTypes.multipoint) {\n        const points = [];\n        for (let i = 0; i < subItem.value.graphicData.length; i += 2) {\n          points.push(new Point2D(\n            subItem.value.graphicData[i],\n            subItem.value.graphicData[i + 1]\n          ));\n        }\n        annotation.referencePoints = points;\n      }\n      // plane points\n      if (subItem.valueType === ValueTypes.scoord3d &&\n        subItem.relationshipType === RelationshipTypes.hasProperties &&\n        isEqualCode(\n          subItem.conceptNameCode, getReferenceGeometryCode()) &&\n        subItem.value.graphicType === GraphicTypes.multipoint) {\n        const data = subItem.value.graphicData;\n        const points = [];\n        const nPoints = Math.floor(data.length / 3);\n        for (let i = 0; i < nPoints; ++i) {\n          const j = i * 3;\n          points.push(new Point3D(data[j], data[j + 1], data[j + 2]));\n        }\n        annotation.planePoints = points;\n      }\n      // quantification\n      if (subItem.valueType === ValueTypes.num &&\n        subItem.relationshipType === RelationshipTypes.contains) {\n        const quantifName =\n          getQuantificationName(subItem.conceptNameCode);\n        if (typeof quantifName === 'undefined') {\n          continue;\n        }\n        const measuredValue = subItem.value.measuredValue;\n        const quantifUnit = getQuantificationUnit(\n          measuredValue.measurementUnitsCode);\n        if (typeof annotation.quantification === 'undefined') {\n          annotation.quantification = {};\n        }\n        annotation.quantification[quantifName] = {\n          value: measuredValue.numericValue,\n          unit: quantifUnit\n        };\n      }\n    }\n    return annotation;\n  }\n\n  /**\n   * Get an {@link Annotation} object from the read DICOM file.\n   *\n   * @param {Object<string, DataElement>} dataElements The DICOM tags.\n   * @returns {AnnotationGroup} A new annotation group.\n   * @throws Error for missing or wrong data.\n   */\n  create(dataElements) {\n    const annotations = [];\n    const srContent = getSRContent(dataElements);\n    for (const item of srContent.contentSequence) {\n      if (item.valueType === ValueTypes.scoord) {\n        annotations.push(this.#scoordToAnnotation(item));\n      }\n    }\n    const annotationGroup = new AnnotationGroup(annotations);\n\n    const safeGetLocal = function (key) {\n      return safeGet(dataElements, key);\n    };\n\n    // StudyInstanceUID\n    annotationGroup.setMetaValue('StudyInstanceUID', safeGetLocal('0020000D'));\n    // Modality\n    annotationGroup.setMetaValue('Modality', safeGetLocal('00080060'));\n    // patient info\n    annotationGroup.setMetaValue('PatientName', safeGetLocal('00100010'));\n    annotationGroup.setMetaValue('PatientID', safeGetLocal('00100020'));\n    annotationGroup.setMetaValue('PatientBirthDate', safeGetLocal('00100030'));\n    annotationGroup.setMetaValue('PatientSex', safeGetLocal('00100040'));\n\n    // ReferencedSeriesSequence\n    const element = dataElements['00081115'];\n    if (typeof element !== 'undefined') {\n      const seriesElement = element.value[0]['0020000E'];\n      if (typeof seriesElement !== 'undefined') {\n        annotationGroup.setMetaValue(\n          'ReferencedSeriesSequence', {\n            value: [{\n              SeriesInstanceUID: seriesElement.value[0]\n            }]\n          }\n        );\n      }\n    }\n\n    return annotationGroup;\n  }\n\n  /**\n   * Convert an annotation into a DICOM SCOORD.\n   *\n   * @param {Annotation} annotation The input annotation.\n   * @returns {DicomSRContent} An SR content of type SCOORD.\n   */\n  #annotationToScoord(annotation) {\n    const srScoord = new DicomSRContent(ValueTypes.scoord);\n    srScoord.relationshipType = RelationshipTypes.contains;\n    if (annotation.mathShape instanceof Line) {\n      srScoord.conceptNameCode = getPathCode();\n    } else {\n      srScoord.conceptNameCode = getImageRegionCode();\n    }\n    srScoord.value = getScoordFromShape(annotation.mathShape);\n\n    const itemContentSequence = [];\n\n    // reference image UID\n    const srImage = new DicomSRContent(ValueTypes.image);\n    srImage.relationshipType = RelationshipTypes.selectedFrom;\n    srImage.conceptNameCode = getSourceImageCode();\n    const sopRef = new SopInstanceReference();\n    sopRef.referencedSOPClassUID = '';\n    sopRef.referencedSOPInstanceUID = annotation.referenceSopUID;\n    const imageRef = new ImageReference();\n    imageRef.referencedSOPSequence = sopRef;\n    srImage.value = imageRef;\n    itemContentSequence.push(srImage);\n\n    // annotation id\n    const srUid = new DicomSRContent(ValueTypes.uidref);\n    srUid.relationshipType = RelationshipTypes.hasProperties;\n    srUid.conceptNameCode = getTrackingIdentifierCode();\n    srUid.value = annotation.id;\n    itemContentSequence.push(srUid);\n\n    // text expr\n    const shortLabel = new DicomSRContent(ValueTypes.text);\n    shortLabel.relationshipType = RelationshipTypes.hasProperties;\n    shortLabel.conceptNameCode = getShortLabelCode();\n    shortLabel.value = annotation.textExpr;\n    // label position\n    if (typeof annotation.labelPosition !== 'undefined') {\n      const labelPosition = new DicomSRContent(ValueTypes.scoord);\n      labelPosition.relationshipType = RelationshipTypes.hasProperties;\n      labelPosition.conceptNameCode = getReferencePointsCode();\n      const labelPosScoord = new SpatialCoordinate();\n      labelPosScoord.graphicType = GraphicTypes.point;\n      const graphicData = [\n        annotation.labelPosition.getX().toString(),\n        annotation.labelPosition.getY().toString()\n      ];\n      labelPosScoord.graphicData = graphicData;\n      labelPosition.value = labelPosScoord;\n\n      // add position to label sequence\n      shortLabel.contentSequence = [labelPosition];\n    }\n    itemContentSequence.push(shortLabel);\n\n    // colour\n    const colour = new DicomSRContent(ValueTypes.text);\n    colour.relationshipType = RelationshipTypes.hasProperties;\n    colour.conceptNameCode = getColourCode();\n    colour.value = annotation.colour;\n    itemContentSequence.push(colour);\n\n    // reference points\n    if (typeof annotation.referencePoints !== 'undefined') {\n      const referencePoints = new DicomSRContent(ValueTypes.scoord);\n      referencePoints.relationshipType = RelationshipTypes.hasProperties;\n      referencePoints.conceptNameCode = getReferencePointsCode();\n      const refPointsScoord = new SpatialCoordinate();\n      refPointsScoord.graphicType = GraphicTypes.multipoint;\n      const graphicData = [];\n      for (const point of annotation.referencePoints) {\n        graphicData.push(point.getX().toString());\n        graphicData.push(point.getY().toString());\n      }\n      refPointsScoord.graphicData = graphicData;\n\n      referencePoints.value = refPointsScoord;\n      itemContentSequence.push(referencePoints);\n    }\n\n    // plane points\n    if (typeof annotation.planePoints !== 'undefined') {\n      const planePoints = new DicomSRContent(ValueTypes.scoord3d);\n      planePoints.relationshipType = RelationshipTypes.hasProperties;\n      planePoints.conceptNameCode = getReferenceGeometryCode();\n      const pointsScoord = new SpatialCoordinate3D();\n      pointsScoord.graphicType = GraphicTypes.multipoint;\n      const graphicData = [];\n      for (const planePoint of annotation.planePoints) {\n        graphicData.push(planePoint.getX().toString());\n        graphicData.push(planePoint.getY().toString());\n        graphicData.push(planePoint.getZ().toString());\n      }\n      pointsScoord.graphicData = graphicData;\n\n      planePoints.value = pointsScoord;\n      itemContentSequence.push(planePoints);\n    }\n\n    // quantification\n    if (typeof annotation.quantification !== 'undefined') {\n      for (const key in annotation.quantification) {\n        const quatifContent = getSRContentFromValue(\n          key,\n          annotation.quantification[key].value,\n          annotation.quantification[key].unit\n        );\n        if (typeof quatifContent !== 'undefined') {\n          itemContentSequence.push(quatifContent);\n        }\n      }\n    }\n\n    srScoord.contentSequence = itemContentSequence;\n    return srScoord;\n  }\n\n  /**\n   * Convert an annotation group into a DICOM SR object.\n   *\n   * @param {AnnotationGroup} annotationGroup The annotation group.\n   * @param {Object<string, any>} [extraTags] Optional list of extra tags.\n   * @returns {Object<string, DataElement>} A list of dicom elements.\n   */\n  toDicom(annotationGroup, extraTags) {\n    let tags = annotationGroup.getMeta();\n\n    // transfer syntax: ExplicitVRLittleEndian\n    tags.TransferSyntaxUID = '1.2.840.10008.1.2.1';\n    // class: Basic Text SR Storage\n    tags.SOPClassUID = '1.2.840.10008.5.1.4.1.1.88.11';\n    tags.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.88.11';\n    tags.CompletionFlag = 'PARTIAL';\n    tags.VerificationFlag = 'UNVERIFIED';\n\n    const now = new Date();\n    tags.ContentDate = getDicomDate(dateToDateObj(now));\n    tags.ContentTime = getDicomTime(dateToTimeObj(now));\n\n    const contentSequence = [];\n    for (const annotation of annotationGroup.getList()) {\n      contentSequence.push(this.#annotationToScoord(annotation));\n    }\n\n    // main\n    if (contentSequence.length !== 0) {\n      const srContent = new DicomSRContent(ValueTypes.container);\n      srContent.conceptNameCode = getMeasurementGroupCode();\n      srContent.contentSequence = contentSequence;\n\n      tags = {\n        ...tags,\n        ...getDicomSRContentItem(srContent)\n      };\n    }\n\n    // merge extra tags if provided\n    if (typeof extraTags !== 'undefined') {\n      mergeTags(tags, extraTags);\n    }\n\n    return getElementsFromJSONTags(tags);\n  }\n\n}","import {ListenerHandler} from '../utils/listen';\nimport {mergeObjects} from '../utils/operator';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from '../image/image';\nimport {AnnotationGroup} from '../image/annotationGroup';\n/* eslint-enable no-unused-vars */\n\n/**\n * DICOM data: meta and possible image.\n */\nexport class DicomData {\n  /**\n   * DICOM meta data.\n   *\n   * @type {object}\n   */\n  meta;\n\n  /**\n   * Image extracted from meta data.\n   *\n   * @type {Image|undefined}\n   */\n  image;\n  /**\n   * Annotattion group extracted from meta data.\n   *\n   * @type {AnnotationGroup|undefined}\n   */\n  annotationGroup;\n\n  /**\n   * @param {object} meta The DICOM meta data.\n   */\n  constructor(meta) {\n    this.meta = meta;\n  }\n}\n\n/*\n * DicomData controller.\n */\nexport class DataController {\n\n  /**\n   * List of DICOM data.\n   *\n   * @type {Object<string, DicomData>}\n   */\n  #dataList = {};\n\n  /**\n   * Distinct data loaded counter.\n   *\n   * @type {number}\n   */\n  #dataIdCounter = -1;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Get the next data id.\n   *\n   * @returns {string} The data id.\n   */\n  getNextDataId() {\n    ++this.#dataIdCounter;\n    return this.#dataIdCounter.toString();\n  }\n\n  /**\n   * Get the list of ids in the data storage.\n   *\n   * @returns {string[]} The list of data ids.\n   */\n  getDataIds() {\n    return Object.keys(this.#dataList);\n  }\n\n  /**\n   * Reset the class: empty the data storage.\n   */\n  reset() {\n    this.#dataList = {};\n  }\n\n  /**\n   * Get a data at a given index.\n   *\n   * @param {string} dataId The data id.\n   * @returns {DicomData|undefined} The DICOM data.\n   */\n  get(dataId) {\n    return this.#dataList[dataId];\n  }\n\n  /**\n   * Get the list of dataIds that contain the input UIDs.\n   *\n   * @param {string[]} uids A list of UIDs.\n   * @returns {string[]} The list of dataIds that contain the UIDs.\n   */\n  getDataIdsFromSopUids(uids) {\n    const res = [];\n    // check input\n    if (typeof uids === 'undefined' ||\n      uids.length === 0) {\n      return res;\n    }\n    const keys = Object.keys(this.#dataList);\n    for (const key of keys) {\n      if (typeof this.#dataList[key].image !== 'undefined' &&\n        this.#dataList[key].image.containsImageUids(uids)) {\n        res.push(key);\n      }\n    }\n    return res;\n  }\n\n  /**\n   * Set the image at a given index.\n   *\n   * @param {string} dataId The data id.\n   * @param {Image} image The image to set.\n   */\n  setImage(dataId, image) {\n    this.#dataList[dataId].image = image;\n    /**\n     * Data image set event.\n     *\n     * @event DataController#dataimageset\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} value The event value, first element is the image.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'dataimageset',\n      value: [image],\n      dataid: dataId\n    });\n    // listen to image change\n    image.addEventListener('imagecontentchange', this.#getFireEvent(dataId));\n    image.addEventListener('imagegeometrychange', this.#getFireEvent(dataId));\n  }\n\n  /**\n   * Add a new data.\n   *\n   * @param {string} dataId The data id.\n   * @param {DicomData} data The data.\n   */\n  add(dataId, data) {\n    if (typeof this.#dataList[dataId] !== 'undefined') {\n      throw new Error('Data id already used in storage: ' + dataId);\n    }\n    // store the new image\n    this.#dataList[dataId] = data;\n    /**\n     * Data add event.\n     *\n     * @event DataController#dataadd\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'dataadd',\n      dataid: dataId\n    });\n    // listen to image change\n    if (typeof data.image !== 'undefined') {\n      data.image.addEventListener(\n        'imagecontentchange', this.#getFireEvent(dataId));\n      data.image.addEventListener(\n        'imagegeometrychange', this.#getFireEvent(dataId));\n    }\n    if (typeof data.annotationGroup !== 'undefined') {\n      data.annotationGroup.addEventListener(\n        'annotationadd', this.#getFireEvent(dataId));\n      data.annotationGroup.addEventListener(\n        'annotationupdate', this.#getFireEvent(dataId));\n      data.annotationGroup.addEventListener(\n        'annotationremove', this.#getFireEvent(dataId));\n    }\n  }\n\n  /**\n   * Remove a data from the list.\n   *\n   * @param {string} dataId The data id.\n   */\n  remove(dataId) {\n    if (typeof this.#dataList[dataId] !== 'undefined') {\n      // stop listeners\n      const image = this.#dataList[dataId].image;\n      if (typeof image !== 'undefined') {\n        image.removeEventListener(\n          'imagecontentchange', this.#getFireEvent(dataId));\n        image.removeEventListener(\n          'imagegeometrychange', this.#getFireEvent(dataId));\n      }\n      const annotationGroup = this.#dataList[dataId].annotationGroup;\n      if (typeof annotationGroup !== 'undefined') {\n        annotationGroup.removeEventListener(\n          'annotationadd', this.#getFireEvent(dataId));\n        annotationGroup.removeEventListener(\n          'annotationupdate', this.#getFireEvent(dataId));\n        annotationGroup.removeEventListener(\n          'annotationremove', this.#getFireEvent(dataId));\n      }\n      // remove data from list\n      delete this.#dataList[dataId];\n      /**\n       * Data remove event.\n       *\n       * @event DataController#dataremove\n       * @type {object}\n       * @property {string} type The event type.\n       * @property {string} dataid The data id.\n       */\n      this.#fireEvent({\n        type: 'dataremove',\n        dataid: dataId\n      });\n    }\n  }\n\n  /**\n   * Update the current data.\n   *\n   * @param {string} dataId The data id.\n   * @param {DicomData} data The data.\n   */\n  update(dataId, data) {\n    if (typeof this.#dataList[dataId] === 'undefined') {\n      throw new Error('Cannot find data to update: ' + dataId);\n    }\n    const dataToUpdate = this.#dataList[dataId];\n\n    // add slice to current image\n    if (typeof dataToUpdate.image !== 'undefined' &&\n      typeof data.image !== 'undefined'\n    ) {\n      dataToUpdate.image.appendSlice(data.image);\n    }\n\n    // update meta data\n    // TODO add time support\n    let idKey = '';\n    if (typeof data.meta['00020010'] !== 'undefined') {\n      // dicom case, use 'InstanceNumber'\n      idKey = '00200013';\n    } else {\n      idKey = 'imageUid';\n    }\n    dataToUpdate.meta = mergeObjects(\n      dataToUpdate.meta,\n      data.meta,\n      idKey,\n      'value');\n\n    /**\n     * Data udpate event.\n     *\n     * @event DataController#dataupdate\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'dataupdate',\n      dataid: dataId\n    });\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  /**\n   * Get a fireEvent function that adds the input data id\n   * to the event value.\n   *\n   * @param {string} dataId The data id.\n   * @returns {Function} A fireEvent function.\n   */\n  #getFireEvent(dataId) {\n    return (event) => {\n      event.dataid = dataId;\n      this.#fireEvent(event);\n    };\n  }\n\n} // DataController class\n","import {arrayEquals} from './array';\n\n/**\n * Merge two similar objects.\n *\n * Objects need to be in the form of:\n * <code>\n * {\n *   idKey: {valueKey: [0]},\n *   key0: {valueKey: [\"abc\"]},\n *   key1: {valueKey: [33]}\n * }\n * </code>.\n *\n * Merged objects will be in the form of:\n * <code>\n * {\n *   idKey: {valueKey: [0,1,2], merged: true},\n *   key0: {valueKey: {\n *     0: [\"abc\"],\n *     1: [\"def\"],\n *     2: [\"ghi\"]\n *   }},\n *   key1: {valueKey: {\n *     0: [33],\n *     1: [44],\n *     2: [55]\n *   }}\n * }\n * </code>.\n *\n * @param {object} obj1 The first object, can be the result of a previous merge.\n * @param {object} obj2 The second object.\n * @param {string} idKey The key to use as index for duplicate values.\n * @param {string} valueKey The key to use to access object values.\n * @returns {object} The merged object.\n */\nexport function mergeObjects(obj1, obj2, idKey, valueKey) {\n  const res = {};\n  // check id key\n  if (!idKey) {\n    throw new Error('Cannot merge object with an undefined id key: ' + idKey);\n  } else {\n    if (!Object.prototype.hasOwnProperty.call(obj1, idKey)) {\n      throw new Error('Id key not found in first object while merging: ' +\n        idKey + ', obj: ' + obj1);\n    }\n    if (!Object.prototype.hasOwnProperty.call(obj2, idKey)) {\n      throw new Error('Id key not found in second object while merging: ' +\n        idKey + ', obj: ' + obj2);\n    }\n  }\n  // check value key\n  if (!valueKey) {\n    throw new Error('Cannot merge object with an undefined value key: ' +\n      valueKey);\n  }\n\n  // check if merged object\n  let mergedObj1 = false;\n  if (Object.prototype.hasOwnProperty.call(obj1[idKey], 'merged') &&\n    obj1[idKey].merged) {\n    mergedObj1 = true;\n  }\n  // handle the id part\n  if (!Object.prototype.hasOwnProperty.call(obj1[idKey], valueKey)) {\n    throw new Error('Id value not found in first object while merging: ' +\n      idKey + ', valueKey: ' + valueKey + ', ojb: ' + obj1);\n  }\n  if (!Object.prototype.hasOwnProperty.call(obj2[idKey], valueKey)) {\n    throw new Error('Id value not found in second object while merging: ' +\n      idKey + ', valueKey: ' + valueKey + ', ojb: ' + obj2);\n  }\n  let id1 = obj1[idKey][valueKey];\n  const id2 = obj2[idKey][valueKey][0];\n  // update id key\n  res[idKey] = obj1[idKey];\n  if (mergedObj1) {\n    // check if array does not include id2\n    for (let k = 0; k < id1.length; ++k) {\n      if (id1[k] === id2) {\n        throw new Error('The first object already contains id2: ' +\n          id2 + ', id1: ' + id1);\n      }\n    }\n    res[idKey][valueKey].push(id2);\n  } else {\n    id1 = id1[0];\n    if (id1 === id2) {\n      throw new Error('Cannot merge object with same ids: ' +\n        id1 + ', id2: ' + id2);\n    }\n    // update merge object\n    res[idKey][valueKey].push(id2);\n    res[idKey].merged = true;\n  }\n\n  // get keys\n  const keys1 = Object.keys(obj1);\n  // keys2 without duplicates of keys1\n  const keys2 = Object.keys(obj2).filter(function (item) {\n    return keys1.indexOf(item) < 0;\n  });\n  const keys = keys1.concat(keys2);\n\n  // loop through keys\n  for (let i = 0; i < keys.length; ++i) {\n    const key = keys[i];\n    if (key !== idKey) {\n      // first\n      let value1;\n      let subValue1;\n      if (Object.prototype.hasOwnProperty.call(obj1, key)) {\n        value1 = obj1[key];\n        if (Object.prototype.hasOwnProperty.call(value1, valueKey)) {\n          subValue1 = value1[valueKey];\n        }\n      }\n      // second\n      let value2;\n      let subValue2;\n      if (Object.prototype.hasOwnProperty.call(obj2, key)) {\n        value2 = obj2[key];\n        if (Object.prototype.hasOwnProperty.call(value2, valueKey)) {\n          subValue2 = value2[valueKey];\n        }\n      }\n      // result value\n      let value;\n      // use existing to copy properties\n      if (typeof value1 !== 'undefined') {\n        value = value1;\n      } else if (typeof value2 !== 'undefined') {\n        value = value2;\n      }\n      // create merge object if different values\n      if (!arrayEquals(subValue1, subValue2)) {\n        // add to merged object or create new\n        if (mergedObj1) {\n          if (Array.isArray(subValue1)) {\n            // merged object with repeated value\n            // copy it with the index list\n            value[valueKey] = {};\n            for (let j = 0; j < id1.length; ++j) {\n              value[valueKey][id1[j]] = subValue1;\n            }\n          } else {\n            value[valueKey] = subValue1;\n          }\n          // undefined subValue1\n          if (typeof value[valueKey] === 'undefined') {\n            value[valueKey] = {};\n          }\n          // add obj2 value\n          value[valueKey][id2] = subValue2;\n        } else {\n          // create merge object\n          const newValue = {};\n          newValue[id1] = subValue1;\n          newValue[id2] = subValue2;\n          value[valueKey] = newValue;\n        }\n      }\n      // store value in result object\n      res[key] = value;\n    }\n  }\n  return res;\n}\n","import {logger} from '../utils/logger';\nimport {\n  DicomParser,\n  getSyntaxDecompressionName\n} from '../dicom/dicomParser';\nimport {ImageFactory} from './imageFactory';\nimport {MaskFactory} from './maskFactory';\nimport {PixelBufferDecoder} from './decoder';\nimport {AnnotationGroupFactory} from './annotationGroupFactory';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {DataElement} from '../dicom/dataElement';\nimport {DicomData} from '../app/dataController';\n/* eslint-enable no-unused-vars */\n\n/**\n * Create a View from a DICOM buffer.\n */\nexport class DicomBufferToView {\n\n  /**\n   * Converter options.\n   *\n   * @type {object}\n   */\n  #options;\n\n  /**\n   * Set the converter options.\n   *\n   * @param {object} opt The input options.\n   */\n  setOptions(opt) {\n    this.#options = opt;\n  }\n\n  /**\n   * Pixel buffer decoder.\n   * Define only once to allow optional asynchronous mode.\n   *\n   * @type {object}\n   */\n  #pixelDecoder = null;\n\n  // local tmp storage\n  #dicomParserStore = [];\n  #finalBufferStore = [];\n  #decompressedSizes = [];\n  #factories = [];\n\n  /**\n   * Get the factory associated to input DICOM elements.\n   *\n   * @param {Object<string, DataElement>} elements The DICOM elements.\n   * @returns {ImageFactory|MaskFactory|AnnotationGroupFactory|undefined}\n   *   The associated factory.\n   */\n  #getFactory(elements) {\n    let factory;\n    const modalityElement = elements['00080060'];\n    if (typeof modalityElement !== 'undefined') {\n      const modality = modalityElement.value[0];\n      if (modality === 'SEG') {\n        // mask factory for DICOM SEG\n        factory = new MaskFactory();\n      } else if (modality === 'SR') {\n        // annotation factory for DICOM SR\n        factory = new AnnotationGroupFactory();\n      }\n    }\n    // image factory for pixel data\n    if (typeof factory === 'undefined') {\n      const pixelElement = elements['7FE00010'];\n      if (typeof pixelElement !== 'undefined') {\n        factory = new ImageFactory();\n      }\n    }\n    return factory;\n  }\n\n  /**\n   * Generate the data object.\n   *\n   * @param {number} index The data index.\n   * @param {string} origin The data origin.\n   * @returns {boolean} True if the generation went ok.\n   */\n  #generateData(index, origin) {\n    const dataElements = this.#dicomParserStore[index].getDicomElements();\n    const factory = this.#factories[index];\n    // exit if no factory\n    if (typeof factory === 'undefined') {\n      return false;\n    }\n    // create data\n    try {\n      const data = new DicomData(dataElements);\n      if (factory instanceof AnnotationGroupFactory) {\n        data.annotationGroup = factory.create(dataElements);\n      } else {\n        data.image = factory.create(\n          dataElements,\n          this.#finalBufferStore[index],\n          this.#options.numberOfFiles);\n      }\n      // call onloaditem\n      this.onloaditem({\n        data: data,\n        source: origin,\n        warn: factory.getWarning()\n      });\n    } catch (error) {\n      this.onerror({\n        error: error,\n        source: origin\n      });\n      this.onloadend({\n        source: origin\n      });\n      // false for error\n      return false;\n    }\n\n    // all good\n    return true;\n  }\n\n  /**\n   * Generate a single data object.\n   *\n   * @param {number} index The data index.\n   * @param {string} origin The data origin.\n   */\n  #generateSingleData(index, origin) {\n    // generate image\n    if (this.#generateData(index, origin)) {\n      // send load event\n      this.onload({\n        source: origin\n      });\n    }\n    // allways send loadend\n    this.onloadend({\n      source: origin\n    });\n  }\n\n  /**\n   * Generate the image object from an uncompressed buffer.\n   *\n   * @param {number} index The data index.\n   * @param {string} origin The data origin.\n   */\n  #generateImageUncompressed(index, origin) {\n    // send 100% progress\n    this.onprogress({\n      lengthComputable: true,\n      loaded: 100,\n      total: 100,\n      index: index,\n      source: origin\n    });\n    // generate single data\n    this.#generateSingleData(index, origin);\n  }\n\n  /**\n   * Generate the image object from an compressed buffer.\n   *\n   * @param {number} index The data index.\n   * @param {Array} pixelBuffer The dicom parser.\n   * @param {string} algoName The compression algorithm name.\n   */\n  #generateImageCompressed(index, pixelBuffer, algoName) {\n    const dicomParser = this.#dicomParserStore[index];\n\n    // gather pixel buffer meta data\n    const bitsAllocated =\n      dicomParser.getDicomElements()['00280100'].value[0];\n    const pixelRepresentation =\n      dicomParser.getDicomElements()['00280103'].value[0];\n    const pixelMeta = {\n      bitsAllocated: bitsAllocated,\n      isSigned: (pixelRepresentation === 1)\n    };\n    const columnsElement = dicomParser.getDicomElements()['00280011'];\n    const rowsElement = dicomParser.getDicomElements()['00280010'];\n    if (typeof columnsElement !== 'undefined' &&\n      typeof rowsElement !== 'undefined') {\n      pixelMeta.sliceSize = columnsElement.value[0] * rowsElement.value[0];\n    }\n    const samplesPerPixelElement =\n      dicomParser.getDicomElements()['00280002'];\n    if (typeof samplesPerPixelElement !== 'undefined') {\n      pixelMeta.samplesPerPixel = samplesPerPixelElement.value[0];\n    }\n    const planarConfigurationElement =\n      dicomParser.getDicomElements()['00280006'];\n    if (typeof planarConfigurationElement !== 'undefined') {\n      pixelMeta.planarConfiguration = planarConfigurationElement.value[0];\n    }\n\n    const numberOfItems = pixelBuffer.length;\n\n    // setup the decoder (one decoder per all converts)\n    if (this.#pixelDecoder === null) {\n      this.#pixelDecoder = new PixelBufferDecoder(\n        algoName, numberOfItems);\n      // callbacks\n      // pixelDecoder.ondecodestart: nothing to do\n      this.#pixelDecoder.ondecodeditem = (event) => {\n        this.#onDecodedItem(event);\n        // send onload and onloadend when all items have been decoded\n        if (event.itemNumber + 1 === event.numberOfItems) {\n          this.onload(event);\n          this.onloadend(event);\n        }\n      };\n      // pixelDecoder.ondecoded: nothing to do\n      // pixelDecoder.ondecodeend: nothing to do\n      this.#pixelDecoder.onerror = this.onerror;\n      this.#pixelDecoder.onabort = this.onabort;\n    }\n\n    // launch decode\n    for (let i = 0; i < numberOfItems; ++i) {\n      this.#pixelDecoder.decode(pixelBuffer[i], pixelMeta,\n        {\n          itemNumber: i,\n          numberOfItems: numberOfItems,\n          index: index\n        }\n      );\n    }\n  }\n\n  /**\n   * Handle a decoded item event.\n   *\n   * @param {object} event The decoded item event.\n   */\n  #onDecodedItem(event) {\n    // send progress\n    this.onprogress({\n      lengthComputable: true,\n      loaded: event.itemNumber + 1,\n      total: event.numberOfItems,\n      index: event.index,\n      source: origin\n    });\n\n    const dataIndex = event.index;\n\n    // store decoded data\n    const decodedData = event.data[0];\n    if (event.numberOfItems !== 1) {\n      // allocate buffer if not done yet\n      if (typeof this.#decompressedSizes[dataIndex] === 'undefined') {\n        this.#decompressedSizes[dataIndex] = decodedData.length;\n        const fullSize = event.numberOfItems *\n          this.#decompressedSizes[dataIndex];\n        try {\n          this.#finalBufferStore[dataIndex] =\n            new decodedData.constructor(fullSize);\n        } catch (error) {\n          if (error instanceof RangeError) {\n            const powerOf2 = Math.floor(Math.log(fullSize) / Math.log(2));\n            logger.error('Cannot allocate ' +\n              decodedData.constructor.name +\n              ' of size: ' +\n              fullSize + ' (>2^' + powerOf2 + ') for decompressed data.');\n          }\n          // abort\n          this.#pixelDecoder.abort();\n          // send events\n          this.onerror({\n            error: error,\n            source: origin\n          });\n          this.onloadend({\n            source: origin\n          });\n          // exit\n          return;\n        }\n      }\n      // hoping for all items to have the same size...\n      if (decodedData.length !== this.#decompressedSizes[dataIndex]) {\n        logger.warn('Unsupported varying decompressed data size: ' +\n          decodedData.length + ' != ' + this.#decompressedSizes[dataIndex]);\n      }\n      // set buffer item data\n      this.#finalBufferStore[dataIndex].set(\n        decodedData, this.#decompressedSizes[dataIndex] * event.itemNumber);\n    } else {\n      this.#finalBufferStore[dataIndex] = decodedData;\n    }\n\n    // create image for the first item\n    if (event.itemNumber === 0) {\n      this.#generateData(dataIndex, origin);\n    }\n  }\n\n  /**\n   * Handle non image data.\n   *\n   * @param {number} index The data index.\n   * @param {string} origin The data origin.\n   */\n  #handleNonImageData(index, origin) {\n    // generate single data\n    this.#generateSingleData(index, origin);\n  }\n\n  /**\n   * Handle image data.\n   *\n   * @param {number} index The data index.\n   * @param {string} origin The data origin.\n   */\n  #handleImageData(index, origin) {\n    const dicomParser = this.#dicomParserStore[index];\n\n    const pixelBuffer = dicomParser.getDicomElements()['7FE00010'].value;\n    // help GC: discard pixel buffer from elements\n    dicomParser.getDicomElements()['7FE00010'].value = [];\n    this.#finalBufferStore[index] = pixelBuffer[0];\n\n    // transfer syntax (always there)\n    const syntax = dicomParser.getDicomElements()['00020010'].value[0];\n    const algoName = getSyntaxDecompressionName(syntax);\n    const needDecompression = typeof algoName !== 'undefined';\n\n    if (needDecompression) {\n      // generate image\n      this.#generateImageCompressed(\n        index,\n        pixelBuffer,\n        algoName);\n    } else {\n      this.#generateImageUncompressed(index, origin);\n    }\n  }\n\n  /**\n   * Get data from an input buffer using a DICOM parser.\n   *\n   * @param {ArrayBuffer} buffer The input data buffer.\n   * @param {string} origin The data origin.\n   * @param {number} dataIndex The data index.\n   */\n  convert(buffer, origin, dataIndex) {\n    // start event\n    this.onloadstart({\n      source: origin,\n      index: dataIndex\n    });\n\n    // DICOM parser\n    const dicomParser = new DicomParser();\n\n    if (typeof this.#options.defaultCharacterSet !== 'undefined') {\n      dicomParser.setDefaultCharacterSet(this.#options.defaultCharacterSet);\n    }\n    // parse the buffer\n    let factory;\n    try {\n      dicomParser.parse(buffer);\n      // check elements\n      factory = this.#getFactory(dicomParser.getDicomElements());\n      if (typeof factory !== 'undefined') {\n        factory.checkElements(dicomParser.getDicomElements());\n      }\n    } catch (error) {\n      this.onerror({\n        error: error,\n        source: origin\n      });\n      this.onloadend({\n        source: origin\n      });\n      return;\n    }\n\n    // store\n    this.#dicomParserStore[dataIndex] = dicomParser;\n    this.#factories[dataIndex] = factory;\n\n    // handle parsed data\n    if (factory instanceof AnnotationGroupFactory) {\n      this.#handleNonImageData(dataIndex, origin);\n    } else {\n      this.#handleImageData(dataIndex, origin);\n    }\n  }\n\n  /**\n   * Abort a conversion.\n   */\n  abort() {\n    // abort decoding, will trigger pixelDecoder.onabort\n    if (this.#pixelDecoder) {\n      this.#pixelDecoder.abort();\n    }\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n  /**\n   * Handle a load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class DicomBufferToView\n","import {MultiProgressHandler} from '../utils/progress';\nimport {loaderList} from './loaderList';\n\n/**\n * Memory loader.\n */\nexport class MemoryLoader {\n\n  /**\n   * Input data.\n   *\n   * @type {Array}\n   */\n  #inputData = null;\n\n  /**\n   * Data loader.\n   *\n   * @type {object}\n   */\n  #runningLoader = null;\n\n  /**\n   * Number of loaded data.\n   *\n   * @type {number}\n   */\n  #nLoad = 0;\n\n  /**\n   * Number of load end events.\n   *\n   * @type {number}\n   */\n  #nLoadend = 0;\n\n  /**\n   * The default character set (optional).\n   *\n   * @type {string}\n   */\n  #defaultCharacterSet;\n\n  /**\n   * Get the default character set.\n   *\n   * @returns {string} The default character set.\n   */\n  getDefaultCharacterSet() {\n    return this.#defaultCharacterSet;\n  }\n\n  /**\n   * Set the default character set.\n   *\n   * @param {string} characterSet The character set.\n   */\n  setDefaultCharacterSet(characterSet) {\n    this.#defaultCharacterSet = characterSet;\n  }\n\n  /**\n   * Store the current input.\n   *\n   * @param {object} data The input data.\n   */\n  #storeInputData(data) {\n    this.#inputData = data;\n    // reset counters\n    this.#nLoad = 0;\n    this.#nLoadend = 0;\n    // clear storage\n    this.#clearStoredLoader();\n  }\n\n  /**\n   * Store the launched loader.\n   *\n   * @param {object} loader The launched loader.\n   */\n  #storeLoader(loader) {\n    this.#runningLoader = loader;\n  }\n\n  /**\n   * Clear the stored loader.\n   *\n   */\n  #clearStoredLoader() {\n    this.#runningLoader = null;\n  }\n\n  /**\n   * Increment the number of loaded data\n   *   and call onload if loaded all data.\n   *\n   * @param {object} _event The load data event.\n   */\n  #addLoad = (_event) => {\n    this.#nLoad++;\n    // call onload when all is loaded\n    // (not using the input event since it is not the\n    //   general load)\n    if (this.#nLoad === this.#inputData.length) {\n      this.onload({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * Increment the counter of load end events\n   *   and run callbacks when all done, erroneus or not.\n   *\n   * @param {object} _event The load end event.\n   */\n  #addLoadend = (_event) => {\n    this.#nLoadend++;\n    // call onloadend when all is run\n    // (not using the input event since it is not the\n    //   general load end)\n    if (this.#nLoadend === this.#inputData.length) {\n      this.onloadend({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * Load a list of buffers.\n   *\n   * @param {Array} data The list of buffers to load.\n   */\n  load(data) {\n    // check input\n    if (typeof data === 'undefined' || data.length === 0) {\n      return;\n    }\n    this.#storeInputData(data);\n\n    // send start event\n    this.onloadstart({\n      source: data\n    });\n\n    // create prgress handler\n    const mproghandler = new MultiProgressHandler(this.onprogress);\n    mproghandler.setNToLoad(data.length);\n    mproghandler.setNumberOfDimensions(1);\n\n    // create loaders\n    const loaders = [];\n    for (let m = 0; m < loaderList.length; ++m) {\n      loaders.push(new loaderList[m]());\n    }\n\n    // find an appropriate loader\n    let dataElement = data[0];\n    let loader = null;\n    let foundLoader = false;\n    for (let l = 0; l < loaders.length; ++l) {\n      loader = loaders[l];\n      if (loader.canLoadMemory(dataElement)) {\n        foundLoader = true;\n        // load options\n        loader.setOptions({\n          numberOfFiles: data.length,\n          defaultCharacterSet: this.getDefaultCharacterSet()\n        });\n        // set loader callbacks\n        // loader.onloadstart: nothing to do\n        loader.onprogress = mproghandler.getUndefinedMonoProgressHandler(0);\n        loader.onloaditem = this.onloaditem;\n        loader.onload = this.#addLoad;\n        loader.onloadend = this.#addLoadend;\n        loader.onerror = this.onerror;\n        loader.onabort = this.onabort;\n\n        // store loader\n        this.#storeLoader(loader);\n        // exit\n        break;\n      }\n    }\n    if (!foundLoader) {\n      throw new Error('No loader found for data: ' + dataElement.filename);\n    }\n\n    // loop on I/O elements\n    for (let i = 0; i < data.length; ++i) {\n      dataElement = data[i];\n      // check loader\n      if (!loader.canLoadMemory(dataElement)) {\n        throw new Error('Input data of different type: ' +\n          dataElement.filename);\n      }\n      // read\n      loader.load(dataElement.data, dataElement.filename, i);\n    }\n  }\n\n  /**\n   * Abort a load.\n   */\n  abort() {\n    // abort loader\n    if (this.#runningLoader && this.#runningLoader.isLoading()) {\n      this.#runningLoader.abort();\n    }\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle a load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class MemoryLoader\n","import {Size} from '../image/size';\nimport {Spacing} from '../image/spacing';\nimport {Geometry} from '../image/geometry';\nimport {Image} from '../image/image';\nimport {Point3D} from '../math/point';\n\n/**\n * Convert a string into an UID.\n *\n * @param {string} str The input string.\n * @returns {string} The input string converted to numbers\n *   using parseInt with a 36 radix\n *   (10 digits from 0 to 9 + 26 digits from a to z).\n */\nfunction toUID(str) {\n  return parseInt(str, 36).toString();\n}\n\n/**\n * Create a simple array buffer from an ImageData buffer.\n *\n * @param {object} imageData The ImageData taken from a context.\n * @returns {Uint8Array} The image buffer.\n */\nfunction imageDataToBuffer(imageData) {\n  // remove alpha\n  // TODO support passing the full image data\n  const dataLen = imageData.data.length;\n  const buffer = new Uint8Array((dataLen / 4) * 3);\n  let j = 0;\n  for (let i = 0; i < dataLen; i += 4) {\n    buffer[j] = imageData.data[i];\n    buffer[j + 1] = imageData.data[i + 1];\n    buffer[j + 2] = imageData.data[i + 2];\n    j += 3;\n  }\n  return buffer;\n}\n\n/**\n * Get an image from an input context imageData.\n *\n * @param {number} width The width of the coresponding image.\n * @param {number} height The height of the coresponding image.\n * @param {number} sliceIndex The slice index of the imageData.\n * @param {object} imageBuffer The image buffer.\n * @param {number} numberOfFrames The final number of frames.\n * @param {string} imageUid The image UID.\n * @returns {object} The corresponding view.\n */\nfunction getDefaultImage(\n  width, height, sliceIndex,\n  imageBuffer, numberOfFrames,\n  imageUid) {\n  // image size\n  const imageSize = new Size([width, height, 1]);\n  // default spacing\n  // TODO: misleading...\n  const imageSpacing = new Spacing([1, 1, 1]);\n  // default origin\n  const origin = new Point3D(0, 0, sliceIndex);\n  // create image\n  const geometry = new Geometry([origin], imageSize, imageSpacing);\n  const image = new Image(geometry, imageBuffer, [imageUid]);\n  image.setPhotometricInterpretation('RGB');\n  // meta information\n  const meta = {};\n  meta.BitsStored = 8;\n  if (typeof numberOfFrames !== 'undefined') {\n    meta.numberOfFiles = numberOfFrames;\n  }\n  image.setMeta(meta);\n  // return\n  return image;\n}\n\n/**\n * Get data from an input image using a canvas.\n *\n * @param {HTMLImageElement} domImage The DOM Image,\n *   an HTMLImageElement with extra info.\n * @param {string|File} origin The data origin.\n * @param {number} index The data index.\n * @returns {object} A load data event.\n */\nexport function getViewFromDOMImage(domImage, origin, index) {\n  // image size\n  const width = domImage.width;\n  const height = domImage.height;\n\n  // draw the image in the canvas in order to get its data\n  const canvas = document.createElement('canvas');\n  canvas.width = width;\n  canvas.height = height;\n  const ctx = canvas.getContext('2d');\n  ctx.drawImage(domImage, 0, 0);\n  // get the image data\n  const imageData = ctx.getImageData(0, 0, width, height);\n\n  // image properties\n  const info = {};\n  let seriesUID;\n  if (typeof origin === 'string') {\n    info['origin'] = {value: origin};\n    seriesUID = toUID(origin);\n  } else {\n    info['fileName'] = {value: origin.name};\n    seriesUID = toUID(origin.name);\n    info['fileType'] = {value: origin.type};\n    info['fileLastModifiedDate'] = {value: origin.lastModified};\n  }\n  info['imageWidth'] = {value: width};\n  info['imageHeight'] = {value: height};\n\n  // image identifier (~UID like)\n  const sliceIndex = index ? index : 0;\n  info['imageUid'] = {value: sliceIndex};\n  // series identifier (~UID like)\n  info['seriesUid'] = {value: seriesUID};\n\n  // create view\n  const imageBuffer = imageDataToBuffer(imageData);\n  const image = getDefaultImage(\n    width, height, sliceIndex, imageBuffer, 1, sliceIndex.toString());\n\n  // add seriesUID to meta\n  const meta = image.getMeta();\n  meta.SeriesInstanceUID = seriesUID;\n  image.setMeta(meta);\n\n  // return\n  return {\n    data: {\n      image: image,\n      meta: info\n    },\n    source: origin\n  };\n}\n\n/**\n * Get data from an input image using a canvas.\n *\n * @param {object} video The DOM Video, an HTMLVideoElement with extra info.\n * @param {Function} onloaditem On load callback.\n * @param {object} onload The function to call once the data is loaded.\n * @param {object} onprogress The function to call to report progress.\n * @param {object} onloadend The function to call to report load end.\n * @param {string|File} origin The data origin.\n * @param {number} dataIndex The data index.\n */\nexport function getViewFromDOMVideo(\n  video, onloaditem, onload, onprogress, onloadend,\n  origin, dataIndex) {\n  // video size\n  const width = video.videoWidth;\n  const height = video.videoHeight;\n\n  // default frame rate...\n  const frameRate = 30;\n  // number of frames\n  const numberOfFrames = Math.ceil(video.duration * frameRate);\n\n  // video properties\n  const info = {};\n  let seriesUID;\n  if (typeof origin === 'string') {\n    info['origin'] = {value: origin};\n    seriesUID = toUID(origin);\n  } else {\n    info['fileName'] = {value: origin.name};\n    seriesUID = toUID(origin.name);\n    info['fileType'] = {value: origin.type};\n    info['fileLastModifiedDate'] = {value: origin.lastModified};\n  }\n  info['imageWidth'] = {value: width};\n  info['imageHeight'] = {value: height};\n  info['numberOfFrames'] = {value: numberOfFrames};\n\n  // image identifier (~UID like)\n  info['imageUid'] = {value: 0};\n  // series identifier (~UID like)\n  info['seriesUid'] = {value: seriesUID};\n\n  // draw the image in the canvas in order to get its data\n  const canvas = document.createElement('canvas');\n  canvas.width = width;\n  canvas.height = height;\n  const ctx = canvas.getContext('2d');\n\n  // using seeked to loop through all video frames\n  video.addEventListener('seeked', onseeked, false);\n\n  // current frame index\n  let frameIndex = 0;\n  // video image\n  let image = null;\n\n  /**\n   * Draw the context and store it as a frame.\n   */\n  function storeFrame() {\n    // send progress\n    onprogress({\n      lengthComputable: true,\n      loaded: frameIndex,\n      total: numberOfFrames,\n      index: dataIndex,\n      source: origin\n    });\n    // draw image\n    ctx.drawImage(video, 0, 0);\n    // context to image buffer\n    const imgBuffer = imageDataToBuffer(\n      ctx.getImageData(0, 0, width, height));\n    if (frameIndex === 0) {\n      // create view\n      image = getDefaultImage(\n        width, height, 1, imgBuffer, numberOfFrames, dataIndex.toString());\n      // add seriesUID to meta\n      const meta = image.getMeta();\n      meta.SeriesInstanceUID = seriesUID;\n      image.setMeta(meta);\n      // call callback\n      onloaditem({\n        data: {\n          image: image,\n          meta: info\n        },\n        source: origin\n      });\n    } else {\n      image.appendFrameBuffer(imgBuffer, frameIndex);\n    }\n    // increment index\n    ++frameIndex;\n  }\n\n  let nextTime = 0;\n\n  /**\n   * Handle seeked event.\n   *\n   * @param {object} event The seeked event.\n   */\n  function onseeked(event) {\n    // store\n    storeFrame();\n    // set the next time\n    // (not using currentTime, it seems to get offseted)\n    nextTime += 1 / frameRate;\n    if (nextTime <= event.target.duration) {\n      this.currentTime = nextTime;\n    } else {\n      onload({\n        source: origin\n      });\n      onloadend({\n        source: origin\n      });\n      // stop listening\n      video.removeEventListener('seeked', onseeked);\n    }\n  }\n\n  // trigger the first seek\n  video.currentTime = nextTime;\n}\n","import {DicomDataLoader} from './dicomDataLoader';\nimport {JSONTextLoader} from './jsonTextLoader';\nimport {MultipartLoader} from './multipartLoader';\nimport {RawImageLoader} from './rawImageLoader';\nimport {RawVideoLoader} from './rawVideoLoader';\nimport {ZipLoader} from './zipLoader';\n\nexport const loaderList = [\n  DicomDataLoader,\n  JSONTextLoader,\n  MultipartLoader,\n  RawImageLoader,\n  RawVideoLoader,\n  ZipLoader\n];\n","import {startsWith, getFileExtension} from '../utils/string';\nimport {getUrlFromUri} from '../utils/uri';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\nimport {DicomBufferToView} from '../image/dicomBufferToView';\n\n/**\n * DICOM data loader.\n */\nexport class DicomDataLoader {\n\n  /**\n   * Loader options.\n   *\n   * @type {object}\n   */\n  #options = {};\n\n  /**\n   * Loading flag.\n   *\n   * @type {boolean}\n   */\n  #isLoading = false;\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} opt The input options.\n   */\n  setOptions(opt) {\n    this.#options = opt;\n  }\n\n  /**\n   * Is the load ongoing?\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return this.#isLoading;\n  }\n\n  /**\n   * DICOM buffer to View (asynchronous).\n   *\n   */\n  #db2v = new DicomBufferToView();\n\n  /**\n   * Load data.\n   *\n   * @param {object} buffer The DICOM buffer.\n   * @param {string} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(buffer, origin, index) {\n    // setup db2v ony once\n    if (!this.#isLoading) {\n      // pass options\n      this.#db2v.setOptions(this.#options);\n      // connect handlers\n      this.#db2v.onloadstart = this.onloadstart;\n      this.#db2v.onprogress = this.onprogress;\n      this.#db2v.onloaditem = this.onloaditem;\n      this.#db2v.onload = this.onload;\n      this.#db2v.onloadend = (event) => {\n        // reset loading flag\n        this.#isLoading = false;\n        // call listeners\n        this.onloadend(event);\n      };\n      this.#db2v.onerror = (event) => {\n        event.source = origin;\n        this.onerror(event);\n      };\n      this.#db2v.onabort = this.onabort;\n    }\n\n    // set loading flag\n    this.#isLoading = true;\n    // convert\n    this.#db2v.convert(buffer, origin, index);\n  }\n\n  /**\n   * Abort load.\n   */\n  abort() {\n    // reset loading flag\n    this.#isLoading = false;\n    // abort conversion, will trigger db2v.onabort\n    this.#db2v.abort();\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * True if one of the folowing conditions is true:\n   * - the file has a 'dcm' extension,\n   * - the file has no extension.\n   *\n   * @param {File} file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(file) {\n    const ext = getFileExtension(file.name);\n    const hasNoExt = (ext === null);\n    const hasDcmExt = (ext === 'dcm');\n    return hasNoExt || hasDcmExt;\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'dicom',\n   * - the `options.requestHeaders` contains a 'Accept: application/dicom',\n   * - the url has a 'contentType' and it is 'application/dicom'\n   *   (as in wado urls),\n   * - the url has no 'contentType' and no extension or the extension is 'dcm'.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'dicom') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'application/dicom' and no '+'\n          const acceptValue = 'application/dicom';\n          return startsWith(acceptHeader.value, acceptValue) &&\n            acceptHeader.value[acceptValue.length] !== '+';\n        }\n      }\n    }\n\n    const urlObjext = getUrlFromUri(url);\n    // extension\n    const ext = getFileExtension(urlObjext.pathname);\n    const hasNoExt = (ext === null);\n    const hasDcmExt = (ext === 'dcm');\n    // content type (for wado url)\n    const contentType = urlObjext.searchParams.get('contentType');\n    const hasContentType = contentType !== null &&\n      typeof contentType !== 'undefined';\n    const hasDicomContentType = (contentType === 'application/dicom');\n\n    return hasContentType ? hasDicomContentType : (hasNoExt || hasDcmExt);\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} mem The memory object.\n   * @returns {boolean} True if the object can be loaded.\n   */\n  canLoadMemory(mem) {\n    const contentType = mem['Content-Type'];\n    if (typeof contentType !== 'undefined' &&\n      contentType.startsWith('application/dicom')) {\n      return true;\n    }\n    if (typeof mem.filename !== 'undefined') {\n      const tmpFile = new File(['from memory'], mem.filename);\n      return this.canLoadFile(tmpFile);\n    }\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class DicomDataLoader\n","import {startsWith, getFileExtension} from '../utils/string';\nimport {getUrlFromUri} from '../utils/uri';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\n\n/**\n * JSON text loader.\n */\nexport class JSONTextLoader {\n\n  /**\n   * Loading flag.\n   *\n   * @type {boolean}\n   */\n  #isLoading = false;\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} _opt The input options.\n   */\n  setOptions(_opt) {\n    // does nothing\n  }\n\n  /**\n   * Is the load ongoing?\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return this.#isLoading;\n  }\n\n  /**\n   * Load data.\n   *\n   * @param {object} text The input text.\n   * @param {string} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(text, origin, index) {\n    // set loading flag\n    this.#isLoading = true;\n    this.onloadstart({\n      source: origin\n    });\n\n    try {\n      this.onprogress({\n        lengthComputable: true,\n        loaded: 100,\n        total: 100,\n        index: index,\n        source: origin\n      });\n      const data = {\n        data: text,\n        source: origin\n      };\n      // only expecting one item\n      this.onloaditem(data);\n      this.onload(data);\n    } catch (error) {\n      this.onerror({\n        error: error,\n        source: origin\n      });\n    } finally {\n      // reset loading flag\n      this.#isLoading = false;\n      this.onloadend({\n        source: origin\n      });\n    }\n  }\n\n  /**\n   * Abort load: pass to listeners.\n   */\n  abort() {\n    // reset loading flag\n    this.#isLoading = false;\n    // call listeners\n    this.onabort({});\n    this.onloadend({});\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * True if the file has a 'json' extension.\n   *\n   * @param {File} file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(file) {\n    const ext = getFileExtension(file.name);\n    return (ext === 'json');\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'json',\n   * - the `options.requestHeaders` contains a 'Accept: application/json' or\n   *   'Accept: application/dicom+json',\n   * - the url has a 'json' extension.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'json') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'application/json' or 'application/dicom+json\n          return startsWith(acceptHeader.value, 'application/json') ||\n            startsWith(acceptHeader.value, 'application/dicom+json');\n        }\n      }\n    }\n\n    const urlObjext = getUrlFromUri(url);\n    const ext = getFileExtension(urlObjext.pathname);\n    return (ext === 'json');\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} mem The memory object.\n   * @returns {boolean} True if the object can be loaded.\n   */\n  canLoadMemory(mem) {\n    const contentType = mem['Content-Type'];\n    if (typeof contentType !== 'undefined' &&\n      contentType.startsWith('application/json')) {\n      return true;\n    }\n    if (typeof mem.filename !== 'undefined') {\n      const tmpFile = new File(['from memory'], mem.filename);\n      return this.canLoadFile(tmpFile);\n    }\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.Text;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.Text;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class JSONTextLoader\n","import {startsWith} from '../utils/string';\nimport {parseMultipart} from '../utils/array';\nimport {MemoryLoader} from './memoryLoader';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\n\n/**\n * Multipart data loader.\n */\nexport class MultipartLoader {\n\n  /**\n   * Loading flag.\n   *\n   * @type {boolean}\n   */\n  #isLoading = false;\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} _opt The input options.\n   */\n  setOptions(_opt) {\n    // does nothing\n  }\n\n  /**\n   * Is the load ongoing?\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return this.#isLoading;\n  }\n\n  /**\n   * Load data.\n   *\n   * @param {object} buffer The DICOM buffer.\n   * @param {string} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(buffer, origin, index) {\n    // send start event\n    this.onloadstart({\n      source: origin\n    });\n    // set loading flag\n    this.#isLoading = true;\n\n    const memoryIO = new MemoryLoader();\n    // memoryIO.onloadstart: nothing to do\n    memoryIO.onprogress = (progress) => {\n      // add 50% to take into account the un-Multipartping\n      progress.loaded = 50 + progress.loaded / 2;\n      // set data index\n      progress.index = index;\n      this.onprogress(progress);\n    };\n    memoryIO.onloaditem = this.onloaditem;\n    memoryIO.onload = this.onload;\n    memoryIO.onloadend = (event) => {\n      // reset loading flag\n      this.#isLoading = false;\n      // call listeners\n      this.onloadend(event);\n    };\n    memoryIO.onerror = this.onerror;\n    memoryIO.onabort = this.onabort;\n    // launch\n    memoryIO.load(parseMultipart(buffer));\n  }\n\n  /**\n   * Abort load: pass to listeners.\n   */\n  abort() {\n    // reset loading flag\n    this.#isLoading = false;\n    // call listeners\n    this.onabort({});\n    this.onloadend({});\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * Always returns false.\n   *\n   * @param {File} _file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(_file) {\n    return false;\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'multipart',\n   * - the `options.requestHeaders` contains a 'Accept: multipart/related'.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'multipart') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'multipart/related'\n          return startsWith(acceptHeader.value, 'multipart/related');\n        }\n      }\n    }\n\n    return false;\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} _mem The memory object.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadMemory(_mem) {\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class MultipartLoader\n","import {startsWith, getFileExtension} from '../utils/string';\nimport {getUrlFromUri} from '../utils/uri';\nimport {getViewFromDOMImage} from '../image/domReader';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\n\n/**\n * Raw image loader.\n */\nexport class RawImageLoader {\n\n  /**\n   * If abort is triggered, all image.onload callbacks have to be cancelled.\n   *\n   * @type {boolean}\n   */\n  #aborted = false;\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} _opt The input options.\n   */\n  setOptions(_opt) {\n    // does nothing\n  }\n\n  /**\n   * Is the load ongoing? TODO...\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return true;\n  }\n\n  /**\n   * Create a Data URI from an HTTP request response.\n   *\n   * @param {ArrayBuffer} response The HTTP request response.\n   * @param {string} dataType The data type.\n   * @returns {string} The data URI.\n   */\n  #createDataUri(response, dataType) {\n    // image type\n    let imageType = dataType;\n    if (!imageType || imageType === 'jpg') {\n      imageType = 'jpeg';\n    }\n    // create uri\n    const file = new Blob([response], {type: 'image/' + imageType});\n    return window.URL.createObjectURL(file);\n  }\n\n  /**\n   * Load data.\n   *\n   * @param {ArrayBuffer|string} buffer The read data.\n   * @param {string|File} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(buffer, origin, index) {\n    this.#aborted = false;\n    // create a DOM image\n    const image = new Image();\n    // triggered by ctx.drawImage\n    image.onload = (/*event*/) => {\n      try {\n        if (!this.#aborted) {\n          this.onprogress({\n            lengthComputable: true,\n            loaded: 100,\n            total: 100,\n            index: index,\n            source: origin\n          });\n          const data = getViewFromDOMImage(image, origin, index);\n          // only expecting one item\n          this.onloaditem(data);\n          this.onload(data);\n        }\n      } catch (error) {\n        this.onerror({\n          error: error,\n          source: origin\n        });\n      } finally {\n        this.onloadend({\n          source: origin\n        });\n      }\n    };\n    // storing values to pass them on\n    if (typeof buffer === 'string') {\n      // file case\n      image.src = buffer;\n    } else if (typeof origin === 'string') {\n      // url case\n      const ext = origin.split('.').pop().toLowerCase();\n      image.src = this.#createDataUri(buffer, ext);\n    }\n  }\n\n  /**\n   * Abort load.\n   */\n  abort() {\n    this.#aborted = true;\n    this.onabort({});\n    this.onloadend({});\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * True for files with type 'image.*'.\n   *\n   * @param {File} file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(file) {\n    return (typeof file.type !== 'undefined' &&\n      file.type.match('image.*') !== null);\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'rawimage',\n   * - the `options.requestHeaders` contains an item\n   *   starting with 'Accept: image/'.\n   * - the url has a 'contentType' and it is 'image/jpeg', 'image/png'\n   *   or 'image/gif' (as in wado urls),\n   * - the url has no 'contentType' and the extension is 'jpeg', 'jpg',\n   *   'png' or 'gif'.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'rawimage') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'image/'\n          return startsWith(acceptHeader.value, 'image/');\n        }\n      }\n    }\n\n    const urlObjext = getUrlFromUri(url);\n    // extension\n    const ext = getFileExtension(urlObjext.pathname);\n    const hasImageExt = (ext === 'jpeg') || (ext === 'jpg') ||\n      (ext === 'png') || (ext === 'gif');\n    // content type (for wado url)\n    const contentType = urlObjext.searchParams.get('contentType');\n    const hasContentType = contentType !== null &&\n      typeof contentType !== 'undefined';\n    const hasImageContentType = (contentType === 'image/jpeg') ||\n      (contentType === 'image/png') ||\n      (contentType === 'image/gif');\n\n    return hasContentType ? hasImageContentType : hasImageExt;\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} mem The memory object.\n   * @returns {boolean} True if the object can be loaded.\n   */\n  canLoadMemory(mem) {\n    if (typeof mem.filename !== 'undefined') {\n      const tmpFile = new File(['from memory'], mem.filename);\n      return this.canLoadFile(tmpFile);\n    }\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.DataURL;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class RawImageLoader","import {startsWith, getFileExtension} from '../utils/string';\nimport {getUrlFromUri} from '../utils/uri';\nimport {getViewFromDOMVideo} from '../image/domReader';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\n\n/**\n * Raw video loader.\n *\n * Url example (cors enabled):\n *   {@link https://raw.githubusercontent.com/clappr/clappr/master/test/fixtures/SampleVideo_360x240_1mb.mp4}.\n */\nexport class RawVideoLoader {\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} _opt The input options.\n   */\n  setOptions(_opt) {\n    // does nothing\n  }\n\n  /**\n   * Is the load ongoing? TODO...\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return true;\n  }\n\n  /**\n   * Create a Data URI from an HTTP request response.\n   *\n   * @param {object} response The HTTP request response.\n   * @param {string} dataType The data type.\n   * @returns {string} The data URI.\n   */\n  #createDataUri(response, dataType) {\n    // image data as string\n    const bytes = new Uint8Array(response);\n    let videoDataStr = '';\n    for (let i = 0; i < bytes.byteLength; ++i) {\n      videoDataStr += String.fromCharCode(bytes[i]);\n    }\n    // create uri\n    const uri = 'data:video/' + dataType +\n      ';base64,' + window.btoa(videoDataStr);\n    return uri;\n  }\n\n  /**\n   * Internal Data URI load.\n   *\n   * @param {object} buffer The read data.\n   * @param {string} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(buffer, origin, index) {\n    // create a DOM video\n    const video = document.createElement('video');\n    if (typeof origin === 'string') {\n      // url case\n      const ext = origin.split('.').pop().toLowerCase();\n      video.src = this.#createDataUri(buffer, ext);\n    } else {\n      video.src = buffer;\n    }\n    // onload handler\n    video.onloadedmetadata = (event) => {\n      try {\n        getViewFromDOMVideo(event.target,\n          this.onloaditem, this.onload,\n          this.onprogress, this.onloadend,\n          origin, index);\n      } catch (error) {\n        this.onerror({\n          error: error,\n          source: origin\n        });\n        this.onloadend({\n          source: origin\n        });\n      }\n    };\n  }\n\n  /**\n   * Abort load.\n   */\n  abort() {\n    this.onabort({});\n    this.onloadend({});\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * True for files with type 'video.*'.\n   *\n   * @param {File} file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(file) {\n    return (typeof file.type !== 'undefined' &&\n      file.type.match('video.*') !== null);\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'rawvideo',\n   * - the `options.requestHeaders` contains an item\n   *   starting with 'Accept: video/'.\n   * - the url has a 'mp4', 'ogg' or 'webm' extension.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'rawvideo') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'video/'\n          return startsWith(acceptHeader.value, 'video/');\n        }\n      }\n    }\n\n    const urlObjext = getUrlFromUri(url);\n    const ext = getFileExtension(urlObjext.pathname);\n    return (ext === 'mp4') ||\n      (ext === 'ogg') ||\n      (ext === 'webm');\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} mem The memory object.\n   * @returns {boolean} True if the object can be loaded.\n   */\n  canLoadMemory(mem) {\n    if (typeof mem.filename !== 'undefined') {\n      const tmpFile = new File(['from memory'], mem.filename);\n      return this.canLoadFile(tmpFile);\n    }\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.DataURL;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   * when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   * when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class RawVideoLoader\n","import {startsWith, getFileExtension} from '../utils/string';\nimport {getUrlFromUri} from '../utils/uri';\nimport {fileContentTypes} from './filesLoader';\nimport {urlContentTypes} from './urlsLoader';\nimport {MemoryLoader} from './memoryLoader';\n\n/**\n * The zip library.\n *\n * Ref: {@link https://github.com/Stuk/jszip}.\n *\n * @external JSZip\n */\nimport JSZip from 'jszip';\n\n/**\n * ZIP data loader.\n */\nexport class ZipLoader {\n\n  /**\n   * Loading flag.\n   *\n   * @type {boolean}\n   */\n  #isLoading = false;\n\n  /**\n   * Set the loader options.\n   *\n   * @param {object} _opt The input options.\n   */\n  setOptions(_opt) {\n    // does nothing\n  }\n\n  /**\n   * Is the load ongoing?\n   *\n   * @returns {boolean} True if loading.\n   */\n  isLoading() {\n    return this.#isLoading;\n  }\n\n  #filename = '';\n  #files = [];\n  #zobjs = null;\n\n  /**\n   * JSZip.async callback.\n   *\n   * @param {ArrayBuffer} content Unzipped file image.\n   * @param {object} origin The origin of the file.\n   * @param {number} index The data index.\n   */\n  #zipAsyncCallback(content, origin, index) {\n    this.#files.push({filename: this.#filename, data: content});\n\n    // sent un-ziped progress with the data index\n    // (max 50% to take into account the memory loading)\n    const unzipPercent = this.#files.length * 100 / this.#zobjs.length;\n    this.onprogress({\n      lengthComputable: true,\n      loaded: (unzipPercent / 2),\n      total: 100,\n      index: index,\n      item: {\n        loaded: unzipPercent,\n        total: 100,\n        source: origin\n      }\n    });\n\n    // recursively call until we have all the files\n    if (this.#files.length < this.#zobjs.length) {\n      const num = this.#files.length;\n      this.#filename = this.#zobjs[num].name;\n      this.#zobjs[num].async('arrayBuffer').then((content) => {\n        this.#zipAsyncCallback(content, origin, index);\n      });\n    } else {\n      const memoryIO = new MemoryLoader();\n      // memoryIO.onloadstart: nothing to do\n      memoryIO.onprogress = (progress) => {\n        // add 50% to take into account the un-zipping\n        progress.loaded = 50 + progress.loaded / 2;\n        // set data index\n        progress.index = index;\n        this.onprogress(progress);\n      };\n      memoryIO.onloaditem = this.onloaditem;\n      memoryIO.onload = this.onload;\n      memoryIO.onloadend = (event) => {\n        // reset loading flag\n        this.#isLoading = false;\n        // call listeners\n        this.onloadend(event);\n      };\n      memoryIO.onerror = this.onerror;\n      memoryIO.onabort = this.onabort;\n      // launch\n      memoryIO.load(this.#files);\n    }\n  }\n\n  /**\n   * Load data.\n   *\n   * @param {object} buffer The DICOM buffer.\n   * @param {string} origin The data origin.\n   * @param {number} index The data index.\n   */\n  load(buffer, origin, index) {\n    // send start event\n    this.onloadstart({\n      source: origin\n    });\n    // set loading flag\n    this.#isLoading = true;\n\n    JSZip.loadAsync(buffer).then((zip) => {\n      this.#files = [];\n      this.#zobjs = zip.file(/.*\\.dcm/);\n      // recursively load zip files into the files array\n      const num = this.#files.length;\n      this.#filename = this.#zobjs[num].name;\n      this.#zobjs[num].async('arrayBuffer').then((content) => {\n        this.#zipAsyncCallback(content, origin, index);\n      });\n    });\n  }\n\n  /**\n   * Abort load: pass to listeners.\n   */\n  abort() {\n    // reset loading flag\n    this.#isLoading = false;\n    // call listeners\n    this.onabort({});\n    this.onloadend({});\n  }\n\n  /**\n   * Check if the loader can load the provided file.\n   * True if the file has a 'zip' extension.\n   *\n   * @param {File} file The file to check.\n   * @returns {boolean} True if the file can be loaded.\n   */\n  canLoadFile(file) {\n    const ext = getFileExtension(file.name);\n    return (ext === 'zip');\n  }\n\n  /**\n   * Check if the loader can load the provided url.\n   * True if one of the folowing conditions is true:\n   * - the `options.forceLoader` is 'zip',\n   * - the `options.requestHeaders` contains an item\n   *   starting with 'Accept: application/zip'.\n   * - the url has a 'zip' extension.\n   *\n   * @param {string} url The url to check.\n   * @param {object} [options] Optional url request options.\n   * @returns {boolean} True if the url can be loaded.\n   */\n  canLoadUrl(url, options) {\n    // check options\n    if (typeof options !== 'undefined') {\n      // check options.forceLoader\n      if (typeof options.forceLoader !== 'undefined' &&\n        options.forceLoader === 'zip') {\n        return true;\n      }\n      // check options.requestHeaders for 'Accept'\n      if (typeof options.requestHeaders !== 'undefined') {\n        const isNameAccept = function (element) {\n          return element.name === 'Accept';\n        };\n        const acceptHeader = options.requestHeaders.find(isNameAccept);\n        if (typeof acceptHeader !== 'undefined') {\n          // starts with 'application/zip'\n          return startsWith(acceptHeader.value, 'application/zip');\n        }\n      }\n    }\n\n    const urlObjext = getUrlFromUri(url);\n    const ext = getFileExtension(urlObjext.pathname);\n    return (ext === 'zip');\n  }\n\n  /**\n   * Check if the loader can load the provided memory object.\n   *\n   * @param {object} mem The memory object.\n   * @returns {boolean} True if the object can be loaded.\n   */\n  canLoadMemory(mem) {\n    const contentType = mem['Content-Type'];\n    if (typeof contentType !== 'undefined' &&\n      contentType.startsWith('application/zip')) {\n      return true;\n    }\n    if (typeof mem.filename !== 'undefined') {\n      const tmpFile = new File(['from memory'], mem.filename);\n      return this.canLoadFile(tmpFile);\n    }\n    return false;\n  }\n\n  /**\n   * Get the file content type needed by the loader.\n   *\n   * @returns {number} One of the 'fileContentTypes'.\n   */\n  loadFileAs() {\n    return fileContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Get the url content type needed by the loader.\n   *\n   * @returns {number} One of the 'urlContentTypes'.\n   */\n  loadUrlAs() {\n    return urlContentTypes.ArrayBuffer;\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle an load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class ZipLoader\n","import {MultiProgressHandler} from '../utils/progress';\nimport {loaderList} from './loaderList';\n\n// file content types\nexport const fileContentTypes = {\n  Text: 0,\n  ArrayBuffer: 1,\n  DataURL: 2\n};\n\n/**\n * Files loader.\n */\nexport class FilesLoader {\n\n  /**\n   * Input data.\n   *\n   * @type {File[]}\n   */\n  #inputData = null;\n\n  /**\n   * Array of launched file readers.\n   *\n   * @type {FileReader[]}\n   */\n  #readers = [];\n\n  /**\n   * Data loader.\n   *\n   * @type {object}\n   */\n  #runningLoader = null;\n\n  /**\n   * Number of loaded data.\n   *\n   * @type {number}\n   */\n  #nLoad = 0;\n\n  /**\n   * Number of load end events.\n   *\n   * @type {number}\n   */\n  #nLoadend = 0;\n\n  /**\n   * The default character set (optional).\n   *\n   * @type {string}\n   */\n  #defaultCharacterSet;\n\n  /**\n   * Get the default character set.\n   *\n   * @returns {string} The default character set.\n   */\n  getDefaultCharacterSet() {\n    return this.#defaultCharacterSet;\n  }\n\n  /**\n   * Set the default character set.\n   *\n   * @param {string} characterSet The character set.\n   */\n  setDefaultCharacterSet(characterSet) {\n    this.#defaultCharacterSet = characterSet;\n  }\n\n  /**\n   * Store the current input.\n   *\n   * @param {File[]} data The input data.\n   */\n  #storeInputData(data) {\n    this.#inputData = data;\n    // reset counters\n    this.#nLoad = 0;\n    this.#nLoadend = 0;\n    // clear storage\n    this.#clearStoredReaders();\n    this.#clearStoredLoader();\n  }\n\n  /**\n   * Store a launched reader.\n   *\n   * @param {FileReader} reader The launched reader.\n   */\n  #storeReader(reader) {\n    this.#readers.push(reader);\n  }\n\n  /**\n   * Clear the stored readers.\n   *\n   */\n  #clearStoredReaders() {\n    this.#readers = [];\n  }\n\n  /**\n   * Store the launched loader.\n   *\n   * @param {object} loader The launched loader.\n   */\n  #storeLoader(loader) {\n    this.#runningLoader = loader;\n  }\n\n  /**\n   * Clear the stored loader.\n   *\n   */\n  #clearStoredLoader() {\n    this.#runningLoader = null;\n  }\n\n  /**\n   * Increment the number of loaded data\n   *   and call onload if loaded all data.\n   *\n   * @param {object} _event The load data event.\n   */\n  #addLoad = (_event) => {\n    this.#nLoad++;\n    // call onload when all is loaded\n    // (not using the input event since it is\n    //   an individual load)\n    if (this.#nLoad === this.#inputData.length) {\n      this.onload({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * Increment the counter of load end events\n   *   and run callbacks when all done, erroneus or not.\n   *\n   * @param {object} _event The load end event.\n   */\n  #addLoadend = (_event) => {\n    this.#nLoadend++;\n    // call onloadend when all is run\n    // (not using the input event since it is\n    //   an individual load end)\n    if (this.#nLoadend === this.#inputData.length) {\n      this.onloadend({\n        source: this.#inputData\n      });\n    }\n  };\n\n  /**\n   * @callback eventFn\n   * @param {object} event The event.\n   */\n\n  /**\n   * Augment a callback event with a srouce.\n   *\n   * @param {object} callback The callback to augment its event.\n   * @param {object} source The source to add to the event.\n   * @returns {eventFn} The augmented callback.\n   */\n  #augmentCallbackEvent(callback, source) {\n    return (event) => {\n      event.source = source;\n      callback(event);\n    };\n  }\n\n  /**\n   * Get a load handler for a data element.\n   *\n   * @param {object} loader The associated loader.\n   * @param {File} dataElement The data element.\n   * @param {number} i The index of the element.\n   * @returns {eventFn} A load handler.\n   */\n  #getLoadHandler(loader, dataElement, i) {\n    return (event) => {\n      loader.load(event.target.result, dataElement, i);\n    };\n  }\n\n\n  /**\n   * Load a list of files.\n   *\n   * @param {File[]} data The list of files to load.\n   */\n  load(data) {\n    // check input\n    if (typeof data === 'undefined' || data.length === 0) {\n      return;\n    }\n    this.#storeInputData(data);\n\n    // send start event\n    this.onloadstart({\n      source: data\n    });\n\n    // create prgress handler\n    const mproghandler = new MultiProgressHandler(this.onprogress);\n    mproghandler.setNToLoad(data.length);\n\n    // create loaders\n    const loaders = [];\n    for (let m = 0; m < loaderList.length; ++m) {\n      loaders.push(new loaderList[m]());\n    }\n\n    // find an appropriate loader\n    let dataElement = data[0];\n    let loader = null;\n    let foundLoader = false;\n    for (let l = 0; l < loaders.length; ++l) {\n      loader = loaders[l];\n      if (loader.canLoadFile(dataElement)) {\n        foundLoader = true;\n        // load options\n        loader.setOptions({\n          numberOfFiles: data.length,\n          defaultCharacterSet: this.getDefaultCharacterSet()\n        });\n        // set loader callbacks\n        // loader.onloadstart: nothing to do\n        loader.onprogress = mproghandler.getUndefinedMonoProgressHandler(1);\n        loader.onloaditem = this.onloaditem;\n        loader.onload = this.#addLoad;\n        loader.onloadend = this.#addLoadend;\n        loader.onerror = this.onerror;\n        loader.onabort = this.onabort;\n\n        // store loader\n        this.#storeLoader(loader);\n        // exit\n        break;\n      }\n    }\n    if (!foundLoader) {\n      throw new Error('No loader found for file: ' + dataElement.name);\n    }\n\n    // loop on I/O elements\n    for (let i = 0; i < data.length; ++i) {\n      dataElement = data[i];\n\n      // check loader\n      if (!loader.canLoadFile(dataElement)) {\n        throw new Error('Input file of different type: ' + dataElement);\n      }\n\n      /**\n       * The file reader.\n       *\n       * Ref: {@link https://developer.mozilla.org/en-US/docs/Web/API/FileReader}.\n       *\n       * @external FileReader\n       */\n      const reader = new FileReader();\n      // store reader\n      this.#storeReader(reader);\n\n      // set reader callbacks\n      // reader.onloadstart: nothing to do\n      reader.onprogress = this.#augmentCallbackEvent(\n        mproghandler.getMonoProgressHandler(i, 0), dataElement);\n      reader.onload = this.#getLoadHandler(loader, dataElement, i);\n      // reader.onloadend: nothing to do\n      const errorCallback =\n        this.#augmentCallbackEvent(this.onerror, dataElement);\n      reader.onerror = (event) => {\n        this.#addLoadend();\n        errorCallback(event);\n      };\n      const abortCallback =\n        this.#augmentCallbackEvent(this.onabort, dataElement);\n      reader.onabort = (event) => {\n        this.#addLoadend();\n        abortCallback(event);\n      };\n      // read\n      if (loader.loadFileAs() === fileContentTypes.Text) {\n        reader.readAsText(dataElement);\n      } else if (loader.loadFileAs() === fileContentTypes.DataURL) {\n        reader.readAsDataURL(dataElement);\n      } else if (loader.loadFileAs() === fileContentTypes.ArrayBuffer) {\n        reader.readAsArrayBuffer(dataElement);\n      }\n    }\n  }\n\n  /**\n   * Abort a load.\n   */\n  abort() {\n    // abort readers\n    for (let i = 0; i < this.#readers.length; ++i) {\n      // 0: EMPTY, 1: LOADING, 2: DONE\n      if (this.#readers[i].readyState === 1) {\n        this.#readers[i].abort();\n      }\n    }\n    // abort loader\n    if (this.#runningLoader && this.#runningLoader.isLoading()) {\n      this.#runningLoader.abort();\n    }\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load item event fired\n   *   when a file item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle a load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class FilesLoader\n","import {FilesLoader} from '../io/filesLoader';\nimport {MemoryLoader} from '../io/memoryLoader';\nimport {UrlsLoader} from '../io/urlsLoader';\n\n/**\n * Load controller.\n */\nexport class LoadController {\n\n  /**\n   * The default character set.\n   *\n   * @type {string}\n   */\n  #defaultCharacterSet;\n\n  /**\n   * List of current loaders.\n   *\n   * @type {object}\n   */\n  #currentLoaders = {};\n\n  /**\n   * @param {string} defaultCharacterSet The default character set.\n   */\n  constructor(defaultCharacterSet) {\n    this.#defaultCharacterSet = defaultCharacterSet;\n  }\n\n  /**\n   * Load a list of files. Can be image files or a state file.\n   *\n   * @param {File[]} files The list of files to load.\n   * @param {string} dataId The data Id.\n   */\n  loadFiles(files, dataId) {\n    // has been checked for emptiness.\n    const ext = files[0].name.split('.').pop().toLowerCase();\n    if (ext === 'json') {\n      this.#loadStateFile(files[0], dataId);\n    } else {\n      this.#loadImageFiles(files, dataId);\n    }\n  }\n\n  /**\n   * Load a list of URLs. Can be image files or a state file.\n   *\n   * @param {string[]} urls The list of urls to load.\n   * @param {string} dataId The data Id.\n   * @param {object} [options] The load options:\n   * - requestHeaders: an array of {name, value} to use as request headers.\n   * - withCredentials: credentials flag to pass to the request.\n   */\n\n  loadURLs(urls, dataId, options) {\n    // has been checked for emptiness.\n    const ext = urls[0].split('.').pop().toLowerCase();\n    if (ext === 'json') {\n      this.#loadStateUrl(urls[0], dataId, options);\n    } else {\n      this.#loadImageUrls(urls, dataId, options);\n    }\n  }\n\n  /**\n   * Load a list of ArrayBuffers.\n   *\n   * @param {Array} data The list of ArrayBuffers to load\n   *   in the form of [{name: '', filename: '', data: data}].\n   * @param {string} dataId The data Id.\n   */\n  loadImageObject(data, dataId) {\n    // create IO\n    const memoryIO = new MemoryLoader();\n    // load data\n    this.#loadData(data, memoryIO, 'image', dataId);\n  }\n\n  /**\n   * Get the currently loaded data ids.\n   *\n   * @returns {string[]} The data ids.\n   */\n  getLoadingDataIds() {\n    return Object.keys(this.#currentLoaders);\n  }\n\n  /**\n   * Abort an individual current loader.\n   *\n   * @param {string} dataId The data to stop loading.\n   */\n  abort(dataId) {\n    if (typeof this.#currentLoaders[dataId] !== 'undefined') {\n      this.#currentLoaders[dataId].loader.abort();\n      delete this.#currentLoaders[dataId];\n    }\n  }\n\n  // private ----------------------------------------------------------------\n\n  /**\n   * Load a list of image files.\n   *\n   * @param {File[]} files The list of image files to load.\n   * @param {string} dataId The data Id.\n   */\n  #loadImageFiles(files, dataId) {\n    // create IO\n    const fileIO = new FilesLoader();\n    fileIO.setDefaultCharacterSet(this.#defaultCharacterSet);\n    // load data\n    this.#loadData(files, fileIO, 'image', dataId);\n  }\n\n  /**\n   * Load a list of image URLs.\n   *\n   * @param {string[]} urls The list of urls to load.\n   * @param {string} [dataId] The data Id.\n   * @param {object} [options] The load options:\n   * - requestHeaders: an array of {name, value} to use as request headers.\n   * - withCredentials: credentials flag to pass to the request.\n   */\n  #loadImageUrls(urls, dataId, options) {\n    // create IO\n    const urlIO = new UrlsLoader();\n    urlIO.setDefaultCharacterSet(this.#defaultCharacterSet);\n    // load data\n    this.#loadData(urls, urlIO, 'image', dataId, options);\n  }\n\n  /**\n   * Load a State file.\n   *\n   * @param {File} file The state file to load.\n   * @param {string} dataId The data Id.\n   */\n  #loadStateFile(file, dataId) {\n    // create IO\n    const fileIO = new FilesLoader();\n    // load data\n    this.#loadData([file], fileIO, 'state', dataId);\n  }\n\n\n  /**\n   * Load a State url.\n   *\n   * @param {string} url The state url to load.\n   * @param {string} [dataId] The data Id.\n   * @param {object} [options] The load options:\n   * - requestHeaders: an array of {name, value} to use as request headers.\n   * - withCredentials: credentials flag to pass to the request.\n   */\n  #loadStateUrl(url, dataId, options) {\n    // create IO\n    const urlIO = new UrlsLoader();\n    // load data\n    this.#loadData([url], urlIO, 'state', dataId, options);\n  }\n\n  /**\n   * Load a list of data.\n   *\n   * @param {string[]|File[]|Array} data Array of data to load.\n   * @param {object} loader The data loader.\n   * @param {string} loadType The data load type: 'image' or 'state'.\n   * @param {string} dataId The data id.\n   * @param {object} [options] Options passed to the final loader.\n   */\n  #loadData(data, loader, loadType, dataId, options) {\n    const eventInfo = {\n      loadtype: loadType,\n      dataid: dataId\n    };\n\n    // set callbacks\n    loader.onloadstart = (event) => {\n      // store loader to allow abort\n      this.#currentLoaders[dataId] = {\n        loader: loader,\n        isFirstItem: true\n      };\n      // callback\n      this.#augmentCallbackEvent(this.onloadstart, eventInfo)(event);\n    };\n    loader.onprogress = this.#augmentCallbackEvent(this.onprogress, eventInfo);\n    loader.onloaditem = (event) => {\n      const eventInfoItem = {\n        loadtype: loadType,\n        dataid: dataId\n      };\n      if (typeof this.#currentLoaders[dataId] !== 'undefined') {\n        eventInfoItem.isfirstitem = this.#currentLoaders[dataId].isFirstItem;\n      }\n      // callback\n      this.#augmentCallbackEvent(this.onloaditem, eventInfoItem)(event);\n      // update loader\n      if (typeof this.#currentLoaders[dataId] !== 'undefined' &&\n        this.#currentLoaders[dataId].isFirstItem) {\n        this.#currentLoaders[dataId].isFirstItem = false;\n      }\n    };\n    loader.onload = this.#augmentCallbackEvent(this.onload, eventInfo);\n    loader.onloadend = (event) => {\n      // reset current loader\n      delete this.#currentLoaders[dataId];\n      // callback\n      this.#augmentCallbackEvent(this.onloadend, eventInfo)(event);\n    };\n    loader.onerror = this.#augmentCallbackEvent(this.onerror, eventInfo);\n    loader.onabort = this.#augmentCallbackEvent(this.onabort, eventInfo);\n    if (typeof loader.ontimeout !== 'undefined') {\n      loader.ontimeout = this.#augmentCallbackEvent(this.ontimeout, eventInfo);\n    }\n    // launch load\n    try {\n      loader.load(data, options);\n    } catch (error) {\n      this.onerror({\n        error: error,\n        dataid: dataId\n      });\n      this.onloadend({\n        dataid: dataId\n      });\n      return;\n    }\n  }\n\n  /**\n   * Augment a callback event: adds loadtype to the event\n   *  passed to a callback.\n   *\n   * @param {object} callback The callback to update.\n   * @param {object} info Info object to append to the event.\n   * @returns {object} A function representing the modified callback.\n   */\n  #augmentCallbackEvent(callback, info) {\n    return function (event) {\n      const keys = Object.keys(info);\n      for (let i = 0; i < keys.length; ++i) {\n        const key = keys[i];\n        event[key] = info[key];\n      }\n      callback(event);\n    };\n  }\n\n  /**\n   * Handle a load start event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load start event.\n   */\n  onloadstart(_event) {}\n\n  /**\n   * Handle a load progress event.\n   * Default does nothing.\n   *\n   * @param {object} _event The progress event.\n   */\n  onprogress(_event) {}\n\n  /**\n   * Handle a load event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when a file has been loaded successfully.\n   */\n  onload(_event) {}\n\n  /**\n   * Handle a load item event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load event fired\n   *   when an item has been loaded successfully.\n   */\n  onloaditem(_event) {}\n\n  /**\n   * Handle a load end event.\n   * Default does nothing.\n   *\n   * @param {object} _event The load end event fired\n   *  when a file load has completed, successfully or not.\n   */\n  onloadend(_event) {}\n\n  /**\n   * Handle an error event.\n   * Default does nothing.\n   *\n   * @param {object} _event The error event.\n   */\n  onerror(_event) {}\n\n  /**\n   * Handle a timeout event.\n   * Default does nothing.\n   *\n   * @param {object} _event The timeout event.\n   */\n  ontimeout(_event) {}\n\n  /**\n   * Handle an abort event.\n   * Default does nothing.\n   *\n   * @param {object} _event The abort event.\n   */\n  onabort(_event) {}\n\n} // class LoadController\n","import {ListenerHandler} from '../utils/listen';\nimport {getReverseOrientation} from '../dicom/dicomParser';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {App} from '../app/application';\n/* eslint-enable no-unused-vars */\n\n/**\n * Get a number toprecision function with the provided precision.\n *\n * @param {number} precision The precision to achieve.\n * @returns {Function} The to precision function.\n */\nfunction getNumberToPrecision(precision) {\n  return function (num) {\n    return Number(num).toPrecision(precision);\n  };\n}\n\n/**\n * Create a default replace format from a given length.\n * For example: '{v0}, {v1}'.\n *\n * @param {number} length The length of the format.\n * @returns {string} A replace format.\n */\nfunction createDefaultReplaceFormat(length) {\n  let res = '';\n  for (let i = 0; i < length; ++i) {\n    if (i !== 0) {\n      res += ', ';\n    }\n    res += '{v' + i + '}';\n  }\n  return res;\n}\n\n/**\n * Replace flags in a input string. Flags are keywords surrounded with curly\n * braces in the form: '{v0}, {v1}'.\n *\n * @param {string} inputStr The input string.\n * @param {string[]} values An array of strings.\n * @example\n *    var values = [\"a\", \"b\"];\n *    var str = \"The length is: {v0}. The size is: {v1}\";\n *    var res = replaceFlags(str, values);\n *    // \"The length is: a. The size is: b\"\n * @returns {string} The result string.\n */\nfunction replaceFlags(inputStr, values) {\n  let res = inputStr;\n  for (let i = 0; i < values.length; ++i) {\n    res = res.replace('{v' + i + '}', values[i]);\n  }\n  return res;\n}\n\n/**\n * DICOM Header overlay info.\n */\nexport class OverlayData {\n\n  /**\n   * Associated app.\n   *\n   * @type {App}\n   */\n  #app;\n\n  /**\n   * Associated data id.\n   *\n   * @type {string}\n   */\n  #dataId;\n\n  /**\n   * Overlay config.\n   *\n   * @type {object}\n   */\n  #configs;\n\n  /**\n   * List of event used by the config.\n   *\n   * @type {string[]}\n   */\n  #eventNames = [];\n\n  /**\n   * Flag to know if listening to app.\n   *\n   * @type {boolean}\n   */\n  #isListening;\n\n  /**\n   * Overlay data.\n   *\n   * @type {Array}\n   */\n  #data = [];\n\n  /**\n   * Current data uid: set on pos change.\n   *\n   * @type {number}\n   */\n  #currentDataUid;\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * @param {App} app The associated application.\n   * @param {string} dataId The associated data id.\n   * @param {object} configs The overlay config.\n   */\n  constructor(app, dataId, configs) {\n    this.#app = app;\n    this.#dataId = dataId;\n    this.#configs = configs;\n\n    // parse overlays to get the list of events to listen to\n    const keys = Object.keys(this.#configs);\n    for (let i = 0; i < keys.length; ++i) {\n      const config = this.#configs[keys[i]];\n      for (let j = 0; j < config.length; ++j) {\n        const eventType = config[j].event;\n        if (typeof eventType !== 'undefined') {\n          if (!this.#eventNames.includes(eventType)) {\n            this.#eventNames.push(eventType);\n          }\n        }\n      }\n    }\n    // add app listeners\n    this.addAppListeners();\n  }\n\n  /**\n   * Reset the data.\n   */\n  reset() {\n    this.#data = [];\n    this.#currentDataUid = undefined;\n  }\n\n  /**\n   * Handle a new loaded item event.\n   *\n   * @param {object} data The item meta data.\n   */\n  addItemMeta(data) {\n    // create and store overlay data\n    let dataUid;\n    // check if dicom data (00020010: transfer syntax)\n    if (typeof data['00020010'] !== 'undefined') {\n      if (typeof data['00080018'] !== 'undefined') {\n        // SOP instance UID\n        dataUid = data['00080018'].value[0];\n      } else {\n        dataUid = data.length;\n      }\n      this.#data[dataUid] = createOverlayData(data, this.#configs);\n    } else {\n      // image file case\n      const keys = Object.keys(data);\n      for (let d = 0; d < keys.length; ++d) {\n        const obj = data[keys[d]];\n        if (keys[d] === 'imageUid') {\n          dataUid = obj.value;\n          break;\n        }\n      }\n      this.#data[dataUid] = createOverlayDataForDom(data, this.#configs);\n    }\n    // store uid\n    this.#currentDataUid = dataUid;\n  }\n\n  /**\n   * Handle a changed slice event.\n   *\n   * @param {object} event The slicechange event.\n   */\n  #onSliceChange = (event) => {\n    if (event.dataid !== this.#dataId) {\n      return;\n    }\n    if (typeof event.data !== 'undefined' &&\n      typeof event.data.imageUid !== 'undefined' &&\n      this.#currentDataUid !== event.data.imageUid) {\n      this.#currentDataUid = event.data.imageUid;\n      this.#updateData(event);\n    }\n  };\n\n  /**\n   * Update the overlay data.\n   *\n   * @param {object} event An event defined by the overlay map and\n   *   registered in toggleListeners.\n   */\n  #updateData = (event) => {\n    if (event.dataid !== this.#dataId) {\n      return;\n    }\n\n    const sliceOverlayData = this.#data[this.#currentDataUid];\n    if (typeof sliceOverlayData === 'undefined') {\n      console.warn('No slice overlay data for: ' + this.#currentDataUid);\n      return;\n    }\n\n    for (let n = 0; n < sliceOverlayData.length; ++n) {\n      let text = undefined;\n      if (typeof sliceOverlayData[n].tags !== 'undefined') {\n        // update tags only on slice change\n        if (event.type === 'positionchange') {\n          text = sliceOverlayData[n].value;\n        }\n      } else {\n        // update text if the value is an event type\n        if (typeof sliceOverlayData[n].event !== 'undefined' &&\n          sliceOverlayData[n].event === event.type) {\n          const format = sliceOverlayData[n].format;\n          let values = event.value;\n          // optional number precision\n          if (typeof sliceOverlayData[n].precision !== 'undefined') {\n            let mapFunc = null;\n            if (sliceOverlayData[n].precision === 'round') {\n              mapFunc = Math.round;\n            } else {\n              mapFunc = getNumberToPrecision(sliceOverlayData[n].precision);\n            }\n            values = values.map(mapFunc);\n          }\n          text = replaceFlags(format, values);\n        }\n      }\n      if (typeof text !== 'undefined') {\n        sliceOverlayData[n].value = text;\n      }\n    }\n\n    /**\n     * Value change event.\n     *\n     * @event OverlayData#valuechange\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {Array} data The value of the overlay data.\n     */\n    this.#fireEvent({\n      type: 'valuechange',\n      data: sliceOverlayData\n    });\n  };\n\n  /**\n   * Is this class listening to app events.\n   *\n   * @returns {boolean} True is listening to app events.\n   */\n  isListening() {\n    return this.#isListening;\n  }\n\n  /**\n   * Toggle info listeners.\n   */\n  addAppListeners() {\n    // listen to update tags data\n    this.#app.addEventListener('positionchange', this.#onSliceChange);\n    // add event listeners\n    for (let i = 0; i < this.#eventNames.length; ++i) {\n      this.#app.addEventListener(this.#eventNames[i], this.#updateData);\n    }\n    // update flag\n    this.#isListening = true;\n  }\n\n  /**\n   * Toggle info listeners.\n   */\n  removeAppListeners() {\n    // stop listening to update tags data\n    this.#app.removeEventListener('positionchange', this.#onSliceChange);\n    // remove event listeners\n    for (let i = 0; i < this.#eventNames.length; ++i) {\n      this.#app.removeEventListener(this.#eventNames[i], this.#updateData);\n    }\n    // update flag\n    this.#isListening = false;\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {object} callback The method associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {object} callback The method associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent(event) {\n    this.#listenerHandler.fireEvent(event);\n  }\n\n} // class OverlayData\n\n/**\n * Create overlay data array for a DICOM image.\n *\n * @param {object} dicomElements DICOM elements of the image.\n * @param {object} configs The overlay data configs.\n * @returns {Array} Overlay data array.\n */\nfunction createOverlayData(dicomElements, configs) {\n  const overlays = [];\n  let modality;\n  const modElement = dicomElements['00080060'];\n  if (typeof modElement !== 'undefined') {\n    modality = modElement.value[0];\n  } else {\n    return overlays;\n  }\n  const config = configs[modality] || configs['*'];\n  if (!config) {\n    return overlays;\n  }\n\n  for (let n = 0; n < config.length; ++n) {\n    // deep copy\n    const overlay = JSON.parse(JSON.stringify(config[n]));\n\n    // add tag values\n    const tags = overlay.tags;\n    if (typeof tags !== 'undefined' && tags.length !== 0) {\n      // get values\n      const values = [];\n      for (let i = 0; i < tags.length; ++i) {\n        const elem = dicomElements[tags[i]];\n        if (typeof elem !== 'undefined') {\n          values.push(dicomElements[tags[i]].value);\n        } else {\n          values.push('');\n        }\n      }\n      // format\n      if (typeof overlay.format === 'undefined' || overlay.format === null) {\n        overlay.format = createDefaultReplaceFormat(values.length);\n      }\n      overlay.value = replaceFlags(overlay.format, values).trim();\n    }\n\n    // store\n    overlays.push(overlay);\n  }\n\n  // (0020,0020) Patient Orientation\n  const poElement = dicomElements['00200020'];\n  if (typeof poElement !== 'undefined' &&\n    poElement.value.length === 2\n  ) {\n    const po0 = poElement.value[0];\n    const po1 = poElement.value[1];\n    overlays.push({\n      pos: 'cr', value: po0, format: '{v0}'\n    });\n    overlays.push({\n      pos: 'cl', value: getReverseOrientation(po0), format: '{v0}'\n    });\n    overlays.push({\n      pos: 'bc', value: po1, format: '{v0}'\n    });\n    overlays.push({\n      pos: 'tc', value: getReverseOrientation(po1), format: '{v0}'\n    });\n  }\n\n  return overlays;\n}\n\n/**\n * Create overlay data array for a DOM image.\n *\n * @param {object} info Meta data.\n * @param {object} configs The overlay data configs.\n * @returns {Array} Overlay data array.\n */\nfunction createOverlayDataForDom(info, configs) {\n  const overlays = [];\n  const config = configs.DOM;\n  if (!config) {\n    return overlays;\n  }\n\n  const infoKeys = Object.keys(info);\n\n  for (let n = 0; n < config.length; ++n) {\n    // deep copy\n    const overlay = JSON.parse(JSON.stringify(config[n]));\n\n    // add tag values\n    const tags = overlay.tags;\n    if (typeof tags !== 'undefined' && tags.length !== 0) {\n      // get values\n      const values = [];\n      for (let i = 0; i < tags.length; ++i) {\n        for (let j = 0; j < infoKeys.length; ++j) {\n          if (tags[i] === infoKeys[j]) {\n            values.push(info[infoKeys[j]].value);\n          }\n        }\n      }\n      // format\n      if (typeof overlay.format === 'undefined' || overlay.format === null) {\n        overlay.format = createDefaultReplaceFormat(values.length);\n      }\n      overlay.value = replaceFlags(overlay.format, values).trim();\n    }\n\n    // store\n    overlays.push(overlay);\n  }\n\n  return overlays;\n}\n","import {viewEventNames} from '../image/view';\nimport {ViewFactory} from '../image/viewFactory';\nimport {\n  getMatrixFromName,\n  getOrientationStringLPS,\n  Orientation,\n  getViewOrientation\n} from '../math/orientation';\nimport {Point3D} from '../math/point';\nimport {Stage} from '../gui/stage';\nimport {Style} from '../gui/style';\nimport {getLayerDetailsFromLayerDivId} from '../gui/layerGroup';\nimport {ListenerHandler} from '../utils/listen';\nimport {State} from '../io/state';\nimport {logger} from '../utils/logger';\nimport {getUriQuery, decodeQuery} from '../utils/uri';\nimport {UndoStack} from '../utils/undoStack';\nimport {ToolboxController} from './toolboxController';\nimport {LoadController} from './loadController';\nimport {DataController} from './dataController';\nimport {OverlayData} from '../gui/overlayData';\nimport {\n  toolList,\n  defaultToolList,\n  toolOptions,\n  defaultToolOptions\n} from '../tools';\nimport {binderList} from '../gui/stage';\nimport {WindowLevel} from '../image/windowLevel';\nimport {PlaneHelper} from '../image/planeHelper';\nimport {AnnotationGroup} from '../image/annotationGroup';\nimport {konvaToAnnotation} from '../gui/drawLayer';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {LayerGroup} from '../gui/layerGroup';\nimport {ViewLayer} from '../gui/viewLayer';\nimport {DrawLayer} from '../gui/drawLayer';\nimport {Image} from '../image/image';\nimport {Matrix33} from '../math/matrix';\nimport {DataElement} from '../dicom/dataElement';\nimport {Scalar3D} from '../math/scalar';\nimport {DicomData} from './dataController';\n/* eslint-enable no-unused-vars */\n\n/**\n * View configuration: mainly defines the ´divId´\n * of the associated HTML div.\n */\nexport class ViewConfig {\n  /**\n   * Associated HTML div id.\n   *\n   * @type {string}\n   */\n  divId;\n  /**\n   * Optional orientation of the data; 'axial', 'coronal' or 'sagittal'.\n   * If undefined, will use the data aquisition plane.\n   *\n   * @type {string|undefined}\n   */\n  orientation;\n  /**\n   * Optional view colour map name.\n   *\n   * @type {string|undefined}\n   */\n  colourMap;\n  /**\n   * Optional layer opacity; in [0, 1] range.\n   *\n   * @type {number|undefined}\n   */\n  opacity;\n  /**\n   * Optional layer window level preset name.\n   * If present, the preset name will be used and\n   * the window centre and width ignored.\n   *\n   * @type {string|undefined}\n   */\n  wlPresetName;\n  /**\n   * Optional layer window center.\n   *\n   * @type {number|undefined}\n   */\n  windowCenter;\n  /**\n   * Optional layer window width.\n   *\n   * @type {number|undefined}\n   */\n  windowWidth;\n\n  /**\n   * @param {string} divId The associated HTML div id.\n   */\n  constructor(divId) {\n    this.divId = divId;\n  }\n}\n\n/**\n * Tool configuration.\n */\nexport class ToolConfig {\n  /**\n   * Optional tool options.\n   * For Draw: list of shape names.\n   * For Filter: list of filter names.\n   *\n   * @type {string[]|undefined}\n   */\n  options;\n\n  /**\n   * @param {string[]} [options] Optional tool options.\n   */\n  constructor(options) {\n    this.options = options;\n  }\n}\n\n/**\n * Application options.\n */\nexport class AppOptions {\n  /**\n   * DataId indexed object containing the data view configurations.\n   *\n   * @type {Object<string, ViewConfig[]>|undefined}\n   */\n  dataViewConfigs;\n  /**\n   * Tool name indexed object containing individual tool configurations.\n   *\n   * @type {Object<string, ToolConfig>|undefined}\n   */\n  tools;\n  /**\n   * Optional array of layerGroup binder names.\n   *\n   * @type {string[]|undefined}\n   */\n  binders;\n  /**\n   * Optional boolean flag to trigger the first data render\n   *   after the first loaded data or not. Defaults to true.\n   *\n   * @type {boolean|undefined}\n   */\n  viewOnFirstLoadItem;\n  /**\n   * Optional default chraracterset string used for DICOM parsing if\n   *   not passed in DICOM file.\n   *\n   * Valid values: {@link https://developer.mozilla.org/en-US/docs/Web/API/Encoding_API/Encodings}.\n   *\n   * @type {string|undefined}\n   */\n  defaultCharacterSet;\n  /**\n   * Optional overlay config.\n   *\n   * @type {object|undefined}\n   */\n  overlayConfig;\n  /**\n   * DOM root document.\n   *\n   * @type {DocumentFragment}\n   */\n  rootDocument;\n\n  /**\n   * @param {Object<string, ViewConfig[]>} [dataViewConfigs] Optional dataId\n   *   indexed object containing the data view configurations.\n   */\n  constructor(dataViewConfigs) {\n    this.dataViewConfigs = dataViewConfigs;\n  }\n}\n\n/**\n * List of ViewConfigs indexed by dataIds.\n *\n * @typedef {Object<string, ViewConfig[]>} DataViewConfigs\n */\n\n/**\n * Main application class.\n *\n * @example\n * // create the dwv app\n * const app = new dwv.App();\n * // initialise\n * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n * const viewConfigs = {'*': [viewConfig0]};\n * const options = new dwv.AppOptions(viewConfigs);\n * app.init(options);\n * // load dicom data\n * app.loadURLs([\n *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n * ]);\n */\nexport class App {\n\n  /**\n   * App options.\n   *\n   * @type {AppOptions}\n   */\n  #options = null;\n\n  /**\n   * Data controller.\n   *\n   * @type {DataController}\n   */\n  #dataController = null;\n\n  /**\n   * Toolbox controller.\n   *\n   * @type {ToolboxController}\n   */\n  #toolboxController = null;\n\n  /**\n   * Load controller.\n   *\n   * @type {LoadController}\n   */\n  #loadController = null;\n\n  /**\n   * Stage.\n   *\n   * @type {Stage}\n   */\n  #stage = null;\n\n  /**\n   * Undo stack.\n   *\n   * @type {UndoStack}\n   */\n  #undoStack = null;\n\n  /**\n   * Style.\n   *\n   * @type {Style}\n   */\n  #style = new Style();\n\n  // overlay datas\n  #overlayDatas = {};\n\n  /**\n   * Listener handler.\n   *\n   * @type {ListenerHandler}\n   */\n  #listenerHandler = new ListenerHandler();\n\n  /**\n   * Get a DicomData.\n   *\n   * @param {string} dataId The data id.\n   * @returns {DicomData|undefined} The data.\n   */\n  getData(dataId) {\n    return this.#dataController.get(dataId);\n  }\n\n  /**\n   * Get the image.\n   *\n   * @param {string} dataId The data id.\n   * @returns {Image|undefined} The associated image.\n   * @deprecated Since v0.34, please use the getData method.\n   */\n  getImage(dataId) {\n    let res;\n    if (typeof this.getData(dataId) !== 'undefined') {\n      res = this.getData(dataId).image;\n    }\n    return res;\n  }\n\n  /**\n   * Set the image at the given id.\n   *\n   * @param {string} dataId The data id.\n   * @param {Image} img The associated image.\n   */\n  setImage(dataId, img) {\n    this.#dataController.setImage(dataId, img);\n  }\n\n  /**\n   * Add a new DicomData.\n   *\n   * @param {DicomData} data The new data.\n   * @returns {string} The data id.\n   */\n  addData(data) {\n    // get a new dataId\n    const dataId = this.#dataController.getNextDataId();\n    // add image to data controller\n    this.#dataController.add(\n      dataId,\n      data\n    );\n    // optional render\n    // if (this.#options.viewOnFirstLoadItem) {\n    //   this.render(dataId);\n    // }\n    // return\n    return dataId;\n  }\n\n  /**\n   * Get the meta data.\n   *\n   * @param {string} dataId The data id.\n   * @returns {Object<string, DataElement>|undefined} The list of meta data.\n   */\n  getMetaData(dataId) {\n    let res;\n    if (typeof this.#dataController.get(dataId) !== 'undefined') {\n      res = this.#dataController.get(dataId).meta;\n    }\n    return res;\n  }\n\n  /**\n   * Get the list of ids in the data storage.\n   *\n   * @returns {string[]} The list of data ids.\n   */\n  getDataIds() {\n    return this.#dataController.getDataIds();\n  }\n\n  /**\n   * Get the list of dataIds that contain the input UIDs.\n   *\n   * @param {string[]} uids A list of UIDs.\n   * @returns {string[]} The list of dataIds that contain the UIDs.\n   */\n  getDataIdsFromSopUids(uids) {\n    return this.#dataController.getDataIdsFromSopUids(uids);\n  }\n\n  /**\n   * Can the data (of the active view of the active layer) be scrolled?\n   *\n   * @returns {boolean} True if the data has a third dimension greater than one.\n   * @deprecated Since v0.33, please use the ViewController\n   *   equivalent directly instead.\n   */\n  canScroll() {\n    const viewLayer = this.#stage.getActiveLayerGroup().getActiveViewLayer();\n    const controller = viewLayer.getViewController();\n    return controller.canScroll();\n  }\n\n  /**\n   * Can window and level be applied to the data\n   * (of the active view of the active layer)?\n   *\n   * @returns {boolean} True if the data is monochrome.\n   * @deprecated Since v0.33, please use the ViewController\n   *   equivalent directly instead.\n   */\n  canWindowLevel() {\n    const viewLayer = this.#stage.getActiveLayerGroup().getActiveViewLayer();\n    const controller = viewLayer.getViewController();\n    return controller.canWindowLevel();\n  }\n\n  /**\n   * Get the active layer group scale on top of the base scale.\n   *\n   * @returns {Scalar3D} The scale as {x,y,z}.\n   */\n  getAddedScale() {\n    return this.#stage.getActiveLayerGroup().getAddedScale();\n  }\n\n  /**\n   * Get the base scale of the active layer group.\n   *\n   * @returns {Scalar3D} The scale as {x,y,z}.\n   */\n  getBaseScale() {\n    return this.#stage.getActiveLayerGroup().getBaseScale();\n  }\n\n  /**\n   * Get the layer offset of the active layer group.\n   *\n   * @returns {Scalar3D} The offset as {x,y,z}.\n   */\n  getOffset() {\n    return this.#stage.getActiveLayerGroup().getOffset();\n  }\n\n  /**\n   * Get the toolbox controller.\n   *\n   * @returns {ToolboxController} The controller.\n   */\n  getToolboxController() {\n    return this.#toolboxController;\n  }\n\n  /**\n   * Get the active layer group.\n   * The layer is available after the first loaded item.\n   *\n   * @returns {LayerGroup|undefined} The layer group.\n   */\n  getActiveLayerGroup() {\n    return this.#stage.getActiveLayerGroup();\n  }\n\n  /**\n   * Set the active layer group.\n   *\n   * @param {number} index The layer group index.\n   */\n  setActiveLayerGroup(index) {\n    this.#stage.setActiveLayerGroup(index);\n  }\n\n  /**\n   * Get the view layers associated to a data id.\n   * The layer are available after the first loaded item.\n   *\n   * @param {string} dataId The data id.\n   * @returns {ViewLayer[]} The layers.\n   */\n  getViewLayersByDataId(dataId) {\n    return this.#stage.getViewLayersByDataId(dataId);\n  }\n\n  /**\n   * Get a list of view layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a ViewLayer as input and returns a boolean. If undefined,\n   *   returns all view layers.\n   * @returns {ViewLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getViewLayers(callbackFn) {\n    return this.#stage.getViewLayers(callbackFn);\n  }\n\n  /**\n   * Get the draw layers associated to a data id.\n   * The layer are available after the first loaded item.\n   *\n   * @param {string} dataId The data id.\n   * @returns {DrawLayer[]} The layers.\n   */\n  getDrawLayersByDataId(dataId) {\n    return this.#stage.getDrawLayersByDataId(dataId);\n  }\n\n  /**\n   * Get a list of draw layers according to an input callback function.\n   *\n   * @param {Function} [callbackFn] A function that takes\n   *   a DrawLayer as input and returns a boolean. If undefined,\n   *   returns all draw layers.\n   * @returns {DrawLayer[]} The layers that\n   *   satisfy the callbackFn.\n   */\n  getDrawLayers(callbackFn) {\n    return this.#stage.getDrawLayers(callbackFn);\n  }\n\n  /**\n   * Get a layer group by div id.\n   * The layer is available after the first loaded item.\n   *\n   * @param {string} divId The div id.\n   * @returns {LayerGroup|undefined} The layer group.\n   */\n  getLayerGroupByDivId(divId) {\n    return this.#stage.getLayerGroupByDivId(divId);\n  }\n\n  /**\n   * Get the number of layer groups.\n   *\n   * @returns {number} The number of groups.\n   */\n  getNumberOfLayerGroups() {\n    return this.#stage.getNumberOfLayerGroups();\n  }\n\n  /**\n   * Get the app style.\n   *\n   * @returns {object} The app style.\n   */\n  getStyle() {\n    return this.#style;\n  }\n\n  /**\n   * Add a command to the undo stack.\n   *\n   * @param {object} cmd The command to add.\n   * @fires UndoStack#undoadd\n   * @function\n   */\n  addToUndoStack = (cmd) => {\n    if (this.#undoStack !== null) {\n      this.#undoStack.add(cmd);\n    }\n  };\n\n  /**\n   * Remove a command from the undo stack.\n   *\n   * @param {string} name The name of the command to remove.\n   * @returns {boolean} True if the command was found and removed.\n   * @fires UndoStack#undoremove\n   * @function\n   */\n  removeFromUndoStack = (name) => {\n    let res = false;\n    if (this.#undoStack !== null) {\n      res = this.#undoStack.remove(name);\n    }\n    return res;\n  };\n\n  /**\n   * Initialise the application.\n   *\n   * @param {AppOptions} opt The application options.\n   * @example\n   * // create the dwv app\n   * const app = new dwv.App();\n   * // initialise\n   * const viewConfig0 = new dwv.ViewConfig('layerGroup0');\n   * const viewConfigs = {'*': [viewConfig0]};\n   * const options = new dwv.AppOptions(viewConfigs);\n   * options.viewOnFirstLoadItem = false;\n   * app.init(options);\n   * // render button\n   * const button = document.createElement('button');\n   * button.id = 'render';\n   * button.disabled = true;\n   * button.appendChild(document.createTextNode('render'));\n   * document.body.appendChild(button);\n   * app.addEventListener('load', function () {\n   *   const button = document.getElementById('render');\n   *   button.disabled = false;\n   *   button.onclick = function () {\n   *     // render data #0\n   *     app.render(0);\n   *   };\n   * });\n   * // load dicom data\n   * app.loadURLs([\n   *   'https://raw.githubusercontent.com/ivmartel/dwv/master/tests/data/bbmri-53323851.dcm'\n   * ]);\n   */\n  init(opt) {\n    // store\n    this.#options = opt;\n    // defaults\n    if (typeof this.#options.viewOnFirstLoadItem === 'undefined') {\n      this.#options.viewOnFirstLoadItem = true;\n    }\n    if (typeof this.#options.dataViewConfigs === 'undefined') {\n      this.#options.dataViewConfigs = {};\n    }\n    if (typeof this.#options.rootDocument === 'undefined') {\n      this.#options.rootDocument = document;\n    }\n\n    // undo stack\n    this.#undoStack = new UndoStack();\n    this.#undoStack.addEventListener('undoadd', this.#fireEvent);\n    this.#undoStack.addEventListener('undo', this.#fireEvent);\n    this.#undoStack.addEventListener('redo', this.#fireEvent);\n\n    // tools\n    if (typeof this.#options.tools !== 'undefined') {\n      // setup the tool list\n      const appToolList = {};\n      const keys = Object.keys(this.#options.tools);\n      for (let t = 0; t < keys.length; ++t) {\n        const toolName = keys[t];\n        // find the tool in the default tool list\n        let toolClass = defaultToolList[toolName];\n        // or use external one\n        if (typeof toolClass === 'undefined') {\n          toolClass = toolList[toolName];\n        }\n        if (typeof toolClass !== 'undefined') {\n          // create tool instance\n          appToolList[toolName] = new toolClass(this);\n          // register listeners\n          if (typeof appToolList[toolName].addEventListener !== 'undefined') {\n            const names = appToolList[toolName].getEventNames();\n            for (let j = 0; j < names.length; ++j) {\n              appToolList[toolName].addEventListener(names[j], this.#fireEvent);\n            }\n          }\n          // tool options\n          const toolParams = this.#options.tools[toolName];\n          if (typeof toolParams.options !== 'undefined' &&\n            toolParams.options.length !== 0) {\n            let type = 'raw';\n            if (typeof appToolList[toolName].getOptionsType !== 'undefined') {\n              type = appToolList[toolName].getOptionsType();\n            }\n            let appToolOptions;\n            if (type === 'instance' || type === 'factory') {\n              appToolOptions = {};\n              for (let i = 0; i < toolParams.options.length; ++i) {\n                const optionName = toolParams.options[i];\n                let optionClassName = optionName;\n                if (type === 'factory') {\n                  optionClassName += 'Factory';\n                }\n                const toolNamespace = toolName.charAt(0).toLowerCase() +\n                  toolName.slice(1);\n                // find the option in the external tool list\n                let tOptions = toolOptions[toolNamespace];\n                let optionClass;\n                if (typeof tOptions !== 'undefined') {\n                  optionClass = tOptions[optionClassName];\n                }\n                // or use the default one\n                if (typeof optionClass === 'undefined') {\n                  tOptions = defaultToolOptions[toolNamespace];\n                  if (typeof tOptions !== 'undefined') {\n                    optionClass = tOptions[optionClassName];\n                  }\n                }\n                if (typeof optionClass !== 'undefined') {\n                  appToolOptions[optionName] = optionClass;\n                } else {\n                  logger.warn('Could not find option class for: ' +\n                    optionName);\n                }\n              }\n            } else {\n              appToolOptions = toolParams.options;\n            }\n            appToolList[toolName].setOptions(appToolOptions);\n          }\n        } else {\n          logger.warn('Could not initialise unknown tool: ' + toolName);\n        }\n      }\n      // add tools to the controller\n      this.#toolboxController = new ToolboxController(appToolList);\n    }\n\n    // create load controller\n    this.#loadController =\n      new LoadController(this.#options.defaultCharacterSet);\n    this.#loadController.onloadstart = this.#onloadstart;\n    this.#loadController.onprogress = this.#onloadprogress;\n    this.#loadController.onloaditem = this.#onloaditem;\n    this.#loadController.onload = this.#onload;\n    this.#loadController.onloadend = this.#onloadend;\n    this.#loadController.onerror = this.#onloaderror;\n    this.#loadController.ontimeout = this.#onloadtimeout;\n    this.#loadController.onabort = this.#onloadabort;\n\n    // create data controller\n    this.#dataController = new DataController();\n    // propagate data events\n    this.#dataController.addEventListener('dataadd', this.#fireEvent);\n    this.#dataController.addEventListener('dataremove', this.#fireEvent);\n    this.#dataController.addEventListener('dataimageset', this.#fireEvent);\n    this.#dataController.addEventListener('dataupdate', this.#fireEvent);\n    // propage individual data events\n    this.#dataController.addEventListener(\n      'imagecontentchange', this.#fireEvent);\n    this.#dataController.addEventListener(\n      'imagegeometrychange', this.#fireEvent);\n    this.#dataController.addEventListener('annotationadd', this.#fireEvent);\n    this.#dataController.addEventListener('annotationupdate', this.#fireEvent);\n    this.#dataController.addEventListener('annotationremove', this.#fireEvent);\n    this.#dataController.addEventListener(\n      'annotationgroupeditablechange', this.#fireEvent);\n    // create stage\n    this.#stage = new Stage();\n    if (typeof this.#options.binders !== 'undefined') {\n      this.#stage.setBinders(this.#options.binders);\n    }\n  }\n\n  /**\n   * Reset the application.\n   */\n  reset() {\n    // clear objects\n    this.#stage.empty();\n    this.#overlayDatas = {};\n    // reset undo/redo\n    if (this.#undoStack) {\n      this.#undoStack = new UndoStack();\n      this.#undoStack.addEventListener('undoadd', this.#fireEvent);\n      this.#undoStack.addEventListener('undo', this.#fireEvent);\n      this.#undoStack.addEventListener('redo', this.#fireEvent);\n    }\n  }\n\n  /**\n   * Reset the layout of the application.\n   */\n  resetLayout() {\n    this.#stage.reset();\n    this.#stage.draw();\n  }\n\n  /**\n   * Add an event listener to this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type, will be called with the fired event.\n   */\n  addEventListener(type, callback) {\n    this.#listenerHandler.add(type, callback);\n  }\n\n  /**\n   * Remove an event listener from this class.\n   *\n   * @param {string} type The event type.\n   * @param {Function} callback The function associated with the provided\n   *   event type.\n   */\n  removeEventListener(type, callback) {\n    this.#listenerHandler.remove(type, callback);\n  }\n\n  // load API [begin] -------------------------------------------------------\n\n  /**\n   * Load a list of files. Can be image files or a state file.\n   *\n   * @param {File[]} files The list of files to load.\n   * @fires App#loadstart\n   * @fires App#loadprogress\n   * @fires App#loaditem\n   * @fires App#loadend\n   * @fires App#error\n   * @fires App#abort\n   * @function\n   */\n  loadFiles = (files) => {\n    // Get new data id\n    const dataId = this.#dataController.getNextDataId();\n    if (files.length === 0) {\n      logger.warn('Ignoring empty input file list.');\n      return;\n    }\n    this.#loadController.loadFiles(files, dataId);\n  };\n\n  /**\n   * Load a list of URLs. Can be image files or a state file.\n   *\n   * @param {string[]} urls The list of urls to load.\n   * @param {object} [options] The options object, can contain:\n   * - requestHeaders: an array of {name, value} to use as request headers,\n   * - withCredentials: boolean xhr.withCredentials flag to pass to the request,\n   * - batchSize: the size of the request url batch.\n   * @fires App#loadstart\n   * @fires App#loadprogress\n   * @fires App#loaditem\n   * @fires App#loadend\n   * @fires App#error\n   * @fires App#abort\n   * @function\n   */\n  loadURLs = (urls, options) => {\n    // Get new data id\n    const dataId = this.#dataController.getNextDataId();\n    if (urls.length === 0) {\n      logger.warn('Ignoring empty input url list.');\n      return;\n    }\n    this.#loadController.loadURLs(urls, dataId, options);\n  };\n\n  /**\n   * Load from an input uri.\n   *\n   * @param {string} uri The input uri, for example: 'window.location.href'.\n   * @param {object} [options] Optional url request options.\n   * @function\n   */\n  loadFromUri = (uri, options) => {\n    const query = getUriQuery(uri);\n\n    // load end callback: loads the state.\n    const onLoadEnd = (/*event*/) => {\n      this.removeEventListener('loadend', onLoadEnd);\n      this.loadURLs([query.state]);\n    };\n\n    // check query\n    if (query && typeof query.input !== 'undefined') {\n      // optional display state\n      if (typeof query.state !== 'undefined') {\n        // queue after main data load\n        this.addEventListener('loadend', onLoadEnd);\n      }\n      // load base image\n      decodeQuery(query, this.loadURLs, options);\n    }\n    // no else to allow for empty uris\n  };\n\n  /**\n   * Load a list of ArrayBuffers.\n   *\n   * @param {Array} data The list of ArrayBuffers to load\n   *   in the form of [{name: \"\", filename: \"\", data: data}].\n   * @fires App#loadstart\n   * @fires App#loadprogress\n   * @fires App#loaditem\n   * @fires App#loadend\n   * @fires App#error\n   * @fires App#abort\n   * @function\n   */\n  loadImageObject = (data) => {\n    // Get new data id\n    const dataId = this.#dataController.getNextDataId();\n    this.#loadController.loadImageObject(data, dataId);\n  };\n\n  /**\n   * Abort all the current loads.\n   */\n  abortAllLoads() {\n    const ids = this.#loadController.getLoadingDataIds();\n    for (const id of ids) {\n      this.abortLoad(id);\n    }\n  }\n\n  /**\n   * Abort an individual data load.\n   *\n   * @param {string} dataId The data to stop loading.\n   */\n  abortLoad(dataId) {\n    // abort load\n    this.#loadController.abort(dataId);\n    // remove data\n    this.#dataController.remove(dataId);\n    // clean up stage\n    this.#stage.removeLayersByDataId(dataId);\n  }\n\n  // load API [end] ---------------------------------------------------------\n\n  /**\n   * Fit the display to the data of each layer group.\n   * To be called once the image is loaded.\n   */\n  fitToContainer() {\n    this.#stage.fitToContainer();\n  }\n\n  /**\n   * Init the Window/Level display\n   * (of the active layer of the active layer group).\n   *\n   * @deprecated Since v0.33, please set the opacity\n   *   of the desired view layer directly.\n   */\n  initWLDisplay() {\n    const viewLayer = this.#stage.getActiveLayerGroup().getActiveViewLayer();\n    const controller = viewLayer.getViewController();\n    controller.initialise();\n  }\n\n  /**\n   * Set the imageSmoothing flag value. Default is false.\n   *\n   * @param {boolean} flag True to enable smoothing.\n   */\n  setImageSmoothing(flag) {\n    this.#stage.setImageSmoothing(flag);\n    this.#stage.draw();\n  }\n\n  /**\n   * Get the layer group configuration from a data id.\n   *\n   * @param {string} dataId The data id.\n   * @param {boolean} [excludeStarConfig] Exclude the star config\n   *  (default to false).\n   * @returns {ViewConfig[]} The list of associated configs.\n   */\n  getViewConfigs(dataId, excludeStarConfig) {\n    if (typeof excludeStarConfig === 'undefined') {\n      excludeStarConfig = false;\n    }\n    // check options\n    if (this.#options.dataViewConfigs === null ||\n      typeof this.#options.dataViewConfigs === 'undefined') {\n      throw new Error('No available data view configuration');\n    }\n    let configs = [];\n    if (typeof this.#options.dataViewConfigs[dataId] !== 'undefined') {\n      configs = this.#options.dataViewConfigs[dataId];\n    } else if (!excludeStarConfig &&\n      typeof this.#options.dataViewConfigs['*'] !== 'undefined') {\n      configs = this.#options.dataViewConfigs['*'];\n    }\n    return configs;\n  }\n\n  /**\n   * Get the layer group configuration for a data id and group\n   * div id.\n   *\n   * @param {string} dataId The data id.\n   * @param {string} groupDivId The layer group div id.\n   * @param {boolean} [excludeStarConfig] Exclude the star config\n   *  (default to false).\n   * @returns {ViewConfig|undefined} The associated config.\n   */\n  getViewConfig(dataId, groupDivId, excludeStarConfig) {\n    const configs = this.getViewConfigs(dataId, excludeStarConfig);\n    return configs.find(function (item) {\n      return item.divId === groupDivId;\n    });\n  }\n\n  /**\n   * Get the data view config.\n   * Carefull, returns a reference, do not modify without resetting.\n   *\n   * @returns {Object<string, ViewConfig[]>} The configuration list.\n   */\n  getDataViewConfigs() {\n    return this.#options.dataViewConfigs;\n  }\n\n  /**\n   * Set the data view configuration.\n   * Resets the stage and recreates all the views.\n   *\n   * @param {Object<string, ViewConfig[]>} configs The configuration list.\n   */\n  setDataViewConfigs(configs) {\n    // clean up\n    this.#stage.empty();\n    // set new\n    this.#options.dataViewConfigs = configs;\n    // create layer groups\n    this.#createLayerGroups(configs);\n  }\n\n  /**\n   * Add a data view config.\n   *\n   * @param {string} dataId The data id.\n   * @param {ViewConfig} config The view configuration.\n   */\n  addDataViewConfig(dataId, config) {\n    // add to list\n    const configs = this.#options.dataViewConfigs;\n    if (typeof configs[dataId] === 'undefined') {\n      configs[dataId] = [];\n    }\n    const equalDivId = function (item) {\n      return item.divId === config.divId;\n    };\n    const itemIndex = configs[dataId].findIndex(equalDivId);\n    if (itemIndex === -1) {\n      this.#options.dataViewConfigs[dataId].push(config);\n    } else {\n      throw new Error('Duplicate view config for data ' + dataId +\n        ' and div ' + config.divId);\n    }\n\n    // add layer group if not done\n    if (typeof this.#stage.getLayerGroupByDivId(config.divId) === 'undefined') {\n      this.#createLayerGroup(config);\n    }\n\n    // render (will create layers)\n    if (typeof this.#dataController.get(dataId) !== 'undefined') {\n      this.render(dataId, [config]);\n    }\n  }\n\n  /**\n   * Remove a data view config.\n   *\n   * @param {string} dataId The data id.\n   * @param {string} divId The div id.\n   */\n  removeDataViewConfig(dataId, divId) {\n    // remove from list\n    const configs = this.#options.dataViewConfigs;\n    if (typeof configs[dataId] === 'undefined') {\n      // no config for dataId\n      return;\n    }\n    const equalDivId = function (item) {\n      return item.divId === divId;\n    };\n    const itemIndex = configs[dataId].findIndex(equalDivId);\n    if (itemIndex === -1) {\n      // no config for divId\n      return;\n    }\n    configs[dataId].splice(itemIndex, 1);\n    if (configs[dataId].length === 0) {\n      delete configs[dataId];\n    }\n\n    // data is loaded, remove view\n    if (typeof this.#dataController.get(dataId) !== 'undefined') {\n      const lg = this.#stage.getLayerGroupByDivId(divId);\n      if (typeof lg !== 'undefined') {\n        const vls = lg.getViewLayersByDataId(dataId);\n        if (vls.length === 1) {\n          lg.removeLayer(vls[0]);\n        }\n        const dls = lg.getDrawLayersByDataId(dataId);\n        if (dls.length === 1) {\n          lg.removeLayer(dls[0]);\n        }\n        if (vls.length === 0 && dls.length === 0) {\n          throw new Error('Expected one layer, got none');\n        }\n        if (lg.getNumberOfLayers() === 0) {\n          this.#stage.removeLayerGroup(lg);\n        }\n      }\n    }\n  }\n\n  /**\n   * Update an existing data view config.\n   * Removes and re-creates the layer if found.\n   *\n   * @param {string} dataId The data id.\n   * @param {string} divId The div id.\n   * @param {ViewConfig} config The view configuration.\n   */\n  updateDataViewConfig(dataId, divId, config) {\n    const configs = this.#options.dataViewConfigs;\n    // check data id\n    if (typeof configs[dataId] === 'undefined') {\n      throw new Error('No config for dataId: ' + dataId);\n    }\n    // check div id\n    const equalDivId = function (item) {\n      return item.divId === divId;\n    };\n    const itemIndex = configs[dataId].findIndex(equalDivId);\n    if (itemIndex === -1) {\n      throw new Error('No config for dataId: ' +\n        dataId + ' and divId: ' + divId);\n    }\n    // update config\n    const configToUpdate = configs[dataId][itemIndex];\n    for (const prop in config) {\n      configToUpdate[prop] = config[prop];\n    }\n\n    // remove previous layers\n    const lg = this.#stage.getLayerGroupByDivId(configToUpdate.divId);\n    if (typeof lg !== 'undefined') {\n      const vls = lg.getViewLayersByDataId(dataId);\n      if (vls.length === 1) {\n        lg.removeLayer(vls[0]);\n      }\n      const dls = lg.getDrawLayersByDataId(dataId);\n      if (dls.length === 1) {\n        lg.removeLayer(dls[0]);\n      }\n      if (vls.length === 0 && dls.length === 0) {\n        throw new Error('Expected one layer, got none');\n      }\n    }\n\n    // render (will create layer)\n    if (typeof this.#dataController.get(dataId) !== 'undefined') {\n      this.render(dataId, [configToUpdate]);\n    }\n  }\n\n  /**\n   * Create layer groups according to a data view config:\n   * adds them to stage and binds them.\n   *\n   * @param {DataViewConfigs} dataViewConfigs The data view config.\n   */\n  #createLayerGroups(dataViewConfigs) {\n    const dataKeys = Object.keys(dataViewConfigs);\n    const divIds = [];\n    for (let i = 0; i < dataKeys.length; ++i) {\n      const viewConfigs = dataViewConfigs[dataKeys[i]];\n      for (let j = 0; j < viewConfigs.length; ++j) {\n        const viewConfig = viewConfigs[j];\n        // view configs can contain the same divIds, avoid duplicating\n        if (!divIds.includes(viewConfig.divId)) {\n          this.#createLayerGroup(viewConfig);\n          divIds.push(viewConfig.divId);\n        }\n      }\n    }\n  }\n\n  /**\n   * Create a layer group according to a view config:\n   * adds it to stage and binds it.\n   *\n   * @param {ViewConfig} viewConfig The view config.\n   */\n  #createLayerGroup(viewConfig) {\n    // create new layer group\n    const element = this.#options.rootDocument.getElementById(viewConfig.divId);\n    const layerGroup = this.#stage.addLayerGroup(element);\n    // bind events\n    this.#bindLayerGroupToApp(layerGroup);\n  }\n\n  /**\n   * Set the layer groups binders.\n   *\n   * @param {string[]} list The list of binder names.\n   */\n  setLayerGroupsBinders(list) {\n    // create instances\n    const instances = [];\n    for (let i = 0; i < list.length; ++i) {\n      if (typeof binderList[list[i]] !== 'undefined') {\n        instances.push(new binderList[list[i]]);\n      }\n    }\n    // pass to stage\n    this.#stage.setBinders(instances);\n  }\n\n  /**\n   * Render the current data.\n   *\n   * @param {string} dataId The data id to render.\n   * @param {ViewConfig[]} [viewConfigs] The list of configs to render.\n   */\n  render(dataId, viewConfigs) {\n    if (typeof dataId === 'undefined' || dataId === null) {\n      throw new Error('Cannot render without data id');\n    }\n    // guess data type\n    const isImage =\n      typeof this.getData(dataId).image !== 'undefined';\n    const isMeasurement =\n      typeof this.getData(dataId).annotationGroup !== 'undefined';\n\n    // create layer groups if not done yet\n    // (create all to allow for ratio sync)\n    if (this.#stage.getNumberOfLayerGroups() === 0) {\n      this.#createLayerGroups(this.#options.dataViewConfigs);\n    }\n\n    // use options list if non provided\n    if (typeof viewConfigs === 'undefined') {\n      viewConfigs = this.getViewConfigs(dataId);\n    }\n\n    // nothing to do if no view config\n    if (viewConfigs.length === 0) {\n      logger.info('Not rendering data: ' + dataId +\n        ' (no data view config)');\n      return;\n    }\n\n    // loop on configs\n    for (let i = 0; i < viewConfigs.length; ++i) {\n      const config = viewConfigs[i];\n      const layerGroup =\n        this.#stage.getLayerGroupByDivId(config.divId);\n      // layer group must exist\n      if (!layerGroup) {\n        throw new Error('No layer group for ' + config.divId);\n      }\n      // create layer if needed\n      // warn: needs a loaded DOM\n      if (typeof this.#dataController.get(dataId) !== 'undefined') {\n        if (isImage &&\n          layerGroup.getViewLayersByDataId(dataId).length === 0\n        ) {\n          this.#addViewLayer(dataId, config);\n        } else if (isMeasurement &&\n          layerGroup.getDrawLayersByDataId(dataId).length === 0\n        ) {\n          this.addDrawLayer(dataId, config);\n        }\n      }\n      // draw\n      layerGroup.draw();\n    }\n  }\n\n  /**\n   * Zoom the layers of the active layer group.\n   *\n   * @param {number} step The step to add to the current zoom.\n   * @param {number} cx The zoom center X coordinate.\n   * @param {number} cy The zoom center Y coordinate.\n   */\n  zoom(step, cx, cy) {\n    const layerGroup = this.#stage.getActiveLayerGroup();\n    const viewController = layerGroup.getBaseViewLayer().getViewController();\n    const k = viewController.getCurrentScrollPosition();\n    const center = new Point3D(cx, cy, k);\n    layerGroup.addScale(step, center);\n    layerGroup.draw();\n  }\n\n  /**\n   * Apply a translation to the layers of the active layer group.\n   *\n   * @param {number} tx The translation along X.\n   * @param {number} ty The translation along Y.\n   */\n  translate(tx, ty) {\n    const layerGroup = this.#stage.getActiveLayerGroup();\n    layerGroup.addTranslation({x: tx, y: ty, z: 0});\n    layerGroup.draw();\n  }\n\n  /**\n   * Set the active view layer (of the active layer group) opacity.\n   *\n   * @param {number} alpha The opacity ([0:1] range).\n   * @deprecated Since v0.33, pplease set the opacity\n   *   of the desired view layer directly.\n   */\n  setOpacity(alpha) {\n    const viewLayer = this.#stage.getActiveLayerGroup().getActiveViewLayer();\n    viewLayer.setOpacity(alpha);\n    viewLayer.draw();\n  }\n\n  /**\n   * Set the drawings of the active layer group.\n   *\n   * @deprecated Since v0.34, please switch to DICOM SR annotations.\n   * @param {Array} drawings An array of drawings.\n   * @param {Array} drawingsDetails An array of drawings details.\n   * @param {string} dataId The converted data id.\n   */\n  setDrawings(drawings, drawingsDetails, dataId) {\n    const layerGroup = this.#stage.getActiveLayerGroup();\n    const viewLayer = layerGroup.getBaseViewLayer();\n    const refDataId = viewLayer.getDataId();\n    const viewController = viewLayer.getViewController();\n\n    // convert konva to annotation\n    const annotations = konvaToAnnotation(drawings, drawingsDetails);\n    // create data\n    const data = this.createAnnotationData(refDataId);\n    // add annotations to data\n    for (const annotation of annotations) {\n      annotation.setViewController(viewController);\n      data.annotationGroup.add(annotation);\n    }\n    // add to data controller\n    this.#dataController.add(dataId, data);\n    // render\n    this.render(dataId);\n  }\n\n  /**\n   * Apply a JSON state to this app.\n   *\n   * @deprecated Since v0.34, please switch to DICOM SR\n   *   for annotations.\n   * @param {string} jsonState The state of the app as a JSON string.\n   * @param {string} dataId The state data id.\n   */\n  applyJsonState(jsonState, dataId) {\n    const state = new State(dataId);\n    state.apply(this, state.fromJSON(jsonState));\n  }\n\n  // Handler Methods -----------------------------------------------------------\n\n  /**\n   * Handle resize: fit the display to the window.\n   * To be called once the image is loaded.\n   * Can be connected to a window 'resize' event.\n   *\n   * @function\n   */\n  onResize = () => {\n    this.fitToContainer();\n  };\n\n  /**\n   * Key down callback. Meant to be used in tools.\n   *\n   * @param {KeyboardEvent} event The key down event.\n   * @fires App#keydown\n   * @function\n   */\n  onKeydown = (event) => {\n    /**\n     * Key down event.\n     *\n     * @event App#keydown\n     * @type {KeyboardEvent}\n     * @property {string} type The event type: keydown.\n     * @property {string} context The tool where the event originated.\n     */\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Key down event handler example.\n   * - CRTL-Z: undo,\n   * - CRTL-Y: redo,\n   * - CRTL-ARROW_LEFT: next element on fourth dim,\n   * - CRTL-ARROW_UP: next element on third dim,\n   * - CRTL-ARROW_RIGHT: previous element on fourth dim,\n   * - CRTL-ARROW_DOWN: previous element on third dim.\n   *\n   * Applies to the active view of the active layer group.\n   *\n   * @param {KeyboardEvent} event The key down event.\n   * @fires UndoStack#undo\n   * @fires UndoStack#redo\n   * @function\n   */\n  defaultOnKeydown = (event) => {\n    if (event.ctrlKey) {\n      if (event.shiftKey) {\n        const layerGroup = this.#stage.getActiveLayerGroup();\n        const positionHelper = layerGroup.getPositionHelper();\n        if (event.key === 'ArrowLeft') { // crtl-shift-arrow-left\n          if (layerGroup.moreThanOne(3)) {\n            positionHelper.decrementPosition(3);\n          }\n        } else if (event.key === 'ArrowUp') { // crtl-shift-arrow-up\n          if (layerGroup.canScroll()) {\n            positionHelper.incrementPositionAlongScroll();\n          }\n        } else if (event.key === 'ArrowRight') { // crtl-shift-arrow-right\n          if (layerGroup.moreThanOne(3)) {\n            positionHelper.incrementPosition(3);\n          }\n        } else if (event.key === 'ArrowDown') { // crtl-shift-arrow-down\n          if (layerGroup.canScroll()) {\n            positionHelper.decrementPositionAlongScroll();\n          }\n        }\n      } else if (event.key === 'y') { // crtl-y\n        this.#undoStack.redo();\n      } else if (event.key === 'z') { // crtl-z\n        this.#undoStack.undo();\n      } else if (event.key === ' ') { // crtl-space\n        for (let i = 0; i < this.#stage.getNumberOfLayerGroups(); ++i) {\n          this.#stage.getLayerGroup(i).setShowCrosshair(\n            !this.#stage.getLayerGroup(i).getShowCrosshair()\n          );\n        }\n      }\n    }\n  };\n\n  // Internal members shortcuts-----------------------------------------------\n\n  /**\n   * Reset the display.\n   */\n  resetDisplay() {\n    this.resetLayout();\n    this.initWLDisplay();\n  }\n\n  /**\n   * Reset the app zoom.\n   */\n  resetZoom() {\n    this.resetLayout();\n  }\n\n  /**\n   * Set the colour map of the active view of the active layer group.\n   *\n   * @param {string} name The colour map name.\n   * @deprecated Since v0.33, please use the ViewController\n   *   equivalent directly instead.\n   */\n  setColourMap(name) {\n    const viewController =\n      this.#stage.getActiveLayerGroup()\n        .getActiveViewLayer().getViewController();\n    viewController.setColourMap(name);\n  }\n\n  /**\n   * Set the window/level preset of the active view of the active layer group.\n   *\n   * @param {string} preset The window/level preset.\n   * @deprecated Since v0.33, please use the ViewController\n   *   equivalent directly instead.\n   */\n  setWindowLevelPreset(preset) {\n    const viewController =\n      this.#stage.getActiveLayerGroup()\n        .getActiveViewLayer().getViewController();\n    viewController.setWindowLevelPreset(preset);\n  }\n\n  /**\n   * Set the tool.\n   *\n   * @param {string} tool The tool.\n   */\n  setTool(tool) {\n    // bind tool to active layer\n    for (let i = 0; i < this.#stage.getNumberOfLayerGroups(); ++i) {\n      const layerGroup = this.#stage.getLayerGroup(i);\n      const layer = layerGroup.getActiveLayer();\n      if (typeof layer !== 'undefined') {\n        this.#toolboxController.bindLayerGroup(layerGroup, layer);\n      }\n    }\n    // set toolbox tool\n    this.#toolboxController.setSelectedTool(tool);\n  }\n\n  /**\n   * Set the tool live features.\n   *\n   * @param {object} list The list of features.\n   */\n  setToolFeatures(list) {\n    this.#toolboxController.setToolFeatures(list);\n  }\n\n  /**\n   * Undo the last action.\n   *\n   * @fires UndoStack#undo\n   */\n  undo() {\n    this.#undoStack.undo();\n  }\n\n  /**\n   * Redo the last action.\n   *\n   * @fires UndoStack#redo\n   */\n  redo() {\n    this.#undoStack.redo();\n  }\n\n  /**\n   * Get the undo stack size.\n   *\n   * @returns {number} The size of the stack.\n   */\n  getStackSize() {\n    return this.#undoStack.getStackSize();\n  }\n\n  /**\n   * Get the current undo stack index.\n   *\n   * @returns {number} The stack index.\n   */\n  getCurrentStackIndex() {\n    return this.#undoStack.getCurrentStackIndex();\n  }\n\n  /**\n   * Get the overlay data for a data id.\n   *\n   * @param {string} dataId The data id.\n   * @returns {OverlayData|undefined} The overlay data.\n   */\n  getOverlayData(dataId) {\n    let data;\n    if (typeof this.#overlayDatas !== 'undefined') {\n      data = this.#overlayDatas[dataId];\n    }\n    return data;\n  }\n\n  /**\n   * Toggle overlay listeners.\n   *\n   * @param {string} dataId The data id.\n   */\n  toggleOverlayListeners(dataId) {\n    const data = this.getOverlayData(dataId);\n    if (typeof data !== 'undefined') {\n      if (data.isListening()) {\n        data.removeAppListeners();\n      } else {\n        data.addAppListeners();\n      }\n    }\n  }\n\n  /**\n   * Create new annotation data based on the data of\n   *   the active view layer.\n   *\n   * @param {string} refDataId The reference data id.\n   * @returns {DicomData} The new data.\n   */\n  createAnnotationData(refDataId) {\n    const refData = this.getData(refDataId);\n    const refMeta = refData.image.getMeta();\n\n    const data = new DicomData({});\n    data.annotationGroup = new AnnotationGroup();\n    data.annotationGroup.setMetaValue('Modality', 'SR');\n    data.annotationGroup.setMetaValue(\n      'PatientID', refMeta.PatientID);\n    data.annotationGroup.setMetaValue(\n      'StudyInstanceUID', refMeta.StudyInstanceUID);\n    data.annotationGroup.setMetaValue(\n      'ReferencedSeriesSequence', {\n        value: [{\n          SeriesInstanceUID: refMeta.SeriesInstanceUID\n        }]\n      });\n    return data;\n  }\n\n  /**\n   * Add new data and render it with a simple new data view config.\n   *\n   * @param {DicomData} data The data to add.\n   * @param {string} divId The div where to draw.\n   * @param {string} refDataId The reference data id.\n   */\n  addAndRenderAnnotationData(data, divId, refDataId) {\n    // add new data\n    const dataId = this.addData(data);\n    // add data view config based on reference data\n    const refDataViewConfigs = this.getViewConfigs(refDataId);\n    const refDataViewConfig = refDataViewConfigs.find(\n      element => element.divId === divId);\n    if (typeof refDataViewConfig === 'undefined') {\n      throw new Error('No reference data view config for draw');\n    }\n    const drawDataViewConfig = new ViewConfig(divId);\n    drawDataViewConfig.orientation = refDataViewConfig.orientation;\n    this.addDataViewConfig(dataId, drawDataViewConfig);\n    // render (will create draw layer)\n    this.render(dataId);\n  }\n\n  // Private Methods -----------------------------------------------------------\n\n  /**\n   * Fire an event: call all associated listeners with the input event object.\n   *\n   * @param {object} event The event to fire.\n   */\n  #fireEvent = (event) => {\n    this.#listenerHandler.fireEvent(event);\n  };\n\n  /**\n   * Data load start callback.\n   *\n   * @param {object} event The load start event.\n   */\n  #onloadstart = (event) => {\n    // create overlay data\n    if (typeof this.#options.overlayConfig !== 'undefined') {\n      this.#overlayDatas[event.dataid] = new OverlayData(\n        this, event.dataid, this.#options.overlayConfig);\n    }\n    /**\n     * Load start event.\n     *\n     * @event App#loadstart\n     * @type {object}\n     * @property {string} type The event type: loadstart.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     */\n    event.type = 'loadstart';\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load progress callback.\n   *\n   * @param {object} event The progress event.\n   */\n  #onloadprogress = (event) => {\n    /**\n     * Load progress event.\n     *\n     * @event App#loadprogress\n     * @type {object}\n     * @property {string} type The event type: loadprogress.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     * @property {number} loaded The loaded percentage.\n     * @property {number} total The total percentage.\n     */\n    event.type = 'loadprogress';\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load callback.\n   *\n   * @param {object} event The load event.\n   */\n  #onloaditem = (event) => {\n    // check event\n    if (typeof event.data === 'undefined') {\n      logger.error('Missing loaditem event data.');\n    }\n    if (typeof event.loadtype === 'undefined') {\n      logger.error('Missing loaditem event load type.');\n    }\n\n    const isFirstLoadItem = event.isfirstitem;\n\n    let eventMetaData = null;\n    if (event.loadtype === 'image') {\n      if (isFirstLoadItem) {\n        this.#dataController.add(event.dataid, event.data);\n      } else {\n        this.#dataController.update(event.dataid, event.data);\n      }\n      eventMetaData = event.data.meta;\n    } else if (event.loadtype === 'state') {\n      this.applyJsonState(event.data, event.dataid);\n      eventMetaData = 'state';\n    }\n\n    /**\n     * Load item event: fired when a load item is successfull.\n     *\n     * @event App#loaditem\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     * @property {object} data The loaded meta data.\n     */\n    this.#fireEvent({\n      type: 'loaditem',\n      data: eventMetaData,\n      source: event.source,\n      loadtype: event.loadtype,\n      dataid: event.dataid,\n      isfirstitem: event.isfirstitem,\n      warn: event.warn\n    });\n\n    // update overlay data if present\n    if (typeof this.#overlayDatas !== 'undefined' &&\n      typeof this.#overlayDatas[event.dataid] !== 'undefined') {\n      this.#overlayDatas[event.dataid].addItemMeta(eventMetaData);\n    }\n\n    // render if first and flag allows\n    if (event.loadtype === 'image' &&\n      this.getViewConfigs(event.dataid).length !== 0 &&\n      isFirstLoadItem && this.#options.viewOnFirstLoadItem) {\n      this.render(event.dataid);\n    }\n  };\n\n  /**\n   * Data load callback.\n   *\n   * @param {object} event The load event.\n   */\n  #onload = (event) => {\n    /**\n     * Load event: fired when a load finishes successfully.\n     *\n     * @event App#load\n     * @type {object}\n     * @property {string} type The event type: load.\n     * @property {string} loadType The load type: image or state.\n     */\n    event.type = 'load';\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load end callback.\n   *\n   * @param {object} event The load end event.\n   */\n  #onloadend = (event) => {\n    /**\n     * Main load end event: fired when the load finishes,\n     *   successfully or not.\n     *\n     * @event App#loadend\n     * @type {object}\n     * @property {string} type The event type: loadend.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     */\n    event.type = 'loadend';\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load error callback.\n   *\n   * @param {object} event The error event.\n   */\n  #onloaderror = (event) => {\n    /**\n     * Load error event.\n     *\n     * @event App#error\n     * @type {object}\n     * @property {string} type The event type: error.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     * @property {object} error The error.\n     * @property {object} target The event target.\n     */\n    if (typeof event.type === 'undefined') {\n      event.type = 'error';\n    }\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load timeout callback.\n   *\n   * @param {object} event The timeout event.\n   */\n  #onloadtimeout = (event) => {\n    /**\n     * Load timeout event.\n     *\n     * @event App#timeout\n     * @type {object}\n     * @property {string} type The event type: timeout.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: an url as a string.\n     * @property {object} target The event target.\n     */\n    if (typeof event.type === 'undefined') {\n      event.type = 'timeout';\n    }\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Data load abort callback.\n   *\n   * @param {object} event The abort event.\n   */\n  #onloadabort = (event) => {\n    /**\n     * Load abort event.\n     *\n     * @event App#abort\n     * @type {object}\n     * @property {string} type The event type: abort.\n     * @property {string} loadType The load type: image or state.\n     * @property {*} source The load source: string for an url,\n     *   File for a file.\n     */\n    if (typeof event.type === 'undefined') {\n      event.type = 'abort';\n    }\n    this.#fireEvent(event);\n  };\n\n  /**\n   * Bind layer group events to app.\n   *\n   * @param {LayerGroup} group The layer group.\n   */\n  #bindLayerGroupToApp(group) {\n    // propagate layer group events\n    group.addEventListener('zoomchange', this.#fireEvent);\n    group.addEventListener('offsetchange', this.#fireEvent);\n    // propagate viewLayer events\n    group.addEventListener('renderstart', this.#fireEvent);\n    group.addEventListener('renderend', this.#fireEvent);\n    // propagate view events\n    for (let j = 0; j < viewEventNames.length; ++j) {\n      group.addEventListener(viewEventNames[j], this.#fireEvent);\n    }\n    // propagate drawLayer events\n    if (this.#toolboxController && this.#toolboxController.hasTool('Draw')) {\n      group.addEventListener('drawcreate', this.#fireEvent);\n      group.addEventListener('drawdelete', this.#fireEvent);\n    }\n    // updata data view config\n    group.addEventListener('wlchange', (event) => {\n      const layerDetails = getLayerDetailsFromLayerDivId(event.srclayerid);\n      const groupId = layerDetails.groupDivId;\n      const config = this.getViewConfig(event.dataid, groupId, true);\n      if (typeof config !== 'undefined') {\n        // reset previous values\n        config.windowCenter = undefined;\n        config.windowWidth = undefined;\n        config.wlPresetName = undefined;\n        // window width, center and name\n        if (event.value.length === 3) {\n          config.windowCenter = event.value[0];\n          config.windowWidth = event.value[1];\n          config.wlPresetName = event.value[2];\n        }\n      }\n    });\n    group.addEventListener('opacitychange', (event) => {\n      const layerDetails = getLayerDetailsFromLayerDivId(event.srclayerid);\n      const groupId = layerDetails.groupDivId;\n      const config = this.getViewConfig(event.dataid, groupId, true);\n      if (typeof config !== 'undefined') {\n        config.opacity = event.value[0];\n      }\n    });\n    group.addEventListener('colourmapchange', (event) => {\n      const layerDetails = getLayerDetailsFromLayerDivId(event.srclayerid);\n      const groupId = layerDetails.groupDivId;\n      const config = this.getViewConfig(event.dataid, groupId, true);\n      if (typeof config !== 'undefined') {\n        config.colourMap = event.value[0];\n      }\n    });\n  }\n\n  /**\n   * Add a view layer.\n   *\n   * @param {string} dataId The data id.\n   * @param {ViewConfig} viewConfig The data view config.\n   */\n  #addViewLayer(dataId, viewConfig) {\n    const data = this.#dataController.get(dataId);\n    if (!data) {\n      throw new Error('Cannot initialise layer with missing data, id: ' +\n        dataId);\n    }\n    const layerGroup = this.#stage.getLayerGroupByDivId(viewConfig.divId);\n    if (!layerGroup) {\n      throw new Error('Cannot initialise layer with missing group, id: ' +\n        viewConfig.divId);\n    }\n    const imageGeometry = data.image.getGeometry();\n\n    // un-bind\n    this.#stage.unbindLayerGroups();\n\n    // create and setup view\n    const viewFactory = new ViewFactory();\n    const view = viewFactory.create(data.meta, data.image);\n    const viewOrientation = getViewOrientation(\n      imageGeometry.getOrientation(),\n      getMatrixFromName(viewConfig.orientation)\n    );\n    view.setOrientation(viewOrientation);\n\n    // make pixel of value 0 transparent for segmentation\n    // (assuming RGB data)\n    if (data.image.getMeta().Modality === 'SEG') {\n      view.setAlphaFunction(function (value /*, index*/) {\n        if (value === 0) {\n          return 0;\n        } else {\n          return 0xff;\n        }\n      });\n    }\n\n    // do we have more than one layer\n    // (the layer has not been added to the layer group yet)\n    const isBaseLayer = layerGroup.getNumberOfViewLayers() === 0;\n\n    // opacity\n    let opacity = 1;\n    if (typeof viewConfig.opacity !== 'undefined') {\n      opacity = viewConfig.opacity;\n    } else {\n      if (!isBaseLayer) {\n        opacity = 0.5;\n      }\n    }\n\n    // view layer\n    const viewLayer = layerGroup.addViewLayer();\n    viewLayer.setView(view, dataId);\n    const size2D = imageGeometry.getSize(viewOrientation).get2D();\n    const spacing2D = imageGeometry.getSpacing(viewOrientation).get2D();\n    viewLayer.initialise(size2D, spacing2D, opacity);\n\n    // view controller\n    const viewController = viewLayer.getViewController();\n    // window/level\n    if (typeof viewConfig.wlPresetName !== 'undefined') {\n      viewController.setWindowLevelPreset(viewConfig.wlPresetName);\n    } else if (typeof viewConfig.windowCenter !== 'undefined' &&\n      typeof viewConfig.windowWidth !== 'undefined') {\n      const wl = new WindowLevel(\n        viewConfig.windowCenter, viewConfig.windowWidth);\n      viewController.setWindowLevel(wl);\n    }\n    // colour map\n    if (typeof viewConfig.colourMap !== 'undefined') {\n      viewController.setColourMap(viewConfig.colourMap);\n    } else {\n      if (!isBaseLayer) {\n        if (data.image.getMeta().Modality === 'PT') {\n          viewController.setColourMap('hot');\n        } else {\n          viewController.setColourMap('rainbow');\n        }\n      }\n    }\n\n    // listen to image set\n    this.#dataController.addEventListener(\n      'dataimageset', viewLayer.onimageset);\n\n    // sync layers position\n    const value = [\n      viewController.getCurrentIndex().getValues(),\n      viewController.getCurrentPosition().getValues()\n    ];\n    layerGroup.updateLayersToPositionChange({\n      value: value,\n      srclayerid: viewLayer.getId()\n    });\n\n    // sync layer groups\n    this.#stage.fitToContainer();\n\n    // layer offset (done before scale)\n    viewLayer.setOffset(layerGroup.getOffset());\n\n    // get and apply flip flags\n    const flipFlags = this.#getViewFlipFlags(\n      imageGeometry.getOrientation(),\n      viewConfig.orientation);\n    this.#applyFlipFlags(flipFlags, viewLayer);\n\n    // layer scale (done after possible flip)\n    if (!isBaseLayer) {\n      // use zoom offset of base layer\n      const baseViewLayer = layerGroup.getBaseViewLayer();\n      viewLayer.initScale(\n        layerGroup.getScale(),\n        baseViewLayer.getAbsoluteZoomOffset()\n      );\n    } else {\n      viewLayer.setScale(layerGroup.getScale());\n    }\n\n    // bind\n    this.#stage.bindLayerGroups();\n    if (this.#toolboxController) {\n      this.#toolboxController.bindLayerGroup(layerGroup, viewLayer);\n    }\n\n    /**\n     * Add view layer event.\n     *\n     * @event App#viewlayeradd\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} layerid The layer id.\n     * @property {string} layergroupid The layer group id.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'viewlayeradd',\n      layerid: viewLayer.getId(),\n      layergroupid: layerGroup.getDivId(),\n      dataid: dataId\n    });\n\n    // initialise the toolbox for base\n    if (isBaseLayer) {\n      if (this.#toolboxController) {\n        this.#toolboxController.init();\n      }\n    }\n  }\n\n  /**\n   * Add a draw layer.\n   *\n   * @param {string} dataId The data id.\n   * @param {ViewConfig} viewConfig The data view config.\n   */\n  addDrawLayer(dataId, viewConfig) {\n    const layerGroup = this.#stage.getLayerGroupByDivId(viewConfig.divId);\n    if (!layerGroup) {\n      throw new Error('Cannot initialise layer with missing group, id: ' +\n        viewConfig.divId);\n    }\n\n    // reference is the data of the view layer with the\n    //   same StudyInstanceUID\n    const data = this.#dataController.get(dataId);\n    if (!data) {\n      throw new Error('Cannot initialise layer with missing data, id: ' +\n        dataId);\n    }\n    const refSeriesSeq =\n      data.annotationGroup.getMetaValue('ReferencedSeriesSequence');\n    const refSeriesInstanceUID = refSeriesSeq.value[0].SeriesInstanceUID;\n    const viewLayers = layerGroup.searchViewLayers({\n      SeriesInstanceUID: refSeriesInstanceUID\n    });\n    if (viewLayers.length === 0) {\n      console.warn(\n        'No loaded data that matches the measurement reference series UID');\n      return;\n    }\n    const refViewLayer = viewLayers[0];\n    const refDataId = refViewLayer.getDataId();\n\n    // un-bind\n    this.#stage.unbindLayerGroups();\n\n    // set annotation view controller (allows quantification)\n    const refViewController = refViewLayer.getViewController();\n    data.annotationGroup.setViewController(refViewController);\n\n    // reference data to use as base for layer properties\n    const refData = this.#dataController.get(refDataId);\n    if (!refData) {\n      throw new Error(\n        'Cannot initialise layer without reference data, id: ' +\n        refDataId);\n    }\n    const imageGeometry = refData.image.getGeometry();\n\n    const viewOrientation = getViewOrientation(\n      imageGeometry.getOrientation(),\n      getMatrixFromName(viewConfig.orientation)\n    );\n    const size2D = imageGeometry.getSize(viewOrientation).get2D();\n    const spacing2D = imageGeometry.getSpacing(viewOrientation).get2D();\n\n    const drawLayer = layerGroup.addDrawLayer();\n    drawLayer.initialise(size2D, spacing2D, refViewLayer.getId());\n\n    const planeHelper = new PlaneHelper(\n      imageGeometry,\n      viewOrientation\n    );\n    drawLayer.setPlaneHelper(planeHelper);\n\n    // sync layers position\n    const value = [\n      refViewController.getCurrentIndex().getValues(),\n      refViewController.getCurrentPosition().getValues()\n    ];\n    layerGroup.updateLayersToPositionChange({\n      value: value,\n      srclayerid: drawLayer.getId()\n    });\n\n    // sync layer groups\n    this.#stage.fitToContainer();\n\n    // layer offset (done before scale)\n    drawLayer.setOffset(layerGroup.getOffset());\n\n    // get and apply flip flags\n    const flipFlags = this.#getViewFlipFlags(\n      imageGeometry.getOrientation(),\n      viewConfig.orientation);\n    this.#applyFlipFlags(flipFlags, drawLayer);\n\n    // layer scale (done after possible flip)\n    // use zoom offset of ref layer\n    drawLayer.initScale(\n      layerGroup.getScale(),\n      refViewLayer.getAbsoluteZoomOffset()\n    );\n\n    // add possible existing data\n    drawLayer.setAnnotationGroup(\n      data.annotationGroup,\n      dataId,\n      this.addToUndoStack);\n\n    drawLayer.setCurrentPosition(\n      refViewController.getCurrentPosition(),\n      refViewController.getCurrentIndex()\n    );\n\n    // bind\n    this.#stage.bindLayerGroups();\n    if (this.#toolboxController) {\n      this.#toolboxController.bindLayerGroup(layerGroup, drawLayer);\n    }\n\n    /**\n     * Add draw layer event.\n     *\n     * @event App#drawlayeradd\n     * @type {object}\n     * @property {string} type The event type.\n     * @property {string} layerid The layer id.\n     * @property {string} layergroupid The layer group id.\n     * @property {string} dataid The data id.\n     */\n    this.#fireEvent({\n      type: 'drawlayeradd',\n      layerid: drawLayer.getId(),\n      layergroupid: layerGroup.getDivId(),\n      dataid: dataId\n    });\n  }\n\n  /**\n   * Get the view flip flags: offset (x, y) and scale (x, y, z) flags.\n   *\n   * @param {Matrix33} imageOrientation The image orientation.\n   * @param {string} viewConfigOrientation The view config orientation.\n   * @returns {object} Offset and scale flip flags.\n   */\n  #getViewFlipFlags(imageOrientation, viewConfigOrientation) {\n    // 'simple' orientation code (does not take into account angles)\n    const orientationCode =\n      getOrientationStringLPS(imageOrientation.asOneAndZeros());\n    if (typeof orientationCode === 'undefined') {\n      throw new Error('Unsupported undefined orientation code');\n    }\n\n    // view orientation flags\n    const isViewUndefined = typeof viewConfigOrientation === 'undefined';\n    const isViewAxial = !isViewUndefined &&\n      viewConfigOrientation === Orientation.Axial;\n    const isViewCoronal = !isViewUndefined &&\n      viewConfigOrientation === Orientation.Coronal;\n    const isViewSagittal = !isViewUndefined &&\n      viewConfigOrientation === Orientation.Sagittal;\n\n    // default flags\n    const flipOffset = {\n      x: false,\n      y: false\n    };\n    const flipScale = {\n      x: false,\n      y: false,\n      z: false\n    };\n\n    if (orientationCode === 'LPS') {\n      // axial\n      if (isViewCoronal || isViewSagittal) {\n        flipScale.z = true;\n        flipOffset.y = true;\n      }\n    } else if (orientationCode === 'LAI') {\n      // axial\n      if (isViewUndefined || isViewAxial) {\n        flipOffset.y = true;\n      } else if (isViewCoronal) {\n        flipScale.z = true;\n      } else if (isViewSagittal) {\n        flipScale.z = true;\n        flipOffset.x = true;\n      }\n    } else if (orientationCode === 'RPI') {\n      // axial\n      if (isViewUndefined || isViewAxial) {\n        flipOffset.x = true;\n      } else if (isViewCoronal) {\n        flipScale.z = true;\n        flipOffset.x = true;\n      } else if (isViewSagittal) {\n        flipScale.z = true;\n      }\n    } else if (orientationCode === 'RAS') {\n      // axial\n      flipOffset.x = true;\n      flipOffset.y = true;\n      if (isViewCoronal || isViewSagittal) {\n        flipScale.z = true;\n      }\n    } else if (orientationCode === 'LSA') {\n      // coronal\n      flipOffset.y = true;\n      if (isViewUndefined || isViewCoronal) {\n        flipScale.z = true;\n      } else if (isViewAxial) {\n        flipScale.y = true;\n      } else if (isViewSagittal) {\n        flipOffset.x = true;\n        flipScale.y = true;\n        flipScale.z = true;\n      }\n    // } else if (orientationCode === 'LIP') { // nothing to do\n    } else if (orientationCode === 'RSP') {\n      // coronal\n      if (isViewUndefined || isViewCoronal) {\n        flipOffset.x = true;\n        flipOffset.y = true;\n        flipScale.x = true;\n        flipScale.z = true;\n      } else if (isViewAxial) {\n        flipOffset.x = true;\n        flipScale.x = true;\n      } else if (isViewSagittal) {\n        flipOffset.y = true;\n        flipScale.z = true;\n      }\n    } else if (orientationCode === 'RIA') {\n      // coronal\n      flipOffset.x = true;\n      if (isViewUndefined || isViewCoronal) {\n        flipScale.x = true;\n      } else if (isViewAxial) {\n        flipOffset.y = true;\n        flipScale.x = true;\n        flipScale.y = true;\n      } else if (isViewSagittal) {\n        flipScale.y = true;\n      }\n    } else if (orientationCode === 'PSL') {\n      // sagittal\n      flipScale.z = true;\n      if (isViewUndefined || isViewSagittal) {\n        flipOffset.y = true;\n      } else if (isViewCoronal) {\n        flipOffset.y = true;\n      }\n    } else if (orientationCode === 'PIR') {\n      // sagittal\n      flipScale.z = true;\n      if (isViewAxial || isViewCoronal) {\n        flipOffset.x = true;\n      }\n    } else if (orientationCode === 'ASR') {\n      // sagittal\n      flipOffset.x = true;\n      flipOffset.y = true;\n      if (isViewUndefined || isViewSagittal) {\n        flipScale.z = true;\n      } else if (isViewCoronal) {\n        flipScale.z = true;\n      }\n    } else if (orientationCode === 'AIL') {\n      // sagittal\n      if (isViewUndefined || isViewSagittal) {\n        flipOffset.x = true;\n        flipScale.z = true;\n      } else if (isViewAxial) {\n        flipOffset.y = true;\n      } else if (isViewCoronal) {\n        flipScale.z = true;\n      }\n    } else {\n      logger.warn('Unsupported orientation code: ' +\n        orientationCode + ', display could be incorrect');\n    }\n\n    return {\n      scale: flipScale,\n      offset: flipOffset\n    };\n  }\n\n  #applyFlipFlags(flipFlags, layer) {\n    if (flipFlags.offset.x) {\n      layer.addFlipOffsetX();\n    }\n    if (flipFlags.offset.y) {\n      layer.addFlipOffsetY();\n    }\n    if (flipFlags.scale.x) {\n      layer.flipScaleX();\n    }\n    if (flipFlags.scale.y) {\n      layer.flipScaleY();\n    }\n    if (flipFlags.scale.z) {\n      layer.flipScaleZ();\n    }\n  }\n\n} // class App\n","import {logger} from '../utils/logger';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {MaskSegment} from '../dicom/dicomSegment';\n/* eslint-enable no-unused-vars */\n\n/**\n * Mask segment helper: helps handling the segments list,\n *   but does *NOT* update the associated mask (use special commands\n *   for that such as DeleteSegmentCommand, ChangeSegmentColourCommand...).\n */\nexport class MaskSegmentHelper {\n\n  /**\n   * The associated mask.\n   *\n   * @type {Image}\n   */\n  #mask;\n\n  /**\n   * The segments: array of segment description.\n   *\n   * @type {MaskSegment[]}\n   */\n  #segments;\n\n  /**\n   * @param {Image} mask The associated mask image.\n   */\n  constructor(mask) {\n    this.#mask = mask;\n    // check segments in meta\n    const meta = mask.getMeta();\n    if (typeof meta.custom === 'undefined') {\n      meta.custom = {};\n    }\n    if (typeof meta.custom.segments === 'undefined') {\n      meta.custom.segments = [];\n    }\n    this.#segments = meta.custom.segments;\n  }\n\n  /**\n   * Find the index of a segment in the segments list.\n   *\n   * @param {number} segmentNumber The number to find.\n   * @returns {number} The index in the segments list, -1 if not found.\n   */\n  #findSegmentIndex(segmentNumber) {\n    return this.#segments.findIndex(function (item) {\n      return item.number === segmentNumber;\n    });\n  }\n\n  /**\n   * Check if a segment is part of the segments list.\n   *\n   * @param {number} segmentNumber The segment number.\n   * @returns {boolean} True if the segment is included.\n   */\n  hasSegment(segmentNumber) {\n    return this.#findSegmentIndex(segmentNumber) !== -1;\n  }\n\n  /**\n   * Get the number of segments of the segmentation.\n   *\n   * @returns {number} The number of segments.\n   */\n  getNumberOfSegments() {\n    return this.#segments.length;\n  }\n\n  /**\n   * Check if a segment is present in a mask image.\n   *\n   * @param {number[]} numbers Array of segment numbers.\n   * @returns {boolean[]} Array of boolean set to true\n   *   if the segment is present in the mask.\n   */\n  maskHasSegments(numbers) {\n    // create values using displayValue\n    const values = [];\n    const unknowns = [];\n    for (let i = 0; i < numbers.length; ++i) {\n      const segment = this.getSegment(numbers[i]);\n      if (typeof segment !== 'undefined') {\n        if (typeof segment.displayValue !== 'undefined') {\n          values.push(segment.displayValue);\n        } else {\n          values.push(segment.number);\n        }\n      } else {\n        logger.warn('Unknown segment in maskHasSegments: ' + numbers[i]);\n        unknowns.push(i);\n      }\n    }\n    const res = this.#mask.hasValues(values);\n    // insert unknowns as false in result\n    for (let j = 0; j < unknowns.length; ++j) {\n      res.splice(unknowns[j], 0, false);\n    }\n    return res;\n  }\n\n  /**\n   * Get a segment from the inner segment list.\n   *\n   * @param {number} segmentNumber The segment number.\n   * @returns {MaskSegment|undefined} The segment or undefined if not found.\n   */\n  getSegment(segmentNumber) {\n    let segment;\n    const index = this.#findSegmentIndex(segmentNumber);\n    if (index !== -1) {\n      segment = this.#segments[index];\n    }\n    return segment;\n  }\n\n  /**\n   * Add a segment to the segments list.\n   *\n   * @param {MaskSegment} segment The segment to add.\n   */\n  addSegment(segment) {\n    const index = this.#findSegmentIndex(segment.number);\n    if (index === -1) {\n      this.#segments.push(segment);\n      // update palette colour map\n      if (typeof segment.displayRGBValue !== 'undefined') {\n        this.#mask.updatePaletteColourMap(\n          segment.number, segment.displayRGBValue);\n      }\n    } else {\n      logger.warn(\n        'Not adding segment, it is allready in the segments list: ' +\n          segment.number);\n    }\n  }\n\n  /**\n   * Remove a segment from the segments list.\n   *\n   * @param {number} segmentNumber The segment number.\n   */\n  removeSegment(segmentNumber) {\n    const index = this.#findSegmentIndex(segmentNumber);\n    if (index !== -1) {\n      this.#segments.splice(index, 1);\n    } else {\n      logger.warn(\n        'Cannot remove segment, it is not in the segments list: ' +\n          segmentNumber);\n    }\n  }\n\n  /**\n   * Update a segment of the segments list.\n   *\n   * @param {MaskSegment} segment The segment to update.\n   */\n  updateSegment(segment) {\n    const index = this.#findSegmentIndex(segment.number);\n    if (index !== -1) {\n      this.#segments[index] = segment;\n    } else {\n      logger.warn(\n        'Cannot update segment, it is not in the segments list: ' +\n          segment.number);\n    }\n  }\n\n} // class MaskSegmentHelper\n","import {MaskSegmentHelper} from './maskSegmentHelper';\n\n// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {MaskSegment} from '../dicom/dicomSegment';\n/* eslint-enable no-unused-vars */\n\n/**\n * Delete segment command.\n */\nexport class DeleteSegmentCommand {\n\n  /**\n   * The associated mask.\n   *\n   * @type {Image}\n   */\n  #mask;\n\n  /**\n   * The segment to remove.\n   *\n   * @type {MaskSegment}\n   */\n  #segment;\n\n  /**\n   * Flag to send creation events.\n   *\n   * @type {boolean}\n   */\n  #isSilent;\n\n  /**\n   * List of offsets.\n   *\n   * @type {number[]}\n   */\n  #offsets;\n\n  /**\n   * @param {Image} mask The mask image.\n   * @param {MaskSegment} segment The segment to remove.\n   * @param {boolean} [silent] Whether to send a creation event or not.\n   */\n  constructor(mask, segment, silent) {\n    this.#mask = mask;\n    this.#segment = segment;\n    this.#isSilent = (typeof silent === 'undefined') ? false : silent;\n    // list of offsets with the colour to delete\n    if (typeof segment.displayRGBValue !== 'undefined') {\n      this.#offsets = mask.getOffsets(segment.number);\n    } else {\n      this.#offsets = mask.getOffsets(segment.displayValue);\n    }\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'Delete-segment';\n  }\n\n  /**\n   * Check if a command is valid and can be executed.\n   *\n   * @returns {boolean} True if the command is valid.\n   */\n  isValid() {\n    // check that input segment is still there\n    const segments = this.#mask.getMeta().custom.segments;\n    return segments.some(segmentItem =>\n      segmentItem.number === this.#segment.number\n    );\n  }\n\n  /**\n   * Execute the command.\n   *\n   * @fires DeleteSegmentCommand#masksegmentdelete\n   */\n  execute() {\n    if (this.#offsets.length !== 0) {\n      // remove from image\n      this.#mask.setAtOffsets(this.#offsets, 0);\n    }\n\n    // remove from segments\n    const segHelper = new MaskSegmentHelper(this.#mask);\n    segHelper.removeSegment(this.#segment.number);\n\n    // callback\n    if (!this.#isSilent) {\n      /**\n       * Segment delete event.\n       *\n       * @event DeleteSegmentCommand#masksegmentdelete\n       * @type {object}\n       * @property {number} segmentnumber The segment number.\n       */\n      this.onExecute({\n        type: 'masksegmentdelete',\n        segmentnumber: this.#segment.number\n      });\n    }\n  }\n\n  /**\n   * Undo the command.\n   *\n   * @fires DeleteSegmentCommand#masksegmentredraw\n   */\n  undo() {\n    if (this.#offsets.length !== 0) {\n      // re-draw in image\n      if (typeof this.#segment.displayRGBValue !== 'undefined') {\n        this.#mask.setAtOffsets(this.#offsets, this.#segment.number);\n      } else {\n        this.#mask.setAtOffsets(this.#offsets, this.#segment.displayValue);\n      }\n    }\n    // add back to segments\n    const segHelper = new MaskSegmentHelper(this.#mask);\n    segHelper.addSegment(this.#segment);\n\n    // callback\n    /**\n     * Segment redraw event.\n     *\n     * @event DeleteSegmentCommand#masksegmentredraw\n     * @type {object}\n     * @property {number} segmentnumber The segment number.\n     */\n    this.onUndo({\n      type: 'masksegmentredraw',\n      segmentnumber: this.#segment.number\n    });\n  }\n\n  /**\n   * Handle an execute event.\n   *\n   * @param {object} _event The execute event with type and id.\n   */\n  onExecute(_event) {\n    // default does nothing.\n  }\n\n  /**\n   * Handle an undo event.\n   *\n   * @param {object} _event The undo event with type and id.\n   */\n  onUndo(_event) {\n    // default does nothing.\n  }\n\n} // DeleteSegmentCommand class\n","// doc imports\n/* eslint-disable no-unused-vars */\nimport {Image} from './image';\nimport {MaskSegment} from '../dicom/dicomSegment';\nimport {RGB} from '../utils/colour';\n/* eslint-enable no-unused-vars */\n\n/**\n * Change segment colour command.\n */\nexport class ChangeSegmentColourCommand {\n\n  /**\n   * The associated mask.\n   *\n   * @type {Image}\n   */\n  #mask;\n\n  /**\n   * The segment to modify.\n   *\n   * @type {MaskSegment}\n   */\n  #segment;\n\n  /**\n   * The new segment colour.\n   *\n   * @type {RGB|number}\n   */\n  #newColour;\n\n  /**\n   * The previous segment colour.\n   *\n   * @type {RGB|number}\n   */\n  #previousColour;\n\n  /**\n   * Flag to send creation events.\n   *\n   * @type {boolean}\n   */\n  #isSilent;\n\n  /**\n   * List of offsets.\n   *\n   * @type {number[]}\n   */\n  #offsets;\n\n  /**\n   * @param {Image} mask The mask image.\n   * @param {MaskSegment} segment The segment to modify.\n   * @param {RGB|number} newColour The new segment colour.\n   * @param {boolean} [silent] Whether to send a creation event or not.\n   */\n  constructor(mask, segment, newColour, silent) {\n    this.#mask = mask;\n    this.#segment = segment;\n    this.#newColour = newColour;\n\n    this.#isSilent = (typeof silent === 'undefined') ? false : silent;\n    // list of offsets with the colour to delete\n    if (typeof segment.displayRGBValue !== 'undefined') {\n      this.#previousColour = segment.displayRGBValue;\n    } else {\n      this.#previousColour = segment.displayValue;\n      this.#offsets = mask.getOffsets(this.#previousColour);\n    }\n  }\n\n  /**\n   * Get the command name.\n   *\n   * @returns {string} The command name.\n   */\n  getName() {\n    return 'Change-segment-colour';\n  }\n\n  /**\n   * Check if a command is valid and can be executed.\n   *\n   * @returns {boolean} True if the command is valid.\n   */\n  isValid() {\n    let valid = true;\n    if (typeof this.#offsets !== 'undefined') {\n      valid = this.#offsets.length !== 0;\n    }\n    return valid;\n  }\n\n  /**\n   * Execute the command.\n   *\n   * @fires ChangeSegmentColourCommand#changemasksegmentcolour\n   */\n  execute() {\n    // update segment property\n    if (typeof this.#newColour === 'number') {\n      // remove\n      this.#mask.setAtOffsets(this.#offsets, this.#newColour);\n      // update segment\n      this.#segment.displayValue = this.#newColour;\n    } else {\n      // update palette colour map (sends update event)\n      this.#mask.updatePaletteColourMap(\n        this.#segment.number,\n        this.#newColour\n      );\n      // update segment\n      this.#segment.displayRGBValue = this.#newColour;\n    }\n\n    // callback\n    if (!this.#isSilent) {\n      /**\n       * Segment delete event.\n       *\n       * @event ChangeSegmentColourCommand#changemasksegmentcolour\n       * @type {object}\n       * @property {number} segmentnumber The segment number.\n       */\n      this.onExecute({\n        type: 'changemasksegmentcolour',\n        segmentnumber: this.#segment.number,\n        value: [this.#newColour]\n      });\n    }\n  }\n\n  /**\n   * Undo the command.\n   *\n   * @fires ChangeSegmentColourCommand#changemasksegmentcolour\n   */\n  undo() {\n    // update segment property\n    if (typeof this.#previousColour === 'number') {\n      // update values\n      this.#mask.setAtOffsets(this.#offsets, this.#previousColour);\n      // update segment\n      this.#segment.displayValue = this.#previousColour;\n    } else {\n      // update palette colour map (sends update event)\n      this.#mask.updatePaletteColourMap(\n        this.#segment.number,\n        this.#previousColour\n      );\n      // udpate segment\n      this.#segment.displayRGBValue = this.#previousColour;\n    }\n\n    // callback\n    /**\n     * Segment redraw event.\n     *\n     * @event ChangeSegmentColourCommand#changemasksegmentcolour\n     * @type {object}\n     * @property {number} segmentnumber The segment number.\n     */\n    this.onUndo({\n      type: 'changemasksegmentcolour',\n      segmentnumber: this.#segment.number,\n      value: [this.#previousColour]\n    });\n  }\n\n  /**\n   * Handle an execute event.\n   *\n   * @param {object} _event The execute event with type and id.\n   */\n  onExecute(_event) {\n    // default does nothing.\n  }\n\n  /**\n   * Handle an undo event.\n   *\n   * @param {object} _event The undo event with type and id.\n   */\n  onUndo(_event) {\n    // default does nothing.\n  }\n\n} // ChangeSegmentColourCommand class\n","import {logger} from '../utils/logger';\n\n/**\n * Mask segment view helper: handles hidden segments.\n */\nexport class MaskSegmentViewHelper {\n\n  /**\n   * List of hidden segment numbers.\n   *\n   * @type {number[]}\n   */\n  #hiddenNumbers = [];\n\n  /**\n   * Get the index of a segment in the hidden list.\n   *\n   * @param {number} segmentNumber The segment number.\n   * @returns {number} The index in the array, -1 if not found.\n   */\n  #findHiddenIndex(segmentNumber) {\n    return this.#hiddenNumbers.indexOf(segmentNumber);\n  }\n\n  /**\n   * Check if a segment is in the hidden list.\n   *\n   * @param {number} segmentNumber The segment number.\n   * @returns {boolean} True if the segment is in the list.\n   */\n  isHidden(segmentNumber) {\n    return this.#findHiddenIndex(segmentNumber) !== -1;\n  }\n\n  /**\n   * Add a segment to the hidden list.\n   *\n   * @param {number} segmentNumber The segment number.\n   */\n  addToHidden(segmentNumber) {\n    if (!this.isHidden(segmentNumber)) {\n      this.#hiddenNumbers.push(segmentNumber);\n    } else {\n      logger.warn(\n        'Not hidding segment, it is allready in the hidden list: ' +\n          segmentNumber);\n    }\n  }\n\n  /**\n   * Remove a segment from the hidden list.\n   *\n   * @param {number} segmentNumber The segment number.\n   */\n  removeFromHidden(segmentNumber) {\n    const index = this.#findHiddenIndex(segmentNumber);\n    if (index !== -1) {\n      this.#hiddenNumbers.splice(index, 1);\n    } else {\n      logger.warn(\n        'Cannot remove segment, it is not in the hidden list: ' +\n          segmentNumber);\n    }\n  }\n\n  /**\n   * @callback alphaFn\n   * @param {number|number[]} value The pixel value.\n   * @param {number} index The values' index.\n   * @returns {number} The opacity of the input value.\n   */\n\n  /**\n   * Get the alpha function to apply hidden colors.\n   *\n   * @returns {alphaFn} The corresponding alpha function.\n   */\n  getAlphaFunc() {\n    // create alpha function\n    // (zero is hidden by default)\n    return (value/*, index*/) => {\n      if (!Array.isArray(value) && (\n        value === 0 ||\n        this.#hiddenNumbers.includes(value))) {\n        return 0;\n      }\n      // default\n      return 255;\n    };\n  }\n}","/**\n * Mutable 2D scalar ({x,y}).\n */\nexport class Scalar2D {\n  /**\n   * X value.\n   *\n   * @type {number}\n   */\n  x;\n\n  /**\n   * Y value.\n   *\n   * @type {number}\n   */\n  y;\n}\n\n/**\n * Mutable 3D scalar ({x,y,z}).\n */\nexport class Scalar3D {\n  /**\n   * X value.\n   *\n   * @type {number}\n   */\n  x;\n\n  /**\n   * Y value.\n   *\n   * @type {number}\n   */\n  y;\n\n  /**\n   * Z value.\n   *\n   * @type {number}\n   */\n  z;\n}"],"names":["root","factory","exports","module","require","define","amd","this","__WEBPACK_EXTERNAL_MODULE__944__","__WEBPACK_EXTERNAL_MODULE__324__","__WEBPACK_EXTERNAL_MODULE__654__","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","n","getter","__esModule","d","a","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","r","Symbol","toStringTag","value","Index","constructor","values","Error","length","every","val","isNaN","i","toString","getValues","slice","canCompare","rhs","equals","leni","compare","diffDims","push","add","dim","console","warn","next","previous","getWithNew2D","j","l","lenl","ModalityLut","rsi","bitsStored","isID","Math","pow","Float32Array","apply","getRSI","getLength","getValue","offset","logger","levels","TRACE","DEBUG","INFO","WARN","ERROR","level","trace","msg","debug","info","error","WindowLevel","center","width","VoiLut","wl","getWindowLevel","c","setSignedOffset","WindowLut","modalityLut","isSigned","isDiscrete","size","getVoiLut","getModalityLut","setVoiLut","lut","getSlope","Uint8ClampedArray","floor","buildLut","func","id","invId","lut_range_max","ColourMap","red","green","blue","luts","plain","invPlain","rainbow","hot","third","hot_iron","pet","hot_metal_blue","pet_20step","RGB","g","b","isEqualRgb","c1","c2","labToUintLab","triplet","d65","x","y","z","srgbToCielab","labFunc","res","illuminant","fy","ciexyzToCielab","invGammaFunc","rl","gl","bl","srgbToCiexyz","colourNameToHex","name","dict","Yellow","Red","White","Green","Blue","Lime","Fuchsia","Black","custom","wlPresets","labelTexts","openRoiDialog","getTagTime","getTagPixelUnit","Vector3D","getX","getY","getZ","norm","sqrt","crossProduct","vector3D","dotProduct","isCodirectional","Number","EPSILON","REAL_WORLD_EPSILON","isSimilar","tol","abs","Matrix33","row","col","getInverse","m","m00","m01","m02","m10","m11","m12","m20","m21","m22","a1212","a2012","a0112","det","getMatrixInverse","p","str","multiply","tmp","k","getAbs","multiplyArray3D","array3D","multiplyVector3D","multiplyPoint3D","point3D","Point3D","multiplyIndex3D","index3D","getRowAbsMax","absMax","max","index","indexOf","getColAbsMax","asOneAndZeros","sign","getThirdColMajorDirection","getIdentityMat33","isIdentityMat33","mat33","Point2D","getCentroid","getDistance","point2D","dx","dy","dz","getClosest","pointList","minIndex","minDist","dist","minus","Point","get3D","values0","values1","mergeWith3D","i18n","t","props","split","mm","cm2","degree","startsWith","search","rawPos","pos","substring","endsWith","getFlags","inputStr","flags","regex","match","exec","getFileExtension","filePath","ext","pathSplit","toLowerCase","pop","test","includes","stringToUint8Array","arr","Uint8Array","charCodeAt","precisionRound","number","precision","factor","delta","round","toStringId","dims","arraySortEquals","arr0","arr1","arrayEquals","sort","element","uint8ArrayToString","String","fromCharCode","findInArraySubset","callbackFn","start","end","getFindArrayInArrayCallback","buildMultipart","parts","boundary","lineBreak","partsSize","headers","headerStr","partKeys","keys","header","byteLength","data","trailer","buffer","set","dictionary","addTagsToDictionary","group","tags","tagGroups","vr32bitVL","OB","OD","OF","OL","OV","OW","SQ","SV","UC","UN","UR","UT","UV","ox","is32bitVLVR","vr","vrCharSetString","SH","LO","ST","LT","PN","isCharSetStringVR","vrTypes","AE","AS","AT","CS","DA","DS","DT","FL","FD","IS","SL","SS","TM","UI","UL","US","transferSyntaxes","transferSyntaxKeywords","Tag","getGroup","getElement","getKey","getNameFromDictionary","getGroupName","isWithVR","isPrivate","parseInt","getVrFromDictionary","tagCompareFunction","getTagFromKey","getItemTag","isItemTag","tag","isItemDelimitationItemTag","isSequenceDelimitationItemTag","getPixelDataTag","isPixelDataTag","getTagFromDictionary","tagName","keys0","keys1","foundTag","k0","lenK0","k1","lenK1","DataElement","vl","undefinedLength","startOffset","endOffset","items","safeGet","flipArrayEndianness","array","blen","u8","byteOffset","bpe","BYTES_PER_ELEMENT","DataReader","Int8Array","Int16Array","isNativeLittleEndian","isLittleEndian","DataView","readUint16","getUint16","readInt16","getInt16","readUint32","getUint32","readBigUint64","getBigUint64","readInt32","getInt32","readBigInt64","getBigInt64","readFloat32","getFloat32","readFloat64","getFloat64","readBinaryArray","bitArray","byteArrayLength","bitNumber","bitIndex","readUint8Array","readInt8Array","readUint16Array","Uint16Array","arraySize","readInt16Array","readUint32Array","Uint32Array","readUint64Array","BigUint64Array","readInt32Array","Int32Array","readInt64Array","BigInt64Array","readFloat32Array","readFloat64Array","Float64Array","readHex","toUpperCase","getDwvVersion","hasDicomPrefix","reduce","current","ZWS","DefaultTextDecoder","decode","result","getReverseOrientation","ori","rlabels","L","R","A","P","H","F","rori","isImplicitTransferSyntax","syntax","isBigEndianTransferSyntax","isJpegBaselineTransferSyntax","isJpegLosslessTransferSyntax","isJpeg2000TransferSyntax","isRleTransferSyntax","getTypedArray","bitsAllocated","pixelRepresentation","RangeError","powerOf2","log","getDataElementPrefixByteSize","isImplicit","TagKeys","DicomParser","getDefaultCharacterSet","setDefaultCharacterSet","characterSet","setDecoderCharacterSet","TextDecoder","getDicomElements","reader","implicit","itemData","item","isSeqDelim","isItemDelim","offsetTableVl","untilTag","readTagRes","is32bitVL","concat","isKnownVR","pixItemData","sqEndOffset","vrType","Array","from","stream","lastIndex","trim","cleanString","raw","stri","stri1","sqBitsAllocated","sqPixelRepresentation","dataElement","subElement","elements","parse","metaReader","dataReader","magicword","metaEnd","tsElement","firstDataElement","oEightGroupLittleEndian","vr0","vr1","guessTransferSyntax","isReadSupportedTransferSyntax","getTransferSyntaxName","reachedUntilTag","charSetTerm","label","getUtfLabel","numberOfFrames","pixItems","nItemPerFrame","newPixItems","f","newBuffer","fragOffset","ListenerHandler","type","callback","remove","nFound","splice","fireEvent","event","stack","range","dataAccessor","maxIter","increment","blockMaxIter","blockIncrement","reverse1","reverse2","nextIndex","finalBlockIncrement","mainCount","blockCount","done","getIteratorValues","iterator","ival","getSliceIterator","image","isRescaled","viewOrientation","getGeometry","getSize","dirMax2Index","posValues","posStart","map","indexToOffset","getRescaledValueAtOffset","getValueAtOffset","ncols","nrows","nslices","sliceSize","getDimSize","ncomp","getNumberOfComponents","isPlanar","getPlanarConfiguration","getRange","iters","r0","r1","r2","range3d","rangeObj","dirMax0","dirMax2","simpleRange","componentIncrement","nextIndex1","nextIndex2","simpleRange3d","valueRange","nextValueIndex","RescaleSlopeAndIntercept","slope","intercept","getIntercept","Size","moreThanOne","dimension","canScroll3D","canScroll","getTotalSize","isInBounds","dirs","offsetToIndex","off","dimSize","get2D","Statistics","min","mean","stdDev","median","p25","p75","getStats","includesFullStatsFlags","stats","getBasicStats","getPercentile","getFullStats","sum","sumSqr","variance","ratio","i0","v0","guid","random","NumberRange","Spacing","Geometry","origins","spacing","orientation","time","getInitialTime","getCurrentTotalNumberOfSlices","count","hasSlicesAtTime","getCurrentNumberOfSlicesBeforeTime","getOrigin","getOrigins","includesOrigin","getOrientedArray3D","geoSliceSpacing","spacings","origin1","origin2","sliceSpacing","getSliceGeometrySpacing","getSpacing","orientedValues","getRealSpacing","getOrientation","getSliceIndex","point","localOrigins","closestOriginIndex","closestOrigin","pointDir","appendOrigin","origin","equalToOrigin","find","appendFrame","sizeValues","spacingValues","isIndexInBounds","worldToIndex","nDims","minValues","fill","maxIndex","indexToWorld","orientedPoint3D","pointToWorld","worldToPoint","getDeOrientedArray3D","padZeroTwoDigit","getDate","daValue","monthBeginIndex","dayBeginIndex","year","monthIndex","day","getTime","tmValue","tmHours","tmMinutes","tmSeconds","tmFracSecondsStr","hours","minutes","seconds","milliseconds","dateToDateObj","date","getFullYear","getMonth","dateToTimeObj","getHours","getMinutes","getSeconds","getDicomDate","dateObj","getDicomTime","getCoronalMat33","Orientation","Axial","Coronal","Sagittal","getMatrixFromName","matrix","getOrientationStringLPS","v1","v2","getVectorStringLPS","vector","orientationX","orientationY","orientationZ","threshold","getOrientationName","cosines","orientMatrix","getOrientationFromCosines","code","orientStr","getLPSGroup","orientationMatrix","rowCosines","colCosines","normal","getViewOrientation","imageOrientation","targetOrientation","getImage2DSize","rows","columns","getSpacingFromMeasure","dataElements","pixelSpacing","parseFloat","isMonochrome","photometricInterpretation","checkTag","warning","ImageFactory","getWarning","checkElements","modality","syntaxElement","spp","samplesPerPixel","photo","jpeg2000","jpegBase","jpegLoss","getPhotometricInterpretation","SOPClassUID","getSopClassUid","isSecondatyCapture","suvFactor","patWeight","patWeightEl","weight","decayedDose","seriesDateObj","totalDose","halfLife","radioStart","radioInfoSq","totalDoseStr","totalDoseEl","dose","halfLifeStr","halfLifeEl","hl","radioStartDateTimeEl","radioStartDateObj","radioStartTimeObj","radioStartDateTime","dtValue","dateDataElement","dtDate","timeDataElement","getDateTime","Date","seriesTimeObj","scanStart","acqDateEl","acqTimeEl","acqDateObj","acqTimeObj","acqDate","frameRefTime","frameRefTimeElStr","frameRefTimeEl","actualFrameDuration","actualFrameDurationElStr","actualFrameDurationEl","decayConstant","decayDuringFrame","offsetSeconds","exp","decayTime","getDecayedDose","getSuvFactor","create","pixelBuffer","numberOfFiles","size2D","numberOfFramesEl","rowSpacing","columnSpacing","getPixelSpacing","imagePositionPatient","slicePosition","imageOrientationPatient","getOrientationMatrix","geometry","sopInstanceUid","siu","bufferSize","Image","setPhotometricInterpretation","planarConfiguration","setPlanarConfiguration","rescaleSlope","rescaleIntercept","meta","Modality","isPetWithSuv","intensityFactor","setRescaleSlopeAndIntercept","safeGetLocal","TransferSyntaxUID","MediaStorageSOPClassUID","ImageType","SamplesPerPixel","PhotometricInterpretation","PixelRepresentation","BitsAllocated","BitsStored","HighBit","StudyDate","StudyTime","StudyInstanceUID","StudyID","SeriesInstanceUID","SeriesNumber","ReferringPhysicianName","PatientName","PatientID","PatientBirthDate","PatientSex","Manufacturer","ManufacturerModelName","DeviceSerialNumber","SoftwareVersions","ImageOrientationPatient","FrameOfReferenceUID","IsSigned","pixelUnit","unit","defaultGetTagPixelUnit","windowPresets","windowCenter","windowWidth","windowCWExplanation","redLutElement","greenLutElement","blueLutElement","redLut","greenLut","blueLut","descriptor","doScale","descSize","vlSize","scaleTo8","clone","setPaletteColourMap","recommendedDisplayFrameRate","RecommendedDisplayFrameRate","setMeta","DataWriter","writeUint8","setUint8","writeInt8","setInt8","writeUint16","setUint16","writeInt16","setInt16","writeUint32","setUint32","writeUint64","setBigUint64","writeInt32","setInt32","writeInt64","setBigInt64","writeFloat32","setFloat32","writeFloat64","setFloat64","writeHex","writeBinaryArray","byte","len","writeUint8Array","writeInt8Array","writeUint16Array","writeInt16Array","writeUint32Array","writeUint64Array","writeInt32Array","writeInt64Array","writeFloat32Array","writeFloat64Array","_uidCount","WriterRule","action","writerActions","copy","clear","replace","getUID","prefix","getDwvUIDPrefix","uid","datePart","toISOString","countPart","nonTagLength","tagNumber","isEven","isStringVr","uint8ArrayPush","newArr","DefaultTextEncoder","encode","DicomWriter","default","setUseUnVrForPrivateSq","flag","setFixUnknownVR","setRules","rules","addMissingTags","rule","tagKey","isKey","useSpecialTextEncoder","TextEncoder","getElementToWrite","groupName","writer","itemTag","subItem","itemElement","itemDelimElement","hexString","hexString1","hexString2","atValue","diff","message","finalValue","initialArray","initialArrayLength","arrayLength","flattenendArrayLength","flattenedArray","indexFlattenedArray","flattenArrayOfTypedArrays","isTagWithVR","undefinedLengthSequence","undefinedLengthItem","seqDelimElement","getBuffer","isBigEndian","oldscs","totalSize","localSize","metaElements","rawElements","metaLength","fmiglTag","fmivTag","icUIDTag","ivnTag","missingTags","originalElement","checkAndFixUnknownVR","fmiv","getDataElement","fmivSize","icUID","icUIDSize","icUIDValue","ivn","ivnSize","ivnValue","elemSortFunc","fmigl","fmiglSize","ArrayBuffer","metaWriter","dataWriter","lenj","metaOffset","lenk","newItems","oldItemElements","newItemElements","subSize","itemKeys","itemKey","padStr","pad","getVrPad","join","padOBValue","isTypedArrayVr","isArray","itemPrefixSize","getBpeForVrType","dictVr","getUint8ToVrValue","getElementsFromJSONTags","simpleTags","simpleTag","CodeValue","CodingSchemeDesignator","CodeMeaning","LongCodeValue","URNCodeValue","DicomCode","meaning","longValue","urnValue","schemeDesignator","isEqualCode","code1","code2","getCode","getDicomCodeItem","DcmCodes","SctCodes","UcumCodes","deg","getDicomCode","scheme","getMeasurementGroupCode","getReferenceGeometryCode","getSourceImageCode","getTrackingIdentifierCode","getShortLabelCode","getReferencePointsCode","getColourCode","QuantificationName2DictItem","angle","surface","height","radius","stddev","getQuantificationName","propKey","QuantificationUnit2UcumKey","HU","MGML","ED","PCT","CNTS","NONE","CM2","CM2ML","PCNT","CPS","BQML","MGMINML","UMOLMINML","MLMING","MLG","UMOLML","PROPCNTS","PROPCPS","MLMINML","MLML","GML","SUV","getQuantificationUnit","ucumKey","MaskSegment","algorithmType","algorithmName","displayValue","displayRGBValue","propertyTypeCode","propertyCategoryCode","trackingUid","trackingId","getSegment","segment","cielabElement","rgb","gammaFunc","ciexyzToSrgb","invLabFunc","l0","cielabToCiexyz","cielabToSrgb","getDicomSegmentItem","algoType","segmentItem","SegmentNumber","SegmentLabel","SegmentAlgorithmType","SegmentAlgorithmName","cieLab","RecommendedDisplayCIELabValue","RecommendedDisplayGrayscaleValue","SegmentedPropertyCategoryCodeSequence","SegmentedPropertyTypeCodeSequence","TrackingID","TrackingUID","DicomSegmentFrameInfo","dimIndex","imagePosPat","derivationImages","refSegmentNumber","getSegmentFrameInfo","derivationImageSq","sourceImages","sourceImageSq","sourceImage","referencedSOPClassUID","referencedSOPInstanceUID","segmentIdSq","frameInfo","framePlaneOrientationSeq","frameImageOrientation","framePixelMeasuresSeq","frameSpacing","getDicomSegmentFrameInfoItem","FrameContentSequence","DimensionIndexValues","PlanePositionSequence","ImagePositionPatient","SegmentIdentificationSequence","ReferencedSegmentNumber","sourceImgPurposeOfReferenceCode","segDerivationCode","derivationImageItems","derivationImage","PurposeOfReferenceCodeSequence","ReferencedSOPClassUID","ReferencedSOPInstanceUID","DerivationCodeSequence","SourceImageSequence","DerivationImageSequence","equalPosPat","pos1","pos2","JSON","stringify","tagDefinition","tagValue","enum","createRoiSliceBuffers","segments","sliceOffset","buffers","inputOffset","pixelValue","segmentIndex","RequiredDicomSegTags","getDefaultDicomSegJson","reqTag","MaskFactory","_dicomElements","frames","framesElem","orgSq","orgUID","indices","indexSqElem","indexSq","indexPointer","indexOrg","DimensionOrganizationUID","DimensionIndexPointer","DimensionDescriptionLabel","organizations","getDimensionOrganization","segSequence","paletteColourMap","hasDisplayRGBValue","sharedFunctionalGroupsSeq","funcGroup0","planeOrientationSeq","pixelMeasuresSeq","includesPosPat","some","arrVal","findIndexPosPat","findIndex","perFrameFuncGroupSequence","frameInfos","framePosPats","ii","invOrientation","p1","p2","getComparePosPat","point3DFromArray","frameOrigins","tmpGeometry","isAboveEpsilon","posPats","sliceIndex","frameOrigin","distPrevious","numberOfSlices","uids","getFindSegmentFunc","frameOffset","frameSegment","SeriesDate","SeriesTime","DimensionOrganizationSequence","DimensionIndexSequence","SOPInstanceUID","frameOfReferenceUID","lossyImageCompression","LossyImageCompression","toDicom","extraTags","getMeta","Rows","Columns","now","ContentDate","ContentTime","segmentItems","SegmentSequence","SharedFunctionalGroupsSequence","PlaneOrientationSequence","PixelMeasuresSequence","SpacingBetweenSlices","PixelSpacing","roiBuffers","key0","createRoiBuffers","finalBuffers","referencedSOPs","number40","number4","key1","posPat","posPatArray","sourceIndex","getImageUid","NumberOfFrames","frameInfosTag","PerFrameFunctionalGroupsSequence","refSeriesTag","ReferencedInstanceSequence","ReferencedSeriesSequence","tags1","tags2","keys2","tagName2","mergeTags","dicomElements","pixVl","de","createImage","createMaskImage","imageUids","getSecondaryOffset","getOriginForImageUid","uidIndex","includesImageUid","containsImageUids","itemArr1","arrayContains","canQuantify","canWindowLevel","nFiles","getRescaleSlopeAndIntercept","isConstantRSI","inRsi","isIdentityRSI","interp","getPaletteColourMap","updatePaletteColourMap","colour","config","getOffsets","bufferValue","offsets","equal","hasValues","finalValues","equalFunc","getEqualCallback","valuesToFind","indicesToRemove","v","clonedBuffer","tmpBuffer","appendSlice","rhsSize","rhsRange","getDataRange","rhsResRange","getRescaledDataRange","resRange","timeId","isNewFrame","volumeGeometry","sliceGeometry","fullBufferSize","fullSliceIndex","indexOffset","maxOffset","subarray","numberOfImages","rhsPresets","pkey","rhsPreset","windowPreset","perslice","appendFrameBuffer","frameBuffer","frameIndex","frameSize","calculateDataRange","calculateRescaledDataRange","getHistogram","calculateHistogram","dataRange","rescaledDataRange","histogram","addEventListener","removeEventListener","setAtOffsets","setAtOffsetsAndGetOriginals","offsetsLists","originalValuesLists","previousValue","originalValues","currentValue","setAtOffsetsWithIterator","isValueArray","getValueAtIndex","getRescaledValue","getRescaledValueAtIndex","resmin","resmax","rmin","rmax","rvalue","histo","convolute2D","weights","newImage","imgSize","dimOffset","convoluteBuffer","componentOffset","wOff","wOff00","wOff0x","wOff0n","wOffx0","wOffxn","wOffn0","wOffnx","wOffnn","pixelOffset","newValue","wOffFinal","wi","transform","operator","compose","defaultWlPresets","CT","mediastinum","lung","bone","brain","head","ViewFactory","view","View","setColourMap","minmax","preset","setWindowPresets","init","viewEventNames","createView","getCurrentIndex","setCurrentIndex","getImage","setImage","inImage","setOrientation","setInitialIndex","getPlaybackMilliseconds","_value","_index","getAlphaFunction","setAlphaFunction","currentIndex","sliceWl","setWindowLevel","setWindowLevelPresetById","voiLut","voiLutWl","getWindowPresets","getWindowPresetsNames","presets","addWindowPresets","getCurrentWindowPresetName","getColourMap","getCurrentPosition","position","getCurrentImageUid","isPositionInBounds","getScrollDimIndex","originIndex","silent","setCurrentPosition","valid","minLen","maxLen","posEvent","imageUid","pixValue","isNewWl","isNewName","manual","wc","ww","skipGenerate","setWindowLevelPreset","getWindowLevelMinMax","setWindowLevelMinMax","generateImageData","photoInterpretation","alphaFunc","windowLut","colourMap","pxValue","generateImageDataMonochrome","is16BitsStored","to8","generateImageDataPaletteColor","generateImageDataRgb","cb","cr","generateImageDataYbrFull","isAquisitionOrientation","PlaneHelper","imageGeometry","getTargetOrientation","getOffset3DFromPlaneOffset","offset2D","planeOffset","getTargetDeOrientedVector3D","getPlaneOffsetFromOffset3D","offset3D","getTargetOrientedVector3D","planeVector","getTargetDeOrientedPoint3D","planePoint","getImageOrientedVector3D","getImageOrientedPoint3D","getImageDeOrientedVector3D","getImageDeOrientedPoint3D","getPositionFromPlanePoint","getPlanePointFromPosition","getCosines","getPlanePoints","snapPosition","planeOrigin","imageOrigin","pValues","iValues","scrollDimIndex","getNativeScrollDimIndex","getTargetOrientedPositiveXYZ","ViewPositionAccessor","PositionHelper","getMaximumDimValue","getMaximumScrollValue","getCurrentPositionDimValue","getCurrentPositionScrollValue","getCurrentPositionAtDimValue","getCurrentPositionAtScrollValue","setCurrentPositionSafe","merge","geometry1","geometry2","minByIndex","array1","array2","newSize","newSpacing","range1","range2","newOrigins","mergeGeometries","getIncrementPosition","getDecrementPosition","previousIndex","incrementPosition","decrementPosition","incrementPositionAlongScroll","decrementPositionAlongScroll","ViewController","getPlaneHelper","isMask","initialise","getModality","getWindowLevelPresetsNames","addWindowLevelPresets","isPlaying","getPositionHelper","getCurrentOrientedIndex","getCurrentIndexScrollValue","getCurrentScrollPosition","img","get2DSpacing","getRescaledImageValue","getPixelUnit","sliceValues","sliceOrigin","getImageRegionValues","imageIndex","rescaled","iter","rangeNumberOfColumns","regionSize","regionOffset","regionElementCount","rangeRegion","getRegionSliceIterator","getImageVariableRegionValues","regions","offsetRegions","region","regionIndex","regionCount","rangeRegions","getVariableRegionSliceIterator","canQuantifyImage","getImageSize","getImageWorldSize","getImageRescaledDataRange","equalImageMeta","imageMeta","metaKeys","metaKey","getPlanePositionFromPosition","getIndexFromPosition","getPlanePositionFromPlanePoint","play","window","setInterval","canDoMore","stop","clearInterval","setViewAlphaFunction","bindImageAndLayer","viewLayer","onimagecontentchange","onimagegeometrychange","unbindImageAndLayer","InteractionEventNames","getTouchesPositions","touches","offsetLeft","offsetTop","target","offsetParent","positions","pageX","pageY","getTouchPoints","targetTouches","changedTouches","getMousePoint","offsetX","offsetY","canCreateCanvas","testCvs","document","createElement","cropCvs","testCtx","getContext","cropCtx","fillRect","drawImage","getImageData","ViewLayer","containerDiv","className","getDataId","getScale","getAbsoluteZoomOffset","setImageSmoothing","setView","dataId","bindImage","getViewController","onimageset","dataid","unbindImage","draw","vcSize","origin0","scrollOffset","setBaseOffset","getId","removeFromDOM","getBaseSize","getOpacity","setOpacity","alpha","addFlipOffsetX","addFlipOffsetY","flipScaleX","flipScaleY","flipScaleZ","setScale","newScale","helper","orientedNewScale","finalNewScale","resetOffset","worldCenter","newOffset","getScaledOffset","newZoomOffset","initScale","absoluteZoomOffset","layerGroupOrigin","layerGroupOrigin0","needsUpdate","setOffset","planeNewOffset","displayToPlaneIndex","planePos","displayToPlanePos","displayToPlaneScale","deScaled","planePosToDisplay","posX","posY","displayToMainPlanePos","display","style","isVisible","layerid","globalAlpha","setTransform","imageSmoothingEnabled","appendChild","alert","clearRect","createImageData","fitToContainer","containerSize","divToWorldSizeRatio","fitOffset","needsDraw","divToImageSizeRatio","newViewOffset","scaledImageSize","newFlipOffset","bindInteraction","pointerEvents","names","eventName","passive","unbindInteraction","srclayerid","putImageData","dims3D","indexScrollDimIndex","filter","save","restore","ScrollSum","getSum","wheelDeltaY","deltaY","getSpinY","isTick","ScrollWheel","app","wheel","up","preventDefault","layerDetails","getLayerDetailsFromEvent","layerGroup","getLayerGroupByDivId","groupDivId","positionHelper","Line","begin","getBegin","getEnd","getDeltaX","getDeltaY","getWorldLength","spacing2D","wlen","dxs","dys","getMidpoint","getInclination","atan2","PI","quantify","viewController","quant","getAngle","line0","line1","dx0","dy0","dx1","dy1","dot","areOrthogonal","getPerpendicularLine","line","perpSlope","getLineFromEquation","getPerpendicularLineAtDistance","distance","lineFromEq","startPoint","minX","maxX","minY","maxY","isPointInLineRange","beginX","beginY","endX","endY","sx2","sy2","AddAnnotationCommand","annotation","drawController","getName","execute","addAnnotation","undo","removeAnnotation","RemoveAnnotationCommand","UpdateAnnotationCommand","originaProps","newProps","updateAnnotation","Style","getFontFamily","getFontSize","getStrokeWidth","getTextColour","getLineColour","setLineColour","setBaseScale","scale","setZoomScale","getBaseScale","getZoomScale","applyZoomScale","applyZoomRatio","getShadowOffset","getTagOpacity","getTextPadding","getFontStr","getLineHeight","getScaledFontSize","getScaledStrokeWidth","getShadowLineColour","hexColour","hexStr","defaultLabelTexts","arrow","circle","ellipse","protractor","rectangle","roi","ruler","isNodeNameLabel","node","isNodeNameShape","isPositionNode","getLineShape","kshape","getChildren","Konva","getAnchorShape","isNodeWithId","getDefaultAnchor","absRadius","stroke","strokeWidth","strokeScaleEnabled","radiusX","radiusY","dragOnTop","draggable","visible","getAnchorIndex","DrawShapeEditor","eventCallback","setShape","inshape","drawLayer","getFactory","getShape","getAnnotation","isActive","enable","getLayer","disable","reset","resetAnchors","getParent","forEach","anchor","setAnchorsActive","anchors","getAnchors","getStyle","originalProps","on","cancelBubble","mathShape","referencePoints","stageSize","changed","boundNodePosition","validateAnchorPosition","constrainAnchorMove","updateAnnotationOnAnchorMove","updateShapeGroupOnAnchorMove","command","getDrawController","addToUndoStack","moveToTop","DrawTrash","createTrashIcon","trashLine1","points","trashLine2","activate","stage","getKonvaStage","konvaLayer","getKonvaLayer","invscale","changeChildrenColourOnTrashHover","eventPosition","shapeGroup","originalShapeColour","isOverTrash","changeGroupChildrenColour","tshape","trashHalfWidth","scaleX","trashHalfHeight","scaleY","DrawShapeHandler","setEditorShape","shape","isAnnotationGroupEditable","getEditorShapeGroup","getEditorAnnotation","disableAndResetEditor","storeMouseOverCursor","cursor","body","opacity","onMouseOutShapeGroup","addShapeGroupListeners","originalTextExpr","textExpr","onSaveCallback","newTextExpr","prompt","defaultOpenRoiDialog","dragStartPos","previousPos","getShapePositionRange","boundRect","getClientRect","relativeTo","isShapeInRange","children","labelWithDefaultPosition","labelPosition","child","move","updateAnnotationOnTranslation","updateLabelContent","updateConnector","mousePoint","evt","eventPos","translation","originalLabelPosition","newLabelPosition","removeShapeListeners","ROI","getPoint","getPoints","addPoint","addPoints","cx","cy","pi","pi1","ai","a1","Path","inputPointArray","inputControlPointIndexArray","pointArray","controlPointIndexArray","isControlPoint","addControlPoint","newPointArray","appenPath","other","oldSize","indexArray","BucketQueue","bits","cost_functor","bucketCount","mask","loc","cost","buckets","buildArray","bucket","getBucket","ret","isEmpty","__twothirdpi","gradUnitVector","gradX","gradY","px","py","out","oy","gvm","Scissors","curPoint","searchGranBits","searchGran","pointsPerPost","greyscale","laplace","gradient","parents","working","trained","trainingPoints","edgeWidth","trainingLength","edgeGran","edgeTraining","gradPointsNeeded","gradGran","gradTraining","insideGran","insideTraining","outsideGran","outsideTraining","getTrainingIdx","granularity","getTrainedEdge","edge","getTrainedGrad","grad","getTrainedInside","inside","getTrainedOutside","outside","setWorking","setDimensions","setData","gradMagnitude","lap","computeGreyscale","computeLaplace","computeGradient","computeGradX","computeGradY","sides","guv","ix","iy","computeSides","findTrainingPoints","resetTraining","doTraining","calculateTraining","addInStaticGrad","input","output","maxVal","idx","gaussianBlur","have","need","gradDirection","qx","qy","__dgpuv","__gdquv","dp","dq","SQRT1_2","acos","dir","adj","list","sx","sy","ex","ey","setPoint","sp","visited","MAX_VALUE","pq","doWork","timeout","pointCount","newPoints","adjList","q","pqCost","LabelFactory","positionGetter","getPosition","ktext","fontSize","fontFamily","padding","shadowColor","shadowOffset","labelText","getText","setText","zoomScale","labelScale","klabel","updatePosition","getLabelAnchorsPosition","lx","ly","getClosestPoints","points1","points2","point1","point2","getConnector","connectorsPos","labelAnchorsPos","anchorPoints","dash","kconnect","updateContent","text","Circle","centre","getCenter","getRadius","getSurface","getWorldSurface","mulABC","getRound","centerX","centerY","rSquare","transX","quantif","Ellipse","getA","getB","radiusRatio","rySquare","getEllipseIndices","centerValues","radiusI","radiusJ","radiusJ2","di","dj","jmax","jmin","imax","imin","Protractor","_viewController","_flags","Rectangle","getRealWidth","getRealHeight","getWidth","getHeight","getRectangleIndices","sizeI","halfSizeI","sizeJ","halfSizeJ","ThresholdFilter","getMin","setMin","getMax","setMax","setOriginalImage","getOriginalImage","update","imageMin","SharpenFilter","SobelFilter","RunFilterCommand","render","onExecute","onUndo","_event","toolList","toolOptions","defaultToolList","divId","getActiveViewLayer","diffX","diffY","pixelToIntensity","WindowLevelValues","mousedown","mousemove","mouseup","mouseout","touchstart","touchPoints","touchmove","touchend","dblclick","getData","keydown","context","onKeydown","_bool","setFeatures","_features","Scroll","getActiveDrawLayer","getViewLayerById","getReferenceLayerId","yMove","xMove","setTimeout","clearTimeout","showTooltip","removeTooltipDiv","features","displayTooltip","ZoomAndPan","tx","ty","addTranslation","#twoTouchUpdate","lineRatio","zoom","addScale","step","Opacity","layer","getActiveLayer","op","Draw","refDataId","seriesInstanceUID","createAnnotationData","addAndRenderAnnotationData","setShapeHandler","setActiveLayerByDataId","getAnnotationGroup","isEditable","getIntersection","selectedShape","annotationid","getNPoints","timer","getTimeout","getActiveLayerGroup","destroy","tmpPoints","colours","drawLayerId","layerId","Annotation","groupColour","getColour","setAnnotationMathShape","createShapeGroup","setLabelVisibility","listening","finalPoints","activateCurrentPositionShapes","drawLayers","getDrawLayers","setOptions","options","getOptionsType","autoShapeColour","shapeColour","shapeName","hasShape","mouseOverCursor","withScroll","blacklist","getEventNames","listener","Filter","bool","getSelectedFilter","filterName","hasFilter","run","args","runArgs","getFilterList","Floodfill","setExtend","getExtend","#getIndex","simple","bytes","MagicWand","cs","icsl","newMathShape","originalMathShape","extend","ini","imageSize","jl","onThresholdChange","getAbsoluteScale","movedpoint","Livewire","pn","p0","results","_p","_q","defaultToolOptions","ArrowFactory","supports","setTextExpr","updateQuantification","extras","extra","_anchor","kline","pointBegin","pointEnd","endPoint","newBegin","newEnd","_style","linePerp0","linePerp1","hitFunc","beginPath","moveTo","lineTo","closePath","fillStrokeShape","perpLine","closed","ktriangle","_annotation","_group","CircleFactory","left","right","bottom","top","anchorPoint","newRadius","newCenter","swapX","swapY","kshadow","pixelLine","EllipseFactory","ProtractorFactory","mid","pointMid","newPointList","inclination","innerRadius","outerRadius","rotation","midX","midY","karc","arcPos","RectangleFactory","topLeft","bottomRight","pointTopLeft","pointBottomRight","krect","topRight","bottomLeft","rWidth","rHeight","RoiFactory","kroi","newPoint","RulerFactory","ktick0","ktick1","Threshold","Sobel","Sharpen","referenceSopUID","quantification","planePoints","isCompatibleView","planeHelper","cosine1","cosine2","setViewController","originPoint","valueObj","valueStr","toPrecision","replaceFlags","fac","factoryName","AnnotationGroup","getList","setEditable","setColour","propKeys","hasMeta","getMetaValue","setMetaValue","DrawController","setAnnotationGroupEditable","removeAnnotationWithCommand","exeCallback","updateAnnotationWithCommand","removeAllAnnotationsWithCommand","hasAnnotationMeta","setAnnotationMeta","DrawLayer","handler","getLayers","setPlaneHelper","refLayerId","container","getContent","setAttribute","setAnnotationGroup","annotationGroup","allPosGroups","posGroup","shapeGroups","posGroupId","layerChildren","posChildren","isAnnotationVisible","setAnnotationVisibility","setLabelsVisibility","posGroups","connector","deleteDraw","_id","_exeCallback","deleteDraws","getNumberOfDraws","findOne","ratioX","ratioY","labels","getLayerDetailsFromLayerDivId","idString","layerIndex","layerDiv","closest","indexCenter","LayerGroup","getShowCrosshair","setShowCrosshair","getDivId","getAddedScale","getOffset","getNumberOfLayers","getViewLayers","someViewLayer","hasOne","getNumberOfViewLayers","activeLayer","getBaseViewLayer","baseLayer","layers","getViewLayersByDataId","searchViewLayers","getViewDataIndices","getDrawLayerById","getDrawLayersByDataId","setActiveLayer","addViewLayer","viewLayerIndex","div","append","addDrawLayer","updateLayersToPositionChange","empty","getElementsByClassName","removeLayersByDataId","removeLayer","displayPos","lineH","offsetWidth","lineV","offsetHeight","span","createTextNode","viewLayerOffsets","baseViewLayerOrigin0","baseViewLayerOrigin","hasSetOffset","vc","scrollDiff","planeDiff","scroll","plane","refOffsets","hasSetPos","getDivToWorldSizeRatio","maxWorldSize","getMaxWorldSize","maxSize","scaleStep","binderList","WindowLevelBinder","getEventType","getCallback","viewLayers","PositionBinder","pointValues","currentPos","currentDims","inputDims","ZoomBinder","OffsetBinder","OpacityBinder","ColourMapBinder","Stage","getLayerGroup","getNumberOfLayerGroups","setActiveLayerGroup","addLayerGroup","htmlElement","isBound","unbindLayerGroups","bindLayerGroups","setBinders","removeLayerGroup","minRatio","hasRatio","binder","binderObj","elem","State","fromJSON","json","version","baseScale","scaleCenter","originX","originY","oldTx","oldTy","setDrawings","drawings","drawingsDetails","v02DAndD","inputDrawings","newDrawings","drawGroups","drawGroup","lenf","newFrameDrawings","leng","karcs","ktexts","toObject","txtLen","longText","v01Tov02DrawingsAndDetails","v02Tov03Drawings","v03Tov04DrawingsDetails","v04Tov05Data","v04Tov05Drawings","details","groupDetails","v02Tov03DrawingsDetails","groupShapes","parentGroup","groupDrawings","currentPosition","gnode","detail","ids","attrs","sliceNumber","frameNumber","newId","getUrlFromUri","uri","base","location","URL","splitUri","sepIndex","hashIndex","query","pairs","pair","splitKeyValueString","UndoStack","getStackSize","getCurrentStackIndex","cmd","redo","ToolboxController","enableShortcuts","getToolList","hasTool","getSelectedTool","getSelectedToolEventHandler","eventType","setSelectedTool","setToolFeatures","bindLayerGroup","layerGroupDivId","applySelectedTool","MultiProgressHandler","setNumberOfDimensions","num","setNToLoad","onprogress","lengthComputable","subindex","percent","loaded","total","source","lenprog","getMonoProgressHandler","getUndefinedMonoProgressHandler","UrlsLoader","request","loader","onload","onloadend","load","onloadstart","status","onerror","responseURL","statusText","response","mproghandler","loaders","loaderList","foundLoader","canLoadUrl","defaultCharacterSet","onloaditem","onabort","lastRunRequestIndex","requestOnLoadEnd","send","XMLHttpRequest","open","requestHeaders","setRequestHeader","withCredentials","errorCallback","timeoutCallback","ontimeout","abortCallback","loadUrlAs","responseType","batchSize","dicomDirUrl","urls","parser","dirSeq","records","series","study","recType","refFileIds","getFileListFromDicomDir","rootUrl","fullUrls","abort","readyState","isLoading","ThreadPool","poolSize","taskQueue","freeThreads","WorkerThread","runningThreads","addWorkerTask","workerTask","onworkstart","workerThread","shift","onworkend","onTaskEnd","onwork","handleWorkerError","onworkitem","parentPool","runningTask","worker","Worker","script","onmessage","postMessage","startMessage","terminate","itemNumber","numberOfItems","WorkerTask","hasJpegBaselineDecoder","JpegImage","hasJpegLosslessDecoder","jpeg","lossless","hasJpeg2000Decoder","JpxImage","decoderScripts","rle","AsynchPixelBufferDecoder","_numberOfData","pixelMeta","ondecodestart","ondecodeditem","ondecoded","ondecodeend","SynchPixelBufferDecoder","algoName","numberOfData","decoder","decodedBuffer","buf","Decoder","decoded","tiles","dwvdecoder","RleDecoder","PixelBufferDecoder","NumericValue","FloatingPointValue","RationalNumeratorValue","RationalDenominatorValue","MeasurementUnitsCodeSequence","MeasuredValue","numericValue","floatingPointValue","rationalNumeratorValue","rationalDenominatorValue","measurementUnitsCode","getDicomMeasuredValueItem","MeasuredValueSequence","NumericValueQualifierCodeSequence","NumericMeasurement","measuredValue","numericValueQualifierCode","getDicomNumericMeasurementItem","measurement","SopInstanceReference","getSopInstanceReference","ref","getDicomSopInstanceReferenceItem","ReferencedFrameNumber","ReferencedSOPSequence","ImageReference","referencedSOPSequence","referencedFrameNumber","referencedSegmentNumber","fiducialUID","getDicomImageReferenceItem","PixelOriginInterpretation","GraphicData","GraphicType","FiducialUID","GraphicTypes","SpatialCoordinate","graphicData","graphicType","pixelOriginInterpretation","getDicomSpatialCoordinateItem","scoord","ReferencedFrameofReferenceUID","SpatialCoordinate3D","referencedFrameofReferenceUID","getDicomSpatialCoordinate3DItem","RelationshipType","ValueType","ConceptNameCodeSequence","ConceptCodeSequence","ContentSequence","DateTime","Time","UID","PersonName","TextValue","ContinuityOfContent","RelationshipTypes","ValueTypes","datetime","uidref","pname","composite","waveform","scoord3d","tcoord","table","ValueTypeValueTagName","TEXT","DATE","TIME","DATETIME","UIDREF","PNAME","CONTAINER","DicomSRContent","valueType","conceptNameCode","relationshipType","contentSequence","getSRContent","content","getMeasuredValue","getNumericMeasurement","getImageReference","getSpatialCoordinate","getSpatialCoordinate3D","valueTagName","getDicomSRContentItem","contentItem","getSRContentFromValue","getConceptNameCode","measure","getMeasurementUnitsCode","numMeasure","AnnotationGroupFactory","srContent","dataLength","isClosed","numberOfPoints","firstPoint","lastPoint","line2","line3","getShapeFromScoord","subsubItem","nPoints","quantifName","quantifUnit","annotations","seriesElement","srScoord","pointPerimeter","getScoordFromShape","itemContentSequence","srImage","sopRef","imageRef","srUid","shortLabel","labelPosScoord","refPointsScoord","pointsScoord","quatifContent","CompletionFlag","VerificationFlag","DicomData","DataController","getNextDataId","getDataIds","getDataIdsFromSopUids","dataToUpdate","idKey","obj1","obj2","valueKey","mergedObj1","merged","id1","id2","value1","subValue1","value2","subValue2","mergeObjects","DicomBufferToView","opt","modalityElement","dicomParser","columnsElement","rowsElement","samplesPerPixelElement","planarConfigurationElement","dataIndex","decodedData","fullSize","algo","getSyntaxDecompressionName","convert","MemoryLoader","canLoadMemory","filename","toUID","imageDataToBuffer","imageData","dataLen","getDefaultImage","imageBuffer","imageSpacing","canLoadFile","file","url","forceLoader","isNameAccept","acceptHeader","acceptValue","urlObjext","pathname","hasNoExt","hasDcmExt","contentType","searchParams","mem","tmpFile","File","loadFileAs","fileContentTypes","_opt","Text","memoryIO","progress","u8Array","partHeaderEndCb","partHeaderEndIndex","lines","boundaryStr","boundaryCb","boundaryLen","nextBoundaryIndex","part","partHeaderLines","semiColonIndex","dataBeginIndex","dataEndIndex","parseMultipart","_file","_mem","dataType","imageType","Blob","createObjectURL","domImage","canvas","ctx","seriesUID","lastModified","getViewFromDOMImage","src","hasImageExt","DataURL","videoDataStr","btoa","video","onloadedmetadata","videoWidth","videoHeight","ceil","duration","onseeked","imgBuffer","storeFrame","nextTime","currentTime","getViewFromDOMVideo","unzipPercent","async","then","JSZip","zip","FilesLoader","FileReader","readAsText","readAsDataURL","readAsArrayBuffer","LoadController","loadFiles","files","loadURLs","loadImageObject","getLoadingDataIds","fileIO","urlIO","loadType","eventInfo","loadtype","isFirstItem","eventInfoItem","isfirstitem","getNumberToPrecision","createDefaultReplaceFormat","OverlayData","configs","addAppListeners","addItemMeta","dataUid","overlays","modElement","overlay","format","poElement","po0","po1","createOverlayData","DOM","infoKeys","createOverlayDataForDom","sliceOverlayData","mapFunc","isListening","removeAppListeners","ViewConfig","wlPresetName","ToolConfig","AppOptions","dataViewConfigs","tools","binders","viewOnFirstLoadItem","overlayConfig","rootDocument","App","addData","getMetaData","getToolboxController","removeFromUndoStack","appToolList","toolName","toolClass","toolParams","appToolOptions","optionName","optionClassName","toolNamespace","charAt","optionClass","tOptions","resetLayout","loadFromUri","getUriQuery","onLoadEnd","state","protocol","host","decodeURIComponent","manifest","rootURL","getElementsByTagName","getAttribute","patientList","studyList","studyUID","seriesList","instanceList","link","decodeManifest","responseXML","decodeManifestQuery","replaceMode","repeatKeyReplaceMode","queryUri","inputQueryPairs","repeatKey","repeatList","baseUrl","gotOneArg","decodeKeyValueUri","dwvReplaceMode","decodeQuery","abortAllLoads","abortLoad","initWLDisplay","getViewConfigs","excludeStarConfig","getViewConfig","getDataViewConfigs","setDataViewConfigs","addDataViewConfig","removeDataViewConfig","itemIndex","lg","vls","dls","updateDataViewConfig","configToUpdate","dataKeys","divIds","viewConfigs","viewConfig","getElementById","setLayerGroupsBinders","instances","isImage","isMeasurement","translate","statePosGroups","statePosKids","stateGroup","pointsArray","absPosition","absolutePosition","konvaToAnnotation","applyJsonState","jsonState","onResize","defaultOnKeydown","ctrlKey","shiftKey","resetDisplay","resetZoom","setTool","tool","getOverlayData","toggleOverlayListeners","refMeta","refDataViewConfig","drawDataViewConfig","isFirstLoadItem","eventMetaData","groupId","isBaseLayer","flipFlags","baseViewLayer","layergroupid","refSeriesInstanceUID","refViewLayer","refViewController","refData","viewConfigOrientation","orientationCode","isViewUndefined","isViewAxial","isViewCoronal","isViewSagittal","flipOffset","flipScale","MaskSegmentHelper","segmentNumber","hasSegment","getNumberOfSegments","maskHasSegments","numbers","unknowns","addSegment","removeSegment","updateSegment","DeleteSegmentCommand","isValid","segmentnumber","ChangeSegmentColourCommand","newColour","MaskSegmentViewHelper","isHidden","addToHidden","removeFromHidden","getAlphaFunc","Scalar2D","Scalar3D"],"sourceRoot":""}
\ No newline at end of file