From 84a451df6448d78785b586a673a0bb2d5cd2525b Mon Sep 17 00:00:00 2001 From: ivmartel Date: Mon, 10 Feb 2025 13:01:05 +0100 Subject: [PATCH] Beta v0.35.0-beta.15 --- dist/dwv.d.ts | 7 +++++++ dist/dwv.min.js | 2 +- dist/dwv.min.js.map | 2 +- package.json | 2 +- resources/api/dwv.api.md | 1 + resources/doc/jsdoc.conf.json | 4 ++-- src/dicom/dicomParser.js | 2 +- 7 files changed, 14 insertions(+), 6 deletions(-) diff --git a/dist/dwv.d.ts b/dist/dwv.d.ts index d5485fc6b6..5bd7b31a2d 100644 --- a/dist/dwv.d.ts +++ b/dist/dwv.d.ts @@ -3235,6 +3235,7 @@ export declare class LayerGroup { * methods to define the active index. * * @param {ViewLayer | DrawLayer} layer The layer to remove. + * @fires LayerGroup#removelayer */ removeLayer(layer: ViewLayer | DrawLayer): void; /** @@ -5576,6 +5577,12 @@ export declare class ViewController { * @returns {PositionHelper} The helper. */ getPositionHelper(): PositionHelper; + /** + * Get a clone of the position helper. + * + * @returns {PositionHelper} The helper clone. + */ + getPositionHelperClone(): PositionHelper; /** * Get the current position. * diff --git a/dist/dwv.min.js b/dist/dwv.min.js index 668d652ff3..fc4920fb7a 100644 --- a/dist/dwv.min.js +++ b/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 St},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 ge},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();tthis.#d?this.#c:e*this.#h+this.#g}}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;t255?255:t})),green:g((function(e){const t=256/3;let n=0;return e>=t&&(n=3*(e-t),n>255)?255:n})),blue:g((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)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;i0?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=e.length)throw new Error("Non valid dimension for toStringId");let n="";for(let i=0;i=e.length)&&(n=0),(void 0===i||i<=n||i>e.length)&&(i=e.length);for(let r=n;ro;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;e2^"+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;t8&&"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=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(;n1&&t.length>e){const n=t.length/e,i=[];let o=0;for(let r=0;r{if(void 0===this.#z[e.type])return;const t=this.#z[e.type].slice();for(let n=0;n2?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),g=r.get(2);let S=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=g*h,D=1===e.index?f(u,c,o,d,h,S,n,r):f(u,c,o,S,g,d,n,r);else{if(1!==t.index)throw new Error("Unknown direction: "+t.index);o=g*d,D=0===e.index?f(u,c,o,1,d,S,n,r):f(u,c,o,S,g,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=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;ethis.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;in-1)throw new Error("Wrong input dir value: "+t[e]);for(let n=0;n=0&&ithis.length()-1)throw new Error("Invalid start value for indexToOffset");let n=0;for(let i=t;i0;--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;sn&&(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;nw&&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 gt(){return new A([1,0,0,0,0,1,0,-1,0])}const St={Axial:"axial",Coronal:"coronal",Sagittal:"sagittal"};function pt(e){let t;return e===St.Axial?t=b():e===St.Coronal?t=gt():e===St.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=St.Axial:["LSA","LIP","RSP","RIA","ILA","IRP","SLP","SRA"].includes(e)?t=St.Coronal:["PSL","PIR","ASR","AIL","IAR","IPL","SAL","SPR"].includes(e)&&(t=St.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=9?lt(r):void 0}}(h);g=e.date,S=e.time}void 0===S&&(S={hours:0,minutes:0,seconds:0,milliseconds:0}),a=new Date(g.year,g.monthIndex,g.day,S.hours,S.minutes,S.seconds,S.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 g="ActualFrameDuration (0018,1242)",S=e["00181242"];if(n+=Lt(S,g),void 0!==S&&(h=S.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 g;if(void 0!==u&&void 0!==a&&void 0!==r&&void 0!==o){const e=(u.getTime()-a.getTime())/1e3;g=r*Math.pow(2,-e/o)}return{value:g,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,n;const i=["00280030","00181164","00182010","00280034"];for(let r=0;rparseFloat(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>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;r1){let t="";for(let n=0;npe(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=Se(),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}#ge(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;t1&&(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;iObject.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",gn="0062000F",Sn="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}else c.warn("No recommended colour for segment, using default"),t.displayRGBValue=function(e){const t=[new D(0,0,0),new D(255,0,0),new D(0,255,0),new D(0,0,255),new D(255,255,0),new D(0,255,255),new D(255,0,255),new D(255,239,213),new D(0,0,205),new D(205,133,63),new D(210,180,140),new D(102,205,170),new D(0,0,128),new D(0,139,139),new D(46,139,87),new D(255,228,225)];let n;return n=e1&&(y=!0,p=new m(h,g,S));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;ew;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;eo)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=0;--i){const a=Number.parseInt(o[i],10);S.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})}g.push(c)}}r.NumberOfFrames=S.length.toString();const m=[];for(const e of g)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=S.length*D/8,C=new ve("OB");return C.tag=new de("7FE0","0010"),C.vl=y,C.value=S,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=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=3&&(r=i.getDimSize(3));for(let i=0;it&&(t=n),nn?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;it&&(t=n),ni&&(i=r),ra&&(a=s),s{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{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(gt().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 nt(n(e.getSpacing().getValues(),t.getSpacing().getValues())),r=e.getRange(),o=t.getRange(),a=n(r[0].getValues(),o[0].getValues()),s=(l=r[1].getValues(),c=o[1].getValues(),l.map(((e,t)=>Math.max(e,c[t]))));var l,c;const u=[];for(let e=0;e{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{this.#vt===e.dataid&&(this.#nt.setImage(e.value[0]),this.#bt(this.#nt.getImageSize().get2D()),this.#Ct=!0)};bindImage(){this.#nt&&this.#nt.bindImageAndLayer(this)}unbindImage(){this.#nt&&this.#nt.unbindImageAndLayer(this)}onimagecontentchange=e=>{this.#vt===e.dataid&&(this.#at=this.#nt.isPositionInBounds(),this.#Ct=!0,this.draw())};onimagegeometrychange=e=>{if(this.#vt===e.dataid){const e=this.#nt.getImageSize().get2D();if(this.#lt.x!==e.x||this.#lt.y!==e.y){if(void 0!==this.#Tt&&void 0!==this.#Lt){const e=this.#nt.getOrigin(),t=this.#Lt.minus(e),n=this.#nt.getOrigin(this.#nt.getCurrentPosition()),i=this.#Tt.minus(n);this.setBaseOffset(t,i)}this.#bt(e),this.#Ct=!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.#yt.x+=this.#it.width/this.#dt.x,this.#St.x+=this.#yt.x}addFlipOffsetY(){this.#yt.y+=this.#it.height/this.#dt.y,this.#St.y+=this.#yt.y}flipScaleX(){this.#gt.x*=-1}flipScaleY(){this.#gt.y*=-1}flipScaleZ(){this.#gt.z*=-1}setScale(e,t){const n=this.#nt.getPlaneHelper(),i=n.getTargetOrientedPositiveXYZ({x:e.x*this.#gt.x,y:e.y*this.#gt.y,z:e.z*this.#gt.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.#St.x-this.#ft.x,y:this.#St.y-this.#ft.y};this.#ft={x:0,y:0},this.#St=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.#St,this.#dt,r,e),o={x:this.#ft.x+i.x-this.#St.x,y:this.#ft.y+i.y-this.#St.y};this.#ft=o,this.#St=i}this.#dt=r}initScale(e,t){const n=this.#nt.getPlaneHelper().getTargetOrientedPositiveXYZ({x:e.x*this.#gt.x,y:e.y*this.#gt.y,z:e.z*this.#gt.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.#St={x:this.#St.x+this.#ft.x,y:this.#St.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.#Tt=n,this.#Lt=i),s&&(this.#St={x:this.#St.x-this.#pt.x+a.x,y:this.#St.y-this.#pt.y+a.y},this.#pt=a),s}setOffset(e){const t=this.#nt.getPlaneHelper().getPlaneOffsetFromOffset3D(e);this.#St={x:this.#St.x-this.#Dt.x+t.x,y:this.#St.y-this.#Dt.y+t.y},this.#Dt=t}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.#St.x,t.getY()+this.#St.y)}planePosToDisplay(e){let t=(e.getX()-this.#St.x+this.#pt.x)*this.#dt.x,n=(e.getY()-this.#St.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.#Ct&&this.#xt(),this.#ot.globalAlpha=this.#ut,this.clear(),this.#ot.setTransform(this.#dt.x,0,0,this.#dt.y,-1*this.#St.x*this.#dt.x,-1*this.#St.y*this.#dt.y),this.#ot.imageSmoothingEnabled=this.#It,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.#bt(e),this.#Ct=!0):alert("Error: failed to get the 2D context.")):alert("Error: no canvas.getContext method.")}#bt(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;const r={x:t*this.#ct.x,y:t*this.#ct.y},o=r.x/this.#ht.x,a=r.y/this.#ht.y,s=e.x/(this.#it.width*o),l=e.y/(this.#it.height*a);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 c={x:this.#dt.x*o,y:this.#dt.y*a};this.#dt.x===c.x&&this.#dt.y===c.y||(this.#ht=r,this.#dt=c,i=!0);const u={x:n.x/r.x,y:n.y/r.y},d={x:e.x/r.x,y:e.y/r.y},h={x:0!==this.#yt.x?d.x:0,y:0!==this.#yt.y?d.y:0};if(this.#mt.x!==u.x||this.#mt.y!==u.y||this.#yt.x!==h.x||this.#yt.y!==h.y){const e={x:this.#ft.x*s,y:this.#ft.y*l};this.#St={x:this.#St.x+u.x-this.#mt.x+h.x-this.#yt.x+e.x-this.#ft.x,y:this.#St.y+u.y-this.#mt.y+h.y-this.#yt.y+e.y-this.#ft.y},this.#yt=h,this.#mt=u,this.#ft=e,i=!0}i&&this.draw()}bindInteraction(){this.#tt.style.pointerEvents="auto";const e=Wn;for(let t=0;t{e.srclayerid=this.getId(),e.dataid=this.#vt,this.#be.fireEvent(e)};#xt(){this.#nt.generateImageData(this.#st),this.#rt.getContext("2d").putImageData(this.#st,0,0),this.#Ct=!1}#Pt=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#Ct=!0,this.draw())};#wt=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#Ct=!0,this.draw())};#Ot=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.#Ct=!0,this.draw())}else this.#at&&(this.#at=!1,this.clear())}};#At=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#Ct=!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{#Rt=0;getSum(){return this.#Rt}add(e){this.#Rt+=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.#Rt=0}isTick(){return Math.abs(this.#Rt)>=1}}class Jn{#Ft;#Et=new Kn;constructor(e){this.#Ft=e}wheel(e){this.#Et.add(e);const t=this.#Et.getSum()>=0;if(!this.#Et.isTick())return;this.#Et.clear(),e.preventDefault();const n=Ki(e),i=this.#Ft.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{#qt;#Ut;constructor(e,t){this.#qt=e,this.#Ut=t}getBegin(){return this.#qt}getEnd(){return this.#Ut}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{#Mt;#Qt;constructor(e,t){this.#Mt=e,this.#Qt=t}getName(){return"AddAnnotation-"+this.#Mt.id}execute(){this.#Qt.addAnnotation(this.#Mt)}undo(){this.#Qt.removeAnnotation(this.#Mt.id)}}class li{#Mt;#Qt;constructor(e,t){this.#Mt=e,this.#Qt=t}getName(){return"RemoveAnnotation-"+this.#Mt.id}execute(){this.#Qt.removeAnnotation(this.#Mt.id)}undo(){this.#Qt.addAnnotation(this.#Mt)}}class ci{#Mt;#Qt;#Vt;#Nt;constructor(e,t,n,i){this.#Mt=e,this.#Qt=i,this.#Vt=t,this.#Nt=n}getName(){return"UpdateAnnotation-"+this.#Mt.id}execute(){const e=Object.keys(this.#Nt);for(const t of e)this.#Mt[t]=this.#Nt[t];this.#Qt.updateAnnotation(this.#Mt,e)}undo(){const e=Object.keys(this.#Vt);for(const t of e)this.#Mt[t]=this.#Vt[t];this.#Qt.updateAnnotation(this.#Mt,e)}}class ui{#Bt=10;#Gt="Verdana";#kt="#fff";#Ht="#ffff80";#zt={x:1,y:1};#Wt={x:1,y:1};#Yt=2;#Xt={x:.25,y:.25};#jt=.2;#Zt=3;getFontFamily(){return this.#Gt}getFontSize(){return this.#Bt}getStrokeWidth(){return this.#Yt}getTextColour(){return this.#kt}getLineColour(){return this.#Ht}setLineColour(e){this.#Ht=e}setBaseScale(e){this.#zt=e}setZoomScale(e){this.#Wt=e}getBaseScale(){return this.#zt}getZoomScale(){return this.#Wt}scale(e){return e/this.#zt.x}applyZoomScale(e){return{x:e/this.#Wt.x,y:e/this.#Wt.y}}applyZoomRatio(e){return e*this.#Wt.x/this.#Wt.y}getShadowOffset(){return this.#Xt}getTagOpacity(){return this.#jt}getTextPadding(){return this.#Zt}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 gi(e){return"shape"===e.name()}function Si(e){return"position-group"===e.name()}function pi(e){const t=e.getChildren(gi)[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{#Ft;#_t;constructor(e,t){this.#Ft=e,this.#_t=t}#Kt=null;#Jt=null;#$t;#Mt;#en=!1;setShape(e,t,n){if(this.#Jt=e,this.#$t=t,this.#Mt=n,this.#Jt){if(this.#tn(),this.#Kt=n.getFactory(),null===this.#Kt)throw new Error("Could not find a factory to update shape.");this.#nn()}}getShape(){return this.#Jt}getAnnotation(){return this.#Mt}isActive(){return this.#en}enable(){this.#en=!0,this.#Jt&&(this.#in(!0),this.#Jt.getLayer()&&this.#Jt.getLayer().draw())}disable(){this.#en=!1,this.#Jt&&(this.#in(!1),this.#Jt.getLayer()&&this.#Jt.getLayer().draw())}reset(){this.#Jt=void 0,this.#$t=void 0,this.#Mt=void 0}resetAnchors(){this.#tn(),this.#nn(),this.#in(!0)}#rn(e){this.#Jt&&this.#Jt.getParent()&&this.#Jt.getParent().find(".anchor").forEach(e)}#in(e){this.#rn((function(t){t.visible(e)}))}setAnchorsActive(e){let t=null;t=e?e=>{this.#on(e)}:e=>{this.#an(e)},this.#rn(t)}#tn(){this.#rn((function(e){e.remove()}))}#nn(){if(!this.#Jt||!this.#Jt.getLayer())return;const e=this.#Jt.getParent(),t=this.#Kt.getAnchors(this.#Jt,this.#Ft.getStyle());for(let n=0;n{e.cancelBubble=!0,t={mathShape:this.#Mt.mathShape,referencePoints:this.#Mt.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()n.getX()&&(e.x(n.getX()),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.#$t.getBaseSize(),t),void 0!==this.#Kt.constrainAnchorMove&&this.#Kt.constrainAnchorMove(t),this.#Kt.updateAnnotationOnAnchorMove(this.#Mt,t),this.#Kt.updateShapeGroupOnAnchorMove(this.#Mt,t,this.#Ft.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.#Mt.mathShape,referencePoints:this.#Mt.referencePoints},i=new ci(this.#Mt,t,n,this.#$t.getDrawController());this.#Ft.addToUndoStack(i),this.#_t({type:"annotationupdate",data:this.#Mt,dataid:this.#$t.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!"))}))}#an(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{#sn;constructor(){this.createTrashIcon()}createTrashIcon(){this.#sn=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.#sn.width(20),this.#sn.height(20),this.#sn.add(e),this.#sn.add(t)}activate(e){const t=e.getKonvaStage(),n=t.scale(),i=e.getKonvaLayer(),r={x:1/n.x,y:1/n.y};this.#sn.x(t.offset().x+t.width()/(2*n.x)),this.#sn.y(t.offset().y+t.height()/(15*n.y)),this.#sn.scale(r),i.add(this.#sn),i.draw()}changeChildrenColourOnTrashHover(e,t,n){if(this.isOverTrash(e))return this.changeGroupChildrenColour(this.#sn,"orange"),void this.changeGroupChildrenColour(t,"red");this.changeGroupChildrenColour(this.#sn,"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.#sn.remove()}isOverTrash(e){const t=this.#sn.width()*Math.abs(this.#sn.scaleX())/2,n=this.#sn.height()*Math.abs(this.#sn.scaleY())/2;return Math.abs(e.x-this.#sn.x()){this.#dn=e,this.#gn()})),e.on("mouseout",(()=>{this.onMouseOutShapeGroup(),this.#dn=void 0}))}#pn(e){e.off("mouseover"),e.off("mouseout")}addShapeGroupListeners(e,t,n){this.#Sn(e),this.#mn(e,t,n),this.#fn(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.#Ft.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)}))}#mn(e,t,n){const i=n.getKonvaLayer(),r=e.getChildren(gi)[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.#sn.activate(n),this.#ln.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.xt.getY()&&i.y{if(this.#sn.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()},g=this.#hn(h,n);if(this.#sn.isOverTrash(g)){e.x(o.x),e.y(o.y),this.#ln.disable(),this.#ln.reset(),this.#sn.changeGroupChildrenColour(e,l),t.mathShape=s.mathShape,t.referencePoints=s.referencePoints;const i=new li(t,n.getDrawController());this.#Ft.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.#Ft.addToUndoStack(i),this.#_t({type:"annotationupdate",data:t,dataid:n.getDataId(),keys:Object.keys(e)}),s={mathShape:e.mathShape,referencePoints:e.referencePoints}}this.#ln.setAnchorsActive(!0),this.#ln.resetAnchors()}i.draw(),o={x:r.x(),y:r.y()}}))}#fn(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.#Ft.addToUndoStack(r),this.#_t({type:"annotationupdate",data:t,dataid:n.getDataId(),keys:["labelPosition"]}),o=e}r={x:i.x(),y:i.y()}}))}removeShapeListeners(e){this.#pn(e),e.off("dblclick");const t=e.getChildren(gi)[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{#Dn=[];constructor(e){void 0!==e&&(this.#Dn=e)}getPoint(e){return this.#Dn[e]}getPoints(){return this.#Dn}getLength(){return this.#Dn.length}addPoint(e){this.#Dn.push(e)}addPoints(e){this.#Dn=this.#Dn.concat(e)}getCentroid(){let e,t=0,n=0,i=0;for(let e=0;e.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;nMath.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;n3)throw new Error("Too many points for a protractor");this.#Dn=e.slice(0,3)}getPoint(e){return this.#Dn[e]}getLength(){return this.#Dn.length}getCentroid(){return this.#Dn[1]}quantify(e,t){const n={};if(3===this.#Dn.length){let e=ei(new $n(this.#Dn[0],this.#Dn[1]),new $n(this.#Dn[1],this.#Dn[2]));e>180&&(e=360-e),n.angle={value:e,unit:"unit.degree"}}return n}}class Mi{#qt;#Ut;constructor(e,t){this.#qt=new R(Math.min(e.getX(),t.getX()),Math.min(e.getY(),t.getY())),this.#Ut=new R(Math.max(e.getX(),t.getX()),Math.max(e.getY(),t.getY()))}getBegin(){return this.#qt}getEnd(){return this.#Ut}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;eethis.getMax()?t:e))}}class Ni{getName(){return"Sharpen"}#On=null;setOriginalImage(e){this.#On=e}getOriginalImage(){return this.#On}update(){return this.getOriginalImage().convolute2D([0,-1,0,-1,5,-1,0,-1,0])}}class Bi{getName(){return"Sobel"}#On=null;setOriginalImage(e){this.#On=e}getOriginalImage(){return this.#On}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{#An;#vt;#Ft;constructor(e,t,n){this.#An=e,this.#vt=t,this.#Ft=n}getName(){return"Filter-"+this.#An.getName()}execute(){this.#Ft.setImage(this.#vt,this.#An.update()),this.#Ft.render(this.#vt);const e={type:"filterrun",id:this.getName(),dataId:this.#vt};this.onExecute(e)}undo(){this.#Ft.setImage(this.#vt,this.#An.getOriginalImage()),this.#Ft.render(this.#vt);const e={type:"filterundo",id:this.getName(),dataid:this.#vt};this.onUndo(e)}onExecute(e){}onUndo(e){}}const ki={},Hi={},zi={WindowLevel:class{#Ft;#bn=!1;#xn;#Rn;constructor(e){this.#Ft=e,this.#Rn=new Jn(e)}#Fn(e,t){const n=this.#Ft.getLayerGroupByDivId(t).getActiveViewLayer();void 0!==n&&n.getViewController().isMonochrome()&&(this.#bn=!0,this.#xn=e)}#En(e,t){if(!this.#bn)return;const n=this.#Ft.getLayerGroupByDivId(t).getActiveViewLayer();if(void 0===n)return;const i=n.getViewController(),r=e.getX()-this.#xn.getX(),o=this.#xn.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 g;h=(g=h)<1?1:g;const S=new u(d,h);i.setWindowLevel(S),this.#xn=e}#qn(){this.#bn&&(this.#bn=!1)}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup=e=>{this.#qn()};mouseout=e=>{this.#qn()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#En(t[0],n.groupDivId)};touchend=e=>{this.#qn()};dblclick=e=>{const t=Ki(e),n=jn(e),i=this.#Ft.getLayerGroupByDivId(t.groupDivId).getActiveViewLayer();if(void 0===i)return;const r=i.displayToPlaneIndex(n),o=i.getViewController();if(!o.isMonochrome())return;const a=this.#Ft.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.#Rn.wheel(e)};keydown=e=>{e.context="WindowLevel",this.#Ft.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Scroll:class{#Ft;#bn=!1;#xn;#Rn;#Un;#Mn=!1;#Qn;constructor(e){this.#Ft=e,this.#Rn=new Jn(e)}#Vn(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}#Fn(e,t){this.#Nn();const n=this.#Ft.getLayerGroupByDivId(t),i=this.#Vn(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.#bn=!0,this.#xn=e}#En(e,t){if(!this.#bn)return void(this.#Mn&&this.#Bn(e,t));const n=this.#Ft.getLayerGroupByDivId(t),i=n.getPositionHelper(),r=e.getY()-this.#xn.getY(),o=Math.abs(r)>15,a=e.getX()-this.#xn.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.#xn=e)}#qn(){this.#bn&&(this.#bn=!1)}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup=e=>{this.#qn()};mouseout=e=>{this.#qn(),this.#Nn()};touchstart=e=>{this.#Un=setTimeout((()=>{this.dblclick(e)}),500);const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchmove=e=>{null!==this.#Un&&(clearTimeout(this.#Un),this.#Un=null);const t=Xn(e),n=Ki(e);this.#En(t[0],n.groupDivId)};touchend=e=>{null!==this.#Un&&(clearTimeout(this.#Un),this.#Un=null),this.#qn()};wheel=e=>{this.#Rn.wheel(e)};keydown=e=>{e.context="Scroll",this.#Ft.onKeydown(e)};dblclick=e=>{const t=Ki(e),n=this.#Ft.getLayerGroupByDivId(t.groupDivId).getActiveViewLayer();void 0!==n&&n.getViewController().play()};#Bn(e,t){const n=this.#Ft.getLayerGroupByDivId(t);this.#Qn=t,n.showTooltip(e)}#Nn(){void 0!==this.#Qn&&(this.#Ft.getLayerGroupByDivId(this.#Qn).removeTooltipDiv(),this.#Qn=void 0)}activate(e){e||this.#Nn()}setFeatures(e){void 0!==e.displayTooltip&&(this.#Mn=e.displayTooltip)}init(){}},ZoomAndPan:class{#Ft;#bn=!1;#xn;#Gn;#kn;#Hn;constructor(e){this.#Ft=e}#Vn(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}#Fn(e){this.#bn=!0,this.#xn=e,this.#Gn=!1}#zn=e=>{this.#bn=!0,this.#xn=e[0],this.#Gn=!1,this.#kn=new $n(e[0],e[1]),this.#Hn=this.#kn.getMidpoint()};#En(e,t){if(!this.#bn)return;this.#Gn=!0;const n=e.getX()-this.#xn.getX(),i=e.getY()-this.#xn.getY(),r=this.#Ft.getLayerGroupByDivId(t),o=this.#Vn(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.#xn=e}#Wn=(e,t)=>{if(!this.#bn)return;this.#Gn=!0;const n=new $n(e[0],e[1]).getLength()/this.#kn.getLength(),i=this.#Ft.getLayerGroupByDivId(t),r=i.getPositionHelper();if(1===n){const t=e[0].getY()-this.#xn.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.#Hn){const t=this.#Vn(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.#Hn),o=n.getPlanePositionFromPlanePoint(r);i.addScale(e,o),i.draw()}}};#Yn(e,t){const n=this.#Ft.getLayerGroupByDivId(t),i=this.#Vn(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)}#qn(){this.#bn&&(this.#bn=!1)}mousedown=e=>{const t=jn(e);this.#Fn(t)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup=e=>{if(!this.#Gn){const t=jn(e),n=Ki(e);this.#Yn(t,n.groupDivId)}this.#qn()};mouseout=e=>{this.#qn()};touchstart=e=>{const t=Xn(e);1===t.length?this.#Fn(t[0]):2===t.length&&this.#zn(t)};touchmove=e=>{const t=Xn(e),n=Ki(e);1===t.length?this.#En(t[0],n.groupDivId):2===t.length&&this.#Wn(t,n.groupDivId)};touchend=e=>{if(!this.#Gn){const t=jn(e),n=Ki(e);this.#Yn(t,n.groupDivId)}this.#qn()};wheel=e=>{e.preventDefault();const t=-e.deltaY/500,n=Ki(e),i=jn(e),r=this.#Ft.getLayerGroupByDivId(n.groupDivId),o=this.#Vn(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.#Ft.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Opacity:class{#Ft;#bn=!1;#xn;#Rn;constructor(e){this.#Ft=e,this.#Rn=new Jn(e)}#Fn(e){this.#bn=!0,this.#xn=e}#En(e,t){if(!this.#bn)return;const n=e.getX()-this.#xn.getX();if(Math.abs(n)>15){const i=this.#Ft.getLayerGroupByDivId(t).getActiveLayer(),r=i.getOpacity();i.setOpacity(r+n/200),i.draw(),this.#xn=e}}#qn(){this.#bn&&(this.#bn=!1)}mousedown=e=>{const t=jn(e);this.#Fn(t)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup=e=>{this.#qn()};mouseout=e=>{this.#qn()};touchstart=e=>{const t=Xn(e);this.#Fn(t[0])};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#En(t[0],n.groupDivId)};touchend=e=>{this.#qn()};wheel=e=>{this.#Rn.wheel(e)};keydown=e=>{e.context="Opacity",this.#Ft.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Draw:class{#Ft;#Rn;#Xn;#jn=!1;#Zn=null;#Kt=null;#_n=null;#Kn;#Dn=[];#Jn=null;#$n=!0;#ei=[];#ti;#ni=!1;#z={};#ii=!1;#ri=[];constructor(e){this.#Ft=e,this.#Rn=new Jn(e),this.#ti=new Ii(e,this.#Fe),this.#Xn=e.getStyle()}#oi(e,t){const n=this.#Ft.getLayerGroupByDivId(t);let i=n.getActiveDrawLayer();if(void 0===i){const e=n.getActiveViewLayer().getDataId(),r=this.#Ft.getData(e).image.getMeta().SeriesInstanceUID;if(this.#ei.includes(r))return void this.#Fe({type:"warn",message:"Cannot create draw layer, data is in black list"});const o=this.#Ft.createAnnotationData(e);this.#Ft.addAndRenderAnnotationData(o,t,e),i=n.getActiveDrawLayer(),i.setShapeHandler(this.#ti),n.setActiveLayerByDataId(i.getDataId())}const r=i.getDrawController().getAnnotationGroup(),o=i.getKonvaStage();if(this.#Xn.setZoomScale(o.scale()),r.isEditable()){const t=o.getIntersection({x:e.getX(),y:e.getY()});t?this.#ai(i,t):this.#si(n,e)}}#Vn(e){const t=e.getActiveDrawLayer();if(void 0!==t)return e.getViewLayerById(t.getReferenceLayerId());c.warn("No draw layer to do draw")}#si(e,t){this.#ti.disableAndResetEditor(),this.#li();const n=this.#Vn(e);void 0!==n?(this.#Jn=n.displayToPlanePos(t),this.#Dn.push(this.#Jn)):c.warn("No view layer to start shape")}#li(){this.#jn=!0,this.#Kt=new this.#Zn[this.#Kn],this.#Dn=[]}#ci(){this.#jn=!1,this.#Dn=[]}#ai(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.#ti.setEditorShape(i,e))}#ui(e,t){const n=this.#Ft.getLayerGroupByDivId(t),i=this.#Vn(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.#Jn.getX())>0||Math.abs(r.getY()-this.#Jn.getY())>0)&&(this.#ii&&this.#Dn.pop(),this.#Jn=r,this.#ii=!0,this.#Dn.push(this.#Jn),this.#di(this.#Dn,n))}#hi(e){if(0!==this.#Dn.length){if(this.#Dn.length===this.#Kt.getNPoints()){const t=this.#Ft.getLayerGroupByDivId(e);this.#gi(this.#Dn,t),this.#ci()}this.#ii=!1}else c.warn("Draw mouseup but no points...")}mousedown=e=>{if(this.#jn)return;const t=jn(e),n=Ki(e);this.#oi(t,n.groupDivId)};mousemove=e=>{if(!this.#jn)return;const t=jn(e),n=Ki(e);this.#ui(t,n.groupDivId)};mouseup=e=>{if(!this.#jn)return;const t=Ki(e);this.#hi(t.groupDivId)};dblclick=e=>{if(this.#Kt&&void 0!==this.#Kt.getNPoints())return;if(!this.#jn)return;if(0===this.#Dn.length)return void c.warn("Draw dblclick but no points...");const t=Ki(e),n=this.#Ft.getLayerGroupByDivId(t.groupDivId);this.#gi(this.#Dn,n),this.#ci()};mouseout=e=>{if(!this.#jn)return;const t=Ki(e);this.#hi(t.groupDivId)};touchstart=e=>{if(this.#jn)return;const t=Xn(e),n=Ki(e);this.#oi(t[0],n.groupDivId)};touchmove=e=>{if(!this.#jn)return;const t=Ki(e),n=Xn(e),i=this.#Ft.getLayerGroupByDivId(t.groupDivId),r=this.#Vn(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.#Jn.getX())>0||Math.abs(o.getY()-this.#Jn.getY())>0)&&(1!==this.#Dn.length&&this.#Dn.pop(),this.#Jn=o,this.#Dn.push(this.#Jn),this.#Dn.length{this.#Dn.push(this.#Jn)}),this.#Kt.getTimeout())),this.#di(this.#Dn,i))};touchend=e=>{this.dblclick(e)};wheel=e=>{this.#$n&&this.#Rn.wheel(e)};keydown=e=>{this.#jn||(e.context="Draw",this.#Ft.onKeydown(e));const t=this.#ti.getEditorAnnotation();if(("Delete"===e.key||"Backspace"===e.key)&&void 0!==t){const e=this.#Ft.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.#Ft.addToUndoStack(i),i.execute(),this.#ti.onMouseOutShapeGroup()}if("Escape"===e.key&&null!==this.#_n){const e=this.#_n.getLayer();this.#_n.destroy(),this.#_n=null,this.#ci(),e.draw()}};#di(e,t){this.#_n&&(this.#_n.destroy(),this.#_n=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.#ni){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.#Xn.setLineColour(r)}const s=new Yi,l=i.getAnnotationGroup().getColour();s.colour=void 0!==l?l:this.#Xn.getLineColour(),s.init(a),this.#Kt.setAnnotationMathShape(s,e),this.#_n=this.#Kt.createShapeGroup(s,this.#Xn),n.setLabelVisibility(this.#_n),this.#_n.getChildren(gi)[0].listening(!1),r.listening(!1),r.add(this.#_n),r.draw()}#gi(e,t){this.#_n&&(this.#_n.destroy(),this.#_n=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.#Xn.getLineColour(),s.id=et(),s.init(a),this.#Kt.setAnnotationMathShape(s,e);const u=new si(s,r);this.#Ft.addToUndoStack(u),u.execute(),i.listening(!0)}#Si(e){const t=e.getId();return void 0===this.#ri[t]&&(this.#ri[t]=()=>{e.activateCurrentPositionShapes(!0)}),this.#ri[t]}#pi(e,t){e.setShapeHandler(this.#ti),e.activateCurrentPositionShapes(t),t?this.#Ft.addEventListener("positionchange",this.#Si(e)):this.#Ft.removeEventListener("positionchange",this.#Si(e))}activate(e){e||this.#ti.onMouseOutShapeGroup();const t=this.#Ft.getDrawLayers();for(const n of t)void 0!==n&&this.#pi(n,e);this.#Ft.addEventListener("drawlayeradd",(t=>{const n=this.#Ft.getDrawLayers((function(e){return e.getId()===t.layerid}));1===n.length&&this.#pi(n[0],e)}))}setOptions(e){this.#Zn=e}getOptionsType(){return"factory"}setFeatures(e){if(void 0!==e.autoShapeColour&&(this.#ni=e.autoShapeColour),void 0!==e.shapeColour&&(this.#Xn.setLineColour(e.shapeColour),this.#ni=!1),void 0!==e.shapeName){if(!this.hasShape(e.shapeName))throw new Error("Unknown shape: '"+e.shapeName+"'");this.#Kn=e.shapeName}void 0!==e.mouseOverCursor&&this.#ti.storeMouseOverCursor(e.mouseOverCursor),void 0!==e.withScroll&&(this.#$n=e.withScroll),void 0!==e.blacklist&&(this.#ei=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{if(void 0!==this.#z[e.type])for(let t=0;t{e.context="Filter",this.#Ft.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.#fi}setFeatures(e){if(void 0!==e.filterName){if(!this.hasFilter(e.filterName))throw new Error("Unknown filter: '"+e.filterName+"'");this.#fi&&this.#fi.activate(!1),this.#fi=this.#mi[e.filterName],this.#fi.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.#mi}hasFilter(e){return this.#mi[e]}},Floodfill:class{#Ft;constructor(e){this.#Ft=e}#Di=5;#yi=0;#Ci=2e3;#vi=null;#Ii=null;#Ti=10;#Li=null;#bn=!1;#Mt;#Pi;#wi=null;#Oi=[];#Ai=!1;#Xn=new ui;setExtend(e){this.#Ai=e}getExtend(){return this.#Ai}#Vn(e){const t=e.getActiveDrawLayer();if(void 0!==t)return e.getViewLayerById(t.getReferenceLayerId());c.warn("No draw layer to do floodfill")}#bi=(e,t)=>{const n=this.#Ft.getLayerGroupByDivId(t),i=this.#Vn(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)}};#xi(e,t,n){this.#Oi=[];const i={data:this.#vi.data,width:this.#vi.width,height:this.#vi.height,bytes:4};this.#Ii=Pi().floodFill(i,e.x,e.y,t),this.#Ii=Pi().gaussBlurOnlyBorder(this.#Ii,this.#Di);let r=Pi().traceContours(this.#Ii);if(r=Pi().simplifyContours(r,this.#yi,this.#Ci),r.length>0&&r[0].points[0].x){if(n)return r[0].points;for(let e=0,t=r[0].points.length;er&&this.#Ri(this.#Pi,l,n);t--)i.decrementPositionAlongScroll();o.setCurrentIndex(a)}onThresholdChange(e){}#Fn(e,t){this.#Mt=void 0;const n=this.#Ft.getLayerGroupByDivId(t);let i,r=n.getActiveDrawLayer();if(void 0===r){i=n.getActiveViewLayer();const e=i.getDataId(),o=this.#Ft.createAnnotationData(e);this.#Ft.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.#vi=i.getImageData(),this.#vi?(this.#Xn.setZoomScale(r.getKonvaLayer().getAbsoluteScale()),this.#bn=!0,this.#Pi=this.#bi(e,t),this.#Ri(this.#Pi,this.#Ti,n),this.onThresholdChange(this.#Ti)):c.error("No image found")}#En(e,t){if(!this.#bn)return;const n=this.#bi(e,t);this.#Li=Math.round(Math.sqrt(Math.pow(this.#Pi.x-n.x,2)+Math.pow(this.#Pi.y-n.y,2))/2),this.#Li=this.#Li{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup=e=>{this.#qn()};mouseout=e=>{this.#qn()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#En(t[0],n.groupDivId)};touchend=e=>{this.#qn()};keydown=e=>{e.context="Floodfill",this.#Ft.onKeydown(e)};activate(e){e&&(this.#Xn.setBaseScale(this.#Ft.getBaseScale()),this.setFeatures({shapeColour:this.#Xn.getLineColour()}))}init(){}setFeatures(e){void 0!==e.shapeColour&&this.#Xn.setLineColour(e.shapeColour)}},Livewire:class{#Ft;constructor(e){this.#Ft=e}#bn=!1;#xn;#Mt;#Xn=new ui;#Fi=new wi;#Ei=new wi;#Oi=[];#qi=5;#Ui(e){const t=e.get(1);for(let e=0;e{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup(e){}mouseout=e=>{};dblclick=e=>{this.#Vi()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#En(t[0],n.groupDivId)};touchend=e=>{};keydown=e=>{e.context="Livewire",this.#Ft.onKeydown(e)};activate(e){e&&(this.#Xn.setBaseScale(this.#Ft.getBaseScale()),this.setFeatures({shapeColour:this.#Xn.getLineColour()}))}init(){}setFeatures(e){void 0!==e.shapeColour&&this.#Xn.setLineColour(e.shapeColour)}}},Wi={draw:{ArrowFactory:class{#Ni="arrow";#Bi=new Ri(this.#Gi);static supports(e){return e instanceof R}getName(){return this.#Ni}getGroupName(){return this.#Ni+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#ki(t),e.referencePoints=[t[1]],e.setTextExpr(this.#Hi()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#zi(e,t);n.add(i);const r=this.#Wi(e,t);for(const e of r)n.add(e);const o=this.#Bi.create(e,t);n.add(o);const a=this.#Yi(i);return n.add(this.#Bi.getConnector(a,o,t)),n}#Yi(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)]}#Xi(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.#Xi(e),i=[];for(let e=0;e180&&(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"})]}#Gi(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)}#ji(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.#Zi(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),g=r.getInclination();h>180&&(h=360-h,g+=h);const S=33*Math.min(r.getLength(),o.getLength())/100;l.innerRadius(S),l.outerRadius(S),l.angle(h),l.rotation(-g);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)}))}#_i(e,t){}#Ki(e,t){}},RectangleFactory:class{#Ni="rectangle";#Bi=new Ri(this.#Gi);static supports(e){return e instanceof Mi}getName(){return this.#Ni}getGroupName(){return this.#Ni+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#ki(t),e.setTextExpr(this.#Hi()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#zi(e,t);n.add(i);const r=this.#Bi.create(e,t);n.add(r);const o=this.#Yi(i);return n.add(this.#Bi.getConnector(o,r,t)),n}#Yi(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)]}#Xi(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.#Xi(e),i=[];for(let e=0;e{this.#be.fireEvent(e)}},Sobel:class{#Ft;constructor(e){this.#Ft=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.#Ft.getData(e.dataId).image;t.setOriginalImage(n);const i=new Gi(t,e.dataId,this.#Ft);i.onExecute=this.#Fe,i.onUndo=this.#Fe,i.execute(),this.#Ft.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{#Ft;constructor(e){this.#Ft=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.#Ft.getData(e.dataId).image;t.setOriginalImage(n);const i=new Gi(t,e.dataId,this.#Ft);i.onExecute=this.#Fe,i.onUndo=this.#Fe,i.execute(),this.#Ft.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))}#$i(){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&&void 0!==this.mathShape.getCentroid()){const t=this.#$i(),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;et.id===e.id));-1!==n?((t.includes("mathShape")||t.includes("textExpr"))&&e.updateQuantification(),this.#er[n]=e,this.#Fe({type:"annotationupdate",data:e,keys:t})):c.warn("Cannot find annotation to update")}remove(e){const t=this.#er.findIndex((t=>t.id===e));if(-1!==t){const e=this.#er.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.#er)t.setViewController(e),t.updateQuantification()}find(e){return this.#er.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{#ir;getAnnotation(e){return this.#ir.find(e)}getAnnotationGroup(){return this.#ir}isAnnotationGroupEditable(){return this.#ir.isEditable()}setAnnotationGroupEditable(e){this.#ir.setEditable(e)}addAnnotation(e){this.#ir.add(e)}updateAnnotation(e,t){this.#ir.update(e,t)}removeAnnotation(e){this.#ir.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.#ir.getList())this.removeAnnotationWithCommand(t.id,e)}constructor(e){this.#ir=void 0!==e?e:new Xi}hasAnnotationMeta(e){return this.#ir.hasMeta(e)}setAnnotationMeta(e,t){this.#ir.setMetaValue(e,t)}}class Zi{#tt;#rr=null;#lt;#ct;#ht={x:1,y:1};#gt={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};#yt={x:0,y:0};#Qt;#_e;#vt;#or;#ar;#ti;#sr=!0;constructor(e){this.#tt=e,this.#tt.className+=" drawLayer"}setShapeHandler(e){this.#ti=e}getDataId(){return this.#vt}getReferenceLayerId(){return this.#or}#be=new He;getKonvaStage(){return this.#rr}getKonvaLayer(){return this.#rr.getLayers()[0]}getDrawController(){return this.#Qt}setPlaneHelper(e){this.#_e=e}getId(){return this.#tt.id}removeFromDOM(){this.#tt.remove()}getBaseSize(){return this.#lt}getOpacity(){return this.#rr.opacity()}setOpacity(e){this.#rr.opacity(Math.min(Math.max(e,0),1))}addFlipOffsetX(){const e=this.#rr.scale(),t=this.#rr.size();this.#yt.x+=t.width/e.x;const n=this.#rr.offset();n.x+=this.#yt.x,this.#rr.offset(n)}addFlipOffsetY(){const e=this.#rr.scale(),t=this.#rr.size();this.#yt.y+=t.height/e.y;const n=this.#rr.offset();n.y+=this.#yt.y,this.#rr.offset(n)}flipScaleX(){this.#gt.x*=-1}flipScaleY(){this.#gt.y*=-1}flipScaleZ(){this.#gt.z*=-1}setScale(e,t){const n=this.#_e.getTargetOrientedPositiveXYZ({x:e.x*this.#gt.x,y:e.y*this.#gt.y,z:e.z*this.#gt.z}),i={x:this.#ht.x*n.x,y:this.#ht.y*n.y},r=this.#rr.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.#rr.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.#rr.scale(),i,e),o={x:this.#ft.x+n.x-r.x,y:this.#ft.y+n.y-r.y};this.#ft=o,this.#rr.offset(n)}this.#rr.scale(i),this.#lr(i)}initScale(e,t){const n=this.#_e.getTargetOrientedPositiveXYZ({x:e.x*this.#gt.x,y:e.y*this.#gt.y,z:e.z*this.#gt.z}),i={x:this.#ht.x*n.x,y:this.#ht.y*n.y};this.#rr.scale(i),this.#ft={x:t.x/this.#ht.x,y:t.y/this.#ht.y};const r=this.#rr.offset();this.#rr.offset({x:r.x+this.#ft.x,y:r.y+this.#ft.y})}setOffset(e){const t=this.#_e.getPlaneOffsetFromOffset3D(e),n=this.#rr.offset();this.#rr.offset({x:n.x-this.#Dt.x+t.x,y:n.y-this.#Dt.y+t.y}),this.#Dt=t}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.#rr.offset();this.#rr.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.#rr.draw()}initialise(e,t,n){this.#lt=e,this.#ct=t,this.#or=n,this.#rr=new(ai().Stage)({container:this.#tt,width:this.#lt.x,height:this.#lt.y,listening:!1}),this.#rr.getContent().setAttribute("style","");const i=new(ai().Layer)({listening:!1,visible:!0});this.#rr.add(i)}setAnnotationGroup(e,t,n){if(this.#vt=t,e.addEventListener("annotationadd",(e=>{this.#cr(e.data,!0),this.getKonvaLayer().draw()})),e.addEventListener("annotationupdate",(e=>{this.#ur(e.data),this.getKonvaLayer().draw()})),e.addEventListener("annotationremove",(e=>{this.#dr(e.data),this.getKonvaLayer().draw()})),e.addEventListener("annotationgroupeditablechange",(e=>{this.activateCurrentPositionShapes(e.data)})),this.#Qt=new ji(e),0!==e.getLength())for(const t of e.getList())this.#cr(t,!1),n(new si(t,this.getDrawController()))}activateCurrentPositionShapes(e){const t=this.getKonvaLayer();if(this.#rr.listening(!1),void 0!==this.#ti){this.#ti.disableAndResetEditor();const e=t.getChildren();for(const t of e)t instanceof ai().Group&&t.getChildren().forEach((e=>{e instanceof ai().Group&&this.#ti.removeShapeListeners(e)}))}const n=this.getDrawController();if(e&&n.getAnnotationGroup().isEditable()){this.#rr.listening(!0);const e=this.#hr().getChildren();0!==e.length&&t.listening(!0),void 0!==this.#ti&&e.forEach((e=>{if(e instanceof ai().Group){const t=n.getAnnotation(e.id());this.#ti.addShapeGroupListeners(e,t,this)}}))}t.draw()}#gr(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}#pr(e){let t;const n=this.#gr(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}#cr(e,t){if(!e.isCompatibleView(this.#_e))return;const n=this.#gr(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.#ti&&this.#ti.addShapeGroupListeners(a,e,this),this.setLabelVisibility(a)}#dr(e){const t=this.#pr(e);return t instanceof ai().Group?(t.remove(),!0):(c.debug("No shape group to remove"),!1)}#ur(e){this.#dr(e)&&this.#cr(e,!0)}fitToContainer(e,t,n){const i={x:t*this.#ct.x,y:t*this.#ct.y},r=i.x/this.#ht.x,o=i.y/this.#ht.y,a=e.x/(this.#rr.width()*r),s=e.y/(this.#rr.height()*o);this.#rr.width()===e.x&&this.#rr.height()===e.y||(this.#rr.width(e.x),this.#rr.height(e.y));const l={x:this.#rr.scale().x*r,y:this.#rr.scale().y*o};this.#rr.scale().x===l.x&&this.#rr.scale().y===l.y||(this.#ht=i,this.#rr.scale(l));const c={x:n.x/i.x,y:n.y/i.y},u={x:e.x/i.x,y:e.y/i.y},d={x:0!==this.#yt.x?u.x:0,y:0!==this.#yt.y?u.y:0};if(this.#mt.x!==c.x||this.#mt.y!==c.y||this.#yt.x!==d.x||this.#yt.y!==d.y){const e={x:this.#ft.x*a,y:this.#ft.y*s};this.#rr.offset({x:this.#rr.offset().x+c.x-this.#mt.x+d.x-this.#yt.x+e.x-this.#ft.x,y:this.#rr.offset().y+c.y-this.#mt.y+d.y-this.#yt.y+e.y-this.#ft.y}),this.#yt=d,this.#mt=c,this.#ft=e}}isAnnotationVisible(e){const t=this.#mr(e);return void 0!==t&&t.isVisible()}setAnnotationVisibility(e,t){const n=this.#mr(e);return void 0!==n&&(void 0===t&&(t=!n.isVisible()),n.visible(t),this.draw(),!0)}setLabelsVisibility(e){this.#sr=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.#fr(n,e)}}#fr(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.#fr(e,this.#sr)}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.#rr.listening(!0),this.#tt.style.pointerEvents="auto";const e=Wn;for(let t=0;te.id()===this.#ar));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.#ar),t.visible(!0),this.getKonvaLayer().add(t)):c.warn("Unexpected number of draw position groups"),t}#mr(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.#vt,this.#be.fireEvent(e)};#lr(e){const t=2/e.x,n=2/e.y,i=this.#rr.find("Label");for(let e=0;e{this.#Pr()};getDivId(){let e;return null!==this.#tt&&(e=this.#tt.id),e}getScale(){return this.#dt}getBaseScale(){return this.#zt}getAddedScale(){return{x:this.#dt.x/this.#zt.x,y:this.#dt.y/this.#zt.y,z:this.#dt.z/this.#zt.z}}getOffset(){return this.#St}getNumberOfLayers(){let e=0;return this.#yr.forEach((t=>{void 0!==t&&e++})),e}includes(e){if(void 0===e)return!1;for(const t of this.#yr)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.#yr)n instanceof _n&&e(n)&&t.push(n);return t}someViewLayer(e){let t=!1;for(const n of this.#yr)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.#yr)n instanceof Zi&&e(n)&&t.push(n);return t}getNumberOfViewLayers(){let e=0;return this.#yr.forEach((t=>{void 0!==t&&t instanceof _n&&e++})),e}getActiveLayer(){let e;return void 0!==this.#Cr&&(e=this.#yr[this.#Cr]),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.#yr)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.#yr)n instanceof _n&&n.getViewController().equalImageMeta(e)&&t.push(n);return t}getViewDataIndices(){const e=[];for(const t of this.#yr)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.#Cr=e,this.#Fe({type:"activelayerchange",value:[this.#yr[e]]})}setActiveLayerByDataId(e){let t;for(let n=0;n0;)e[0].remove()}removeLayersByDataId(e){for(const t of this.#yr)void 0!==t&&t.getDataId()===e&&this.removeLayer(t)}removeLayer(e){const t=this.#yr.findIndex((t=>t===e));if(-1===t)throw new Error("Cannot find layer to remove");this.#Cr===t&&(this.#Cr=void 0),e instanceof _n?this.#xr(e):this.#Rr(e),this.#yr[t]=void 0,this.#Ke=void 0,e.removeFromDOM()}#Pr(e){let t;void 0===e&&(e=this.#Be),this.#wr();for(const e of this.#yr)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.#Ir.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.#Ir.push(e),this.#tt.appendChild(e)}}#wr(){for(const e of this.#Ir)e.remove();this.#Ir=[]}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.#Tr=t,this.#tt.appendChild(t)}}removeTooltipDiv(){void 0!==this.#Tr&&(this.#Tr.remove(),this.#Tr=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.#yr)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.#vr&&this.#Pr(n);const i={};let r,o;for(const a of this.#yr){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.#yr)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 with id '"+this.#tt.id+"'.");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.#yr)void 0!==t&&t.fitToContainer(n,e,i);this.#vr&&this.#Pr()}getMaxWorldSize(){let e={x:0,y:0};for(const t of this.#yr)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.#zt.z*=-1,this.setScale(this.#zt)}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.#yr)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.#St.x-e.x,y:this.#St.y-e.y,z:this.#St.z-e.z})}setOffset(e){this.#St=e;for(const e of this.#yr)void 0!==e&&e.setOffset(this.#St);this.#Fe({type:"offsetchange",value:[this.#St.x,this.#St.y,this.#St.z]})}reset(){this.setScale(this.#zt),this.setOffset({x:0,y:0,z:0})}draw(){for(const e of this.#yr)void 0!==e&&e.draw()}display(e){for(const t of this.#yr)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;#It=!1;#qr=[];#ri=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.#It);const n=this.#ri&&0!==this.#ri.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.#Mr(t,e),e.getCallback(this.#Fr[t])(n),this.#Ur(t,e)}},this.#ri[t].push(n)),n.callback}#Ur(e,t){for(let n=0;n0&&(this.dispatchEvent(new Event("undo")),--this.#zr,this.#Hr[this.#zr].undo())}redo(){this.#zr{const n=t.value[0];void 0!==n&&this.#_r(e,n)}}#Jr(e){e.bindInteraction();const t=Wn;for(let n=0;n{if(this.#Yr){const t=this.#Yr[e.type];t&&t(e)}};this.#ri[e][t]=n}return this.#ri[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{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{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()}#go(e){this.#oo.push(e)}#do(){this.#oo=[]}#So(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{s{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.#go(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{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{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;e0){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.#vo(),this.onerror({error:e}),this.onworkend({type:"work-end"})};#vo(){this.taskQueue=[];for(let e=0;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 gr(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;i2){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{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;n2^"+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()}#So(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{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{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{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 g=h.getContext("2d");e.addEventListener("seeked",(function h(f){(function(){i({lengthComputable:!0,loaded:S,total:c,index:a,source:o}),g.drawImage(e,0,0);const n=co(g.getImageData(0,0,s,l));if(0===S){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,S);++S})(),m+=1/30,m<=f.target.duration?this.currentTime=m:(n({source:o}),r({source:o}),e.removeEventListener("seeked",h))}),!1);let S=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.#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,go().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=[]}#So(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{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.#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{e.dataid===this.#vt&&void 0!==e.data&&void 0!==e.data.imageUid&&this.#Sa!==e.data.imageUid&&(this.#Sa=e.data.imageUid,this.#ma(e))};#ma=e=>{if(e.dataid!==this.#vt)return;const t=this.#ga[this.#Sa];if(void 0!==t){for(let n=0;n{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{if(0===e.length)return c.warn("Ignoring empty input file list."),"-1";const t=this.#fa.getNextDataId();return this.#ya.loadFiles(e,t),t};loadURLs=(e,t)=>{if(0===e.length)return c.warn("Ignoring empty input url list."),"-1";const n=this.#fa.getNextDataId();return this.#ya.loadURLs(e,n,t),n};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{const t=this.#fa.getNextDataId();return this.#ya.loadImageObject(e,t),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{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;ee.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=>{let t;void 0===e.data&&c.error("Missing loaditem event data."),void 0===e.loadtype&&c.error("Missing loaditem event load type."),"image"===e.loadtype?t=e.data.meta:"state"===e.loadtype&&(t="state"),this.#Fe({type:"loaditem",data:t,source:e.source,loadtype:e.loadtype,dataid:e.dataid,isfirstitem:e.isfirstitem,warn:e.warn});const n=e.isfirstitem;"image"===e.loadtype?n?this.#fa.add(e.dataid,e.data):this.#fa.update(e.dataid,e.data):"state"===e.loadtype&&this.applyJsonState(e.data,e.dataid),void 0!==this.#Ia&&void 0!==this.#Ia[e.dataid]&&this.#Ia[e.dataid].addItemMeta(t),"image"===e.loadtype&&0!==this.getViewConfigs(e.dataid).length&&n&&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{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 g=c.getViewController();if(void 0!==t.wlPresetName)g.setWindowLevelPreset(t.wlPresetName);else if(void 0!==t.windowCenter&&void 0!==t.windowWidth){const e=new u(t.windowCenter,t.windowWidth);g.setWindowLevel(e)}void 0!==t.colourMap?g.setColourMap(t.colourMap):s||("PT"===n.image.getMeta().Modality?g.setColourMap("hot"):g.setColourMap("rainbow")),this.#fa.addEventListener("dataimageset",c.onimageset);const S=[g.getCurrentIndex().getValues(),g.getCurrentPosition().getValues()];i.updateLayersToPositionChange({value:S,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(),g=u.getSpacing(d).get2D(),S=n.addDrawLayer();S.initialise(h,g,a.getId());const p=new Gn(u,d);S.setPlaneHelper(p);const m=[l.getCurrentIndex().getValues(),l.getCurrentPosition().getValues()];n.updateLayersToPositionChange({value:m,srclayerid:S.getId()}),this.#Ca.fitToContainer(),S.setOffset(n.getOffset());const f=this.#Ua(u.getOrientation(),t.orientation);this.#Ma(f,S),S.initScale(n.getScale(),a.getAbsoluteZoomOffset()),S.setAnnotationGroup(i.annotationGroup,e,this.addToUndoStack),S.setCurrentPosition(l.getCurrentPosition(),l.getCurrentIndex()),this.#Ca.bindLayerGroups(),this.#Da&&this.#Da.bindLayerGroup(n,S),this.#Fe({type:"drawlayeradd",layerid:S.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===St.Axial,o=!i&&t===St.Coronal,a=!i&&t===St.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{#Ii;#Qa;constructor(e){this.#Ii=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;ie.number===this.#Na.number))}execute(){0!==this.#Ga.length&&this.#Ii.setAtOffsets(this.#Ga,0),new wo(this.#Ii).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.#Ii.setAtOffsets(this.#Ga,this.#Na.number):this.#Ii.setAtOffsets(this.#Ga,this.#Na.displayValue)),new wo(this.#Ii).addSegment(this.#Na),this.onUndo({type:"masksegmentredraw",segmentnumber:this.#Na.number})}onExecute(e){}onUndo(e){}}class Ao{#Ii;#Na;#ka;#Ha;#Ba;#Ga;constructor(e,t,n,i){this.#Ii=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.#Ii.setAtOffsets(this.#Ga,this.#ka),this.#Na.displayValue=this.#ka):(this.#Ii.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.#Ii.setAtOffsets(this.#Ga,this.#Ha),this.#Na.displayValue=this.#Ha):(this.#Ii.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 St},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 ge},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();tthis.#d?this.#c:e*this.#h+this.#g}}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;t255?255:t})),green:g((function(e){const t=256/3;let n=0;return e>=t&&(n=3*(e-t),n>255)?255:n})),blue:g((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)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;i0?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=e.length)throw new Error("Non valid dimension for toStringId");let n="";for(let i=0;i=e.length)&&(n=0),(void 0===i||i<=n||i>e.length)&&(i=e.length);for(let r=n;ro;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;e2^"+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;t8&&"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=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(;n1&&t.length>e){const n=t.length/e,i=[];let o=0;for(let r=0;r{if(void 0===this.#z[e.type])return;const t=this.#z[e.type].slice();for(let n=0;n2?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),g=r.get(2);let S=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=g*h,D=1===e.index?f(u,c,o,d,h,S,n,r):f(u,c,o,S,g,d,n,r);else{if(1!==t.index)throw new Error("Unknown direction: "+t.index);o=g*d,D=0===e.index?f(u,c,o,1,d,S,n,r):f(u,c,o,S,g,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=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;ethis.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;in-1)throw new Error("Wrong input dir value: "+t[e]);for(let n=0;n=0&&ithis.length()-1)throw new Error("Invalid start value for indexToOffset");let n=0;for(let i=t;i0;--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;sn&&(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;nw&&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 gt(){return new A([1,0,0,0,0,1,0,-1,0])}const St={Axial:"axial",Coronal:"coronal",Sagittal:"sagittal"};function pt(e){let t;return e===St.Axial?t=b():e===St.Coronal?t=gt():e===St.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=St.Axial:["LSA","LIP","RSP","RIA","ILA","IRP","SLP","SRA"].includes(e)?t=St.Coronal:["PSL","PIR","ASR","AIL","IAR","IPL","SAL","SPR"].includes(e)&&(t=St.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=9?lt(r):void 0}}(h);g=e.date,S=e.time}void 0===S&&(S={hours:0,minutes:0,seconds:0,milliseconds:0}),a=new Date(g.year,g.monthIndex,g.day,S.hours,S.minutes,S.seconds,S.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 g="ActualFrameDuration (0018,1242)",S=e["00181242"];if(n+=Lt(S,g),void 0!==S&&(h=S.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 g;if(void 0!==u&&void 0!==a&&void 0!==r&&void 0!==o){const e=(u.getTime()-a.getTime())/1e3;g=r*Math.pow(2,-e/o)}return{value:g,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,n;const i=["00280030","00181164","00182010","00280034"];for(let r=0;rparseFloat(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>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;r1){let t="";for(let n=0;npe(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=Se(),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}#ge(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;t1&&(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;iObject.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",gn="0062000F",Sn="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}else c.warn("No recommended colour for segment, using default"),t.displayRGBValue=function(e){const t=[new D(0,0,0),new D(255,0,0),new D(0,255,0),new D(0,0,255),new D(255,255,0),new D(0,255,255),new D(255,0,255),new D(255,239,213),new D(0,0,205),new D(205,133,63),new D(210,180,140),new D(102,205,170),new D(0,0,128),new D(0,139,139),new D(46,139,87),new D(255,228,225)];let n;return n=e1&&(y=!0,p=new m(h,g,S));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;ew;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;eo)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=0;--i){const a=Number.parseInt(o[i],10);S.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})}g.push(c)}}r.NumberOfFrames=S.length.toString();const m=[];for(const e of g)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=S.length*D/8,C=new ve("OB");return C.tag=new de("7FE0","0010"),C.vl=y,C.value=S,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=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=3&&(r=i.getDimSize(3));for(let i=0;it&&(t=n),nn?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;it&&(t=n),ni&&(i=r),ra&&(a=s),s{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{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(gt().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 nt(n(e.getSpacing().getValues(),t.getSpacing().getValues())),r=e.getRange(),o=t.getRange(),a=n(r[0].getValues(),o[0].getValues()),s=(l=r[1].getValues(),c=o[1].getValues(),l.map(((e,t)=>Math.max(e,c[t]))));var l,c;const u=[];for(let e=0;e{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{this.#vt===e.dataid&&(this.#nt.setImage(e.value[0]),this.#bt(this.#nt.getImageSize().get2D()),this.#Ct=!0)};bindImage(){this.#nt&&this.#nt.bindImageAndLayer(this)}unbindImage(){this.#nt&&this.#nt.unbindImageAndLayer(this)}onimagecontentchange=e=>{this.#vt===e.dataid&&(this.#at=this.#nt.isPositionInBounds(),this.#Ct=!0,this.draw())};onimagegeometrychange=e=>{if(this.#vt===e.dataid){const e=this.#nt.getImageSize().get2D();if(this.#lt.x!==e.x||this.#lt.y!==e.y){if(void 0!==this.#Tt&&void 0!==this.#Lt){const e=this.#nt.getOrigin(),t=this.#Lt.minus(e),n=this.#nt.getOrigin(this.#nt.getCurrentPosition()),i=this.#Tt.minus(n);this.setBaseOffset(t,i)}this.#bt(e),this.#Ct=!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.#yt.x+=this.#it.width/this.#dt.x,this.#St.x+=this.#yt.x}addFlipOffsetY(){this.#yt.y+=this.#it.height/this.#dt.y,this.#St.y+=this.#yt.y}flipScaleX(){this.#gt.x*=-1}flipScaleY(){this.#gt.y*=-1}flipScaleZ(){this.#gt.z*=-1}setScale(e,t){const n=this.#nt.getPlaneHelper(),i=n.getTargetOrientedPositiveXYZ({x:e.x*this.#gt.x,y:e.y*this.#gt.y,z:e.z*this.#gt.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.#St.x-this.#ft.x,y:this.#St.y-this.#ft.y};this.#ft={x:0,y:0},this.#St=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.#St,this.#dt,r,e),o={x:this.#ft.x+i.x-this.#St.x,y:this.#ft.y+i.y-this.#St.y};this.#ft=o,this.#St=i}this.#dt=r}initScale(e,t){const n=this.#nt.getPlaneHelper().getTargetOrientedPositiveXYZ({x:e.x*this.#gt.x,y:e.y*this.#gt.y,z:e.z*this.#gt.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.#St={x:this.#St.x+this.#ft.x,y:this.#St.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.#Tt=n,this.#Lt=i),s&&(this.#St={x:this.#St.x-this.#pt.x+a.x,y:this.#St.y-this.#pt.y+a.y},this.#pt=a),s}setOffset(e){const t=this.#nt.getPlaneHelper().getPlaneOffsetFromOffset3D(e);this.#St={x:this.#St.x-this.#Dt.x+t.x,y:this.#St.y-this.#Dt.y+t.y},this.#Dt=t}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.#St.x,t.getY()+this.#St.y)}planePosToDisplay(e){let t=(e.getX()-this.#St.x+this.#pt.x)*this.#dt.x,n=(e.getY()-this.#St.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.#Ct&&this.#xt(),this.#ot.globalAlpha=this.#ut,this.clear(),this.#ot.setTransform(this.#dt.x,0,0,this.#dt.y,-1*this.#St.x*this.#dt.x,-1*this.#St.y*this.#dt.y),this.#ot.imageSmoothingEnabled=this.#It,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.#bt(e),this.#Ct=!0):alert("Error: failed to get the 2D context.")):alert("Error: no canvas.getContext method.")}#bt(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;const r={x:t*this.#ct.x,y:t*this.#ct.y},o=r.x/this.#ht.x,a=r.y/this.#ht.y,s=e.x/(this.#it.width*o),l=e.y/(this.#it.height*a);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 c={x:this.#dt.x*o,y:this.#dt.y*a};this.#dt.x===c.x&&this.#dt.y===c.y||(this.#ht=r,this.#dt=c,i=!0);const u={x:n.x/r.x,y:n.y/r.y},d={x:e.x/r.x,y:e.y/r.y},h={x:0!==this.#yt.x?d.x:0,y:0!==this.#yt.y?d.y:0};if(this.#mt.x!==u.x||this.#mt.y!==u.y||this.#yt.x!==h.x||this.#yt.y!==h.y){const e={x:this.#ft.x*s,y:this.#ft.y*l};this.#St={x:this.#St.x+u.x-this.#mt.x+h.x-this.#yt.x+e.x-this.#ft.x,y:this.#St.y+u.y-this.#mt.y+h.y-this.#yt.y+e.y-this.#ft.y},this.#yt=h,this.#mt=u,this.#ft=e,i=!0}i&&this.draw()}bindInteraction(){this.#tt.style.pointerEvents="auto";const e=Wn;for(let t=0;t{e.srclayerid=this.getId(),e.dataid=this.#vt,this.#be.fireEvent(e)};#xt(){this.#nt.generateImageData(this.#st),this.#rt.getContext("2d").putImageData(this.#st,0,0),this.#Ct=!1}#Pt=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#Ct=!0,this.draw())};#wt=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#Ct=!0,this.draw())};#Ot=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.#Ct=!0,this.draw())}else this.#at&&(this.#at=!1,this.clear())}};#At=e=>{void 0!==e.skipGenerate&&!0===e.skipGenerate||(this.#Ct=!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{#Rt=0;getSum(){return this.#Rt}add(e){this.#Rt+=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.#Rt=0}isTick(){return Math.abs(this.#Rt)>=1}}class Jn{#Ft;#Et=new Kn;constructor(e){this.#Ft=e}wheel(e){this.#Et.add(e);const t=this.#Et.getSum()>=0;if(!this.#Et.isTick())return;this.#Et.clear(),e.preventDefault();const n=Ki(e),i=this.#Ft.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{#qt;#Ut;constructor(e,t){this.#qt=e,this.#Ut=t}getBegin(){return this.#qt}getEnd(){return this.#Ut}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{#Mt;#Qt;constructor(e,t){this.#Mt=e,this.#Qt=t}getName(){return"AddAnnotation-"+this.#Mt.id}execute(){this.#Qt.addAnnotation(this.#Mt)}undo(){this.#Qt.removeAnnotation(this.#Mt.id)}}class li{#Mt;#Qt;constructor(e,t){this.#Mt=e,this.#Qt=t}getName(){return"RemoveAnnotation-"+this.#Mt.id}execute(){this.#Qt.removeAnnotation(this.#Mt.id)}undo(){this.#Qt.addAnnotation(this.#Mt)}}class ci{#Mt;#Qt;#Vt;#Nt;constructor(e,t,n,i){this.#Mt=e,this.#Qt=i,this.#Vt=t,this.#Nt=n}getName(){return"UpdateAnnotation-"+this.#Mt.id}execute(){const e=Object.keys(this.#Nt);for(const t of e)this.#Mt[t]=this.#Nt[t];this.#Qt.updateAnnotation(this.#Mt,e)}undo(){const e=Object.keys(this.#Vt);for(const t of e)this.#Mt[t]=this.#Vt[t];this.#Qt.updateAnnotation(this.#Mt,e)}}class ui{#Bt=10;#Gt="Verdana";#kt="#fff";#Ht="#ffff80";#zt={x:1,y:1};#Wt={x:1,y:1};#Yt=2;#Xt={x:.25,y:.25};#jt=.2;#Zt=3;getFontFamily(){return this.#Gt}getFontSize(){return this.#Bt}getStrokeWidth(){return this.#Yt}getTextColour(){return this.#kt}getLineColour(){return this.#Ht}setLineColour(e){this.#Ht=e}setBaseScale(e){this.#zt=e}setZoomScale(e){this.#Wt=e}getBaseScale(){return this.#zt}getZoomScale(){return this.#Wt}scale(e){return e/this.#zt.x}applyZoomScale(e){return{x:e/this.#Wt.x,y:e/this.#Wt.y}}applyZoomRatio(e){return e*this.#Wt.x/this.#Wt.y}getShadowOffset(){return this.#Xt}getTagOpacity(){return this.#jt}getTextPadding(){return this.#Zt}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 gi(e){return"shape"===e.name()}function Si(e){return"position-group"===e.name()}function pi(e){const t=e.getChildren(gi)[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{#Ft;#_t;constructor(e,t){this.#Ft=e,this.#_t=t}#Kt=null;#Jt=null;#$t;#Mt;#en=!1;setShape(e,t,n){if(this.#Jt=e,this.#$t=t,this.#Mt=n,this.#Jt){if(this.#tn(),this.#Kt=n.getFactory(),null===this.#Kt)throw new Error("Could not find a factory to update shape.");this.#nn()}}getShape(){return this.#Jt}getAnnotation(){return this.#Mt}isActive(){return this.#en}enable(){this.#en=!0,this.#Jt&&(this.#in(!0),this.#Jt.getLayer()&&this.#Jt.getLayer().draw())}disable(){this.#en=!1,this.#Jt&&(this.#in(!1),this.#Jt.getLayer()&&this.#Jt.getLayer().draw())}reset(){this.#Jt=void 0,this.#$t=void 0,this.#Mt=void 0}resetAnchors(){this.#tn(),this.#nn(),this.#in(!0)}#rn(e){this.#Jt&&this.#Jt.getParent()&&this.#Jt.getParent().find(".anchor").forEach(e)}#in(e){this.#rn((function(t){t.visible(e)}))}setAnchorsActive(e){let t=null;t=e?e=>{this.#on(e)}:e=>{this.#an(e)},this.#rn(t)}#tn(){this.#rn((function(e){e.remove()}))}#nn(){if(!this.#Jt||!this.#Jt.getLayer())return;const e=this.#Jt.getParent(),t=this.#Kt.getAnchors(this.#Jt,this.#Ft.getStyle());for(let n=0;n{e.cancelBubble=!0,t={mathShape:this.#Mt.mathShape,referencePoints:this.#Mt.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()n.getX()&&(e.x(n.getX()),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.#$t.getBaseSize(),t),void 0!==this.#Kt.constrainAnchorMove&&this.#Kt.constrainAnchorMove(t),this.#Kt.updateAnnotationOnAnchorMove(this.#Mt,t),this.#Kt.updateShapeGroupOnAnchorMove(this.#Mt,t,this.#Ft.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.#Mt.mathShape,referencePoints:this.#Mt.referencePoints},i=new ci(this.#Mt,t,n,this.#$t.getDrawController());this.#Ft.addToUndoStack(i),this.#_t({type:"annotationupdate",data:this.#Mt,dataid:this.#$t.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!"))}))}#an(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{#sn;constructor(){this.createTrashIcon()}createTrashIcon(){this.#sn=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.#sn.width(20),this.#sn.height(20),this.#sn.add(e),this.#sn.add(t)}activate(e){const t=e.getKonvaStage(),n=t.scale(),i=e.getKonvaLayer(),r={x:1/n.x,y:1/n.y};this.#sn.x(t.offset().x+t.width()/(2*n.x)),this.#sn.y(t.offset().y+t.height()/(15*n.y)),this.#sn.scale(r),i.add(this.#sn),i.draw()}changeChildrenColourOnTrashHover(e,t,n){if(this.isOverTrash(e))return this.changeGroupChildrenColour(this.#sn,"orange"),void this.changeGroupChildrenColour(t,"red");this.changeGroupChildrenColour(this.#sn,"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.#sn.remove()}isOverTrash(e){const t=this.#sn.width()*Math.abs(this.#sn.scaleX())/2,n=this.#sn.height()*Math.abs(this.#sn.scaleY())/2;return Math.abs(e.x-this.#sn.x()){this.#dn=e,this.#gn()})),e.on("mouseout",(()=>{this.onMouseOutShapeGroup(),this.#dn=void 0}))}#pn(e){e.off("mouseover"),e.off("mouseout")}addShapeGroupListeners(e,t,n){this.#Sn(e),this.#mn(e,t,n),this.#fn(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.#Ft.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)}))}#mn(e,t,n){const i=n.getKonvaLayer(),r=e.getChildren(gi)[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.#sn.activate(n),this.#ln.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.xt.getY()&&i.y{if(this.#sn.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()},g=this.#hn(h,n);if(this.#sn.isOverTrash(g)){e.x(o.x),e.y(o.y),this.#ln.disable(),this.#ln.reset(),this.#sn.changeGroupChildrenColour(e,l),t.mathShape=s.mathShape,t.referencePoints=s.referencePoints;const i=new li(t,n.getDrawController());this.#Ft.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.#Ft.addToUndoStack(i),this.#_t({type:"annotationupdate",data:t,dataid:n.getDataId(),keys:Object.keys(e)}),s={mathShape:e.mathShape,referencePoints:e.referencePoints}}this.#ln.setAnchorsActive(!0),this.#ln.resetAnchors()}i.draw(),o={x:r.x(),y:r.y()}}))}#fn(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.#Ft.addToUndoStack(r),this.#_t({type:"annotationupdate",data:t,dataid:n.getDataId(),keys:["labelPosition"]}),o=e}r={x:i.x(),y:i.y()}}))}removeShapeListeners(e){this.#pn(e),e.off("dblclick");const t=e.getChildren(gi)[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{#Dn=[];constructor(e){void 0!==e&&(this.#Dn=e)}getPoint(e){return this.#Dn[e]}getPoints(){return this.#Dn}getLength(){return this.#Dn.length}addPoint(e){this.#Dn.push(e)}addPoints(e){this.#Dn=this.#Dn.concat(e)}getCentroid(){let e,t=0,n=0,i=0;for(let e=0;e.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;nMath.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;n3)throw new Error("Too many points for a protractor");this.#Dn=e.slice(0,3)}getPoint(e){return this.#Dn[e]}getLength(){return this.#Dn.length}getCentroid(){return this.#Dn[1]}quantify(e,t){const n={};if(3===this.#Dn.length){let e=ei(new $n(this.#Dn[0],this.#Dn[1]),new $n(this.#Dn[1],this.#Dn[2]));e>180&&(e=360-e),n.angle={value:e,unit:"unit.degree"}}return n}}class Mi{#qt;#Ut;constructor(e,t){this.#qt=new R(Math.min(e.getX(),t.getX()),Math.min(e.getY(),t.getY())),this.#Ut=new R(Math.max(e.getX(),t.getX()),Math.max(e.getY(),t.getY()))}getBegin(){return this.#qt}getEnd(){return this.#Ut}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;eethis.getMax()?t:e))}}class Ni{getName(){return"Sharpen"}#On=null;setOriginalImage(e){this.#On=e}getOriginalImage(){return this.#On}update(){return this.getOriginalImage().convolute2D([0,-1,0,-1,5,-1,0,-1,0])}}class Bi{getName(){return"Sobel"}#On=null;setOriginalImage(e){this.#On=e}getOriginalImage(){return this.#On}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{#An;#vt;#Ft;constructor(e,t,n){this.#An=e,this.#vt=t,this.#Ft=n}getName(){return"Filter-"+this.#An.getName()}execute(){this.#Ft.setImage(this.#vt,this.#An.update()),this.#Ft.render(this.#vt);const e={type:"filterrun",id:this.getName(),dataId:this.#vt};this.onExecute(e)}undo(){this.#Ft.setImage(this.#vt,this.#An.getOriginalImage()),this.#Ft.render(this.#vt);const e={type:"filterundo",id:this.getName(),dataid:this.#vt};this.onUndo(e)}onExecute(e){}onUndo(e){}}const ki={},Hi={},zi={WindowLevel:class{#Ft;#bn=!1;#xn;#Rn;constructor(e){this.#Ft=e,this.#Rn=new Jn(e)}#Fn(e,t){const n=this.#Ft.getLayerGroupByDivId(t).getActiveViewLayer();void 0!==n&&n.getViewController().isMonochrome()&&(this.#bn=!0,this.#xn=e)}#En(e,t){if(!this.#bn)return;const n=this.#Ft.getLayerGroupByDivId(t).getActiveViewLayer();if(void 0===n)return;const i=n.getViewController(),r=e.getX()-this.#xn.getX(),o=this.#xn.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 g;h=(g=h)<1?1:g;const S=new u(d,h);i.setWindowLevel(S),this.#xn=e}#qn(){this.#bn&&(this.#bn=!1)}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup=e=>{this.#qn()};mouseout=e=>{this.#qn()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#En(t[0],n.groupDivId)};touchend=e=>{this.#qn()};dblclick=e=>{const t=Ki(e),n=jn(e),i=this.#Ft.getLayerGroupByDivId(t.groupDivId).getActiveViewLayer();if(void 0===i)return;const r=i.displayToPlaneIndex(n),o=i.getViewController();if(!o.isMonochrome())return;const a=this.#Ft.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.#Rn.wheel(e)};keydown=e=>{e.context="WindowLevel",this.#Ft.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Scroll:class{#Ft;#bn=!1;#xn;#Rn;#Un;#Mn=!1;#Qn;constructor(e){this.#Ft=e,this.#Rn=new Jn(e)}#Vn(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}#Fn(e,t){this.#Nn();const n=this.#Ft.getLayerGroupByDivId(t),i=this.#Vn(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.#bn=!0,this.#xn=e}#En(e,t){if(!this.#bn)return void(this.#Mn&&this.#Bn(e,t));const n=this.#Ft.getLayerGroupByDivId(t),i=n.getPositionHelper(),r=e.getY()-this.#xn.getY(),o=Math.abs(r)>15,a=e.getX()-this.#xn.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.#xn=e)}#qn(){this.#bn&&(this.#bn=!1)}mousedown=e=>{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup=e=>{this.#qn()};mouseout=e=>{this.#qn(),this.#Nn()};touchstart=e=>{this.#Un=setTimeout((()=>{this.dblclick(e)}),500);const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchmove=e=>{null!==this.#Un&&(clearTimeout(this.#Un),this.#Un=null);const t=Xn(e),n=Ki(e);this.#En(t[0],n.groupDivId)};touchend=e=>{null!==this.#Un&&(clearTimeout(this.#Un),this.#Un=null),this.#qn()};wheel=e=>{this.#Rn.wheel(e)};keydown=e=>{e.context="Scroll",this.#Ft.onKeydown(e)};dblclick=e=>{const t=Ki(e),n=this.#Ft.getLayerGroupByDivId(t.groupDivId).getActiveViewLayer();void 0!==n&&n.getViewController().play()};#Bn(e,t){const n=this.#Ft.getLayerGroupByDivId(t);this.#Qn=t,n.showTooltip(e)}#Nn(){void 0!==this.#Qn&&(this.#Ft.getLayerGroupByDivId(this.#Qn).removeTooltipDiv(),this.#Qn=void 0)}activate(e){e||this.#Nn()}setFeatures(e){void 0!==e.displayTooltip&&(this.#Mn=e.displayTooltip)}init(){}},ZoomAndPan:class{#Ft;#bn=!1;#xn;#Gn;#kn;#Hn;constructor(e){this.#Ft=e}#Vn(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}#Fn(e){this.#bn=!0,this.#xn=e,this.#Gn=!1}#zn=e=>{this.#bn=!0,this.#xn=e[0],this.#Gn=!1,this.#kn=new $n(e[0],e[1]),this.#Hn=this.#kn.getMidpoint()};#En(e,t){if(!this.#bn)return;this.#Gn=!0;const n=e.getX()-this.#xn.getX(),i=e.getY()-this.#xn.getY(),r=this.#Ft.getLayerGroupByDivId(t),o=this.#Vn(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.#xn=e}#Wn=(e,t)=>{if(!this.#bn)return;this.#Gn=!0;const n=new $n(e[0],e[1]).getLength()/this.#kn.getLength(),i=this.#Ft.getLayerGroupByDivId(t),r=i.getPositionHelper();if(1===n){const t=e[0].getY()-this.#xn.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.#Hn){const t=this.#Vn(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.#Hn),o=n.getPlanePositionFromPlanePoint(r);i.addScale(e,o),i.draw()}}};#Yn(e,t){const n=this.#Ft.getLayerGroupByDivId(t),i=this.#Vn(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)}#qn(){this.#bn&&(this.#bn=!1)}mousedown=e=>{const t=jn(e);this.#Fn(t)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup=e=>{if(!this.#Gn){const t=jn(e),n=Ki(e);this.#Yn(t,n.groupDivId)}this.#qn()};mouseout=e=>{this.#qn()};touchstart=e=>{const t=Xn(e);1===t.length?this.#Fn(t[0]):2===t.length&&this.#zn(t)};touchmove=e=>{const t=Xn(e),n=Ki(e);1===t.length?this.#En(t[0],n.groupDivId):2===t.length&&this.#Wn(t,n.groupDivId)};touchend=e=>{if(!this.#Gn){const t=jn(e),n=Ki(e);this.#Yn(t,n.groupDivId)}this.#qn()};wheel=e=>{e.preventDefault();const t=-e.deltaY/500,n=Ki(e),i=jn(e),r=this.#Ft.getLayerGroupByDivId(n.groupDivId),o=this.#Vn(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.#Ft.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Opacity:class{#Ft;#bn=!1;#xn;#Rn;constructor(e){this.#Ft=e,this.#Rn=new Jn(e)}#Fn(e){this.#bn=!0,this.#xn=e}#En(e,t){if(!this.#bn)return;const n=e.getX()-this.#xn.getX();if(Math.abs(n)>15){const i=this.#Ft.getLayerGroupByDivId(t).getActiveLayer(),r=i.getOpacity();i.setOpacity(r+n/200),i.draw(),this.#xn=e}}#qn(){this.#bn&&(this.#bn=!1)}mousedown=e=>{const t=jn(e);this.#Fn(t)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup=e=>{this.#qn()};mouseout=e=>{this.#qn()};touchstart=e=>{const t=Xn(e);this.#Fn(t[0])};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#En(t[0],n.groupDivId)};touchend=e=>{this.#qn()};wheel=e=>{this.#Rn.wheel(e)};keydown=e=>{e.context="Opacity",this.#Ft.onKeydown(e)};activate(e){}init(){}setFeatures(e){}},Draw:class{#Ft;#Rn;#Xn;#jn=!1;#Zn=null;#Kt=null;#_n=null;#Kn;#Dn=[];#Jn=null;#$n=!0;#ei=[];#ti;#ni=!1;#z={};#ii=!1;#ri=[];constructor(e){this.#Ft=e,this.#Rn=new Jn(e),this.#ti=new Ii(e,this.#Fe),this.#Xn=e.getStyle()}#oi(e,t){const n=this.#Ft.getLayerGroupByDivId(t);let i=n.getActiveDrawLayer();if(void 0===i){const e=n.getActiveViewLayer().getDataId(),r=this.#Ft.getData(e).image.getMeta().SeriesInstanceUID;if(this.#ei.includes(r))return void this.#Fe({type:"warn",message:"Cannot create draw layer, data is in black list"});const o=this.#Ft.createAnnotationData(e);this.#Ft.addAndRenderAnnotationData(o,t,e),i=n.getActiveDrawLayer(),i.setShapeHandler(this.#ti),n.setActiveLayerByDataId(i.getDataId())}const r=i.getDrawController().getAnnotationGroup(),o=i.getKonvaStage();if(this.#Xn.setZoomScale(o.scale()),r.isEditable()){const t=o.getIntersection({x:e.getX(),y:e.getY()});t?this.#ai(i,t):this.#si(n,e)}}#Vn(e){const t=e.getActiveDrawLayer();if(void 0!==t)return e.getViewLayerById(t.getReferenceLayerId());c.warn("No draw layer to do draw")}#si(e,t){this.#ti.disableAndResetEditor(),this.#li();const n=this.#Vn(e);void 0!==n?(this.#Jn=n.displayToPlanePos(t),this.#Dn.push(this.#Jn)):c.warn("No view layer to start shape")}#li(){this.#jn=!0,this.#Kt=new this.#Zn[this.#Kn],this.#Dn=[]}#ci(){this.#jn=!1,this.#Dn=[]}#ai(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.#ti.setEditorShape(i,e))}#ui(e,t){const n=this.#Ft.getLayerGroupByDivId(t),i=this.#Vn(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.#Jn.getX())>0||Math.abs(r.getY()-this.#Jn.getY())>0)&&(this.#ii&&this.#Dn.pop(),this.#Jn=r,this.#ii=!0,this.#Dn.push(this.#Jn),this.#di(this.#Dn,n))}#hi(e){if(0!==this.#Dn.length){if(this.#Dn.length===this.#Kt.getNPoints()){const t=this.#Ft.getLayerGroupByDivId(e);this.#gi(this.#Dn,t),this.#ci()}this.#ii=!1}else c.warn("Draw mouseup but no points...")}mousedown=e=>{if(this.#jn)return;const t=jn(e),n=Ki(e);this.#oi(t,n.groupDivId)};mousemove=e=>{if(!this.#jn)return;const t=jn(e),n=Ki(e);this.#ui(t,n.groupDivId)};mouseup=e=>{if(!this.#jn)return;const t=Ki(e);this.#hi(t.groupDivId)};dblclick=e=>{if(this.#Kt&&void 0!==this.#Kt.getNPoints())return;if(!this.#jn)return;if(0===this.#Dn.length)return void c.warn("Draw dblclick but no points...");const t=Ki(e),n=this.#Ft.getLayerGroupByDivId(t.groupDivId);this.#gi(this.#Dn,n),this.#ci()};mouseout=e=>{if(!this.#jn)return;const t=Ki(e);this.#hi(t.groupDivId)};touchstart=e=>{if(this.#jn)return;const t=Xn(e),n=Ki(e);this.#oi(t[0],n.groupDivId)};touchmove=e=>{if(!this.#jn)return;const t=Ki(e),n=Xn(e),i=this.#Ft.getLayerGroupByDivId(t.groupDivId),r=this.#Vn(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.#Jn.getX())>0||Math.abs(o.getY()-this.#Jn.getY())>0)&&(1!==this.#Dn.length&&this.#Dn.pop(),this.#Jn=o,this.#Dn.push(this.#Jn),this.#Dn.length{this.#Dn.push(this.#Jn)}),this.#Kt.getTimeout())),this.#di(this.#Dn,i))};touchend=e=>{this.dblclick(e)};wheel=e=>{this.#$n&&this.#Rn.wheel(e)};keydown=e=>{this.#jn||(e.context="Draw",this.#Ft.onKeydown(e));const t=this.#ti.getEditorAnnotation();if(("Delete"===e.key||"Backspace"===e.key)&&void 0!==t){const e=this.#Ft.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.#Ft.addToUndoStack(i),i.execute(),this.#ti.onMouseOutShapeGroup()}if("Escape"===e.key&&null!==this.#_n){const e=this.#_n.getLayer();this.#_n.destroy(),this.#_n=null,this.#ci(),e.draw()}};#di(e,t){this.#_n&&(this.#_n.destroy(),this.#_n=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.#ni){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.#Xn.setLineColour(r)}const s=new Yi,l=i.getAnnotationGroup().getColour();s.colour=void 0!==l?l:this.#Xn.getLineColour(),s.init(a),this.#Kt.setAnnotationMathShape(s,e),this.#_n=this.#Kt.createShapeGroup(s,this.#Xn),n.setLabelVisibility(this.#_n),this.#_n.getChildren(gi)[0].listening(!1),r.listening(!1),r.add(this.#_n),r.draw()}#gi(e,t){this.#_n&&(this.#_n.destroy(),this.#_n=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.#Xn.getLineColour(),s.id=et(),s.init(a),this.#Kt.setAnnotationMathShape(s,e);const u=new si(s,r);this.#Ft.addToUndoStack(u),u.execute(),i.listening(!0)}#Si(e){const t=e.getId();return void 0===this.#ri[t]&&(this.#ri[t]=()=>{e.activateCurrentPositionShapes(!0)}),this.#ri[t]}#pi(e,t){e.setShapeHandler(this.#ti),e.activateCurrentPositionShapes(t),t?this.#Ft.addEventListener("positionchange",this.#Si(e)):this.#Ft.removeEventListener("positionchange",this.#Si(e))}activate(e){e||this.#ti.onMouseOutShapeGroup();const t=this.#Ft.getDrawLayers();for(const n of t)void 0!==n&&this.#pi(n,e);this.#Ft.addEventListener("drawlayeradd",(t=>{const n=this.#Ft.getDrawLayers((function(e){return e.getId()===t.layerid}));1===n.length&&this.#pi(n[0],e)}))}setOptions(e){this.#Zn=e}getOptionsType(){return"factory"}setFeatures(e){if(void 0!==e.autoShapeColour&&(this.#ni=e.autoShapeColour),void 0!==e.shapeColour&&(this.#Xn.setLineColour(e.shapeColour),this.#ni=!1),void 0!==e.shapeName){if(!this.hasShape(e.shapeName))throw new Error("Unknown shape: '"+e.shapeName+"'");this.#Kn=e.shapeName}void 0!==e.mouseOverCursor&&this.#ti.storeMouseOverCursor(e.mouseOverCursor),void 0!==e.withScroll&&(this.#$n=e.withScroll),void 0!==e.blacklist&&(this.#ei=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{if(void 0!==this.#z[e.type])for(let t=0;t{e.context="Filter",this.#Ft.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.#fi}setFeatures(e){if(void 0!==e.filterName){if(!this.hasFilter(e.filterName))throw new Error("Unknown filter: '"+e.filterName+"'");this.#fi&&this.#fi.activate(!1),this.#fi=this.#mi[e.filterName],this.#fi.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.#mi}hasFilter(e){return this.#mi[e]}},Floodfill:class{#Ft;constructor(e){this.#Ft=e}#Di=5;#yi=0;#Ci=2e3;#vi=null;#Ii=null;#Ti=10;#Li=null;#bn=!1;#Mt;#Pi;#wi=null;#Oi=[];#Ai=!1;#Xn=new ui;setExtend(e){this.#Ai=e}getExtend(){return this.#Ai}#Vn(e){const t=e.getActiveDrawLayer();if(void 0!==t)return e.getViewLayerById(t.getReferenceLayerId());c.warn("No draw layer to do floodfill")}#bi=(e,t)=>{const n=this.#Ft.getLayerGroupByDivId(t),i=this.#Vn(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)}};#xi(e,t,n){this.#Oi=[];const i={data:this.#vi.data,width:this.#vi.width,height:this.#vi.height,bytes:4};this.#Ii=Pi().floodFill(i,e.x,e.y,t),this.#Ii=Pi().gaussBlurOnlyBorder(this.#Ii,this.#Di);let r=Pi().traceContours(this.#Ii);if(r=Pi().simplifyContours(r,this.#yi,this.#Ci),r.length>0&&r[0].points[0].x){if(n)return r[0].points;for(let e=0,t=r[0].points.length;er&&this.#Ri(this.#Pi,l,n);t--)i.decrementPositionAlongScroll();o.setCurrentIndex(a)}onThresholdChange(e){}#Fn(e,t){this.#Mt=void 0;const n=this.#Ft.getLayerGroupByDivId(t);let i,r=n.getActiveDrawLayer();if(void 0===r){i=n.getActiveViewLayer();const e=i.getDataId(),o=this.#Ft.createAnnotationData(e);this.#Ft.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.#vi=i.getImageData(),this.#vi?(this.#Xn.setZoomScale(r.getKonvaLayer().getAbsoluteScale()),this.#bn=!0,this.#Pi=this.#bi(e,t),this.#Ri(this.#Pi,this.#Ti,n),this.onThresholdChange(this.#Ti)):c.error("No image found")}#En(e,t){if(!this.#bn)return;const n=this.#bi(e,t);this.#Li=Math.round(Math.sqrt(Math.pow(this.#Pi.x-n.x,2)+Math.pow(this.#Pi.y-n.y,2))/2),this.#Li=this.#Li{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup=e=>{this.#qn()};mouseout=e=>{this.#qn()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#En(t[0],n.groupDivId)};touchend=e=>{this.#qn()};keydown=e=>{e.context="Floodfill",this.#Ft.onKeydown(e)};activate(e){e&&(this.#Xn.setBaseScale(this.#Ft.getBaseScale()),this.setFeatures({shapeColour:this.#Xn.getLineColour()}))}init(){}setFeatures(e){void 0!==e.shapeColour&&this.#Xn.setLineColour(e.shapeColour)}},Livewire:class{#Ft;constructor(e){this.#Ft=e}#bn=!1;#xn;#Mt;#Xn=new ui;#Fi=new wi;#Ei=new wi;#Oi=[];#qi=5;#Ui(e){const t=e.get(1);for(let e=0;e{const t=jn(e),n=Ki(e);this.#Fn(t,n.groupDivId)};mousemove=e=>{const t=jn(e),n=Ki(e);this.#En(t,n.groupDivId)};mouseup(e){}mouseout=e=>{};dblclick=e=>{this.#Vi()};touchstart=e=>{const t=Xn(e),n=Ki(e);this.#Fn(t[0],n.groupDivId)};touchmove=e=>{const t=Xn(e),n=Ki(e);this.#En(t[0],n.groupDivId)};touchend=e=>{};keydown=e=>{e.context="Livewire",this.#Ft.onKeydown(e)};activate(e){e&&(this.#Xn.setBaseScale(this.#Ft.getBaseScale()),this.setFeatures({shapeColour:this.#Xn.getLineColour()}))}init(){}setFeatures(e){void 0!==e.shapeColour&&this.#Xn.setLineColour(e.shapeColour)}}},Wi={draw:{ArrowFactory:class{#Ni="arrow";#Bi=new Ri(this.#Gi);static supports(e){return e instanceof R}getName(){return this.#Ni}getGroupName(){return this.#Ni+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#ki(t),e.referencePoints=[t[1]],e.setTextExpr(this.#Hi()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#zi(e,t);n.add(i);const r=this.#Wi(e,t);for(const e of r)n.add(e);const o=this.#Bi.create(e,t);n.add(o);const a=this.#Yi(i);return n.add(this.#Bi.getConnector(a,o,t)),n}#Yi(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)]}#Xi(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.#Xi(e),i=[];for(let e=0;e180&&(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"})]}#Gi(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)}#ji(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.#Zi(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),g=r.getInclination();h>180&&(h=360-h,g+=h);const S=33*Math.min(r.getLength(),o.getLength())/100;l.innerRadius(S),l.outerRadius(S),l.angle(h),l.rotation(-g);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)}))}#_i(e,t){}#Ki(e,t){}},RectangleFactory:class{#Ni="rectangle";#Bi=new Ri(this.#Gi);static supports(e){return e instanceof Mi}getName(){return this.#Ni}getGroupName(){return this.#Ni+"-group"}getNPoints(){return 2}getTimeout(){return 0}setAnnotationMathShape(e,t){e.mathShape=this.#ki(t),e.setTextExpr(this.#Hi()),e.updateQuantification()}createShapeGroup(e,t){const n=new(ai().Group);n.name(this.getGroupName()),n.visible(!0),n.id(e.id);const i=this.#zi(e,t);n.add(i);const r=this.#Bi.create(e,t);n.add(r);const o=this.#Yi(i);return n.add(this.#Bi.getConnector(o,r,t)),n}#Yi(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)]}#Xi(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.#Xi(e),i=[];for(let e=0;e{this.#be.fireEvent(e)}},Sobel:class{#Ft;constructor(e){this.#Ft=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.#Ft.getData(e.dataId).image;t.setOriginalImage(n);const i=new Gi(t,e.dataId,this.#Ft);i.onExecute=this.#Fe,i.onUndo=this.#Fe,i.execute(),this.#Ft.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{#Ft;constructor(e){this.#Ft=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.#Ft.getData(e.dataId).image;t.setOriginalImage(n);const i=new Gi(t,e.dataId,this.#Ft);i.onExecute=this.#Fe,i.onUndo=this.#Fe,i.execute(),this.#Ft.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))}#$i(){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&&void 0!==this.mathShape.getCentroid()){const t=this.#$i(),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;et.id===e.id));-1!==n?((t.includes("mathShape")||t.includes("textExpr"))&&e.updateQuantification(),this.#er[n]=e,this.#Fe({type:"annotationupdate",data:e,keys:t})):c.warn("Cannot find annotation to update")}remove(e){const t=this.#er.findIndex((t=>t.id===e));if(-1!==t){const e=this.#er.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.#er)t.setViewController(e),t.updateQuantification()}find(e){return this.#er.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{#ir;getAnnotation(e){return this.#ir.find(e)}getAnnotationGroup(){return this.#ir}isAnnotationGroupEditable(){return this.#ir.isEditable()}setAnnotationGroupEditable(e){this.#ir.setEditable(e)}addAnnotation(e){this.#ir.add(e)}updateAnnotation(e,t){this.#ir.update(e,t)}removeAnnotation(e){this.#ir.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.#ir.getList())this.removeAnnotationWithCommand(t.id,e)}constructor(e){this.#ir=void 0!==e?e:new Xi}hasAnnotationMeta(e){return this.#ir.hasMeta(e)}setAnnotationMeta(e,t){this.#ir.setMetaValue(e,t)}}class Zi{#tt;#rr=null;#lt;#ct;#ht={x:1,y:1};#gt={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};#yt={x:0,y:0};#Qt;#_e;#vt;#or;#ar;#ti;#sr=!0;constructor(e){this.#tt=e,this.#tt.className+=" drawLayer"}setShapeHandler(e){this.#ti=e}getDataId(){return this.#vt}getReferenceLayerId(){return this.#or}#be=new He;getKonvaStage(){return this.#rr}getKonvaLayer(){return this.#rr.getLayers()[0]}getDrawController(){return this.#Qt}setPlaneHelper(e){this.#_e=e}getId(){return this.#tt.id}removeFromDOM(){this.#tt.remove()}getBaseSize(){return this.#lt}getOpacity(){return this.#rr.opacity()}setOpacity(e){this.#rr.opacity(Math.min(Math.max(e,0),1))}addFlipOffsetX(){const e=this.#rr.scale(),t=this.#rr.size();this.#yt.x+=t.width/e.x;const n=this.#rr.offset();n.x+=this.#yt.x,this.#rr.offset(n)}addFlipOffsetY(){const e=this.#rr.scale(),t=this.#rr.size();this.#yt.y+=t.height/e.y;const n=this.#rr.offset();n.y+=this.#yt.y,this.#rr.offset(n)}flipScaleX(){this.#gt.x*=-1}flipScaleY(){this.#gt.y*=-1}flipScaleZ(){this.#gt.z*=-1}setScale(e,t){const n=this.#_e.getTargetOrientedPositiveXYZ({x:e.x*this.#gt.x,y:e.y*this.#gt.y,z:e.z*this.#gt.z}),i={x:this.#ht.x*n.x,y:this.#ht.y*n.y},r=this.#rr.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.#rr.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.#rr.scale(),i,e),o={x:this.#ft.x+n.x-r.x,y:this.#ft.y+n.y-r.y};this.#ft=o,this.#rr.offset(n)}this.#rr.scale(i),this.#lr(i)}initScale(e,t){const n=this.#_e.getTargetOrientedPositiveXYZ({x:e.x*this.#gt.x,y:e.y*this.#gt.y,z:e.z*this.#gt.z}),i={x:this.#ht.x*n.x,y:this.#ht.y*n.y};this.#rr.scale(i),this.#ft={x:t.x/this.#ht.x,y:t.y/this.#ht.y};const r=this.#rr.offset();this.#rr.offset({x:r.x+this.#ft.x,y:r.y+this.#ft.y})}setOffset(e){const t=this.#_e.getPlaneOffsetFromOffset3D(e),n=this.#rr.offset();this.#rr.offset({x:n.x-this.#Dt.x+t.x,y:n.y-this.#Dt.y+t.y}),this.#Dt=t}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.#rr.offset();this.#rr.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.#rr.draw()}initialise(e,t,n){this.#lt=e,this.#ct=t,this.#or=n,this.#rr=new(ai().Stage)({container:this.#tt,width:this.#lt.x,height:this.#lt.y,listening:!1}),this.#rr.getContent().setAttribute("style","");const i=new(ai().Layer)({listening:!1,visible:!0});this.#rr.add(i)}setAnnotationGroup(e,t,n){if(this.#vt=t,e.addEventListener("annotationadd",(e=>{this.#cr(e.data,!0),this.getKonvaLayer().draw()})),e.addEventListener("annotationupdate",(e=>{this.#ur(e.data),this.getKonvaLayer().draw()})),e.addEventListener("annotationremove",(e=>{this.#dr(e.data),this.getKonvaLayer().draw()})),e.addEventListener("annotationgroupeditablechange",(e=>{this.activateCurrentPositionShapes(e.data)})),this.#Qt=new ji(e),0!==e.getLength())for(const t of e.getList())this.#cr(t,!1),n(new si(t,this.getDrawController()))}activateCurrentPositionShapes(e){const t=this.getKonvaLayer();if(this.#rr.listening(!1),void 0!==this.#ti){this.#ti.disableAndResetEditor();const e=t.getChildren();for(const t of e)t instanceof ai().Group&&t.getChildren().forEach((e=>{e instanceof ai().Group&&this.#ti.removeShapeListeners(e)}))}const n=this.getDrawController();if(e&&n.getAnnotationGroup().isEditable()){this.#rr.listening(!0);const e=this.#hr().getChildren();0!==e.length&&t.listening(!0),void 0!==this.#ti&&e.forEach((e=>{if(e instanceof ai().Group){const t=n.getAnnotation(e.id());this.#ti.addShapeGroupListeners(e,t,this)}}))}t.draw()}#gr(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}#pr(e){let t;const n=this.#gr(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}#cr(e,t){if(!e.isCompatibleView(this.#_e))return;const n=this.#gr(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.#ti&&this.#ti.addShapeGroupListeners(a,e,this),this.setLabelVisibility(a)}#dr(e){const t=this.#pr(e);return t instanceof ai().Group?(t.remove(),!0):(c.debug("No shape group to remove"),!1)}#ur(e){this.#dr(e)&&this.#cr(e,!0)}fitToContainer(e,t,n){const i={x:t*this.#ct.x,y:t*this.#ct.y},r=i.x/this.#ht.x,o=i.y/this.#ht.y,a=e.x/(this.#rr.width()*r),s=e.y/(this.#rr.height()*o);this.#rr.width()===e.x&&this.#rr.height()===e.y||(this.#rr.width(e.x),this.#rr.height(e.y));const l={x:this.#rr.scale().x*r,y:this.#rr.scale().y*o};this.#rr.scale().x===l.x&&this.#rr.scale().y===l.y||(this.#ht=i,this.#rr.scale(l));const c={x:n.x/i.x,y:n.y/i.y},u={x:e.x/i.x,y:e.y/i.y},d={x:0!==this.#yt.x?u.x:0,y:0!==this.#yt.y?u.y:0};if(this.#mt.x!==c.x||this.#mt.y!==c.y||this.#yt.x!==d.x||this.#yt.y!==d.y){const e={x:this.#ft.x*a,y:this.#ft.y*s};this.#rr.offset({x:this.#rr.offset().x+c.x-this.#mt.x+d.x-this.#yt.x+e.x-this.#ft.x,y:this.#rr.offset().y+c.y-this.#mt.y+d.y-this.#yt.y+e.y-this.#ft.y}),this.#yt=d,this.#mt=c,this.#ft=e}}isAnnotationVisible(e){const t=this.#mr(e);return void 0!==t&&t.isVisible()}setAnnotationVisibility(e,t){const n=this.#mr(e);return void 0!==n&&(void 0===t&&(t=!n.isVisible()),n.visible(t),this.draw(),!0)}setLabelsVisibility(e){this.#sr=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.#fr(n,e)}}#fr(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.#fr(e,this.#sr)}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.#rr.listening(!0),this.#tt.style.pointerEvents="auto";const e=Wn;for(let t=0;te.id()===this.#ar));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.#ar),t.visible(!0),this.getKonvaLayer().add(t)):c.warn("Unexpected number of draw position groups"),t}#mr(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.#vt,this.#be.fireEvent(e)};#lr(e){const t=2/e.x,n=2/e.y,i=this.#rr.find("Label");for(let e=0;e{this.#Pr()};getDivId(){let e;return null!==this.#tt&&(e=this.#tt.id),e}getScale(){return this.#dt}getBaseScale(){return this.#zt}getAddedScale(){return{x:this.#dt.x/this.#zt.x,y:this.#dt.y/this.#zt.y,z:this.#dt.z/this.#zt.z}}getOffset(){return this.#St}getNumberOfLayers(){let e=0;return this.#yr.forEach((t=>{void 0!==t&&e++})),e}includes(e){if(void 0===e)return!1;for(const t of this.#yr)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.#yr)n instanceof _n&&e(n)&&t.push(n);return t}someViewLayer(e){let t=!1;for(const n of this.#yr)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.#yr)n instanceof Zi&&e(n)&&t.push(n);return t}getNumberOfViewLayers(){let e=0;return this.#yr.forEach((t=>{void 0!==t&&t instanceof _n&&e++})),e}getActiveLayer(){let e;return void 0!==this.#Cr&&(e=this.#yr[this.#Cr]),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.#yr)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.#yr)n instanceof _n&&n.getViewController().equalImageMeta(e)&&t.push(n);return t}getViewDataIndices(){const e=[];for(const t of this.#yr)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.#Cr=e,this.#Fe({type:"activelayerchange",value:[this.#yr[e]]})}setActiveLayerByDataId(e){let t;for(let n=0;n0;)e[0].remove()}removeLayersByDataId(e){for(const t of this.#yr)void 0!==t&&t.getDataId()===e&&this.removeLayer(t)}removeLayer(e){const t=this.#yr.findIndex((t=>t===e));if(-1===t)throw new Error("Cannot find layer to remove");this.#Cr===t&&(this.#Cr=void 0),e instanceof _n?this.#xr(e):this.#Rr(e),this.#yr[t]=void 0,this.#Ke=void 0,e.removeFromDOM(),this.#Fe({type:"layerremove",layerid:e.getId(),layergroupid:this.getDivId()})}#Pr(e){let t;void 0===e&&(e=this.#Be),this.#wr();for(const e of this.#yr)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.#Ir.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.#Ir.push(e),this.#tt.appendChild(e)}}#wr(){for(const e of this.#Ir)e.remove();this.#Ir=[]}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.#Tr=t,this.#tt.appendChild(t)}}removeTooltipDiv(){void 0!==this.#Tr&&(this.#Tr.remove(),this.#Tr=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.#yr)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.#vr&&this.#Pr(n);const i={};let r,o;for(const a of this.#yr){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.#yr)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 with id '"+this.#tt.id+"'.");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.#yr)void 0!==t&&t.fitToContainer(n,e,i);this.#vr&&this.#Pr()}getMaxWorldSize(){let e={x:0,y:0};for(const t of this.#yr)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.#zt.z*=-1,this.setScale(this.#zt)}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.#yr)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.#St.x-e.x,y:this.#St.y-e.y,z:this.#St.z-e.z})}setOffset(e){this.#St=e;for(const e of this.#yr)void 0!==e&&e.setOffset(this.#St);this.#Fe({type:"offsetchange",value:[this.#St.x,this.#St.y,this.#St.z]})}reset(){this.setScale(this.#zt),this.setOffset({x:0,y:0,z:0})}draw(){for(const e of this.#yr)void 0!==e&&e.draw()}display(e){for(const t of this.#yr)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;#It=!1;#qr=[];#ri=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.#It);const n=this.#ri&&0!==this.#ri.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.#Mr(t,e),e.getCallback(this.#Fr[t])(n),this.#Ur(t,e)}},this.#ri[t].push(n)),n.callback}#Ur(e,t){for(let n=0;n0&&(this.dispatchEvent(new Event("undo")),--this.#zr,this.#Hr[this.#zr].undo())}redo(){this.#zr{const n=t.value[0];void 0!==n&&this.#_r(e,n)}}#Jr(e){e.bindInteraction();const t=Wn;for(let n=0;n{if(this.#Yr){const t=this.#Yr[e.type];t&&t(e)}};this.#ri[e][t]=n}return this.#ri[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{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{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()}#go(e){this.#oo.push(e)}#do(){this.#oo=[]}#So(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{s{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.#go(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{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{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;e0){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.#vo(),this.onerror({error:e}),this.onworkend({type:"work-end"})};#vo(){this.taskQueue=[];for(let e=0;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 gr(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;i2){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{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;n2^"+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()}#So(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{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{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{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 g=h.getContext("2d");e.addEventListener("seeked",(function h(f){(function(){i({lengthComputable:!0,loaded:S,total:c,index:a,source:o}),g.drawImage(e,0,0);const n=co(g.getImageData(0,0,s,l));if(0===S){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,S);++S})(),m+=1/30,m<=f.target.duration?this.currentTime=m:(n({source:o}),r({source:o}),e.removeEventListener("seeked",h))}),!1);let S=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.#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,go().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=[]}#So(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{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.#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{e.dataid===this.#vt&&void 0!==e.data&&void 0!==e.data.imageUid&&this.#Sa!==e.data.imageUid&&(this.#Sa=e.data.imageUid,this.#ma(e))};#ma=e=>{if(e.dataid!==this.#vt)return;const t=this.#ga[this.#Sa];if(void 0!==t){for(let n=0;n{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{if(0===e.length)return c.warn("Ignoring empty input file list."),"-1";const t=this.#fa.getNextDataId();return this.#ya.loadFiles(e,t),t};loadURLs=(e,t)=>{if(0===e.length)return c.warn("Ignoring empty input url list."),"-1";const n=this.#fa.getNextDataId();return this.#ya.loadURLs(e,n,t),n};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{const t=this.#fa.getNextDataId();return this.#ya.loadImageObject(e,t),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{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;ee.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=>{let t;void 0===e.data&&c.error("Missing loaditem event data."),void 0===e.loadtype&&c.error("Missing loaditem event load type."),"image"===e.loadtype?t=e.data.meta:"state"===e.loadtype&&(t="state"),this.#Fe({type:"loaditem",data:t,source:e.source,loadtype:e.loadtype,dataid:e.dataid,isfirstitem:e.isfirstitem,warn:e.warn});const n=e.isfirstitem;"image"===e.loadtype?n?this.#fa.add(e.dataid,e.data):this.#fa.update(e.dataid,e.data):"state"===e.loadtype&&this.applyJsonState(e.data,e.dataid),void 0!==this.#Ia&&void 0!==this.#Ia[e.dataid]&&this.#Ia[e.dataid].addItemMeta(t),"image"===e.loadtype&&0!==this.getViewConfigs(e.dataid).length&&n&&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("layerremove",this.#Fe),e.addEventListener("renderstart",this.#Fe),e.addEventListener("renderend",this.#Fe);for(let t=0;t{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 g=c.getViewController();if(void 0!==t.wlPresetName)g.setWindowLevelPreset(t.wlPresetName);else if(void 0!==t.windowCenter&&void 0!==t.windowWidth){const e=new u(t.windowCenter,t.windowWidth);g.setWindowLevel(e)}void 0!==t.colourMap?g.setColourMap(t.colourMap):s||("PT"===n.image.getMeta().Modality?g.setColourMap("hot"):g.setColourMap("rainbow")),this.#fa.addEventListener("dataimageset",c.onimageset);const S=[g.getCurrentIndex().getValues(),g.getCurrentPosition().getValues()];i.updateLayersToPositionChange({value:S,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(),g=u.getSpacing(d).get2D(),S=n.addDrawLayer();S.initialise(h,g,a.getId());const p=new Gn(u,d);S.setPlaneHelper(p);const m=[l.getCurrentIndex().getValues(),l.getCurrentPosition().getValues()];n.updateLayersToPositionChange({value:m,srclayerid:S.getId()}),this.#Ca.fitToContainer(),S.setOffset(n.getOffset());const f=this.#Ua(u.getOrientation(),t.orientation);this.#Ma(f,S),S.initScale(n.getScale(),a.getAbsoluteZoomOffset()),S.setAnnotationGroup(i.annotationGroup,e,this.addToUndoStack),S.setCurrentPosition(l.getCurrentPosition(),l.getCurrentIndex()),this.#Ca.bindLayerGroups(),this.#Da&&this.#Da.bindLayerGroup(n,S),this.#Fe({type:"drawlayeradd",layerid:S.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===St.Axial,o=!i&&t===St.Coronal,a=!i&&t===St.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{#Ii;#Qa;constructor(e){this.#Ii=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;ie.number===this.#Na.number))}execute(){0!==this.#Ga.length&&this.#Ii.setAtOffsets(this.#Ga,0),new wo(this.#Ii).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.#Ii.setAtOffsets(this.#Ga,this.#Na.number):this.#Ii.setAtOffsets(this.#Ga,this.#Na.displayValue)),new wo(this.#Ii).addSegment(this.#Na),this.onUndo({type:"masksegmentredraw",segmentnumber:this.#Na.number})}onExecute(e){}onUndo(e){}}class Ao{#Ii;#Na;#ka;#Ha;#Ba;#Ga;constructor(e,t,n,i){this.#Ii=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.#Ii.setAtOffsets(this.#Ga,this.#ka),this.#Na.displayValue=this.#ka):(this.#Ii.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.#Ii.setAtOffsets(this.#Ga,this.#Ha),this.#Na.displayValue=this.#Ha):(this.#Ii.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}()})); //# sourceMappingURL=dwv.min.js.map \ No newline at end of file diff --git a/dist/dwv.min.js.map b/dist/dwv.min.js.map index 98abef843f..1183ae0f77 100644 --- a/dist/dwv.min.js.map +++ b/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}\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.>}\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.>}\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} 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} 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>}\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} 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}\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}\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}\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}\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}\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}\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} 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} 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.14';\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} 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}\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 merge 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 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 minRangeValues = minByIndex(\n range1[0].getValues(),\n range2[0].getValues()\n );\n const maxRangeValues = maxByIndex(\n range1[1].getValues(),\n range2[1].getValues()\n );\n\n const sizeValues = [];\n for (let i = 0; i < minRangeValues.length; ++i) {\n sizeValues.push(Math.round(\n Math.abs(maxRangeValues[i] - minRangeValues[i]) / newSpacing.get(i)\n ));\n }\n const newSize = new Size(sizeValues);\n\n // TODO incorporate orientation\n const newOrigins = [];\n for (let i = 0; i < newSize.get(2); ++i) {\n const values = minRangeValues.slice();\n values[2] = minRangeValues[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} 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} 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 let rowSpacing;\n let columnSpacing;\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 (typeof rowSpacing === 'undefined') {\n logger.warn('Undefined row spacing, using default (1mm).');\n rowSpacing = 1;\n } else if (rowSpacing === 0) {\n logger.warn('Zero row spacing, using default (1mm).');\n rowSpacing = 1;\n }\n if (typeof columnSpacing === 'undefined') {\n logger.warn('Undefined column spacing, using default (1mm).');\n columnSpacing = 1;\n } else if (columnSpacing === 0) {\n logger.warn('Zero column spacing, using default (1mm).');\n columnSpacing = 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} 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}\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} 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}\n */\n #defaultRules = {\n default: {action: 'copy', value: null}\n };\n\n /**\n * Writing rules.\n *\n * @type {Object}\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} 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} 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} simpleTags The 'simple' DICOM\n * tags object.\n * @returns {Object} 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} 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} 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';\nimport {logger} from '../utils/logger';\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 * Get a default RGB colour for a segment.\n *\n * @param {number} segmentNumber The segment number.\n * @returns {RGB} A colour.\n */\nfunction getDefaultColour(segmentNumber) {\n // ITK snap colours\n const colours = [\n new RGB(0, 0, 0),\n new RGB(255, 0, 0),\n new RGB(0, 255, 0),\n new RGB(0, 0, 255),\n new RGB(255, 255, 0),\n new RGB(0, 255, 255),\n new RGB(255, 0, 255),\n new RGB(255, 239, 213),\n new RGB(0, 0, 205),\n new RGB(205, 133, 63),\n new RGB(210, 180, 140),\n new RGB(102, 205, 170),\n new RGB(0, 0, 128),\n new RGB(0, 139, 139),\n new RGB(46, 139, 87),\n new RGB(255, 228, 225)\n ];\n let colour;\n if (segmentNumber < colours.length) {\n colour = colours[segmentNumber];\n } else {\n colour = new RGB(\n Math.random() * 255,\n Math.random() * 255,\n Math.random() * 255\n );\n }\n return colour;\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} 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 } else {\n logger.warn('No recommended colour for segment, using default');\n segment.displayRGBValue = getDefaultColour(segment.number);\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} 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} 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} 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} 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} _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} 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} [extraTags] Optional list of extra tags.\n * @returns {Object} 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} 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} 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}\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} 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} 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.>}\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} 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} 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 full layer offset: sum of all other offsets.\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 pan offset.\n *\n * @type {Scalar2D}\n */\n #panOffset = {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 newPanOffset = helper.getPlaneOffsetFromOffset3D(newOffset);\n this.#offset = {\n x: this.#offset.x - this.#panOffset.x + newPanOffset.x,\n y: this.#offset.y - this.#panOffset.y + newPanOffset.y\n };\n this.#panOffset = newPanOffset;\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 // fit scale\n const newFitScale = {\n x: divToWorldSizeRatio * this.#baseSpacing.x,\n y: divToWorldSizeRatio * this.#baseSpacing.y\n };\n const fitRatio = {\n x: newFitScale.x / this.#fitScale.x,\n y: newFitScale.y / this.#fitScale.y\n };\n\n // size ratio (calculated before update)\n const sizeRatio = {\n x: containerSize.x / (this.#canvas.width * fitRatio.x),\n y: containerSize.y / (this.#canvas.height * fitRatio.y)\n };\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 // #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 * fitRatio.x,\n y: this.#scale.y * fitRatio.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 = newFitScale;\n this.#scale = newScale;\n // update draw flag\n needsDraw = true;\n }\n\n // view offset\n const newViewOffset = {\n x: fitOffset.x / newFitScale.x,\n y: fitOffset.y / newFitScale.y\n };\n // flip offset\n const scaledImageSize = {\n x: containerSize.x / newFitScale.x,\n y: containerSize.y / newFitScale.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 const newZoomOffset = {\n x: this.#zoomOffset.x * sizeRatio.x,\n y: this.#zoomOffset.y * sizeRatio.y\n };\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 newZoomOffset.x - this.#zoomOffset.x,\n y: this.#offset.y +\n newViewOffset.y - this.#viewOffset.y +\n newFlipOffset.y - this.#flipOffset.y +\n newZoomOffset.y - this.#zoomOffset.y\n };\n // update private local offsets\n this.#flipOffset = newFlipOffset;\n this.#viewOffset = newViewOffset;\n this.#zoomOffset = newZoomOffset;\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 {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","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.>}\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|undefined} 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\n let res;\n if (a !== 0) {\n const a1 = 1 / (3 * a);\n res = new Point2D(a1 * cx, a1 * cy);\n }\n return res;\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('filterundo', this.#fireEvent);\n } else {\n this.#filterList[key].removeEventListener(\n 'filterrun', this.#fireEvent);\n this.#filterList[key].removeEventListener(\n 'filterundo', 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}\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>}\n */\nexport const toolOptions = {};\n\n/**\n * Default tool list.\n *\n * @type {Object}\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>}\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 Example with slider\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 {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 * 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 this.#annotation = undefined;\n\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 * 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 {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 * 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.#annotation = undefined;\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 /**\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 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.} 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}\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} 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 pan offset.\n *\n * @type {Scalar2D}\n */\n #panOffset = {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 newPanOffset =\n this.#planeHelper.getPlaneOffsetFromOffset3D(newOffset);\n const offset = this.#konvaStage.offset();\n this.#konvaStage.offset({\n x: offset.x - this.#panOffset.x + newPanOffset.x,\n y: offset.y - this.#panOffset.y + newPanOffset.y\n });\n this.#panOffset = newPanOffset;\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 // fit scale\n const newFitScale = {\n x: divToWorldSizeRatio * this.#baseSpacing.x,\n y: divToWorldSizeRatio * this.#baseSpacing.y\n };\n const fitRatio = {\n x: newFitScale.x / this.#fitScale.x,\n y: newFitScale.y / this.#fitScale.y\n };\n\n // size ratio (calculated before update)\n const sizeRatio = {\n x: containerSize.x / (this.#konvaStage.width() * fitRatio.x),\n y: containerSize.y / (this.#konvaStage.height() * fitRatio.y)\n };\n\n // set canvas size if different from previous\n if (this.#konvaStage.width() !== containerSize.x ||\n this.#konvaStage.height() !== containerSize.y) {\n this.#konvaStage.width(containerSize.x);\n this.#konvaStage.height(containerSize.y);\n }\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 * fitRatio.x,\n y: this.#konvaStage.scale().y * fitRatio.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 = newFitScale;\n this.#konvaStage.scale(newScale);\n }\n\n // view offset\n const newViewOffset = {\n x: fitOffset.x / newFitScale.x,\n y: fitOffset.y / newFitScale.y\n };\n // flip offset\n const scaledImageSize = {\n x: containerSize.x / newFitScale.x,\n y: containerSize.y / newFitScale.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 const newZoomOffset = {\n x: this.#zoomOffset.x * sizeRatio.x,\n y: this.#zoomOffset.y * sizeRatio.y\n };\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 newZoomOffset.x - this.#zoomOffset.x,\n y: this.#konvaStage.offset().y +\n newViewOffset.y - this.#viewOffset.y +\n newFlipOffset.y - this.#flipOffset.y +\n newZoomOffset.y - this.#zoomOffset.y\n });\n // update private local offsets\n this.#flipOffset = newFlipOffset;\n this.#viewOffset = newViewOffset;\n this.#zoomOffset = newZoomOffset;\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}\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 }\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 }\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 // force helper update\n this.#positionHelper = 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 with id \\'' +\n this.#containerDiv.id + '\\'.'\n );\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","/**\n * UndoStack class.\n */\nexport class UndoStack extends EventTarget {\n /**\n * Array of commands.\n *\n * @type {Array}\n */\n #stack = [];\n\n /**\n * Current command index.\n * Warning: 1 based.\n *\n * @type {number}\n */\n #curCmdIndex = 0;\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 * Warning: 1 based.\n *\n * @returns {number} The stack index.\n */\n getCurrentStackIndex() {\n return this.#curCmdIndex;\n }\n\n /**\n * Get the current command.\n *\n * @returns {object} The command.\n */\n getCurrentCommand() {\n return this.#stack[this.#curCmdIndex - 1];\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 * Add command to undo stack event.\n * `event.target.getCurrentCommand()` will return the added command.\n *\n * @event UndoStack#undoadd\n * @type {Event}\n */\n this.dispatchEvent(new Event('undoadd'));\n }\n\n /**\n * Remove a command from 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 // result\n res = true;\n /**\n * Remove command from undo stack event.\n * Get the removed command name from the `event.detail`.\n *\n * @event UndoStack#undoremove\n * @type {CustomEvent}\n */\n this.dispatchEvent(new CustomEvent('undoremove', {\n detail: {commandName: name}\n }));\n // remove command\n this.#stack.splice(index, 1);\n // decrement index\n --this.#curCmdIndex;\n }\n return res;\n }\n\n /**\n * Undo the last command.\n *\n * @fires UndoStack#undo\n */\n undo() {\n if (this.#curCmdIndex > 0) {\n /**\n * Command undo event.\n * `event.target.getCurrentCommand()` will return the undone command.\n *\n * @event UndoStack#undo\n * @type {Event}\n */\n this.dispatchEvent(new Event('undo'));\n // decrement command index\n --this.#curCmdIndex;\n // undo last command\n this.#stack[this.#curCmdIndex].undo();\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 // increment command index\n ++this.#curCmdIndex;\n /**\n * Command redo event.\n * `event.target.getCurrentCommand()` will return the re-done command.\n *\n * @event UndoStack#redo\n * @type {Event}\n */\n this.dispatchEvent(new Event('redo'));\n }\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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} [extraTags] Optional list of extra tags.\n * @returns {Object} 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}\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 * \n * {\n * idKey: {valueKey: [0]},\n * key0: {valueKey: [\"abc\"]},\n * key1: {valueKey: [33]}\n * }\n * .\n *\n * Merged objects will be in the form of:\n * \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 * .\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} 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|undefined}\n */\n dataViewConfigs;\n /**\n * Tool name indexed object containing individual tool configurations.\n *\n * @type {Object|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} [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} 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|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 * @returns {string} The data ID, '-1' if problem.\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 if (files.length === 0) {\n logger.warn('Ignoring empty input file list.');\n return '-1';\n }\n const dataId = this.#dataController.getNextDataId();\n this.#loadController.loadFiles(files, dataId);\n return 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 * @returns {string} The data ID, '-1' if problem.\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 if (urls.length === 0) {\n logger.warn('Ignoring empty input url list.');\n return '-1';\n }\n const dataId = this.#dataController.getNextDataId();\n this.#loadController.loadURLs(urls, dataId, options);\n return dataId;\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 * @returns {string} The data ID.\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 const dataId = this.#dataController.getNextDataId();\n this.#loadController.loadImageObject(data, dataId);\n return 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} 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} 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 let eventMetaData;\n if (event.loadtype === 'image') {\n eventMetaData = event.data.meta;\n } else if (event.loadtype === 'state') {\n eventMetaData = 'state';\n }\n\n /**\n * Load item event: fired when an item has been successfully loaded.\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 const isFirstLoadItem = event.isfirstitem;\n\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 } else if (event.loadtype === 'state') {\n this.applyJsonState(event.data, event.dataid);\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 // 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","segmentNumber","colours","colour","getDefaultColour","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","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","newSpacing","range1","range2","minRangeValues","maxRangeValues","newSize","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","newPanOffset","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","newFitScale","fitRatio","sizeRatio","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","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","EventTarget","getStackSize","getCurrentStackIndex","getCurrentCommand","cmd","dispatchEvent","Event","CustomEvent","commandName","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","eventMetaData","isFirstLoadItem","groupId","isBaseLayer","flipFlags","baseViewLayer","layergroupid","refSeriesInstanceUID","refViewLayer","refViewController","refData","viewConfigOrientation","orientationCode","isViewUndefined","isViewAxial","isViewCoronal","isViewSagittal","flipOffset","flipScale","MaskSegmentHelper","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}\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.>}\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.>}\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} 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} 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>}\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} 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}\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}\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}\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}\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}\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}\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} 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} 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.15';\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} 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}\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 merge 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 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 minRangeValues = minByIndex(\n range1[0].getValues(),\n range2[0].getValues()\n );\n const maxRangeValues = maxByIndex(\n range1[1].getValues(),\n range2[1].getValues()\n );\n\n const sizeValues = [];\n for (let i = 0; i < minRangeValues.length; ++i) {\n sizeValues.push(Math.round(\n Math.abs(maxRangeValues[i] - minRangeValues[i]) / newSpacing.get(i)\n ));\n }\n const newSize = new Size(sizeValues);\n\n // TODO incorporate orientation\n const newOrigins = [];\n for (let i = 0; i < newSize.get(2); ++i) {\n const values = minRangeValues.slice();\n values[2] = minRangeValues[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} 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} 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 let rowSpacing;\n let columnSpacing;\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 (typeof rowSpacing === 'undefined') {\n logger.warn('Undefined row spacing, using default (1mm).');\n rowSpacing = 1;\n } else if (rowSpacing === 0) {\n logger.warn('Zero row spacing, using default (1mm).');\n rowSpacing = 1;\n }\n if (typeof columnSpacing === 'undefined') {\n logger.warn('Undefined column spacing, using default (1mm).');\n columnSpacing = 1;\n } else if (columnSpacing === 0) {\n logger.warn('Zero column spacing, using default (1mm).');\n columnSpacing = 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} 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}\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} 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}\n */\n #defaultRules = {\n default: {action: 'copy', value: null}\n };\n\n /**\n * Writing rules.\n *\n * @type {Object}\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} 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} 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} simpleTags The 'simple' DICOM\n * tags object.\n * @returns {Object} 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} 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} 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';\nimport {logger} from '../utils/logger';\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 * Get a default RGB colour for a segment.\n *\n * @param {number} segmentNumber The segment number.\n * @returns {RGB} A colour.\n */\nfunction getDefaultColour(segmentNumber) {\n // ITK snap colours\n const colours = [\n new RGB(0, 0, 0),\n new RGB(255, 0, 0),\n new RGB(0, 255, 0),\n new RGB(0, 0, 255),\n new RGB(255, 255, 0),\n new RGB(0, 255, 255),\n new RGB(255, 0, 255),\n new RGB(255, 239, 213),\n new RGB(0, 0, 205),\n new RGB(205, 133, 63),\n new RGB(210, 180, 140),\n new RGB(102, 205, 170),\n new RGB(0, 0, 128),\n new RGB(0, 139, 139),\n new RGB(46, 139, 87),\n new RGB(255, 228, 225)\n ];\n let colour;\n if (segmentNumber < colours.length) {\n colour = colours[segmentNumber];\n } else {\n colour = new RGB(\n Math.random() * 255,\n Math.random() * 255,\n Math.random() * 255\n );\n }\n return colour;\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} 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 } else {\n logger.warn('No recommended colour for segment, using default');\n segment.displayRGBValue = getDefaultColour(segment.number);\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} 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} 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} 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} 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} _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} 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} [extraTags] Optional list of extra tags.\n * @returns {Object} 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} 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} 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}\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} 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} 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.>}\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} 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} 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 a clone of the position helper.\n *\n * @returns {PositionHelper} The helper clone.\n */\n getPositionHelperClone() {\n return new PositionHelper(this.#view);\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 full layer offset: sum of all other offsets.\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 pan offset.\n *\n * @type {Scalar2D}\n */\n #panOffset = {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 newPanOffset = helper.getPlaneOffsetFromOffset3D(newOffset);\n this.#offset = {\n x: this.#offset.x - this.#panOffset.x + newPanOffset.x,\n y: this.#offset.y - this.#panOffset.y + newPanOffset.y\n };\n this.#panOffset = newPanOffset;\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 // fit scale\n const newFitScale = {\n x: divToWorldSizeRatio * this.#baseSpacing.x,\n y: divToWorldSizeRatio * this.#baseSpacing.y\n };\n const fitRatio = {\n x: newFitScale.x / this.#fitScale.x,\n y: newFitScale.y / this.#fitScale.y\n };\n\n // size ratio (calculated before update)\n const sizeRatio = {\n x: containerSize.x / (this.#canvas.width * fitRatio.x),\n y: containerSize.y / (this.#canvas.height * fitRatio.y)\n };\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 // #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 * fitRatio.x,\n y: this.#scale.y * fitRatio.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 = newFitScale;\n this.#scale = newScale;\n // update draw flag\n needsDraw = true;\n }\n\n // view offset\n const newViewOffset = {\n x: fitOffset.x / newFitScale.x,\n y: fitOffset.y / newFitScale.y\n };\n // flip offset\n const scaledImageSize = {\n x: containerSize.x / newFitScale.x,\n y: containerSize.y / newFitScale.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 const newZoomOffset = {\n x: this.#zoomOffset.x * sizeRatio.x,\n y: this.#zoomOffset.y * sizeRatio.y\n };\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 newZoomOffset.x - this.#zoomOffset.x,\n y: this.#offset.y +\n newViewOffset.y - this.#viewOffset.y +\n newFlipOffset.y - this.#flipOffset.y +\n newZoomOffset.y - this.#zoomOffset.y\n };\n // update private local offsets\n this.#flipOffset = newFlipOffset;\n this.#viewOffset = newViewOffset;\n this.#zoomOffset = newZoomOffset;\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 {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","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.>}\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|undefined} 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\n let res;\n if (a !== 0) {\n const a1 = 1 / (3 * a);\n res = new Point2D(a1 * cx, a1 * cy);\n }\n return res;\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('filterundo', this.#fireEvent);\n } else {\n this.#filterList[key].removeEventListener(\n 'filterrun', this.#fireEvent);\n this.#filterList[key].removeEventListener(\n 'filterundo', 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}\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>}\n */\nexport const toolOptions = {};\n\n/**\n * Default tool list.\n *\n * @type {Object}\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>}\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 Example with slider\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 {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 * 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 this.#annotation = undefined;\n\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 * 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 {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 * 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.#annotation = undefined;\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 /**\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 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.} 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}\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} 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 pan offset.\n *\n * @type {Scalar2D}\n */\n #panOffset = {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 newPanOffset =\n this.#planeHelper.getPlaneOffsetFromOffset3D(newOffset);\n const offset = this.#konvaStage.offset();\n this.#konvaStage.offset({\n x: offset.x - this.#panOffset.x + newPanOffset.x,\n y: offset.y - this.#panOffset.y + newPanOffset.y\n });\n this.#panOffset = newPanOffset;\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 // fit scale\n const newFitScale = {\n x: divToWorldSizeRatio * this.#baseSpacing.x,\n y: divToWorldSizeRatio * this.#baseSpacing.y\n };\n const fitRatio = {\n x: newFitScale.x / this.#fitScale.x,\n y: newFitScale.y / this.#fitScale.y\n };\n\n // size ratio (calculated before update)\n const sizeRatio = {\n x: containerSize.x / (this.#konvaStage.width() * fitRatio.x),\n y: containerSize.y / (this.#konvaStage.height() * fitRatio.y)\n };\n\n // set canvas size if different from previous\n if (this.#konvaStage.width() !== containerSize.x ||\n this.#konvaStage.height() !== containerSize.y) {\n this.#konvaStage.width(containerSize.x);\n this.#konvaStage.height(containerSize.y);\n }\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 * fitRatio.x,\n y: this.#konvaStage.scale().y * fitRatio.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 = newFitScale;\n this.#konvaStage.scale(newScale);\n }\n\n // view offset\n const newViewOffset = {\n x: fitOffset.x / newFitScale.x,\n y: fitOffset.y / newFitScale.y\n };\n // flip offset\n const scaledImageSize = {\n x: containerSize.x / newFitScale.x,\n y: containerSize.y / newFitScale.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 const newZoomOffset = {\n x: this.#zoomOffset.x * sizeRatio.x,\n y: this.#zoomOffset.y * sizeRatio.y\n };\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 newZoomOffset.x - this.#zoomOffset.x,\n y: this.#konvaStage.offset().y +\n newViewOffset.y - this.#viewOffset.y +\n newFlipOffset.y - this.#flipOffset.y +\n newZoomOffset.y - this.#zoomOffset.y\n });\n // update private local offsets\n this.#flipOffset = newFlipOffset;\n this.#viewOffset = newViewOffset;\n this.#zoomOffset = newZoomOffset;\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}\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.getPositionHelperClone();\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 }\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 }\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 * @fires LayerGroup#removelayer\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 // force helper update\n this.#positionHelper = undefined;\n // update html\n layer.removeFromDOM();\n\n /**\n * Remove layer event.\n *\n * @event LayerGroup#removelayer\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 */\n this.#fireEvent({\n type: 'layerremove',\n layerid: layer.getId(),\n layergroupid: this.getDivId()\n });\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 with id \\'' +\n this.#containerDiv.id + '\\'.'\n );\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","/**\n * UndoStack class.\n */\nexport class UndoStack extends EventTarget {\n /**\n * Array of commands.\n *\n * @type {Array}\n */\n #stack = [];\n\n /**\n * Current command index.\n * Warning: 1 based.\n *\n * @type {number}\n */\n #curCmdIndex = 0;\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 * Warning: 1 based.\n *\n * @returns {number} The stack index.\n */\n getCurrentStackIndex() {\n return this.#curCmdIndex;\n }\n\n /**\n * Get the current command.\n *\n * @returns {object} The command.\n */\n getCurrentCommand() {\n return this.#stack[this.#curCmdIndex - 1];\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 * Add command to undo stack event.\n * `event.target.getCurrentCommand()` will return the added command.\n *\n * @event UndoStack#undoadd\n * @type {Event}\n */\n this.dispatchEvent(new Event('undoadd'));\n }\n\n /**\n * Remove a command from 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 // result\n res = true;\n /**\n * Remove command from undo stack event.\n * Get the removed command name from the `event.detail`.\n *\n * @event UndoStack#undoremove\n * @type {CustomEvent}\n */\n this.dispatchEvent(new CustomEvent('undoremove', {\n detail: {commandName: name}\n }));\n // remove command\n this.#stack.splice(index, 1);\n // decrement index\n --this.#curCmdIndex;\n }\n return res;\n }\n\n /**\n * Undo the last command.\n *\n * @fires UndoStack#undo\n */\n undo() {\n if (this.#curCmdIndex > 0) {\n /**\n * Command undo event.\n * `event.target.getCurrentCommand()` will return the undone command.\n *\n * @event UndoStack#undo\n * @type {Event}\n */\n this.dispatchEvent(new Event('undo'));\n // decrement command index\n --this.#curCmdIndex;\n // undo last command\n this.#stack[this.#curCmdIndex].undo();\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 // increment command index\n ++this.#curCmdIndex;\n /**\n * Command redo event.\n * `event.target.getCurrentCommand()` will return the re-done command.\n *\n * @event UndoStack#redo\n * @type {Event}\n */\n this.dispatchEvent(new Event('redo'));\n }\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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} 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} [extraTags] Optional list of extra tags.\n * @returns {Object} 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}\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 * \n * {\n * idKey: {valueKey: [0]},\n * key0: {valueKey: [\"abc\"]},\n * key1: {valueKey: [33]}\n * }\n * .\n *\n * Merged objects will be in the form of:\n * \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 * .\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} 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|undefined}\n */\n dataViewConfigs;\n /**\n * Tool name indexed object containing individual tool configurations.\n *\n * @type {Object|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} [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} 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|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 * @returns {string} The data ID, '-1' if problem.\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 if (files.length === 0) {\n logger.warn('Ignoring empty input file list.');\n return '-1';\n }\n const dataId = this.#dataController.getNextDataId();\n this.#loadController.loadFiles(files, dataId);\n return 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 * @returns {string} The data ID, '-1' if problem.\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 if (urls.length === 0) {\n logger.warn('Ignoring empty input url list.');\n return '-1';\n }\n const dataId = this.#dataController.getNextDataId();\n this.#loadController.loadURLs(urls, dataId, options);\n return dataId;\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 * @returns {string} The data ID.\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 const dataId = this.#dataController.getNextDataId();\n this.#loadController.loadImageObject(data, dataId);\n return 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} 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} 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 let eventMetaData;\n if (event.loadtype === 'image') {\n eventMetaData = event.data.meta;\n } else if (event.loadtype === 'state') {\n eventMetaData = 'state';\n }\n\n /**\n * Load item event: fired when an item has been successfully loaded.\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 const isFirstLoadItem = event.isfirstitem;\n\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 } else if (event.loadtype === 'state') {\n this.applyJsonState(event.data, event.dataid);\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 group.addEventListener('layerremove', 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 // 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","segmentNumber","colours","colour","getDefaultColour","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","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","newSpacing","range1","range2","minRangeValues","maxRangeValues","newSize","newOrigins","mergeGeometries","getIncrementPosition","getDecrementPosition","previousIndex","incrementPosition","decrementPosition","incrementPositionAlongScroll","decrementPositionAlongScroll","ViewController","getPlaneHelper","isMask","initialise","getModality","getWindowLevelPresetsNames","addWindowLevelPresets","isPlaying","getPositionHelper","getPositionHelperClone","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","newPanOffset","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","newFitScale","fitRatio","sizeRatio","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","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","layergroupid","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","EventTarget","getStackSize","getCurrentStackIndex","getCurrentCommand","cmd","dispatchEvent","Event","CustomEvent","commandName","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","eventMetaData","isFirstLoadItem","groupId","isBaseLayer","flipFlags","baseViewLayer","refSeriesInstanceUID","refViewLayer","refViewController","refData","viewConfigOrientation","orientationCode","isViewUndefined","isViewAxial","isViewCoronal","isViewSagittal","flipOffset","flipScale","MaskSegmentHelper","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 diff --git a/package.json b/package.json index 0552509669..1c0e64a020 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dwv", - "version": "0.35.0-beta.14", + "version": "0.35.0-beta.15", "description": "DICOM Web Viewer.", "keywords": [ "DICOM", diff --git a/resources/api/dwv.api.md b/resources/api/dwv.api.md index 3aa3e782b7..4273064284 100644 --- a/resources/api/dwv.api.md +++ b/resources/api/dwv.api.md @@ -1154,6 +1154,7 @@ export class ViewController { getPlanePositionFromPosition(point: Point): Point2D; getPositionFromPlanePoint(point2D: Point2D, k?: number): Point; getPositionHelper(): PositionHelper; + getPositionHelperClone(): PositionHelper; getRescaledImageValue(position: Point): number | undefined; getScrollDimIndex(): number; getWindowLevel(): WindowLevel; diff --git a/resources/doc/jsdoc.conf.json b/resources/doc/jsdoc.conf.json index a3859daede..484ba78387 100644 --- a/resources/doc/jsdoc.conf.json +++ b/resources/doc/jsdoc.conf.json @@ -25,7 +25,7 @@ "package": "package.json", "theme_opts": { "title": "DWV", - "footer": "Documentation generated for dwv v0.35.0-beta.14.", + "footer": "Documentation generated for dwv v0.35.0-beta.15.", "sections": [ "Tutorials", "Namespaces", @@ -50,7 +50,7 @@ "codepen": { "enable_for": ["examples"], "options": { - "js_external": "https://github.com/ivmartel/dwv/releases/download/v0.35.0-beta.14/dwv-0.35.0-beta.14.min.js", + "js_external": "https://github.com/ivmartel/dwv/releases/download/v0.35.0-beta.15/dwv-0.35.0-beta.15.min.js", "html": "
" } } diff --git a/src/dicom/dicomParser.js b/src/dicom/dicomParser.js index 63ad466b54..26cdb31cb2 100755 --- a/src/dicom/dicomParser.js +++ b/src/dicom/dicomParser.js @@ -32,7 +32,7 @@ import {logger} from '../utils/logger'; * @returns {string} The version of the library. */ export function getDwvVersion() { - return '0.35.0-beta.14'; + return '0.35.0-beta.15'; } /**