{
  "version": 3,
  "sources": ["../node_modules/chroma-js/chroma.js", "../src/ArrayHelper.js", "../src/Atom.js", "../src/Vector2.js", "../src/Line.js", "../src/MathHelper.js", "../src/Vertex.js", "../src/RingConnection.js", "../src/Ring.js", "../src/ThemeManager.js", "../src/CanvasWrapper.js", "../src/CIP.ts", "../src/Edge.js", "../src/Graph.js", "../src/Options.js", "../src/BitSet.ts", "../src/CycleBasis.ts", "../src/SSSR.js", "../src/DrawerBase.js", "../src/PixelsToSvg.js", "../src/GaussDrawer.js", "../src/SvgWrapper.js", "../src/SvgDrawer.js", "../src/Drawer.js", "../src/Parser.js", "../src/ParserWrapper.ts", "../src/FormulaToCommonName.js", "../src/ReactionDrawer.js", "../src/Reaction.js", "../src/ReactionParser.js", "../src/SmilesDrawer.js", "../app.ts"],
  "sourcesContent": ["/**\n * chroma.js - JavaScript library for color conversions\n *\n * Copyright (c) 2011-2019, Gregor Aisch\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the documentation\n * and/or other materials provided with the distribution.\n *\n * 3. The name Gregor Aisch may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL GREGOR AISCH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\n * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\n * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * -------------------------------------------------------\n *\n * chroma.js includes colors from colorbrewer2.org, which are released under\n * the following license:\n *\n * Copyright (c) 2002 Cynthia Brewer, Mark Harrower,\n * and The Pennsylvania State University.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\n * either express or implied. See the License for the specific\n * language governing permissions and limitations under the License.\n *\n * ------------------------------------------------------\n *\n * Named colors are taken from X11 Color Names.\n * http://www.w3.org/TR/css3-color/#svg-color\n *\n * @preserve\n */\n\n(function (global, factory) {\n    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n    typeof define === 'function' && define.amd ? define(factory) :\n    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.chroma = factory());\n})(this, (function () { 'use strict';\n\n    var limit$2 = function (x, min, max) {\n        if ( min === void 0 ) min=0;\n        if ( max === void 0 ) max=1;\n\n        return x < min ? min : x > max ? max : x;\n    };\n\n    var limit$1 = limit$2;\n\n    var clip_rgb$3 = function (rgb) {\n        rgb._clipped = false;\n        rgb._unclipped = rgb.slice(0);\n        for (var i=0; i<=3; i++) {\n            if (i < 3) {\n                if (rgb[i] < 0 || rgb[i] > 255) { rgb._clipped = true; }\n                rgb[i] = limit$1(rgb[i], 0, 255);\n            } else if (i === 3) {\n                rgb[i] = limit$1(rgb[i], 0, 1);\n            }\n        }\n        return rgb;\n    };\n\n    // ported from jQuery's $.type\n    var classToType = {};\n    for (var i$1 = 0, list$1 = ['Boolean', 'Number', 'String', 'Function', 'Array', 'Date', 'RegExp', 'Undefined', 'Null']; i$1 < list$1.length; i$1 += 1) {\n        var name = list$1[i$1];\n\n        classToType[(\"[object \" + name + \"]\")] = name.toLowerCase();\n    }\n    var type$p = function(obj) {\n        return classToType[Object.prototype.toString.call(obj)] || \"object\";\n    };\n\n    var type$o = type$p;\n\n    var unpack$B = function (args, keyOrder) {\n        if ( keyOrder === void 0 ) keyOrder=null;\n\n    \t// if called with more than 3 arguments, we return the arguments\n        if (args.length >= 3) { return Array.prototype.slice.call(args); }\n        // with less than 3 args we check if first arg is object\n        // and use the keyOrder string to extract and sort properties\n    \tif (type$o(args[0]) == 'object' && keyOrder) {\n    \t\treturn keyOrder.split('')\n    \t\t\t.filter(function (k) { return args[0][k] !== undefined; })\n    \t\t\t.map(function (k) { return args[0][k]; });\n    \t}\n    \t// otherwise we just return the first argument\n    \t// (which we suppose is an array of args)\n        return args[0];\n    };\n\n    var type$n = type$p;\n\n    var last$4 = function (args) {\n        if (args.length < 2) { return null; }\n        var l = args.length-1;\n        if (type$n(args[l]) == 'string') { return args[l].toLowerCase(); }\n        return null;\n    };\n\n    var PI$2 = Math.PI;\n\n    var utils = {\n    \tclip_rgb: clip_rgb$3,\n    \tlimit: limit$2,\n    \ttype: type$p,\n    \tunpack: unpack$B,\n    \tlast: last$4,\n    \tPI: PI$2,\n    \tTWOPI: PI$2*2,\n    \tPITHIRD: PI$2/3,\n    \tDEG2RAD: PI$2 / 180,\n    \tRAD2DEG: 180 / PI$2\n    };\n\n    var input$h = {\n    \tformat: {},\n    \tautodetect: []\n    };\n\n    var last$3 = utils.last;\n    var clip_rgb$2 = utils.clip_rgb;\n    var type$m = utils.type;\n    var _input = input$h;\n\n    var Color$D = function Color() {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var me = this;\n        if (type$m(args[0]) === 'object' &&\n            args[0].constructor &&\n            args[0].constructor === this.constructor) {\n            // the argument is already a Color instance\n            return args[0];\n        }\n\n        // last argument could be the mode\n        var mode = last$3(args);\n        var autodetect = false;\n\n        if (!mode) {\n            autodetect = true;\n            if (!_input.sorted) {\n                _input.autodetect = _input.autodetect.sort(function (a,b) { return b.p - a.p; });\n                _input.sorted = true;\n            }\n            // auto-detect format\n            for (var i = 0, list = _input.autodetect; i < list.length; i += 1) {\n                var chk = list[i];\n\n                mode = chk.test.apply(chk, args);\n                if (mode) { break; }\n            }\n        }\n\n        if (_input.format[mode]) {\n            var rgb = _input.format[mode].apply(null, autodetect ? args : args.slice(0,-1));\n            me._rgb = clip_rgb$2(rgb);\n        } else {\n            throw new Error('unknown format: '+args);\n        }\n\n        // add alpha channel\n        if (me._rgb.length === 3) { me._rgb.push(1); }\n    };\n\n    Color$D.prototype.toString = function toString () {\n        if (type$m(this.hex) == 'function') { return this.hex(); }\n        return (\"[\" + (this._rgb.join(',')) + \"]\");\n    };\n\n    var Color_1 = Color$D;\n\n    var chroma$k = function () {\n    \tvar args = [], len = arguments.length;\n    \twhile ( len-- ) args[ len ] = arguments[ len ];\n\n    \treturn new (Function.prototype.bind.apply( chroma$k.Color, [ null ].concat( args) ));\n    };\n\n    chroma$k.Color = Color_1;\n    chroma$k.version = '2.4.2';\n\n    var chroma_1 = chroma$k;\n\n    var unpack$A = utils.unpack;\n    var max$2 = Math.max;\n\n    var rgb2cmyk$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var ref = unpack$A(args, 'rgb');\n        var r = ref[0];\n        var g = ref[1];\n        var b = ref[2];\n        r = r / 255;\n        g = g / 255;\n        b = b / 255;\n        var k = 1 - max$2(r,max$2(g,b));\n        var f = k < 1 ? 1 / (1-k) : 0;\n        var c = (1-r-k) * f;\n        var m = (1-g-k) * f;\n        var y = (1-b-k) * f;\n        return [c,m,y,k];\n    };\n\n    var rgb2cmyk_1 = rgb2cmyk$1;\n\n    var unpack$z = utils.unpack;\n\n    var cmyk2rgb = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        args = unpack$z(args, 'cmyk');\n        var c = args[0];\n        var m = args[1];\n        var y = args[2];\n        var k = args[3];\n        var alpha = args.length > 4 ? args[4] : 1;\n        if (k === 1) { return [0,0,0,alpha]; }\n        return [\n            c >= 1 ? 0 : 255 * (1-c) * (1-k), // r\n            m >= 1 ? 0 : 255 * (1-m) * (1-k), // g\n            y >= 1 ? 0 : 255 * (1-y) * (1-k), // b\n            alpha\n        ];\n    };\n\n    var cmyk2rgb_1 = cmyk2rgb;\n\n    var chroma$j = chroma_1;\n    var Color$C = Color_1;\n    var input$g = input$h;\n    var unpack$y = utils.unpack;\n    var type$l = utils.type;\n\n    var rgb2cmyk = rgb2cmyk_1;\n\n    Color$C.prototype.cmyk = function() {\n        return rgb2cmyk(this._rgb);\n    };\n\n    chroma$j.cmyk = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$C, [ null ].concat( args, ['cmyk']) ));\n    };\n\n    input$g.format.cmyk = cmyk2rgb_1;\n\n    input$g.autodetect.push({\n        p: 2,\n        test: function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            args = unpack$y(args, 'cmyk');\n            if (type$l(args) === 'array' && args.length === 4) {\n                return 'cmyk';\n            }\n        }\n    });\n\n    var unpack$x = utils.unpack;\n    var last$2 = utils.last;\n    var rnd = function (a) { return Math.round(a*100)/100; };\n\n    /*\n     * supported arguments:\n     * - hsl2css(h,s,l)\n     * - hsl2css(h,s,l,a)\n     * - hsl2css([h,s,l], mode)\n     * - hsl2css([h,s,l,a], mode)\n     * - hsl2css({h,s,l,a}, mode)\n     */\n    var hsl2css$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var hsla = unpack$x(args, 'hsla');\n        var mode = last$2(args) || 'lsa';\n        hsla[0] = rnd(hsla[0] || 0);\n        hsla[1] = rnd(hsla[1]*100) + '%';\n        hsla[2] = rnd(hsla[2]*100) + '%';\n        if (mode === 'hsla' || (hsla.length > 3 && hsla[3]<1)) {\n            hsla[3] = hsla.length > 3 ? hsla[3] : 1;\n            mode = 'hsla';\n        } else {\n            hsla.length = 3;\n        }\n        return (mode + \"(\" + (hsla.join(',')) + \")\");\n    };\n\n    var hsl2css_1 = hsl2css$1;\n\n    var unpack$w = utils.unpack;\n\n    /*\n     * supported arguments:\n     * - rgb2hsl(r,g,b)\n     * - rgb2hsl(r,g,b,a)\n     * - rgb2hsl([r,g,b])\n     * - rgb2hsl([r,g,b,a])\n     * - rgb2hsl({r,g,b,a})\n     */\n    var rgb2hsl$3 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        args = unpack$w(args, 'rgba');\n        var r = args[0];\n        var g = args[1];\n        var b = args[2];\n\n        r /= 255;\n        g /= 255;\n        b /= 255;\n\n        var min = Math.min(r, g, b);\n        var max = Math.max(r, g, b);\n\n        var l = (max + min) / 2;\n        var s, h;\n\n        if (max === min){\n            s = 0;\n            h = Number.NaN;\n        } else {\n            s = l < 0.5 ? (max - min) / (max + min) : (max - min) / (2 - max - min);\n        }\n\n        if (r == max) { h = (g - b) / (max - min); }\n        else if (g == max) { h = 2 + (b - r) / (max - min); }\n        else if (b == max) { h = 4 + (r - g) / (max - min); }\n\n        h *= 60;\n        if (h < 0) { h += 360; }\n        if (args.length>3 && args[3]!==undefined) { return [h,s,l,args[3]]; }\n        return [h,s,l];\n    };\n\n    var rgb2hsl_1 = rgb2hsl$3;\n\n    var unpack$v = utils.unpack;\n    var last$1 = utils.last;\n    var hsl2css = hsl2css_1;\n    var rgb2hsl$2 = rgb2hsl_1;\n    var round$6 = Math.round;\n\n    /*\n     * supported arguments:\n     * - rgb2css(r,g,b)\n     * - rgb2css(r,g,b,a)\n     * - rgb2css([r,g,b], mode)\n     * - rgb2css([r,g,b,a], mode)\n     * - rgb2css({r,g,b,a}, mode)\n     */\n    var rgb2css$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var rgba = unpack$v(args, 'rgba');\n        var mode = last$1(args) || 'rgb';\n        if (mode.substr(0,3) == 'hsl') {\n            return hsl2css(rgb2hsl$2(rgba), mode);\n        }\n        rgba[0] = round$6(rgba[0]);\n        rgba[1] = round$6(rgba[1]);\n        rgba[2] = round$6(rgba[2]);\n        if (mode === 'rgba' || (rgba.length > 3 && rgba[3]<1)) {\n            rgba[3] = rgba.length > 3 ? rgba[3] : 1;\n            mode = 'rgba';\n        }\n        return (mode + \"(\" + (rgba.slice(0,mode==='rgb'?3:4).join(',')) + \")\");\n    };\n\n    var rgb2css_1 = rgb2css$1;\n\n    var unpack$u = utils.unpack;\n    var round$5 = Math.round;\n\n    var hsl2rgb$1 = function () {\n        var assign;\n\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n        args = unpack$u(args, 'hsl');\n        var h = args[0];\n        var s = args[1];\n        var l = args[2];\n        var r,g,b;\n        if (s === 0) {\n            r = g = b = l*255;\n        } else {\n            var t3 = [0,0,0];\n            var c = [0,0,0];\n            var t2 = l < 0.5 ? l * (1+s) : l+s-l*s;\n            var t1 = 2 * l - t2;\n            var h_ = h / 360;\n            t3[0] = h_ + 1/3;\n            t3[1] = h_;\n            t3[2] = h_ - 1/3;\n            for (var i=0; i<3; i++) {\n                if (t3[i] < 0) { t3[i] += 1; }\n                if (t3[i] > 1) { t3[i] -= 1; }\n                if (6 * t3[i] < 1)\n                    { c[i] = t1 + (t2 - t1) * 6 * t3[i]; }\n                else if (2 * t3[i] < 1)\n                    { c[i] = t2; }\n                else if (3 * t3[i] < 2)\n                    { c[i] = t1 + (t2 - t1) * ((2 / 3) - t3[i]) * 6; }\n                else\n                    { c[i] = t1; }\n            }\n            (assign = [round$5(c[0]*255),round$5(c[1]*255),round$5(c[2]*255)], r = assign[0], g = assign[1], b = assign[2]);\n        }\n        if (args.length > 3) {\n            // keep alpha channel\n            return [r,g,b,args[3]];\n        }\n        return [r,g,b,1];\n    };\n\n    var hsl2rgb_1 = hsl2rgb$1;\n\n    var hsl2rgb = hsl2rgb_1;\n    var input$f = input$h;\n\n    var RE_RGB = /^rgb\\(\\s*(-?\\d+),\\s*(-?\\d+)\\s*,\\s*(-?\\d+)\\s*\\)$/;\n    var RE_RGBA = /^rgba\\(\\s*(-?\\d+),\\s*(-?\\d+)\\s*,\\s*(-?\\d+)\\s*,\\s*([01]|[01]?\\.\\d+)\\)$/;\n    var RE_RGB_PCT = /^rgb\\(\\s*(-?\\d+(?:\\.\\d+)?)%,\\s*(-?\\d+(?:\\.\\d+)?)%\\s*,\\s*(-?\\d+(?:\\.\\d+)?)%\\s*\\)$/;\n    var RE_RGBA_PCT = /^rgba\\(\\s*(-?\\d+(?:\\.\\d+)?)%,\\s*(-?\\d+(?:\\.\\d+)?)%\\s*,\\s*(-?\\d+(?:\\.\\d+)?)%\\s*,\\s*([01]|[01]?\\.\\d+)\\)$/;\n    var RE_HSL = /^hsl\\(\\s*(-?\\d+(?:\\.\\d+)?),\\s*(-?\\d+(?:\\.\\d+)?)%\\s*,\\s*(-?\\d+(?:\\.\\d+)?)%\\s*\\)$/;\n    var RE_HSLA = /^hsla\\(\\s*(-?\\d+(?:\\.\\d+)?),\\s*(-?\\d+(?:\\.\\d+)?)%\\s*,\\s*(-?\\d+(?:\\.\\d+)?)%\\s*,\\s*([01]|[01]?\\.\\d+)\\)$/;\n\n    var round$4 = Math.round;\n\n    var css2rgb$1 = function (css) {\n        css = css.toLowerCase().trim();\n        var m;\n\n        if (input$f.format.named) {\n            try {\n                return input$f.format.named(css);\n            } catch (e) {\n                // eslint-disable-next-line\n            }\n        }\n\n        // rgb(250,20,0)\n        if ((m = css.match(RE_RGB))) {\n            var rgb = m.slice(1,4);\n            for (var i=0; i<3; i++) {\n                rgb[i] = +rgb[i];\n            }\n            rgb[3] = 1;  // default alpha\n            return rgb;\n        }\n\n        // rgba(250,20,0,0.4)\n        if ((m = css.match(RE_RGBA))) {\n            var rgb$1 = m.slice(1,5);\n            for (var i$1=0; i$1<4; i$1++) {\n                rgb$1[i$1] = +rgb$1[i$1];\n            }\n            return rgb$1;\n        }\n\n        // rgb(100%,0%,0%)\n        if ((m = css.match(RE_RGB_PCT))) {\n            var rgb$2 = m.slice(1,4);\n            for (var i$2=0; i$2<3; i$2++) {\n                rgb$2[i$2] = round$4(rgb$2[i$2] * 2.55);\n            }\n            rgb$2[3] = 1;  // default alpha\n            return rgb$2;\n        }\n\n        // rgba(100%,0%,0%,0.4)\n        if ((m = css.match(RE_RGBA_PCT))) {\n            var rgb$3 = m.slice(1,5);\n            for (var i$3=0; i$3<3; i$3++) {\n                rgb$3[i$3] = round$4(rgb$3[i$3] * 2.55);\n            }\n            rgb$3[3] = +rgb$3[3];\n            return rgb$3;\n        }\n\n        // hsl(0,100%,50%)\n        if ((m = css.match(RE_HSL))) {\n            var hsl = m.slice(1,4);\n            hsl[1] *= 0.01;\n            hsl[2] *= 0.01;\n            var rgb$4 = hsl2rgb(hsl);\n            rgb$4[3] = 1;\n            return rgb$4;\n        }\n\n        // hsla(0,100%,50%,0.5)\n        if ((m = css.match(RE_HSLA))) {\n            var hsl$1 = m.slice(1,4);\n            hsl$1[1] *= 0.01;\n            hsl$1[2] *= 0.01;\n            var rgb$5 = hsl2rgb(hsl$1);\n            rgb$5[3] = +m[4];  // default alpha = 1\n            return rgb$5;\n        }\n    };\n\n    css2rgb$1.test = function (s) {\n        return RE_RGB.test(s) ||\n            RE_RGBA.test(s) ||\n            RE_RGB_PCT.test(s) ||\n            RE_RGBA_PCT.test(s) ||\n            RE_HSL.test(s) ||\n            RE_HSLA.test(s);\n    };\n\n    var css2rgb_1 = css2rgb$1;\n\n    var chroma$i = chroma_1;\n    var Color$B = Color_1;\n    var input$e = input$h;\n    var type$k = utils.type;\n\n    var rgb2css = rgb2css_1;\n    var css2rgb = css2rgb_1;\n\n    Color$B.prototype.css = function(mode) {\n        return rgb2css(this._rgb, mode);\n    };\n\n    chroma$i.css = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$B, [ null ].concat( args, ['css']) ));\n    };\n\n    input$e.format.css = css2rgb;\n\n    input$e.autodetect.push({\n        p: 5,\n        test: function (h) {\n            var rest = [], len = arguments.length - 1;\n            while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];\n\n            if (!rest.length && type$k(h) === 'string' && css2rgb.test(h)) {\n                return 'css';\n            }\n        }\n    });\n\n    var Color$A = Color_1;\n    var chroma$h = chroma_1;\n    var input$d = input$h;\n    var unpack$t = utils.unpack;\n\n    input$d.format.gl = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var rgb = unpack$t(args, 'rgba');\n        rgb[0] *= 255;\n        rgb[1] *= 255;\n        rgb[2] *= 255;\n        return rgb;\n    };\n\n    chroma$h.gl = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$A, [ null ].concat( args, ['gl']) ));\n    };\n\n    Color$A.prototype.gl = function() {\n        var rgb = this._rgb;\n        return [rgb[0]/255, rgb[1]/255, rgb[2]/255, rgb[3]];\n    };\n\n    var unpack$s = utils.unpack;\n\n    var rgb2hcg$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var ref = unpack$s(args, 'rgb');\n        var r = ref[0];\n        var g = ref[1];\n        var b = ref[2];\n        var min = Math.min(r, g, b);\n        var max = Math.max(r, g, b);\n        var delta = max - min;\n        var c = delta * 100 / 255;\n        var _g = min / (255 - delta) * 100;\n        var h;\n        if (delta === 0) {\n            h = Number.NaN;\n        } else {\n            if (r === max) { h = (g - b) / delta; }\n            if (g === max) { h = 2+(b - r) / delta; }\n            if (b === max) { h = 4+(r - g) / delta; }\n            h *= 60;\n            if (h < 0) { h += 360; }\n        }\n        return [h, c, _g];\n    };\n\n    var rgb2hcg_1 = rgb2hcg$1;\n\n    var unpack$r = utils.unpack;\n    var floor$3 = Math.floor;\n\n    /*\n     * this is basically just HSV with some minor tweaks\n     *\n     * hue.. [0..360]\n     * chroma .. [0..1]\n     * grayness .. [0..1]\n     */\n\n    var hcg2rgb = function () {\n        var assign, assign$1, assign$2, assign$3, assign$4, assign$5;\n\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n        args = unpack$r(args, 'hcg');\n        var h = args[0];\n        var c = args[1];\n        var _g = args[2];\n        var r,g,b;\n        _g = _g * 255;\n        var _c = c * 255;\n        if (c === 0) {\n            r = g = b = _g;\n        } else {\n            if (h === 360) { h = 0; }\n            if (h > 360) { h -= 360; }\n            if (h < 0) { h += 360; }\n            h /= 60;\n            var i = floor$3(h);\n            var f = h - i;\n            var p = _g * (1 - c);\n            var q = p + _c * (1 - f);\n            var t = p + _c * f;\n            var v = p + _c;\n            switch (i) {\n                case 0: (assign = [v, t, p], r = assign[0], g = assign[1], b = assign[2]); break\n                case 1: (assign$1 = [q, v, p], r = assign$1[0], g = assign$1[1], b = assign$1[2]); break\n                case 2: (assign$2 = [p, v, t], r = assign$2[0], g = assign$2[1], b = assign$2[2]); break\n                case 3: (assign$3 = [p, q, v], r = assign$3[0], g = assign$3[1], b = assign$3[2]); break\n                case 4: (assign$4 = [t, p, v], r = assign$4[0], g = assign$4[1], b = assign$4[2]); break\n                case 5: (assign$5 = [v, p, q], r = assign$5[0], g = assign$5[1], b = assign$5[2]); break\n            }\n        }\n        return [r, g, b, args.length > 3 ? args[3] : 1];\n    };\n\n    var hcg2rgb_1 = hcg2rgb;\n\n    var unpack$q = utils.unpack;\n    var type$j = utils.type;\n    var chroma$g = chroma_1;\n    var Color$z = Color_1;\n    var input$c = input$h;\n\n    var rgb2hcg = rgb2hcg_1;\n\n    Color$z.prototype.hcg = function() {\n        return rgb2hcg(this._rgb);\n    };\n\n    chroma$g.hcg = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$z, [ null ].concat( args, ['hcg']) ));\n    };\n\n    input$c.format.hcg = hcg2rgb_1;\n\n    input$c.autodetect.push({\n        p: 1,\n        test: function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            args = unpack$q(args, 'hcg');\n            if (type$j(args) === 'array' && args.length === 3) {\n                return 'hcg';\n            }\n        }\n    });\n\n    var unpack$p = utils.unpack;\n    var last = utils.last;\n    var round$3 = Math.round;\n\n    var rgb2hex$2 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var ref = unpack$p(args, 'rgba');\n        var r = ref[0];\n        var g = ref[1];\n        var b = ref[2];\n        var a = ref[3];\n        var mode = last(args) || 'auto';\n        if (a === undefined) { a = 1; }\n        if (mode === 'auto') {\n            mode = a < 1 ? 'rgba' : 'rgb';\n        }\n        r = round$3(r);\n        g = round$3(g);\n        b = round$3(b);\n        var u = r << 16 | g << 8 | b;\n        var str = \"000000\" + u.toString(16); //#.toUpperCase();\n        str = str.substr(str.length - 6);\n        var hxa = '0' + round$3(a * 255).toString(16);\n        hxa = hxa.substr(hxa.length - 2);\n        switch (mode.toLowerCase()) {\n            case 'rgba': return (\"#\" + str + hxa);\n            case 'argb': return (\"#\" + hxa + str);\n            default: return (\"#\" + str);\n        }\n    };\n\n    var rgb2hex_1 = rgb2hex$2;\n\n    var RE_HEX = /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;\n    var RE_HEXA = /^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/;\n\n    var hex2rgb$1 = function (hex) {\n        if (hex.match(RE_HEX)) {\n            // remove optional leading #\n            if (hex.length === 4 || hex.length === 7) {\n                hex = hex.substr(1);\n            }\n            // expand short-notation to full six-digit\n            if (hex.length === 3) {\n                hex = hex.split('');\n                hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];\n            }\n            var u = parseInt(hex, 16);\n            var r = u >> 16;\n            var g = u >> 8 & 0xFF;\n            var b = u & 0xFF;\n            return [r,g,b,1];\n        }\n\n        // match rgba hex format, eg #FF000077\n        if (hex.match(RE_HEXA)) {\n            if (hex.length === 5 || hex.length === 9) {\n                // remove optional leading #\n                hex = hex.substr(1);\n            }\n            // expand short-notation to full eight-digit\n            if (hex.length === 4) {\n                hex = hex.split('');\n                hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2]+hex[3]+hex[3];\n            }\n            var u$1 = parseInt(hex, 16);\n            var r$1 = u$1 >> 24 & 0xFF;\n            var g$1 = u$1 >> 16 & 0xFF;\n            var b$1 = u$1 >> 8 & 0xFF;\n            var a = Math.round((u$1 & 0xFF) / 0xFF * 100) / 100;\n            return [r$1,g$1,b$1,a];\n        }\n\n        // we used to check for css colors here\n        // if _input.css? and rgb = _input.css hex\n        //     return rgb\n\n        throw new Error((\"unknown hex color: \" + hex));\n    };\n\n    var hex2rgb_1 = hex2rgb$1;\n\n    var chroma$f = chroma_1;\n    var Color$y = Color_1;\n    var type$i = utils.type;\n    var input$b = input$h;\n\n    var rgb2hex$1 = rgb2hex_1;\n\n    Color$y.prototype.hex = function(mode) {\n        return rgb2hex$1(this._rgb, mode);\n    };\n\n    chroma$f.hex = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$y, [ null ].concat( args, ['hex']) ));\n    };\n\n    input$b.format.hex = hex2rgb_1;\n    input$b.autodetect.push({\n        p: 4,\n        test: function (h) {\n            var rest = [], len = arguments.length - 1;\n            while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];\n\n            if (!rest.length && type$i(h) === 'string' && [3,4,5,6,7,8,9].indexOf(h.length) >= 0) {\n                return 'hex';\n            }\n        }\n    });\n\n    var unpack$o = utils.unpack;\n    var TWOPI$2 = utils.TWOPI;\n    var min$2 = Math.min;\n    var sqrt$4 = Math.sqrt;\n    var acos = Math.acos;\n\n    var rgb2hsi$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        /*\n        borrowed from here:\n        http://hummer.stanford.edu/museinfo/doc/examples/humdrum/keyscape2/rgb2hsi.cpp\n        */\n        var ref = unpack$o(args, 'rgb');\n        var r = ref[0];\n        var g = ref[1];\n        var b = ref[2];\n        r /= 255;\n        g /= 255;\n        b /= 255;\n        var h;\n        var min_ = min$2(r,g,b);\n        var i = (r+g+b) / 3;\n        var s = i > 0 ? 1 - min_/i : 0;\n        if (s === 0) {\n            h = NaN;\n        } else {\n            h = ((r-g)+(r-b)) / 2;\n            h /= sqrt$4((r-g)*(r-g) + (r-b)*(g-b));\n            h = acos(h);\n            if (b > g) {\n                h = TWOPI$2 - h;\n            }\n            h /= TWOPI$2;\n        }\n        return [h*360,s,i];\n    };\n\n    var rgb2hsi_1 = rgb2hsi$1;\n\n    var unpack$n = utils.unpack;\n    var limit = utils.limit;\n    var TWOPI$1 = utils.TWOPI;\n    var PITHIRD = utils.PITHIRD;\n    var cos$4 = Math.cos;\n\n    /*\n     * hue [0..360]\n     * saturation [0..1]\n     * intensity [0..1]\n     */\n    var hsi2rgb = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        /*\n        borrowed from here:\n        http://hummer.stanford.edu/museinfo/doc/examples/humdrum/keyscape2/hsi2rgb.cpp\n        */\n        args = unpack$n(args, 'hsi');\n        var h = args[0];\n        var s = args[1];\n        var i = args[2];\n        var r,g,b;\n\n        if (isNaN(h)) { h = 0; }\n        if (isNaN(s)) { s = 0; }\n        // normalize hue\n        if (h > 360) { h -= 360; }\n        if (h < 0) { h += 360; }\n        h /= 360;\n        if (h < 1/3) {\n            b = (1-s)/3;\n            r = (1+s*cos$4(TWOPI$1*h)/cos$4(PITHIRD-TWOPI$1*h))/3;\n            g = 1 - (b+r);\n        } else if (h < 2/3) {\n            h -= 1/3;\n            r = (1-s)/3;\n            g = (1+s*cos$4(TWOPI$1*h)/cos$4(PITHIRD-TWOPI$1*h))/3;\n            b = 1 - (r+g);\n        } else {\n            h -= 2/3;\n            g = (1-s)/3;\n            b = (1+s*cos$4(TWOPI$1*h)/cos$4(PITHIRD-TWOPI$1*h))/3;\n            r = 1 - (g+b);\n        }\n        r = limit(i*r*3);\n        g = limit(i*g*3);\n        b = limit(i*b*3);\n        return [r*255, g*255, b*255, args.length > 3 ? args[3] : 1];\n    };\n\n    var hsi2rgb_1 = hsi2rgb;\n\n    var unpack$m = utils.unpack;\n    var type$h = utils.type;\n    var chroma$e = chroma_1;\n    var Color$x = Color_1;\n    var input$a = input$h;\n\n    var rgb2hsi = rgb2hsi_1;\n\n    Color$x.prototype.hsi = function() {\n        return rgb2hsi(this._rgb);\n    };\n\n    chroma$e.hsi = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$x, [ null ].concat( args, ['hsi']) ));\n    };\n\n    input$a.format.hsi = hsi2rgb_1;\n\n    input$a.autodetect.push({\n        p: 2,\n        test: function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            args = unpack$m(args, 'hsi');\n            if (type$h(args) === 'array' && args.length === 3) {\n                return 'hsi';\n            }\n        }\n    });\n\n    var unpack$l = utils.unpack;\n    var type$g = utils.type;\n    var chroma$d = chroma_1;\n    var Color$w = Color_1;\n    var input$9 = input$h;\n\n    var rgb2hsl$1 = rgb2hsl_1;\n\n    Color$w.prototype.hsl = function() {\n        return rgb2hsl$1(this._rgb);\n    };\n\n    chroma$d.hsl = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$w, [ null ].concat( args, ['hsl']) ));\n    };\n\n    input$9.format.hsl = hsl2rgb_1;\n\n    input$9.autodetect.push({\n        p: 2,\n        test: function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            args = unpack$l(args, 'hsl');\n            if (type$g(args) === 'array' && args.length === 3) {\n                return 'hsl';\n            }\n        }\n    });\n\n    var unpack$k = utils.unpack;\n    var min$1 = Math.min;\n    var max$1 = Math.max;\n\n    /*\n     * supported arguments:\n     * - rgb2hsv(r,g,b)\n     * - rgb2hsv([r,g,b])\n     * - rgb2hsv({r,g,b})\n     */\n    var rgb2hsl = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        args = unpack$k(args, 'rgb');\n        var r = args[0];\n        var g = args[1];\n        var b = args[2];\n        var min_ = min$1(r, g, b);\n        var max_ = max$1(r, g, b);\n        var delta = max_ - min_;\n        var h,s,v;\n        v = max_ / 255.0;\n        if (max_ === 0) {\n            h = Number.NaN;\n            s = 0;\n        } else {\n            s = delta / max_;\n            if (r === max_) { h = (g - b) / delta; }\n            if (g === max_) { h = 2+(b - r) / delta; }\n            if (b === max_) { h = 4+(r - g) / delta; }\n            h *= 60;\n            if (h < 0) { h += 360; }\n        }\n        return [h, s, v]\n    };\n\n    var rgb2hsv$1 = rgb2hsl;\n\n    var unpack$j = utils.unpack;\n    var floor$2 = Math.floor;\n\n    var hsv2rgb = function () {\n        var assign, assign$1, assign$2, assign$3, assign$4, assign$5;\n\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n        args = unpack$j(args, 'hsv');\n        var h = args[0];\n        var s = args[1];\n        var v = args[2];\n        var r,g,b;\n        v *= 255;\n        if (s === 0) {\n            r = g = b = v;\n        } else {\n            if (h === 360) { h = 0; }\n            if (h > 360) { h -= 360; }\n            if (h < 0) { h += 360; }\n            h /= 60;\n\n            var i = floor$2(h);\n            var f = h - i;\n            var p = v * (1 - s);\n            var q = v * (1 - s * f);\n            var t = v * (1 - s * (1 - f));\n\n            switch (i) {\n                case 0: (assign = [v, t, p], r = assign[0], g = assign[1], b = assign[2]); break\n                case 1: (assign$1 = [q, v, p], r = assign$1[0], g = assign$1[1], b = assign$1[2]); break\n                case 2: (assign$2 = [p, v, t], r = assign$2[0], g = assign$2[1], b = assign$2[2]); break\n                case 3: (assign$3 = [p, q, v], r = assign$3[0], g = assign$3[1], b = assign$3[2]); break\n                case 4: (assign$4 = [t, p, v], r = assign$4[0], g = assign$4[1], b = assign$4[2]); break\n                case 5: (assign$5 = [v, p, q], r = assign$5[0], g = assign$5[1], b = assign$5[2]); break\n            }\n        }\n        return [r,g,b,args.length > 3?args[3]:1];\n    };\n\n    var hsv2rgb_1 = hsv2rgb;\n\n    var unpack$i = utils.unpack;\n    var type$f = utils.type;\n    var chroma$c = chroma_1;\n    var Color$v = Color_1;\n    var input$8 = input$h;\n\n    var rgb2hsv = rgb2hsv$1;\n\n    Color$v.prototype.hsv = function() {\n        return rgb2hsv(this._rgb);\n    };\n\n    chroma$c.hsv = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$v, [ null ].concat( args, ['hsv']) ));\n    };\n\n    input$8.format.hsv = hsv2rgb_1;\n\n    input$8.autodetect.push({\n        p: 2,\n        test: function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            args = unpack$i(args, 'hsv');\n            if (type$f(args) === 'array' && args.length === 3) {\n                return 'hsv';\n            }\n        }\n    });\n\n    var labConstants = {\n        // Corresponds roughly to RGB brighter/darker\n        Kn: 18,\n\n        // D65 standard referent\n        Xn: 0.950470,\n        Yn: 1,\n        Zn: 1.088830,\n\n        t0: 0.137931034,  // 4 / 29\n        t1: 0.206896552,  // 6 / 29\n        t2: 0.12841855,   // 3 * t1 * t1\n        t3: 0.008856452,  // t1 * t1 * t1\n    };\n\n    var LAB_CONSTANTS$3 = labConstants;\n    var unpack$h = utils.unpack;\n    var pow$a = Math.pow;\n\n    var rgb2lab$2 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var ref = unpack$h(args, 'rgb');\n        var r = ref[0];\n        var g = ref[1];\n        var b = ref[2];\n        var ref$1 = rgb2xyz(r,g,b);\n        var x = ref$1[0];\n        var y = ref$1[1];\n        var z = ref$1[2];\n        var l = 116 * y - 16;\n        return [l < 0 ? 0 : l, 500 * (x - y), 200 * (y - z)];\n    };\n\n    var rgb_xyz = function (r) {\n        if ((r /= 255) <= 0.04045) { return r / 12.92; }\n        return pow$a((r + 0.055) / 1.055, 2.4);\n    };\n\n    var xyz_lab = function (t) {\n        if (t > LAB_CONSTANTS$3.t3) { return pow$a(t, 1 / 3); }\n        return t / LAB_CONSTANTS$3.t2 + LAB_CONSTANTS$3.t0;\n    };\n\n    var rgb2xyz = function (r,g,b) {\n        r = rgb_xyz(r);\n        g = rgb_xyz(g);\n        b = rgb_xyz(b);\n        var x = xyz_lab((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / LAB_CONSTANTS$3.Xn);\n        var y = xyz_lab((0.2126729 * r + 0.7151522 * g + 0.0721750 * b) / LAB_CONSTANTS$3.Yn);\n        var z = xyz_lab((0.0193339 * r + 0.1191920 * g + 0.9503041 * b) / LAB_CONSTANTS$3.Zn);\n        return [x,y,z];\n    };\n\n    var rgb2lab_1 = rgb2lab$2;\n\n    var LAB_CONSTANTS$2 = labConstants;\n    var unpack$g = utils.unpack;\n    var pow$9 = Math.pow;\n\n    /*\n     * L* [0..100]\n     * a [-100..100]\n     * b [-100..100]\n     */\n    var lab2rgb$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        args = unpack$g(args, 'lab');\n        var l = args[0];\n        var a = args[1];\n        var b = args[2];\n        var x,y,z, r,g,b_;\n\n        y = (l + 16) / 116;\n        x = isNaN(a) ? y : y + a / 500;\n        z = isNaN(b) ? y : y - b / 200;\n\n        y = LAB_CONSTANTS$2.Yn * lab_xyz(y);\n        x = LAB_CONSTANTS$2.Xn * lab_xyz(x);\n        z = LAB_CONSTANTS$2.Zn * lab_xyz(z);\n\n        r = xyz_rgb(3.2404542 * x - 1.5371385 * y - 0.4985314 * z);  // D65 -> sRGB\n        g = xyz_rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z);\n        b_ = xyz_rgb(0.0556434 * x - 0.2040259 * y + 1.0572252 * z);\n\n        return [r,g,b_,args.length > 3 ? args[3] : 1];\n    };\n\n    var xyz_rgb = function (r) {\n        return 255 * (r <= 0.00304 ? 12.92 * r : 1.055 * pow$9(r, 1 / 2.4) - 0.055)\n    };\n\n    var lab_xyz = function (t) {\n        return t > LAB_CONSTANTS$2.t1 ? t * t * t : LAB_CONSTANTS$2.t2 * (t - LAB_CONSTANTS$2.t0)\n    };\n\n    var lab2rgb_1 = lab2rgb$1;\n\n    var unpack$f = utils.unpack;\n    var type$e = utils.type;\n    var chroma$b = chroma_1;\n    var Color$u = Color_1;\n    var input$7 = input$h;\n\n    var rgb2lab$1 = rgb2lab_1;\n\n    Color$u.prototype.lab = function() {\n        return rgb2lab$1(this._rgb);\n    };\n\n    chroma$b.lab = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$u, [ null ].concat( args, ['lab']) ));\n    };\n\n    input$7.format.lab = lab2rgb_1;\n\n    input$7.autodetect.push({\n        p: 2,\n        test: function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            args = unpack$f(args, 'lab');\n            if (type$e(args) === 'array' && args.length === 3) {\n                return 'lab';\n            }\n        }\n    });\n\n    var unpack$e = utils.unpack;\n    var RAD2DEG = utils.RAD2DEG;\n    var sqrt$3 = Math.sqrt;\n    var atan2$2 = Math.atan2;\n    var round$2 = Math.round;\n\n    var lab2lch$2 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var ref = unpack$e(args, 'lab');\n        var l = ref[0];\n        var a = ref[1];\n        var b = ref[2];\n        var c = sqrt$3(a * a + b * b);\n        var h = (atan2$2(b, a) * RAD2DEG + 360) % 360;\n        if (round$2(c*10000) === 0) { h = Number.NaN; }\n        return [l, c, h];\n    };\n\n    var lab2lch_1 = lab2lch$2;\n\n    var unpack$d = utils.unpack;\n    var rgb2lab = rgb2lab_1;\n    var lab2lch$1 = lab2lch_1;\n\n    var rgb2lch$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var ref = unpack$d(args, 'rgb');\n        var r = ref[0];\n        var g = ref[1];\n        var b = ref[2];\n        var ref$1 = rgb2lab(r,g,b);\n        var l = ref$1[0];\n        var a = ref$1[1];\n        var b_ = ref$1[2];\n        return lab2lch$1(l,a,b_);\n    };\n\n    var rgb2lch_1 = rgb2lch$1;\n\n    var unpack$c = utils.unpack;\n    var DEG2RAD = utils.DEG2RAD;\n    var sin$3 = Math.sin;\n    var cos$3 = Math.cos;\n\n    var lch2lab$2 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        /*\n        Convert from a qualitative parameter h and a quantitative parameter l to a 24-bit pixel.\n        These formulas were invented by David Dalrymple to obtain maximum contrast without going\n        out of gamut if the parameters are in the range 0-1.\n\n        A saturation multiplier was added by Gregor Aisch\n        */\n        var ref = unpack$c(args, 'lch');\n        var l = ref[0];\n        var c = ref[1];\n        var h = ref[2];\n        if (isNaN(h)) { h = 0; }\n        h = h * DEG2RAD;\n        return [l, cos$3(h) * c, sin$3(h) * c]\n    };\n\n    var lch2lab_1 = lch2lab$2;\n\n    var unpack$b = utils.unpack;\n    var lch2lab$1 = lch2lab_1;\n    var lab2rgb = lab2rgb_1;\n\n    var lch2rgb$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        args = unpack$b(args, 'lch');\n        var l = args[0];\n        var c = args[1];\n        var h = args[2];\n        var ref = lch2lab$1 (l,c,h);\n        var L = ref[0];\n        var a = ref[1];\n        var b_ = ref[2];\n        var ref$1 = lab2rgb (L,a,b_);\n        var r = ref$1[0];\n        var g = ref$1[1];\n        var b = ref$1[2];\n        return [r, g, b, args.length > 3 ? args[3] : 1];\n    };\n\n    var lch2rgb_1 = lch2rgb$1;\n\n    var unpack$a = utils.unpack;\n    var lch2rgb = lch2rgb_1;\n\n    var hcl2rgb = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var hcl = unpack$a(args, 'hcl').reverse();\n        return lch2rgb.apply(void 0, hcl);\n    };\n\n    var hcl2rgb_1 = hcl2rgb;\n\n    var unpack$9 = utils.unpack;\n    var type$d = utils.type;\n    var chroma$a = chroma_1;\n    var Color$t = Color_1;\n    var input$6 = input$h;\n\n    var rgb2lch = rgb2lch_1;\n\n    Color$t.prototype.lch = function() { return rgb2lch(this._rgb); };\n    Color$t.prototype.hcl = function() { return rgb2lch(this._rgb).reverse(); };\n\n    chroma$a.lch = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$t, [ null ].concat( args, ['lch']) ));\n    };\n    chroma$a.hcl = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$t, [ null ].concat( args, ['hcl']) ));\n    };\n\n    input$6.format.lch = lch2rgb_1;\n    input$6.format.hcl = hcl2rgb_1;\n\n    ['lch','hcl'].forEach(function (m) { return input$6.autodetect.push({\n        p: 2,\n        test: function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            args = unpack$9(args, m);\n            if (type$d(args) === 'array' && args.length === 3) {\n                return m;\n            }\n        }\n    }); });\n\n    /**\n    \tX11 color names\n\n    \thttp://www.w3.org/TR/css3-color/#svg-color\n    */\n\n    var w3cx11$1 = {\n        aliceblue: '#f0f8ff',\n        antiquewhite: '#faebd7',\n        aqua: '#00ffff',\n        aquamarine: '#7fffd4',\n        azure: '#f0ffff',\n        beige: '#f5f5dc',\n        bisque: '#ffe4c4',\n        black: '#000000',\n        blanchedalmond: '#ffebcd',\n        blue: '#0000ff',\n        blueviolet: '#8a2be2',\n        brown: '#a52a2a',\n        burlywood: '#deb887',\n        cadetblue: '#5f9ea0',\n        chartreuse: '#7fff00',\n        chocolate: '#d2691e',\n        coral: '#ff7f50',\n        cornflower: '#6495ed',\n        cornflowerblue: '#6495ed',\n        cornsilk: '#fff8dc',\n        crimson: '#dc143c',\n        cyan: '#00ffff',\n        darkblue: '#00008b',\n        darkcyan: '#008b8b',\n        darkgoldenrod: '#b8860b',\n        darkgray: '#a9a9a9',\n        darkgreen: '#006400',\n        darkgrey: '#a9a9a9',\n        darkkhaki: '#bdb76b',\n        darkmagenta: '#8b008b',\n        darkolivegreen: '#556b2f',\n        darkorange: '#ff8c00',\n        darkorchid: '#9932cc',\n        darkred: '#8b0000',\n        darksalmon: '#e9967a',\n        darkseagreen: '#8fbc8f',\n        darkslateblue: '#483d8b',\n        darkslategray: '#2f4f4f',\n        darkslategrey: '#2f4f4f',\n        darkturquoise: '#00ced1',\n        darkviolet: '#9400d3',\n        deeppink: '#ff1493',\n        deepskyblue: '#00bfff',\n        dimgray: '#696969',\n        dimgrey: '#696969',\n        dodgerblue: '#1e90ff',\n        firebrick: '#b22222',\n        floralwhite: '#fffaf0',\n        forestgreen: '#228b22',\n        fuchsia: '#ff00ff',\n        gainsboro: '#dcdcdc',\n        ghostwhite: '#f8f8ff',\n        gold: '#ffd700',\n        goldenrod: '#daa520',\n        gray: '#808080',\n        green: '#008000',\n        greenyellow: '#adff2f',\n        grey: '#808080',\n        honeydew: '#f0fff0',\n        hotpink: '#ff69b4',\n        indianred: '#cd5c5c',\n        indigo: '#4b0082',\n        ivory: '#fffff0',\n        khaki: '#f0e68c',\n        laserlemon: '#ffff54',\n        lavender: '#e6e6fa',\n        lavenderblush: '#fff0f5',\n        lawngreen: '#7cfc00',\n        lemonchiffon: '#fffacd',\n        lightblue: '#add8e6',\n        lightcoral: '#f08080',\n        lightcyan: '#e0ffff',\n        lightgoldenrod: '#fafad2',\n        lightgoldenrodyellow: '#fafad2',\n        lightgray: '#d3d3d3',\n        lightgreen: '#90ee90',\n        lightgrey: '#d3d3d3',\n        lightpink: '#ffb6c1',\n        lightsalmon: '#ffa07a',\n        lightseagreen: '#20b2aa',\n        lightskyblue: '#87cefa',\n        lightslategray: '#778899',\n        lightslategrey: '#778899',\n        lightsteelblue: '#b0c4de',\n        lightyellow: '#ffffe0',\n        lime: '#00ff00',\n        limegreen: '#32cd32',\n        linen: '#faf0e6',\n        magenta: '#ff00ff',\n        maroon: '#800000',\n        maroon2: '#7f0000',\n        maroon3: '#b03060',\n        mediumaquamarine: '#66cdaa',\n        mediumblue: '#0000cd',\n        mediumorchid: '#ba55d3',\n        mediumpurple: '#9370db',\n        mediumseagreen: '#3cb371',\n        mediumslateblue: '#7b68ee',\n        mediumspringgreen: '#00fa9a',\n        mediumturquoise: '#48d1cc',\n        mediumvioletred: '#c71585',\n        midnightblue: '#191970',\n        mintcream: '#f5fffa',\n        mistyrose: '#ffe4e1',\n        moccasin: '#ffe4b5',\n        navajowhite: '#ffdead',\n        navy: '#000080',\n        oldlace: '#fdf5e6',\n        olive: '#808000',\n        olivedrab: '#6b8e23',\n        orange: '#ffa500',\n        orangered: '#ff4500',\n        orchid: '#da70d6',\n        palegoldenrod: '#eee8aa',\n        palegreen: '#98fb98',\n        paleturquoise: '#afeeee',\n        palevioletred: '#db7093',\n        papayawhip: '#ffefd5',\n        peachpuff: '#ffdab9',\n        peru: '#cd853f',\n        pink: '#ffc0cb',\n        plum: '#dda0dd',\n        powderblue: '#b0e0e6',\n        purple: '#800080',\n        purple2: '#7f007f',\n        purple3: '#a020f0',\n        rebeccapurple: '#663399',\n        red: '#ff0000',\n        rosybrown: '#bc8f8f',\n        royalblue: '#4169e1',\n        saddlebrown: '#8b4513',\n        salmon: '#fa8072',\n        sandybrown: '#f4a460',\n        seagreen: '#2e8b57',\n        seashell: '#fff5ee',\n        sienna: '#a0522d',\n        silver: '#c0c0c0',\n        skyblue: '#87ceeb',\n        slateblue: '#6a5acd',\n        slategray: '#708090',\n        slategrey: '#708090',\n        snow: '#fffafa',\n        springgreen: '#00ff7f',\n        steelblue: '#4682b4',\n        tan: '#d2b48c',\n        teal: '#008080',\n        thistle: '#d8bfd8',\n        tomato: '#ff6347',\n        turquoise: '#40e0d0',\n        violet: '#ee82ee',\n        wheat: '#f5deb3',\n        white: '#ffffff',\n        whitesmoke: '#f5f5f5',\n        yellow: '#ffff00',\n        yellowgreen: '#9acd32'\n    };\n\n    var w3cx11_1 = w3cx11$1;\n\n    var Color$s = Color_1;\n    var input$5 = input$h;\n    var type$c = utils.type;\n\n    var w3cx11 = w3cx11_1;\n    var hex2rgb = hex2rgb_1;\n    var rgb2hex = rgb2hex_1;\n\n    Color$s.prototype.name = function() {\n        var hex = rgb2hex(this._rgb, 'rgb');\n        for (var i = 0, list = Object.keys(w3cx11); i < list.length; i += 1) {\n            var n = list[i];\n\n            if (w3cx11[n] === hex) { return n.toLowerCase(); }\n        }\n        return hex;\n    };\n\n    input$5.format.named = function (name) {\n        name = name.toLowerCase();\n        if (w3cx11[name]) { return hex2rgb(w3cx11[name]); }\n        throw new Error('unknown color name: '+name);\n    };\n\n    input$5.autodetect.push({\n        p: 5,\n        test: function (h) {\n            var rest = [], len = arguments.length - 1;\n            while ( len-- > 0 ) rest[ len ] = arguments[ len + 1 ];\n\n            if (!rest.length && type$c(h) === 'string' && w3cx11[h.toLowerCase()]) {\n                return 'named';\n            }\n        }\n    });\n\n    var unpack$8 = utils.unpack;\n\n    var rgb2num$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var ref = unpack$8(args, 'rgb');\n        var r = ref[0];\n        var g = ref[1];\n        var b = ref[2];\n        return (r << 16) + (g << 8) + b;\n    };\n\n    var rgb2num_1 = rgb2num$1;\n\n    var type$b = utils.type;\n\n    var num2rgb = function (num) {\n        if (type$b(num) == \"number\" && num >= 0 && num <= 0xFFFFFF) {\n            var r = num >> 16;\n            var g = (num >> 8) & 0xFF;\n            var b = num & 0xFF;\n            return [r,g,b,1];\n        }\n        throw new Error(\"unknown num color: \"+num);\n    };\n\n    var num2rgb_1 = num2rgb;\n\n    var chroma$9 = chroma_1;\n    var Color$r = Color_1;\n    var input$4 = input$h;\n    var type$a = utils.type;\n\n    var rgb2num = rgb2num_1;\n\n    Color$r.prototype.num = function() {\n        return rgb2num(this._rgb);\n    };\n\n    chroma$9.num = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$r, [ null ].concat( args, ['num']) ));\n    };\n\n    input$4.format.num = num2rgb_1;\n\n    input$4.autodetect.push({\n        p: 5,\n        test: function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            if (args.length === 1 && type$a(args[0]) === 'number' && args[0] >= 0 && args[0] <= 0xFFFFFF) {\n                return 'num';\n            }\n        }\n    });\n\n    var chroma$8 = chroma_1;\n    var Color$q = Color_1;\n    var input$3 = input$h;\n    var unpack$7 = utils.unpack;\n    var type$9 = utils.type;\n    var round$1 = Math.round;\n\n    Color$q.prototype.rgb = function(rnd) {\n        if ( rnd === void 0 ) rnd=true;\n\n        if (rnd === false) { return this._rgb.slice(0,3); }\n        return this._rgb.slice(0,3).map(round$1);\n    };\n\n    Color$q.prototype.rgba = function(rnd) {\n        if ( rnd === void 0 ) rnd=true;\n\n        return this._rgb.slice(0,4).map(function (v,i) {\n            return i<3 ? (rnd === false ? v : round$1(v)) : v;\n        });\n    };\n\n    chroma$8.rgb = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$q, [ null ].concat( args, ['rgb']) ));\n    };\n\n    input$3.format.rgb = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var rgba = unpack$7(args, 'rgba');\n        if (rgba[3] === undefined) { rgba[3] = 1; }\n        return rgba;\n    };\n\n    input$3.autodetect.push({\n        p: 3,\n        test: function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            args = unpack$7(args, 'rgba');\n            if (type$9(args) === 'array' && (args.length === 3 ||\n                args.length === 4 && type$9(args[3]) == 'number' && args[3] >= 0 && args[3] <= 1)) {\n                return 'rgb';\n            }\n        }\n    });\n\n    /*\n     * Based on implementation by Neil Bartlett\n     * https://github.com/neilbartlett/color-temperature\n     */\n\n    var log$1 = Math.log;\n\n    var temperature2rgb$1 = function (kelvin) {\n        var temp = kelvin / 100;\n        var r,g,b;\n        if (temp < 66) {\n            r = 255;\n            g = temp < 6 ? 0 : -155.25485562709179 - 0.44596950469579133 * (g = temp-2) + 104.49216199393888 * log$1(g);\n            b = temp < 20 ? 0 : -254.76935184120902 + 0.8274096064007395 * (b = temp-10) + 115.67994401066147 * log$1(b);\n        } else {\n            r = 351.97690566805693 + 0.114206453784165 * (r = temp-55) - 40.25366309332127 * log$1(r);\n            g = 325.4494125711974 + 0.07943456536662342 * (g = temp-50) - 28.0852963507957 * log$1(g);\n            b = 255;\n        }\n        return [r,g,b,1];\n    };\n\n    var temperature2rgb_1 = temperature2rgb$1;\n\n    /*\n     * Based on implementation by Neil Bartlett\n     * https://github.com/neilbartlett/color-temperature\n     **/\n\n    var temperature2rgb = temperature2rgb_1;\n    var unpack$6 = utils.unpack;\n    var round = Math.round;\n\n    var rgb2temperature$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var rgb = unpack$6(args, 'rgb');\n        var r = rgb[0], b = rgb[2];\n        var minTemp = 1000;\n        var maxTemp = 40000;\n        var eps = 0.4;\n        var temp;\n        while (maxTemp - minTemp > eps) {\n            temp = (maxTemp + minTemp) * 0.5;\n            var rgb$1 = temperature2rgb(temp);\n            if ((rgb$1[2] / rgb$1[0]) >= (b / r)) {\n                maxTemp = temp;\n            } else {\n                minTemp = temp;\n            }\n        }\n        return round(temp);\n    };\n\n    var rgb2temperature_1 = rgb2temperature$1;\n\n    var chroma$7 = chroma_1;\n    var Color$p = Color_1;\n    var input$2 = input$h;\n\n    var rgb2temperature = rgb2temperature_1;\n\n    Color$p.prototype.temp =\n    Color$p.prototype.kelvin =\n    Color$p.prototype.temperature = function() {\n        return rgb2temperature(this._rgb);\n    };\n\n    chroma$7.temp =\n    chroma$7.kelvin =\n    chroma$7.temperature = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$p, [ null ].concat( args, ['temp']) ));\n    };\n\n    input$2.format.temp =\n    input$2.format.kelvin =\n    input$2.format.temperature = temperature2rgb_1;\n\n    var unpack$5 = utils.unpack;\n    var cbrt = Math.cbrt;\n    var pow$8 = Math.pow;\n    var sign$1 = Math.sign;\n\n    var rgb2oklab$2 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        // OKLab color space implementation taken from\n        // https://bottosson.github.io/posts/oklab/\n        var ref = unpack$5(args, 'rgb');\n        var r = ref[0];\n        var g = ref[1];\n        var b = ref[2];\n        var ref$1 = [rgb2lrgb(r / 255), rgb2lrgb(g / 255), rgb2lrgb(b / 255)];\n        var lr = ref$1[0];\n        var lg = ref$1[1];\n        var lb = ref$1[2];\n        var l = cbrt(0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb);\n        var m = cbrt(0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb);\n        var s = cbrt(0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb);\n\n        return [\n            0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n            1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n            0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s\n        ];\n    };\n\n    var rgb2oklab_1 = rgb2oklab$2;\n\n    function rgb2lrgb(c) {\n        var abs = Math.abs(c);\n        if (abs < 0.04045) {\n            return c / 12.92;\n        }\n        return (sign$1(c) || 1) * pow$8((abs + 0.055) / 1.055, 2.4);\n    }\n\n    var unpack$4 = utils.unpack;\n    var pow$7 = Math.pow;\n    var sign = Math.sign;\n\n    /*\n     * L* [0..100]\n     * a [-100..100]\n     * b [-100..100]\n     */\n    var oklab2rgb$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        args = unpack$4(args, 'lab');\n        var L = args[0];\n        var a = args[1];\n        var b = args[2];\n\n        var l = pow$7(L + 0.3963377774 * a + 0.2158037573 * b, 3);\n        var m = pow$7(L - 0.1055613458 * a - 0.0638541728 * b, 3);\n        var s = pow$7(L - 0.0894841775 * a - 1.291485548 * b, 3);\n\n        return [\n            255 * lrgb2rgb(+4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),\n            255 * lrgb2rgb(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),\n            255 * lrgb2rgb(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s),\n            args.length > 3 ? args[3] : 1\n        ];\n    };\n\n    var oklab2rgb_1 = oklab2rgb$1;\n\n    function lrgb2rgb(c) {\n        var abs = Math.abs(c);\n        if (abs > 0.0031308) {\n            return (sign(c) || 1) * (1.055 * pow$7(abs, 1 / 2.4) - 0.055);\n        }\n        return c * 12.92;\n    }\n\n    var unpack$3 = utils.unpack;\n    var type$8 = utils.type;\n    var chroma$6 = chroma_1;\n    var Color$o = Color_1;\n    var input$1 = input$h;\n\n    var rgb2oklab$1 = rgb2oklab_1;\n\n    Color$o.prototype.oklab = function () {\n        return rgb2oklab$1(this._rgb);\n    };\n\n    chroma$6.oklab = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$o, [ null ].concat( args, ['oklab']) ));\n    };\n\n    input$1.format.oklab = oklab2rgb_1;\n\n    input$1.autodetect.push({\n        p: 3,\n        test: function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            args = unpack$3(args, 'oklab');\n            if (type$8(args) === 'array' && args.length === 3) {\n                return 'oklab';\n            }\n        }\n    });\n\n    var unpack$2 = utils.unpack;\n    var rgb2oklab = rgb2oklab_1;\n    var lab2lch = lab2lch_1;\n\n    var rgb2oklch$1 = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        var ref = unpack$2(args, 'rgb');\n        var r = ref[0];\n        var g = ref[1];\n        var b = ref[2];\n        var ref$1 = rgb2oklab(r, g, b);\n        var l = ref$1[0];\n        var a = ref$1[1];\n        var b_ = ref$1[2];\n        return lab2lch(l, a, b_);\n    };\n\n    var rgb2oklch_1 = rgb2oklch$1;\n\n    var unpack$1 = utils.unpack;\n    var lch2lab = lch2lab_1;\n    var oklab2rgb = oklab2rgb_1;\n\n    var oklch2rgb = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        args = unpack$1(args, 'lch');\n        var l = args[0];\n        var c = args[1];\n        var h = args[2];\n        var ref = lch2lab(l, c, h);\n        var L = ref[0];\n        var a = ref[1];\n        var b_ = ref[2];\n        var ref$1 = oklab2rgb(L, a, b_);\n        var r = ref$1[0];\n        var g = ref$1[1];\n        var b = ref$1[2];\n        return [r, g, b, args.length > 3 ? args[3] : 1];\n    };\n\n    var oklch2rgb_1 = oklch2rgb;\n\n    var unpack = utils.unpack;\n    var type$7 = utils.type;\n    var chroma$5 = chroma_1;\n    var Color$n = Color_1;\n    var input = input$h;\n\n    var rgb2oklch = rgb2oklch_1;\n\n    Color$n.prototype.oklch = function () {\n        return rgb2oklch(this._rgb);\n    };\n\n    chroma$5.oklch = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        return new (Function.prototype.bind.apply( Color$n, [ null ].concat( args, ['oklch']) ));\n    };\n\n    input.format.oklch = oklch2rgb_1;\n\n    input.autodetect.push({\n        p: 3,\n        test: function () {\n            var args = [], len = arguments.length;\n            while ( len-- ) args[ len ] = arguments[ len ];\n\n            args = unpack(args, 'oklch');\n            if (type$7(args) === 'array' && args.length === 3) {\n                return 'oklch';\n            }\n        }\n    });\n\n    var Color$m = Color_1;\n    var type$6 = utils.type;\n\n    Color$m.prototype.alpha = function(a, mutate) {\n        if ( mutate === void 0 ) mutate=false;\n\n        if (a !== undefined && type$6(a) === 'number') {\n            if (mutate) {\n                this._rgb[3] = a;\n                return this;\n            }\n            return new Color$m([this._rgb[0], this._rgb[1], this._rgb[2], a], 'rgb');\n        }\n        return this._rgb[3];\n    };\n\n    var Color$l = Color_1;\n\n    Color$l.prototype.clipped = function() {\n        return this._rgb._clipped || false;\n    };\n\n    var Color$k = Color_1;\n    var LAB_CONSTANTS$1 = labConstants;\n\n    Color$k.prototype.darken = function(amount) {\n    \tif ( amount === void 0 ) amount=1;\n\n    \tvar me = this;\n    \tvar lab = me.lab();\n    \tlab[0] -= LAB_CONSTANTS$1.Kn * amount;\n    \treturn new Color$k(lab, 'lab').alpha(me.alpha(), true);\n    };\n\n    Color$k.prototype.brighten = function(amount) {\n    \tif ( amount === void 0 ) amount=1;\n\n    \treturn this.darken(-amount);\n    };\n\n    Color$k.prototype.darker = Color$k.prototype.darken;\n    Color$k.prototype.brighter = Color$k.prototype.brighten;\n\n    var Color$j = Color_1;\n\n    Color$j.prototype.get = function (mc) {\n        var ref = mc.split('.');\n        var mode = ref[0];\n        var channel = ref[1];\n        var src = this[mode]();\n        if (channel) {\n            var i = mode.indexOf(channel) - (mode.substr(0, 2) === 'ok' ? 2 : 0);\n            if (i > -1) { return src[i]; }\n            throw new Error((\"unknown channel \" + channel + \" in mode \" + mode));\n        } else {\n            return src;\n        }\n    };\n\n    var Color$i = Color_1;\n    var type$5 = utils.type;\n    var pow$6 = Math.pow;\n\n    var EPS = 1e-7;\n    var MAX_ITER = 20;\n\n    Color$i.prototype.luminance = function(lum) {\n        if (lum !== undefined && type$5(lum) === 'number') {\n            if (lum === 0) {\n                // return pure black\n                return new Color$i([0,0,0,this._rgb[3]], 'rgb');\n            }\n            if (lum === 1) {\n                // return pure white\n                return new Color$i([255,255,255,this._rgb[3]], 'rgb');\n            }\n            // compute new color using...\n            var cur_lum = this.luminance();\n            var mode = 'rgb';\n            var max_iter = MAX_ITER;\n\n            var test = function (low, high) {\n                var mid = low.interpolate(high, 0.5, mode);\n                var lm = mid.luminance();\n                if (Math.abs(lum - lm) < EPS || !max_iter--) {\n                    // close enough\n                    return mid;\n                }\n                return lm > lum ? test(low, mid) : test(mid, high);\n            };\n\n            var rgb = (cur_lum > lum ? test(new Color$i([0,0,0]), this) : test(this, new Color$i([255,255,255]))).rgb();\n            return new Color$i(rgb.concat( [this._rgb[3]]));\n        }\n        return rgb2luminance.apply(void 0, (this._rgb).slice(0,3));\n    };\n\n\n    var rgb2luminance = function (r,g,b) {\n        // relative luminance\n        // see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef\n        r = luminance_x(r);\n        g = luminance_x(g);\n        b = luminance_x(b);\n        return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n    };\n\n    var luminance_x = function (x) {\n        x /= 255;\n        return x <= 0.03928 ? x/12.92 : pow$6((x+0.055)/1.055, 2.4);\n    };\n\n    var interpolator$1 = {};\n\n    var Color$h = Color_1;\n    var type$4 = utils.type;\n    var interpolator = interpolator$1;\n\n    var mix$1 = function (col1, col2, f) {\n        if ( f === void 0 ) f=0.5;\n        var rest = [], len = arguments.length - 3;\n        while ( len-- > 0 ) rest[ len ] = arguments[ len + 3 ];\n\n        var mode = rest[0] || 'lrgb';\n        if (!interpolator[mode] && !rest.length) {\n            // fall back to the first supported mode\n            mode = Object.keys(interpolator)[0];\n        }\n        if (!interpolator[mode]) {\n            throw new Error((\"interpolation mode \" + mode + \" is not defined\"));\n        }\n        if (type$4(col1) !== 'object') { col1 = new Color$h(col1); }\n        if (type$4(col2) !== 'object') { col2 = new Color$h(col2); }\n        return interpolator[mode](col1, col2, f)\n            .alpha(col1.alpha() + f * (col2.alpha() - col1.alpha()));\n    };\n\n    var Color$g = Color_1;\n    var mix = mix$1;\n\n    Color$g.prototype.mix =\n    Color$g.prototype.interpolate = function(col2, f) {\n    \tif ( f === void 0 ) f=0.5;\n    \tvar rest = [], len = arguments.length - 2;\n    \twhile ( len-- > 0 ) rest[ len ] = arguments[ len + 2 ];\n\n    \treturn mix.apply(void 0, [ this, col2, f ].concat( rest ));\n    };\n\n    var Color$f = Color_1;\n\n    Color$f.prototype.premultiply = function(mutate) {\n    \tif ( mutate === void 0 ) mutate=false;\n\n    \tvar rgb = this._rgb;\n    \tvar a = rgb[3];\n    \tif (mutate) {\n    \t\tthis._rgb = [rgb[0]*a, rgb[1]*a, rgb[2]*a, a];\n    \t\treturn this;\n    \t} else {\n    \t\treturn new Color$f([rgb[0]*a, rgb[1]*a, rgb[2]*a, a], 'rgb');\n    \t}\n    };\n\n    var Color$e = Color_1;\n    var LAB_CONSTANTS = labConstants;\n\n    Color$e.prototype.saturate = function(amount) {\n    \tif ( amount === void 0 ) amount=1;\n\n    \tvar me = this;\n    \tvar lch = me.lch();\n    \tlch[1] += LAB_CONSTANTS.Kn * amount;\n    \tif (lch[1] < 0) { lch[1] = 0; }\n    \treturn new Color$e(lch, 'lch').alpha(me.alpha(), true);\n    };\n\n    Color$e.prototype.desaturate = function(amount) {\n    \tif ( amount === void 0 ) amount=1;\n\n    \treturn this.saturate(-amount);\n    };\n\n    var Color$d = Color_1;\n    var type$3 = utils.type;\n\n    Color$d.prototype.set = function (mc, value, mutate) {\n        if ( mutate === void 0 ) mutate = false;\n\n        var ref = mc.split('.');\n        var mode = ref[0];\n        var channel = ref[1];\n        var src = this[mode]();\n        if (channel) {\n            var i = mode.indexOf(channel) - (mode.substr(0, 2) === 'ok' ? 2 : 0);\n            if (i > -1) {\n                if (type$3(value) == 'string') {\n                    switch (value.charAt(0)) {\n                        case '+':\n                            src[i] += +value;\n                            break;\n                        case '-':\n                            src[i] += +value;\n                            break;\n                        case '*':\n                            src[i] *= +value.substr(1);\n                            break;\n                        case '/':\n                            src[i] /= +value.substr(1);\n                            break;\n                        default:\n                            src[i] = +value;\n                    }\n                } else if (type$3(value) === 'number') {\n                    src[i] = value;\n                } else {\n                    throw new Error(\"unsupported value for Color.set\");\n                }\n                var out = new Color$d(src, mode);\n                if (mutate) {\n                    this._rgb = out._rgb;\n                    return this;\n                }\n                return out;\n            }\n            throw new Error((\"unknown channel \" + channel + \" in mode \" + mode));\n        } else {\n            return src;\n        }\n    };\n\n    var Color$c = Color_1;\n\n    var rgb = function (col1, col2, f) {\n        var xyz0 = col1._rgb;\n        var xyz1 = col2._rgb;\n        return new Color$c(\n            xyz0[0] + f * (xyz1[0]-xyz0[0]),\n            xyz0[1] + f * (xyz1[1]-xyz0[1]),\n            xyz0[2] + f * (xyz1[2]-xyz0[2]),\n            'rgb'\n        )\n    };\n\n    // register interpolator\n    interpolator$1.rgb = rgb;\n\n    var Color$b = Color_1;\n    var sqrt$2 = Math.sqrt;\n    var pow$5 = Math.pow;\n\n    var lrgb = function (col1, col2, f) {\n        var ref = col1._rgb;\n        var x1 = ref[0];\n        var y1 = ref[1];\n        var z1 = ref[2];\n        var ref$1 = col2._rgb;\n        var x2 = ref$1[0];\n        var y2 = ref$1[1];\n        var z2 = ref$1[2];\n        return new Color$b(\n            sqrt$2(pow$5(x1,2) * (1-f) + pow$5(x2,2) * f),\n            sqrt$2(pow$5(y1,2) * (1-f) + pow$5(y2,2) * f),\n            sqrt$2(pow$5(z1,2) * (1-f) + pow$5(z2,2) * f),\n            'rgb'\n        )\n    };\n\n    // register interpolator\n    interpolator$1.lrgb = lrgb;\n\n    var Color$a = Color_1;\n\n    var lab = function (col1, col2, f) {\n        var xyz0 = col1.lab();\n        var xyz1 = col2.lab();\n        return new Color$a(\n            xyz0[0] + f * (xyz1[0]-xyz0[0]),\n            xyz0[1] + f * (xyz1[1]-xyz0[1]),\n            xyz0[2] + f * (xyz1[2]-xyz0[2]),\n            'lab'\n        )\n    };\n\n    // register interpolator\n    interpolator$1.lab = lab;\n\n    var Color$9 = Color_1;\n\n    var _hsx = function (col1, col2, f, m) {\n        var assign, assign$1;\n\n        var xyz0, xyz1;\n        if (m === 'hsl') {\n            xyz0 = col1.hsl();\n            xyz1 = col2.hsl();\n        } else if (m === 'hsv') {\n            xyz0 = col1.hsv();\n            xyz1 = col2.hsv();\n        } else if (m === 'hcg') {\n            xyz0 = col1.hcg();\n            xyz1 = col2.hcg();\n        } else if (m === 'hsi') {\n            xyz0 = col1.hsi();\n            xyz1 = col2.hsi();\n        } else if (m === 'lch' || m === 'hcl') {\n            m = 'hcl';\n            xyz0 = col1.hcl();\n            xyz1 = col2.hcl();\n        } else if (m === 'oklch') {\n            xyz0 = col1.oklch().reverse();\n            xyz1 = col2.oklch().reverse();\n        }\n\n        var hue0, hue1, sat0, sat1, lbv0, lbv1;\n        if (m.substr(0, 1) === 'h' || m === 'oklch') {\n            (assign = xyz0, hue0 = assign[0], sat0 = assign[1], lbv0 = assign[2]);\n            (assign$1 = xyz1, hue1 = assign$1[0], sat1 = assign$1[1], lbv1 = assign$1[2]);\n        }\n\n        var sat, hue, lbv, dh;\n\n        if (!isNaN(hue0) && !isNaN(hue1)) {\n            // both colors have hue\n            if (hue1 > hue0 && hue1 - hue0 > 180) {\n                dh = hue1 - (hue0 + 360);\n            } else if (hue1 < hue0 && hue0 - hue1 > 180) {\n                dh = hue1 + 360 - hue0;\n            } else {\n                dh = hue1 - hue0;\n            }\n            hue = hue0 + f * dh;\n        } else if (!isNaN(hue0)) {\n            hue = hue0;\n            if ((lbv1 == 1 || lbv1 == 0) && m != 'hsv') { sat = sat0; }\n        } else if (!isNaN(hue1)) {\n            hue = hue1;\n            if ((lbv0 == 1 || lbv0 == 0) && m != 'hsv') { sat = sat1; }\n        } else {\n            hue = Number.NaN;\n        }\n\n        if (sat === undefined) { sat = sat0 + f * (sat1 - sat0); }\n        lbv = lbv0 + f * (lbv1 - lbv0);\n        return m === 'oklch' ? new Color$9([lbv, sat, hue], m) : new Color$9([hue, sat, lbv], m);\n    };\n\n    var interpolate_hsx$5 = _hsx;\n\n    var lch = function (col1, col2, f) {\n    \treturn interpolate_hsx$5(col1, col2, f, 'lch');\n    };\n\n    // register interpolator\n    interpolator$1.lch = lch;\n    interpolator$1.hcl = lch;\n\n    var Color$8 = Color_1;\n\n    var num = function (col1, col2, f) {\n        var c1 = col1.num();\n        var c2 = col2.num();\n        return new Color$8(c1 + f * (c2-c1), 'num')\n    };\n\n    // register interpolator\n    interpolator$1.num = num;\n\n    var interpolate_hsx$4 = _hsx;\n\n    var hcg = function (col1, col2, f) {\n    \treturn interpolate_hsx$4(col1, col2, f, 'hcg');\n    };\n\n    // register interpolator\n    interpolator$1.hcg = hcg;\n\n    var interpolate_hsx$3 = _hsx;\n\n    var hsi = function (col1, col2, f) {\n    \treturn interpolate_hsx$3(col1, col2, f, 'hsi');\n    };\n\n    // register interpolator\n    interpolator$1.hsi = hsi;\n\n    var interpolate_hsx$2 = _hsx;\n\n    var hsl = function (col1, col2, f) {\n    \treturn interpolate_hsx$2(col1, col2, f, 'hsl');\n    };\n\n    // register interpolator\n    interpolator$1.hsl = hsl;\n\n    var interpolate_hsx$1 = _hsx;\n\n    var hsv = function (col1, col2, f) {\n    \treturn interpolate_hsx$1(col1, col2, f, 'hsv');\n    };\n\n    // register interpolator\n    interpolator$1.hsv = hsv;\n\n    var Color$7 = Color_1;\n\n    var oklab = function (col1, col2, f) {\n        var xyz0 = col1.oklab();\n        var xyz1 = col2.oklab();\n        return new Color$7(\n            xyz0[0] + f * (xyz1[0] - xyz0[0]),\n            xyz0[1] + f * (xyz1[1] - xyz0[1]),\n            xyz0[2] + f * (xyz1[2] - xyz0[2]),\n            'oklab'\n        );\n    };\n\n    // register interpolator\n    interpolator$1.oklab = oklab;\n\n    var interpolate_hsx = _hsx;\n\n    var oklch = function (col1, col2, f) {\n        return interpolate_hsx(col1, col2, f, 'oklch');\n    };\n\n    // register interpolator\n    interpolator$1.oklch = oklch;\n\n    var Color$6 = Color_1;\n    var clip_rgb$1 = utils.clip_rgb;\n    var pow$4 = Math.pow;\n    var sqrt$1 = Math.sqrt;\n    var PI$1 = Math.PI;\n    var cos$2 = Math.cos;\n    var sin$2 = Math.sin;\n    var atan2$1 = Math.atan2;\n\n    var average = function (colors, mode, weights) {\n        if ( mode === void 0 ) mode='lrgb';\n        if ( weights === void 0 ) weights=null;\n\n        var l = colors.length;\n        if (!weights) { weights = Array.from(new Array(l)).map(function () { return 1; }); }\n        // normalize weights\n        var k = l / weights.reduce(function(a, b) { return a + b; });\n        weights.forEach(function (w,i) { weights[i] *= k; });\n        // convert colors to Color objects\n        colors = colors.map(function (c) { return new Color$6(c); });\n        if (mode === 'lrgb') {\n            return _average_lrgb(colors, weights)\n        }\n        var first = colors.shift();\n        var xyz = first.get(mode);\n        var cnt = [];\n        var dx = 0;\n        var dy = 0;\n        // initial color\n        for (var i=0; i<xyz.length; i++) {\n            xyz[i] = (xyz[i] || 0) * weights[0];\n            cnt.push(isNaN(xyz[i]) ? 0 : weights[0]);\n            if (mode.charAt(i) === 'h' && !isNaN(xyz[i])) {\n                var A = xyz[i] / 180 * PI$1;\n                dx += cos$2(A) * weights[0];\n                dy += sin$2(A) * weights[0];\n            }\n        }\n\n        var alpha = first.alpha() * weights[0];\n        colors.forEach(function (c,ci) {\n            var xyz2 = c.get(mode);\n            alpha += c.alpha() * weights[ci+1];\n            for (var i=0; i<xyz.length; i++) {\n                if (!isNaN(xyz2[i])) {\n                    cnt[i] += weights[ci+1];\n                    if (mode.charAt(i) === 'h') {\n                        var A = xyz2[i] / 180 * PI$1;\n                        dx += cos$2(A) * weights[ci+1];\n                        dy += sin$2(A) * weights[ci+1];\n                    } else {\n                        xyz[i] += xyz2[i] * weights[ci+1];\n                    }\n                }\n            }\n        });\n\n        for (var i$1=0; i$1<xyz.length; i$1++) {\n            if (mode.charAt(i$1) === 'h') {\n                var A$1 = atan2$1(dy / cnt[i$1], dx / cnt[i$1]) / PI$1 * 180;\n                while (A$1 < 0) { A$1 += 360; }\n                while (A$1 >= 360) { A$1 -= 360; }\n                xyz[i$1] = A$1;\n            } else {\n                xyz[i$1] = xyz[i$1]/cnt[i$1];\n            }\n        }\n        alpha /= l;\n        return (new Color$6(xyz, mode)).alpha(alpha > 0.99999 ? 1 : alpha, true);\n    };\n\n\n    var _average_lrgb = function (colors, weights) {\n        var l = colors.length;\n        var xyz = [0,0,0,0];\n        for (var i=0; i < colors.length; i++) {\n            var col = colors[i];\n            var f = weights[i] / l;\n            var rgb = col._rgb;\n            xyz[0] += pow$4(rgb[0],2) * f;\n            xyz[1] += pow$4(rgb[1],2) * f;\n            xyz[2] += pow$4(rgb[2],2) * f;\n            xyz[3] += rgb[3] * f;\n        }\n        xyz[0] = sqrt$1(xyz[0]);\n        xyz[1] = sqrt$1(xyz[1]);\n        xyz[2] = sqrt$1(xyz[2]);\n        if (xyz[3] > 0.9999999) { xyz[3] = 1; }\n        return new Color$6(clip_rgb$1(xyz));\n    };\n\n    // minimal multi-purpose interface\n\n    // @requires utils color analyze\n\n    var chroma$4 = chroma_1;\n    var type$2 = utils.type;\n\n    var pow$3 = Math.pow;\n\n    var scale$2 = function(colors) {\n\n        // constructor\n        var _mode = 'rgb';\n        var _nacol = chroma$4('#ccc');\n        var _spread = 0;\n        // const _fixed = false;\n        var _domain = [0, 1];\n        var _pos = [];\n        var _padding = [0,0];\n        var _classes = false;\n        var _colors = [];\n        var _out = false;\n        var _min = 0;\n        var _max = 1;\n        var _correctLightness = false;\n        var _colorCache = {};\n        var _useCache = true;\n        var _gamma = 1;\n\n        // private methods\n\n        var setColors = function(colors) {\n            colors = colors || ['#fff', '#000'];\n            if (colors && type$2(colors) === 'string' && chroma$4.brewer &&\n                chroma$4.brewer[colors.toLowerCase()]) {\n                colors = chroma$4.brewer[colors.toLowerCase()];\n            }\n            if (type$2(colors) === 'array') {\n                // handle single color\n                if (colors.length === 1) {\n                    colors = [colors[0], colors[0]];\n                }\n                // make a copy of the colors\n                colors = colors.slice(0);\n                // convert to chroma classes\n                for (var c=0; c<colors.length; c++) {\n                    colors[c] = chroma$4(colors[c]);\n                }\n                // auto-fill color position\n                _pos.length = 0;\n                for (var c$1=0; c$1<colors.length; c$1++) {\n                    _pos.push(c$1/(colors.length-1));\n                }\n            }\n            resetCache();\n            return _colors = colors;\n        };\n\n        var getClass = function(value) {\n            if (_classes != null) {\n                var n = _classes.length-1;\n                var i = 0;\n                while (i < n && value >= _classes[i]) {\n                    i++;\n                }\n                return i-1;\n            }\n            return 0;\n        };\n\n        var tMapLightness = function (t) { return t; };\n        var tMapDomain = function (t) { return t; };\n\n        // const classifyValue = function(value) {\n        //     let val = value;\n        //     if (_classes.length > 2) {\n        //         const n = _classes.length-1;\n        //         const i = getClass(value);\n        //         const minc = _classes[0] + ((_classes[1]-_classes[0]) * (0 + (_spread * 0.5)));  // center of 1st class\n        //         const maxc = _classes[n-1] + ((_classes[n]-_classes[n-1]) * (1 - (_spread * 0.5)));  // center of last class\n        //         val = _min + ((((_classes[i] + ((_classes[i+1] - _classes[i]) * 0.5)) - minc) / (maxc-minc)) * (_max - _min));\n        //     }\n        //     return val;\n        // };\n\n        var getColor = function(val, bypassMap) {\n            var col, t;\n            if (bypassMap == null) { bypassMap = false; }\n            if (isNaN(val) || (val === null)) { return _nacol; }\n            if (!bypassMap) {\n                if (_classes && (_classes.length > 2)) {\n                    // find the class\n                    var c = getClass(val);\n                    t = c / (_classes.length-2);\n                } else if (_max !== _min) {\n                    // just interpolate between min/max\n                    t = (val - _min) / (_max - _min);\n                } else {\n                    t = 1;\n                }\n            } else {\n                t = val;\n            }\n\n            // domain map\n            t = tMapDomain(t);\n\n            if (!bypassMap) {\n                t = tMapLightness(t);  // lightness correction\n            }\n\n            if (_gamma !== 1) { t = pow$3(t, _gamma); }\n\n            t = _padding[0] + (t * (1 - _padding[0] - _padding[1]));\n\n            t = Math.min(1, Math.max(0, t));\n\n            var k = Math.floor(t * 10000);\n\n            if (_useCache && _colorCache[k]) {\n                col = _colorCache[k];\n            } else {\n                if (type$2(_colors) === 'array') {\n                    //for i in [0.._pos.length-1]\n                    for (var i=0; i<_pos.length; i++) {\n                        var p = _pos[i];\n                        if (t <= p) {\n                            col = _colors[i];\n                            break;\n                        }\n                        if ((t >= p) && (i === (_pos.length-1))) {\n                            col = _colors[i];\n                            break;\n                        }\n                        if (t > p && t < _pos[i+1]) {\n                            t = (t-p)/(_pos[i+1]-p);\n                            col = chroma$4.interpolate(_colors[i], _colors[i+1], t, _mode);\n                            break;\n                        }\n                    }\n                } else if (type$2(_colors) === 'function') {\n                    col = _colors(t);\n                }\n                if (_useCache) { _colorCache[k] = col; }\n            }\n            return col;\n        };\n\n        var resetCache = function () { return _colorCache = {}; };\n\n        setColors(colors);\n\n        // public interface\n\n        var f = function(v) {\n            var c = chroma$4(getColor(v));\n            if (_out && c[_out]) { return c[_out](); } else { return c; }\n        };\n\n        f.classes = function(classes) {\n            if (classes != null) {\n                if (type$2(classes) === 'array') {\n                    _classes = classes;\n                    _domain = [classes[0], classes[classes.length-1]];\n                } else {\n                    var d = chroma$4.analyze(_domain);\n                    if (classes === 0) {\n                        _classes = [d.min, d.max];\n                    } else {\n                        _classes = chroma$4.limits(d, 'e', classes);\n                    }\n                }\n                return f;\n            }\n            return _classes;\n        };\n\n\n        f.domain = function(domain) {\n            if (!arguments.length) {\n                return _domain;\n            }\n            _min = domain[0];\n            _max = domain[domain.length-1];\n            _pos = [];\n            var k = _colors.length;\n            if ((domain.length === k) && (_min !== _max)) {\n                // update positions\n                for (var i = 0, list = Array.from(domain); i < list.length; i += 1) {\n                    var d = list[i];\n\n                  _pos.push((d-_min) / (_max-_min));\n                }\n            } else {\n                for (var c=0; c<k; c++) {\n                    _pos.push(c/(k-1));\n                }\n                if (domain.length > 2) {\n                    // set domain map\n                    var tOut = domain.map(function (d,i) { return i/(domain.length-1); });\n                    var tBreaks = domain.map(function (d) { return (d - _min) / (_max - _min); });\n                    if (!tBreaks.every(function (val, i) { return tOut[i] === val; })) {\n                        tMapDomain = function (t) {\n                            if (t <= 0 || t >= 1) { return t; }\n                            var i = 0;\n                            while (t >= tBreaks[i+1]) { i++; }\n                            var f = (t - tBreaks[i]) / (tBreaks[i+1] - tBreaks[i]);\n                            var out = tOut[i] + f * (tOut[i+1] - tOut[i]);\n                            return out;\n                        };\n                    }\n\n                }\n            }\n            _domain = [_min, _max];\n            return f;\n        };\n\n        f.mode = function(_m) {\n            if (!arguments.length) {\n                return _mode;\n            }\n            _mode = _m;\n            resetCache();\n            return f;\n        };\n\n        f.range = function(colors, _pos) {\n            setColors(colors);\n            return f;\n        };\n\n        f.out = function(_o) {\n            _out = _o;\n            return f;\n        };\n\n        f.spread = function(val) {\n            if (!arguments.length) {\n                return _spread;\n            }\n            _spread = val;\n            return f;\n        };\n\n        f.correctLightness = function(v) {\n            if (v == null) { v = true; }\n            _correctLightness = v;\n            resetCache();\n            if (_correctLightness) {\n                tMapLightness = function(t) {\n                    var L0 = getColor(0, true).lab()[0];\n                    var L1 = getColor(1, true).lab()[0];\n                    var pol = L0 > L1;\n                    var L_actual = getColor(t, true).lab()[0];\n                    var L_ideal = L0 + ((L1 - L0) * t);\n                    var L_diff = L_actual - L_ideal;\n                    var t0 = 0;\n                    var t1 = 1;\n                    var max_iter = 20;\n                    while ((Math.abs(L_diff) > 1e-2) && (max_iter-- > 0)) {\n                        (function() {\n                            if (pol) { L_diff *= -1; }\n                            if (L_diff < 0) {\n                                t0 = t;\n                                t += (t1 - t) * 0.5;\n                            } else {\n                                t1 = t;\n                                t += (t0 - t) * 0.5;\n                            }\n                            L_actual = getColor(t, true).lab()[0];\n                            return L_diff = L_actual - L_ideal;\n                        })();\n                    }\n                    return t;\n                };\n            } else {\n                tMapLightness = function (t) { return t; };\n            }\n            return f;\n        };\n\n        f.padding = function(p) {\n            if (p != null) {\n                if (type$2(p) === 'number') {\n                    p = [p,p];\n                }\n                _padding = p;\n                return f;\n            } else {\n                return _padding;\n            }\n        };\n\n        f.colors = function(numColors, out) {\n            // If no arguments are given, return the original colors that were provided\n            if (arguments.length < 2) { out = 'hex'; }\n            var result = [];\n\n            if (arguments.length === 0) {\n                result = _colors.slice(0);\n\n            } else if (numColors === 1) {\n                result = [f(0.5)];\n\n            } else if (numColors > 1) {\n                var dm = _domain[0];\n                var dd = _domain[1] - dm;\n                result = __range__(0, numColors, false).map(function (i) { return f( dm + ((i/(numColors-1)) * dd) ); });\n\n            } else { // returns all colors based on the defined classes\n                colors = [];\n                var samples = [];\n                if (_classes && (_classes.length > 2)) {\n                    for (var i = 1, end = _classes.length, asc = 1 <= end; asc ? i < end : i > end; asc ? i++ : i--) {\n                        samples.push((_classes[i-1]+_classes[i])*0.5);\n                    }\n                } else {\n                    samples = _domain;\n                }\n                result = samples.map(function (v) { return f(v); });\n            }\n\n            if (chroma$4[out]) {\n                result = result.map(function (c) { return c[out](); });\n            }\n            return result;\n        };\n\n        f.cache = function(c) {\n            if (c != null) {\n                _useCache = c;\n                return f;\n            } else {\n                return _useCache;\n            }\n        };\n\n        f.gamma = function(g) {\n            if (g != null) {\n                _gamma = g;\n                return f;\n            } else {\n                return _gamma;\n            }\n        };\n\n        f.nodata = function(d) {\n            if (d != null) {\n                _nacol = chroma$4(d);\n                return f;\n            } else {\n                return _nacol;\n            }\n        };\n\n        return f;\n    };\n\n    function __range__(left, right, inclusive) {\n      var range = [];\n      var ascending = left < right;\n      var end = !inclusive ? right : ascending ? right + 1 : right - 1;\n      for (var i = left; ascending ? i < end : i > end; ascending ? i++ : i--) {\n        range.push(i);\n      }\n      return range;\n    }\n\n    //\n    // interpolates between a set of colors uzing a bezier spline\n    //\n\n    // @requires utils lab\n    var Color$5 = Color_1;\n\n    var scale$1 = scale$2;\n\n    // nth row of the pascal triangle\n    var binom_row = function(n) {\n        var row = [1, 1];\n        for (var i = 1; i < n; i++) {\n            var newrow = [1];\n            for (var j = 1; j <= row.length; j++) {\n                newrow[j] = (row[j] || 0) + row[j - 1];\n            }\n            row = newrow;\n        }\n        return row;\n    };\n\n    var bezier = function(colors) {\n        var assign, assign$1, assign$2;\n\n        var I, lab0, lab1, lab2;\n        colors = colors.map(function (c) { return new Color$5(c); });\n        if (colors.length === 2) {\n            // linear interpolation\n            (assign = colors.map(function (c) { return c.lab(); }), lab0 = assign[0], lab1 = assign[1]);\n            I = function(t) {\n                var lab = ([0, 1, 2].map(function (i) { return lab0[i] + (t * (lab1[i] - lab0[i])); }));\n                return new Color$5(lab, 'lab');\n            };\n        } else if (colors.length === 3) {\n            // quadratic bezier interpolation\n            (assign$1 = colors.map(function (c) { return c.lab(); }), lab0 = assign$1[0], lab1 = assign$1[1], lab2 = assign$1[2]);\n            I = function(t) {\n                var lab = ([0, 1, 2].map(function (i) { return ((1-t)*(1-t) * lab0[i]) + (2 * (1-t) * t * lab1[i]) + (t * t * lab2[i]); }));\n                return new Color$5(lab, 'lab');\n            };\n        } else if (colors.length === 4) {\n            // cubic bezier interpolation\n            var lab3;\n            (assign$2 = colors.map(function (c) { return c.lab(); }), lab0 = assign$2[0], lab1 = assign$2[1], lab2 = assign$2[2], lab3 = assign$2[3]);\n            I = function(t) {\n                var lab = ([0, 1, 2].map(function (i) { return ((1-t)*(1-t)*(1-t) * lab0[i]) + (3 * (1-t) * (1-t) * t * lab1[i]) + (3 * (1-t) * t * t * lab2[i]) + (t*t*t * lab3[i]); }));\n                return new Color$5(lab, 'lab');\n            };\n        } else if (colors.length >= 5) {\n            // general case (degree n bezier)\n            var labs, row, n;\n            labs = colors.map(function (c) { return c.lab(); });\n            n = colors.length - 1;\n            row = binom_row(n);\n            I = function (t) {\n                var u = 1 - t;\n                var lab = ([0, 1, 2].map(function (i) { return labs.reduce(function (sum, el, j) { return (sum + row[j] * Math.pow( u, (n - j) ) * Math.pow( t, j ) * el[i]); }, 0); }));\n                return new Color$5(lab, 'lab');\n            };\n        } else {\n            throw new RangeError(\"No point in running bezier with only one color.\")\n        }\n        return I;\n    };\n\n    var bezier_1 = function (colors) {\n        var f = bezier(colors);\n        f.scale = function () { return scale$1(f); };\n        return f;\n    };\n\n    /*\n     * interpolates between a set of colors uzing a bezier spline\n     * blend mode formulas taken from http://www.venture-ware.com/kevin/coding/lets-learn-math-photoshop-blend-modes/\n     */\n\n    var chroma$3 = chroma_1;\n\n    var blend = function (bottom, top, mode) {\n        if (!blend[mode]) {\n            throw new Error('unknown blend mode ' + mode);\n        }\n        return blend[mode](bottom, top);\n    };\n\n    var blend_f = function (f) { return function (bottom,top) {\n            var c0 = chroma$3(top).rgb();\n            var c1 = chroma$3(bottom).rgb();\n            return chroma$3.rgb(f(c0, c1));\n        }; };\n\n    var each = function (f) { return function (c0, c1) {\n            var out = [];\n            out[0] = f(c0[0], c1[0]);\n            out[1] = f(c0[1], c1[1]);\n            out[2] = f(c0[2], c1[2]);\n            return out;\n        }; };\n\n    var normal = function (a) { return a; };\n    var multiply = function (a,b) { return a * b / 255; };\n    var darken = function (a,b) { return a > b ? b : a; };\n    var lighten = function (a,b) { return a > b ? a : b; };\n    var screen = function (a,b) { return 255 * (1 - (1-a/255) * (1-b/255)); };\n    var overlay = function (a,b) { return b < 128 ? 2 * a * b / 255 : 255 * (1 - 2 * (1 - a / 255 ) * ( 1 - b / 255 )); };\n    var burn = function (a,b) { return 255 * (1 - (1 - b / 255) / (a/255)); };\n    var dodge = function (a,b) {\n        if (a === 255) { return 255; }\n        a = 255 * (b / 255) / (1 - a / 255);\n        return a > 255 ? 255 : a\n    };\n\n    // # add = (a,b) ->\n    // #     if (a + b > 255) then 255 else a + b\n\n    blend.normal = blend_f(each(normal));\n    blend.multiply = blend_f(each(multiply));\n    blend.screen = blend_f(each(screen));\n    blend.overlay = blend_f(each(overlay));\n    blend.darken = blend_f(each(darken));\n    blend.lighten = blend_f(each(lighten));\n    blend.dodge = blend_f(each(dodge));\n    blend.burn = blend_f(each(burn));\n    // blend.add = blend_f(each(add));\n\n    var blend_1 = blend;\n\n    // cubehelix interpolation\n    // based on D.A. Green \"A colour scheme for the display of astronomical intensity images\"\n    // http://astron-soc.in/bulletin/11June/289392011.pdf\n\n    var type$1 = utils.type;\n    var clip_rgb = utils.clip_rgb;\n    var TWOPI = utils.TWOPI;\n    var pow$2 = Math.pow;\n    var sin$1 = Math.sin;\n    var cos$1 = Math.cos;\n    var chroma$2 = chroma_1;\n\n    var cubehelix = function(start, rotations, hue, gamma, lightness) {\n        if ( start === void 0 ) start=300;\n        if ( rotations === void 0 ) rotations=-1.5;\n        if ( hue === void 0 ) hue=1;\n        if ( gamma === void 0 ) gamma=1;\n        if ( lightness === void 0 ) lightness=[0,1];\n\n        var dh = 0, dl;\n        if (type$1(lightness) === 'array') {\n            dl = lightness[1] - lightness[0];\n        } else {\n            dl = 0;\n            lightness = [lightness, lightness];\n        }\n\n        var f = function(fract) {\n            var a = TWOPI * (((start+120)/360) + (rotations * fract));\n            var l = pow$2(lightness[0] + (dl * fract), gamma);\n            var h = dh !== 0 ? hue[0] + (fract * dh) : hue;\n            var amp = (h * l * (1-l)) / 2;\n            var cos_a = cos$1(a);\n            var sin_a = sin$1(a);\n            var r = l + (amp * ((-0.14861 * cos_a) + (1.78277* sin_a)));\n            var g = l + (amp * ((-0.29227 * cos_a) - (0.90649* sin_a)));\n            var b = l + (amp * (+1.97294 * cos_a));\n            return chroma$2(clip_rgb([r*255,g*255,b*255,1]));\n        };\n\n        f.start = function(s) {\n            if ((s == null)) { return start; }\n            start = s;\n            return f;\n        };\n\n        f.rotations = function(r) {\n            if ((r == null)) { return rotations; }\n            rotations = r;\n            return f;\n        };\n\n        f.gamma = function(g) {\n            if ((g == null)) { return gamma; }\n            gamma = g;\n            return f;\n        };\n\n        f.hue = function(h) {\n            if ((h == null)) { return hue; }\n            hue = h;\n            if (type$1(hue) === 'array') {\n                dh = hue[1] - hue[0];\n                if (dh === 0) { hue = hue[1]; }\n            } else {\n                dh = 0;\n            }\n            return f;\n        };\n\n        f.lightness = function(h) {\n            if ((h == null)) { return lightness; }\n            if (type$1(h) === 'array') {\n                lightness = h;\n                dl = h[1] - h[0];\n            } else {\n                lightness = [h,h];\n                dl = 0;\n            }\n            return f;\n        };\n\n        f.scale = function () { return chroma$2.scale(f); };\n\n        f.hue(hue);\n\n        return f;\n    };\n\n    var Color$4 = Color_1;\n    var digits = '0123456789abcdef';\n\n    var floor$1 = Math.floor;\n    var random = Math.random;\n\n    var random_1 = function () {\n        var code = '#';\n        for (var i=0; i<6; i++) {\n            code += digits.charAt(floor$1(random() * 16));\n        }\n        return new Color$4(code, 'hex');\n    };\n\n    var type = type$p;\n    var log = Math.log;\n    var pow$1 = Math.pow;\n    var floor = Math.floor;\n    var abs$1 = Math.abs;\n\n\n    var analyze = function (data, key) {\n        if ( key === void 0 ) key=null;\n\n        var r = {\n            min: Number.MAX_VALUE,\n            max: Number.MAX_VALUE*-1,\n            sum: 0,\n            values: [],\n            count: 0\n        };\n        if (type(data) === 'object') {\n            data = Object.values(data);\n        }\n        data.forEach(function (val) {\n            if (key && type(val) === 'object') { val = val[key]; }\n            if (val !== undefined && val !== null && !isNaN(val)) {\n                r.values.push(val);\n                r.sum += val;\n                if (val < r.min) { r.min = val; }\n                if (val > r.max) { r.max = val; }\n                r.count += 1;\n            }\n        });\n\n        r.domain = [r.min, r.max];\n\n        r.limits = function (mode, num) { return limits(r, mode, num); };\n\n        return r;\n    };\n\n\n    var limits = function (data, mode, num) {\n        if ( mode === void 0 ) mode='equal';\n        if ( num === void 0 ) num=7;\n\n        if (type(data) == 'array') {\n            data = analyze(data);\n        }\n        var min = data.min;\n        var max = data.max;\n        var values = data.values.sort(function (a,b) { return a-b; });\n\n        if (num === 1) { return [min,max]; }\n\n        var limits = [];\n\n        if (mode.substr(0,1) === 'c') { // continuous\n            limits.push(min);\n            limits.push(max);\n        }\n\n        if (mode.substr(0,1) === 'e') { // equal interval\n            limits.push(min);\n            for (var i=1; i<num; i++) {\n                limits.push(min+((i/num)*(max-min)));\n            }\n            limits.push(max);\n        }\n\n        else if (mode.substr(0,1) === 'l') { // log scale\n            if (min <= 0) {\n                throw new Error('Logarithmic scales are only possible for values > 0');\n            }\n            var min_log = Math.LOG10E * log(min);\n            var max_log = Math.LOG10E * log(max);\n            limits.push(min);\n            for (var i$1=1; i$1<num; i$1++) {\n                limits.push(pow$1(10, min_log + ((i$1/num) * (max_log - min_log))));\n            }\n            limits.push(max);\n        }\n\n        else if (mode.substr(0,1) === 'q') { // quantile scale\n            limits.push(min);\n            for (var i$2=1; i$2<num; i$2++) {\n                var p = ((values.length-1) * i$2)/num;\n                var pb = floor(p);\n                if (pb === p) {\n                    limits.push(values[pb]);\n                } else { // p > pb\n                    var pr = p - pb;\n                    limits.push((values[pb]*(1-pr)) + (values[pb+1]*pr));\n                }\n            }\n            limits.push(max);\n\n        }\n\n        else if (mode.substr(0,1) === 'k') { // k-means clustering\n            /*\n            implementation based on\n            http://code.google.com/p/figue/source/browse/trunk/figue.js#336\n            simplified for 1-d input values\n            */\n            var cluster;\n            var n = values.length;\n            var assignments = new Array(n);\n            var clusterSizes = new Array(num);\n            var repeat = true;\n            var nb_iters = 0;\n            var centroids = null;\n\n            // get seed values\n            centroids = [];\n            centroids.push(min);\n            for (var i$3=1; i$3<num; i$3++) {\n                centroids.push(min + ((i$3/num) * (max-min)));\n            }\n            centroids.push(max);\n\n            while (repeat) {\n                // assignment step\n                for (var j=0; j<num; j++) {\n                    clusterSizes[j] = 0;\n                }\n                for (var i$4=0; i$4<n; i$4++) {\n                    var value = values[i$4];\n                    var mindist = Number.MAX_VALUE;\n                    var best = (void 0);\n                    for (var j$1=0; j$1<num; j$1++) {\n                        var dist = abs$1(centroids[j$1]-value);\n                        if (dist < mindist) {\n                            mindist = dist;\n                            best = j$1;\n                        }\n                        clusterSizes[best]++;\n                        assignments[i$4] = best;\n                    }\n                }\n\n                // update centroids step\n                var newCentroids = new Array(num);\n                for (var j$2=0; j$2<num; j$2++) {\n                    newCentroids[j$2] = null;\n                }\n                for (var i$5=0; i$5<n; i$5++) {\n                    cluster = assignments[i$5];\n                    if (newCentroids[cluster] === null) {\n                        newCentroids[cluster] = values[i$5];\n                    } else {\n                        newCentroids[cluster] += values[i$5];\n                    }\n                }\n                for (var j$3=0; j$3<num; j$3++) {\n                    newCentroids[j$3] *= 1/clusterSizes[j$3];\n                }\n\n                // check convergence\n                repeat = false;\n                for (var j$4=0; j$4<num; j$4++) {\n                    if (newCentroids[j$4] !== centroids[j$4]) {\n                        repeat = true;\n                        break;\n                    }\n                }\n\n                centroids = newCentroids;\n                nb_iters++;\n\n                if (nb_iters > 200) {\n                    repeat = false;\n                }\n            }\n\n            // finished k-means clustering\n            // the next part is borrowed from gabrielflor.it\n            var kClusters = {};\n            for (var j$5=0; j$5<num; j$5++) {\n                kClusters[j$5] = [];\n            }\n            for (var i$6=0; i$6<n; i$6++) {\n                cluster = assignments[i$6];\n                kClusters[cluster].push(values[i$6]);\n            }\n            var tmpKMeansBreaks = [];\n            for (var j$6=0; j$6<num; j$6++) {\n                tmpKMeansBreaks.push(kClusters[j$6][0]);\n                tmpKMeansBreaks.push(kClusters[j$6][kClusters[j$6].length-1]);\n            }\n            tmpKMeansBreaks = tmpKMeansBreaks.sort(function (a,b){ return a-b; });\n            limits.push(tmpKMeansBreaks[0]);\n            for (var i$7=1; i$7 < tmpKMeansBreaks.length; i$7+= 2) {\n                var v = tmpKMeansBreaks[i$7];\n                if (!isNaN(v) && (limits.indexOf(v) === -1)) {\n                    limits.push(v);\n                }\n            }\n        }\n        return limits;\n    };\n\n    var analyze_1 = {analyze: analyze, limits: limits};\n\n    var Color$3 = Color_1;\n\n\n    var contrast = function (a, b) {\n        // WCAG contrast ratio\n        // see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef\n        a = new Color$3(a);\n        b = new Color$3(b);\n        var l1 = a.luminance();\n        var l2 = b.luminance();\n        return l1 > l2 ? (l1 + 0.05) / (l2 + 0.05) : (l2 + 0.05) / (l1 + 0.05);\n    };\n\n    var Color$2 = Color_1;\n    var sqrt = Math.sqrt;\n    var pow = Math.pow;\n    var min = Math.min;\n    var max = Math.max;\n    var atan2 = Math.atan2;\n    var abs = Math.abs;\n    var cos = Math.cos;\n    var sin = Math.sin;\n    var exp = Math.exp;\n    var PI = Math.PI;\n\n    var deltaE = function(a, b, Kl, Kc, Kh) {\n        if ( Kl === void 0 ) Kl=1;\n        if ( Kc === void 0 ) Kc=1;\n        if ( Kh === void 0 ) Kh=1;\n\n        // Delta E (CIE 2000)\n        // see http://www.brucelindbloom.com/index.html?Eqn_DeltaE_CIE2000.html\n        var rad2deg = function(rad) {\n            return 360 * rad / (2 * PI);\n        };\n        var deg2rad = function(deg) {\n            return (2 * PI * deg) / 360;\n        };\n        a = new Color$2(a);\n        b = new Color$2(b);\n        var ref = Array.from(a.lab());\n        var L1 = ref[0];\n        var a1 = ref[1];\n        var b1 = ref[2];\n        var ref$1 = Array.from(b.lab());\n        var L2 = ref$1[0];\n        var a2 = ref$1[1];\n        var b2 = ref$1[2];\n        var avgL = (L1 + L2)/2;\n        var C1 = sqrt(pow(a1, 2) + pow(b1, 2));\n        var C2 = sqrt(pow(a2, 2) + pow(b2, 2));\n        var avgC = (C1 + C2)/2;\n        var G = 0.5*(1-sqrt(pow(avgC, 7)/(pow(avgC, 7) + pow(25, 7))));\n        var a1p = a1*(1+G);\n        var a2p = a2*(1+G);\n        var C1p = sqrt(pow(a1p, 2) + pow(b1, 2));\n        var C2p = sqrt(pow(a2p, 2) + pow(b2, 2));\n        var avgCp = (C1p + C2p)/2;\n        var arctan1 = rad2deg(atan2(b1, a1p));\n        var arctan2 = rad2deg(atan2(b2, a2p));\n        var h1p = arctan1 >= 0 ? arctan1 : arctan1 + 360;\n        var h2p = arctan2 >= 0 ? arctan2 : arctan2 + 360;\n        var avgHp = abs(h1p - h2p) > 180 ? (h1p + h2p + 360)/2 : (h1p + h2p)/2;\n        var T = 1 - 0.17*cos(deg2rad(avgHp - 30)) + 0.24*cos(deg2rad(2*avgHp)) + 0.32*cos(deg2rad(3*avgHp + 6)) - 0.2*cos(deg2rad(4*avgHp - 63));\n        var deltaHp = h2p - h1p;\n        deltaHp = abs(deltaHp) <= 180 ? deltaHp : h2p <= h1p ? deltaHp + 360 : deltaHp - 360;\n        deltaHp = 2*sqrt(C1p*C2p)*sin(deg2rad(deltaHp)/2);\n        var deltaL = L2 - L1;\n        var deltaCp = C2p - C1p;    \n        var sl = 1 + (0.015*pow(avgL - 50, 2))/sqrt(20 + pow(avgL - 50, 2));\n        var sc = 1 + 0.045*avgCp;\n        var sh = 1 + 0.015*avgCp*T;\n        var deltaTheta = 30*exp(-pow((avgHp - 275)/25, 2));\n        var Rc = 2*sqrt(pow(avgCp, 7)/(pow(avgCp, 7) + pow(25, 7)));\n        var Rt = -Rc*sin(2*deg2rad(deltaTheta));\n        var result = sqrt(pow(deltaL/(Kl*sl), 2) + pow(deltaCp/(Kc*sc), 2) + pow(deltaHp/(Kh*sh), 2) + Rt*(deltaCp/(Kc*sc))*(deltaHp/(Kh*sh)));\n        return max(0, min(100, result));\n    };\n\n    var Color$1 = Color_1;\n\n    // simple Euclidean distance\n    var distance = function(a, b, mode) {\n        if ( mode === void 0 ) mode='lab';\n\n        // Delta E (CIE 1976)\n        // see http://www.brucelindbloom.com/index.html?Equations.html\n        a = new Color$1(a);\n        b = new Color$1(b);\n        var l1 = a.get(mode);\n        var l2 = b.get(mode);\n        var sum_sq = 0;\n        for (var i in l1) {\n            var d = (l1[i] || 0) - (l2[i] || 0);\n            sum_sq += d*d;\n        }\n        return Math.sqrt(sum_sq);\n    };\n\n    var Color = Color_1;\n\n    var valid = function () {\n        var args = [], len = arguments.length;\n        while ( len-- ) args[ len ] = arguments[ len ];\n\n        try {\n            new (Function.prototype.bind.apply( Color, [ null ].concat( args) ));\n            return true;\n        } catch (e) {\n            return false;\n        }\n    };\n\n    // some pre-defined color scales:\n    var chroma$1 = chroma_1;\n\n    var scale = scale$2;\n\n    var scales = {\n    \tcool: function cool() { return scale([chroma$1.hsl(180,1,.9), chroma$1.hsl(250,.7,.4)]) },\n    \thot: function hot() { return scale(['#000','#f00','#ff0','#fff']).mode('rgb') }\n    };\n\n    /**\n        ColorBrewer colors for chroma.js\n\n        Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The\n        Pennsylvania State University.\n\n        Licensed under the Apache License, Version 2.0 (the \"License\");\n        you may not use this file except in compliance with the License.\n        You may obtain a copy of the License at\n        http://www.apache.org/licenses/LICENSE-2.0\n\n        Unless required by applicable law or agreed to in writing, software distributed\n        under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n        CONDITIONS OF ANY KIND, either express or implied. See the License for the\n        specific language governing permissions and limitations under the License.\n    */\n\n    var colorbrewer = {\n        // sequential\n        OrRd: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#b30000', '#7f0000'],\n        PuBu: ['#fff7fb', '#ece7f2', '#d0d1e6', '#a6bddb', '#74a9cf', '#3690c0', '#0570b0', '#045a8d', '#023858'],\n        BuPu: ['#f7fcfd', '#e0ecf4', '#bfd3e6', '#9ebcda', '#8c96c6', '#8c6bb1', '#88419d', '#810f7c', '#4d004b'],\n        Oranges: ['#fff5eb', '#fee6ce', '#fdd0a2', '#fdae6b', '#fd8d3c', '#f16913', '#d94801', '#a63603', '#7f2704'],\n        BuGn: ['#f7fcfd', '#e5f5f9', '#ccece6', '#99d8c9', '#66c2a4', '#41ae76', '#238b45', '#006d2c', '#00441b'],\n        YlOrBr: ['#ffffe5', '#fff7bc', '#fee391', '#fec44f', '#fe9929', '#ec7014', '#cc4c02', '#993404', '#662506'],\n        YlGn: ['#ffffe5', '#f7fcb9', '#d9f0a3', '#addd8e', '#78c679', '#41ab5d', '#238443', '#006837', '#004529'],\n        Reds: ['#fff5f0', '#fee0d2', '#fcbba1', '#fc9272', '#fb6a4a', '#ef3b2c', '#cb181d', '#a50f15', '#67000d'],\n        RdPu: ['#fff7f3', '#fde0dd', '#fcc5c0', '#fa9fb5', '#f768a1', '#dd3497', '#ae017e', '#7a0177', '#49006a'],\n        Greens: ['#f7fcf5', '#e5f5e0', '#c7e9c0', '#a1d99b', '#74c476', '#41ab5d', '#238b45', '#006d2c', '#00441b'],\n        YlGnBu: ['#ffffd9', '#edf8b1', '#c7e9b4', '#7fcdbb', '#41b6c4', '#1d91c0', '#225ea8', '#253494', '#081d58'],\n        Purples: ['#fcfbfd', '#efedf5', '#dadaeb', '#bcbddc', '#9e9ac8', '#807dba', '#6a51a3', '#54278f', '#3f007d'],\n        GnBu: ['#f7fcf0', '#e0f3db', '#ccebc5', '#a8ddb5', '#7bccc4', '#4eb3d3', '#2b8cbe', '#0868ac', '#084081'],\n        Greys: ['#ffffff', '#f0f0f0', '#d9d9d9', '#bdbdbd', '#969696', '#737373', '#525252', '#252525', '#000000'],\n        YlOrRd: ['#ffffcc', '#ffeda0', '#fed976', '#feb24c', '#fd8d3c', '#fc4e2a', '#e31a1c', '#bd0026', '#800026'],\n        PuRd: ['#f7f4f9', '#e7e1ef', '#d4b9da', '#c994c7', '#df65b0', '#e7298a', '#ce1256', '#980043', '#67001f'],\n        Blues: ['#f7fbff', '#deebf7', '#c6dbef', '#9ecae1', '#6baed6', '#4292c6', '#2171b5', '#08519c', '#08306b'],\n        PuBuGn: ['#fff7fb', '#ece2f0', '#d0d1e6', '#a6bddb', '#67a9cf', '#3690c0', '#02818a', '#016c59', '#014636'],\n        Viridis: ['#440154', '#482777', '#3f4a8a', '#31678e', '#26838f', '#1f9d8a', '#6cce5a', '#b6de2b', '#fee825'],\n\n        // diverging\n\n        Spectral: ['#9e0142', '#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#e6f598', '#abdda4', '#66c2a5', '#3288bd', '#5e4fa2'],\n        RdYlGn: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee08b', '#ffffbf', '#d9ef8b', '#a6d96a', '#66bd63', '#1a9850', '#006837'],\n        RdBu: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#f7f7f7', '#d1e5f0', '#92c5de', '#4393c3', '#2166ac', '#053061'],\n        PiYG: ['#8e0152', '#c51b7d', '#de77ae', '#f1b6da', '#fde0ef', '#f7f7f7', '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221', '#276419'],\n        PRGn: ['#40004b', '#762a83', '#9970ab', '#c2a5cf', '#e7d4e8', '#f7f7f7', '#d9f0d3', '#a6dba0', '#5aae61', '#1b7837', '#00441b'],\n        RdYlBu: ['#a50026', '#d73027', '#f46d43', '#fdae61', '#fee090', '#ffffbf', '#e0f3f8', '#abd9e9', '#74add1', '#4575b4', '#313695'],\n        BrBG: ['#543005', '#8c510a', '#bf812d', '#dfc27d', '#f6e8c3', '#f5f5f5', '#c7eae5', '#80cdc1', '#35978f', '#01665e', '#003c30'],\n        RdGy: ['#67001f', '#b2182b', '#d6604d', '#f4a582', '#fddbc7', '#ffffff', '#e0e0e0', '#bababa', '#878787', '#4d4d4d', '#1a1a1a'],\n        PuOr: ['#7f3b08', '#b35806', '#e08214', '#fdb863', '#fee0b6', '#f7f7f7', '#d8daeb', '#b2abd2', '#8073ac', '#542788', '#2d004b'],\n\n        // qualitative\n\n        Set2: ['#66c2a5', '#fc8d62', '#8da0cb', '#e78ac3', '#a6d854', '#ffd92f', '#e5c494', '#b3b3b3'],\n        Accent: ['#7fc97f', '#beaed4', '#fdc086', '#ffff99', '#386cb0', '#f0027f', '#bf5b17', '#666666'],\n        Set1: ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf', '#999999'],\n        Set3: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5', '#ffed6f'],\n        Dark2: ['#1b9e77', '#d95f02', '#7570b3', '#e7298a', '#66a61e', '#e6ab02', '#a6761d', '#666666'],\n        Paired: ['#a6cee3', '#1f78b4', '#b2df8a', '#33a02c', '#fb9a99', '#e31a1c', '#fdbf6f', '#ff7f00', '#cab2d6', '#6a3d9a', '#ffff99', '#b15928'],\n        Pastel2: ['#b3e2cd', '#fdcdac', '#cbd5e8', '#f4cae4', '#e6f5c9', '#fff2ae', '#f1e2cc', '#cccccc'],\n        Pastel1: ['#fbb4ae', '#b3cde3', '#ccebc5', '#decbe4', '#fed9a6', '#ffffcc', '#e5d8bd', '#fddaec', '#f2f2f2'],\n    };\n\n    // add lowercase aliases for case-insensitive matches\n    for (var i = 0, list = Object.keys(colorbrewer); i < list.length; i += 1) {\n        var key = list[i];\n\n        colorbrewer[key.toLowerCase()] = colorbrewer[key];\n    }\n\n    var colorbrewer_1 = colorbrewer;\n\n    var chroma = chroma_1;\n\n    // feel free to comment out anything to rollup\n    // a smaller chroma.js built\n\n    // io --> convert colors\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n    // operators --> modify existing Colors\n\n\n\n\n\n\n\n\n\n\n    // interpolators\n\n\n\n\n\n\n\n\n\n\n\n\n    // generators -- > create new colors\n    chroma.average = average;\n    chroma.bezier = bezier_1;\n    chroma.blend = blend_1;\n    chroma.cubehelix = cubehelix;\n    chroma.mix = chroma.interpolate = mix$1;\n    chroma.random = random_1;\n    chroma.scale = scale$2;\n\n    // other utility methods\n    chroma.analyze = analyze_1.analyze;\n    chroma.contrast = contrast;\n    chroma.deltaE = deltaE;\n    chroma.distance = distance;\n    chroma.limits = analyze_1.limits;\n    chroma.valid = valid;\n\n    // scale\n    chroma.scales = scales;\n\n    // colors\n    chroma.colors = w3cx11_1;\n    chroma.brewer = colorbrewer_1;\n\n    var chroma_js = chroma;\n\n    return chroma_js;\n\n}));\n", "// @ts-check\n/**\n * A static class containing helper functions for array-related tasks.\n */\nexport default class ArrayHelper {\n    /**\n     * Clone an array or an object. If an object is passed, a shallow clone will be created.\n     *\n     * @static\n     * @param {*} arr The array or object to be cloned.\n     * @returns {*} A clone of the array or object.\n     */\n    static clone(arr) {\n        let out = Array.isArray(arr) ? [] : {};\n\n        for (let key in arr) {\n            let value = arr[key];\n\n            if (typeof value.clone === 'function') {\n                out[key] = value.clone();\n            }\n            else {\n                out[key] = (typeof value === 'object') ? ArrayHelper.clone(value) : value;\n            }\n        }\n\n        return out;\n    }\n\n    /**\n     * Returns a boolean indicating whether or not the two arrays contain the same elements.\n     * Only supports 1d, non-nested arrays.\n     *\n     * @static\n     * @param {Array} arrA An array.\n     * @param {Array} arrB An array.\n     * @returns {Boolean} A boolean indicating whether or not the two arrays contain the same elements.\n     */\n    static equals(arrA, arrB) {\n        if (arrA.length !== arrB.length) {\n            return false;\n        }\n\n        let tmpA = arrA.slice().sort();\n        let tmpB = arrB.slice().sort();\n\n        for (let i = 0; i < tmpA.length; i++) {\n            if (tmpA[i] !== tmpB[i]) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Returns a string representation of an array. If the array contains objects with an id property, the id property is printed for each of the elements.\n     *\n     * @static\n     * @param {Object[]} arr An array.\n     * @param {*} arr[].id If the array contains an object with the property 'id', the properties value is printed. Else, the array elements value is printend.\n     * @returns {String} A string representation of the array.\n     */\n    static print(arr) {\n        if (arr.length == 0) {\n            return '';\n        }\n\n        let s = '(';\n\n        for (let i = 0; i < arr.length; i++) {\n            s += arr[i].id ? arr[i].id + ', ' : arr[i] + ', ';\n        }\n\n        s = s.substring(0, s.length - 2);\n\n        return s + ')';\n    }\n\n    /**\n     * Run a function for each element in the array. The element is supplied as an argument for the callback function\n     *\n     * @static\n     * @param {Array} arr An array.\n     * @param {Function} callback The callback function that is called for each element.\n     */\n    static each(arr, callback) {\n        for (let i = 0; i < arr.length; i++) {\n            callback(arr[i]);\n        }\n    }\n\n    /**\n     * Return the array element from an array containing objects, where a property of the object is set to a given value.\n     *\n     * @static\n     * @param {Array} arr An array.\n     * @param {(String|Number)} property A property contained within an object in the array.\n     * @param {(String|Number)} value The value of the property.\n     * @returns {*} The array element matching the value.\n     */\n    static get(arr, property, value) {\n        for (let i = 0; i < arr.length; i++) {\n            if (arr[i][property] == value) {\n                return arr[i];\n            }\n        }\n    }\n\n    /**\n     * Checks whether or not an array contains a given value. the options object passed as a second argument can contain three properties. value: The value to be searched for. property: The property that is to be searched for a given value. func: A function that is used as a callback to return either true or false in order to do a custom comparison.\n     *\n     * @static\n     * @param {Array} arr An array.\n     * @param {Object} options See method description.\n     * @param {*} options.value The value for which to check.\n     * @param {String} [options.property=undefined] The property on which to check.\n     * @param {Function} [options.func=undefined] A custom property function.\n     * @returns {Boolean} A boolean whether or not the array contains a value.\n     */\n    static contains(arr, options) {\n        if (!options.property && !options.func) {\n            for (let i = 0; i < arr.length; i++) {\n                if (arr[i] == options.value) {\n                    return true;\n                }\n            }\n        }\n        else if (options.func) {\n            for (let i = 0; i < arr.length; i++) {\n                if (options.func(arr[i])) {\n                    return true;\n                }\n            }\n        }\n        else {\n            for (let i = 0; i < arr.length; i++) {\n                if (arr[i][options.property] == options.value) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Returns an array containing the intersection between two arrays. That is, values that are common to both arrays.\n     *\n     * @static\n     * @param {Array} arrA An array.\n     * @param {Array} arrB An array.\n     * @returns {Array} The intersecting vlaues.\n     */\n    static intersection(arrA, arrB) {\n        let intersection = [];\n\n        for (let i = 0; i < arrA.length; i++) {\n            for (let j = 0; j < arrB.length; j++) {\n                if (arrA[i] === arrB[j]) {\n                    intersection.push(arrA[i]);\n                }\n            }\n        }\n\n        return intersection;\n    }\n\n    /**\n     * Returns an array of unique elements contained in an array.\n     *\n     * @static\n     * @param {Array} arr An array.\n     * @returns {Array} An array of unique elements contained within the array supplied as an argument.\n     */\n    static unique(arr) {\n        let contains = {};\n        return arr.filter(function(i) {\n            // using !== instead of hasOwnProperty (http://andrew.hedges.name/experiments/in/)\n            return contains[i] !== undefined ? false : (contains[i] = true);\n        });\n    }\n\n    /**\n     * Count the number of occurences of a value in an array.\n     *\n     * @static\n     * @param {Array} arr An array.\n     * @param {*} value A value to be counted.\n     * @returns {Number} The number of occurences of a value in the array.\n     */\n    static count(arr, value) {\n        let count = 0;\n\n        for (let i = 0; i < arr.length; i++) {\n            if (arr[i] === value) {\n                count++;\n            }\n        }\n\n        return count;\n    }\n\n    /**\n     * Toggles the value of an array. If a value is not contained in an array, the array returned will contain all the values of the original array including the value. If a value is contained in an array, the array returned will contain all the values of the original array excluding the value.\n     *\n     * @static\n     * @param {Array} arr An array.\n     * @param {*} value A value to be toggled.\n     * @returns {Array} The toggled array.\n     */\n    static toggle(arr, value) {\n        let newArr = [];\n\n        let removed = false;\n        for (let i = 0; i < arr.length; i++) {\n            // Do not copy value if it exists\n            if (arr[i] !== value) {\n                newArr.push(arr[i]);\n            }\n            else {\n                // The element was not copied to the new array, which\n                // means it was removed\n                removed = true;\n            }\n        }\n\n        // If the element was not removed, then it was not in the array\n        // so add it\n        if (!removed) {\n            newArr.push(value);\n        }\n\n        return newArr;\n    }\n\n    /**\n     * Remove a value from an array.\n     *\n     * @static\n     * @param {Array} arr An array.\n     * @param {*} value A value to be removed.\n     * @returns {Array} A new array with the element with a given value removed.\n     */\n    static remove(arr, value) {\n        let tmp = [];\n\n        for (let i = 0; i < arr.length; i++) {\n            if (arr[i] !== value) {\n                tmp.push(arr[i]);\n            }\n        }\n\n        return tmp;\n    }\n\n    /**\n     * Remove a value from an array with unique values.\n     *\n     * @static\n     * @param {Array} arr An array.\n     * @param {*} value A value to be removed.\n     * @returns {Array} An array with the element with a given value removed.\n     */\n    static removeUnique(arr, value) {\n        let index = arr.indexOf(value);\n\n        if (index > -1) {\n            arr.splice(index, 1);\n        }\n\n        return arr;\n    }\n\n    /**\n     * Remove all elements contained in one array from another array.\n     *\n     * @static\n     * @param {Array} arrA The array to be filtered.\n     * @param {Array} arrB The array containing elements that will be removed from the other array.\n     * @returns {Array} The filtered array.\n     */\n    static removeAll(arrA, arrB) {\n        return arrA.filter(function(item) {\n            return arrB.indexOf(item) === -1;\n        });\n    }\n\n    /**\n     * Merges two arrays and returns the result. The first array will be appended to the second array.\n     *\n     * @static\n     * @param {Array} arrA An array.\n     * @param {Array} arrB An array.\n     * @returns {Array} The merged array.\n     */\n    static merge(arrA, arrB) {\n        let arr = new Array(arrA.length + arrB.length);\n\n        for (let i = 0; i < arrA.length; i++) {\n            arr[i] = arrA[i];\n        }\n\n        for (let i = 0; i < arrB.length; i++) {\n            arr[arrA.length + i] = arrB[i];\n        }\n\n        return arr;\n    }\n\n    /**\n     * Checks whether or not an array contains all the elements of another array, without regard to the order.\n     *\n     * @static\n     * @param {Array} arrA An array.\n     * @param {Array} arrB An array.\n     * @returns {Boolean} A boolean indicating whether or not both array contain the same elements.\n     */\n    static containsAll(arrA, arrB) {\n        let containing = 0;\n        for (let i = 0; i < arrA.length; i++) {\n            for (let j = 0; j < arrB.length; j++) {\n                if (arrA[i] === arrB[j]) {\n                    containing++;\n                }\n            }\n        }\n\n        return containing === arrB.length;\n    }\n\n    /**\n     * Sort an array of atomic number information. Where the number is indicated as x, x.y, x.y.z, ...\n     *\n     * @param {Object[]} arr An array of vertex ids with their associated atomic numbers.\n     * @param {Number} arr[].vertexId A vertex id.\n     * @param {String} arr[].atomicNumber The atomic number associated with the vertex id.\n     * @returns {Object[]} The array sorted by atomic number. Example of an array entry: { atomicNumber: 2, vertexId: 5 }.\n     */\n    static sortByAtomicNumberDesc(arr) {\n        let map = arr.map(function(e, i) {\n            return {index: i, value: e.atomicNumber.split('.').map(Number)};\n        });\n\n        map.sort(function(a, b) {\n            let min = Math.min(b.value.length, a.value.length);\n            let i = 0;\n\n            while (i < min && b.value[i] === a.value[i]) {\n                i++;\n            }\n\n            return i === min ? b.value.length - a.value.length : b.value[i] - a.value[i];\n        });\n\n        return map.map(function(e) {\n            return arr[e.index];\n        });\n    }\n\n    /**\n     * Copies a an n-dimensional array.\n     *\n     * @param {Array} arr The array to be copied.\n     * @returns {Array} The copy.\n     */\n    static deepCopy(arr) {\n        let newArr = [];\n\n        for (let i = 0; i < arr.length; i++) {\n            let item = arr[i];\n\n            if (item instanceof Array) {\n                newArr[i] = ArrayHelper.deepCopy(item);\n            }\n            else {\n                newArr[i] = item;\n            }\n        }\n\n        return newArr;\n    }\n}\n", "// @ts-check\nimport ArrayHelper from './ArrayHelper';\n\n/**\n * A class representing an atom.\n *\n * @property {String} element The element symbol of this atom. Single-letter symbols are always uppercase. Examples: H, C, F, Br, Si, ...\n * @property {Boolean} drawExplicit A boolean indicating whether or not this atom is drawn explicitly (for example, a carbon atom). This overrides the default behaviour.\n * @property {Object[]} ringbonds An array containing the ringbond ids and bond types as specified in the original SMILE.\n * @property {String} branchBond The branch bond as defined in the SMILES.\n * @property {Number} ringbonds[].id The ringbond id as defined in the SMILES.\n * @property {String} ringbonds[].bondType The bond type of the ringbond as defined in the SMILES.\n * @property {Number[]} rings The ids of rings which contain this atom.\n * @property {String} bondType The bond type associated with this array. Examples: -, =, #, ...\n * @property {Boolean} isBridge A boolean indicating whether or not this atom is part of a bridge in a bridged ring (contained by the largest ring).\n * @property {Boolean} isBridgeNode A boolean indicating whether or not this atom is a bridge node (a member of the largest ring in a bridged ring which is connected to a bridge-atom).\n * @property {Number[]} originalRings Used to back up rings when they are replaced by a bridged ring.\n * @property {Number} bridgedRing The id of the bridged ring if the atom is part of a bridged ring.\n * @property {Number[]} anchoredRings The ids of the rings that are anchored to this atom. The centers of anchored rings are translated when this atom is translated.\n * @property {Object} bracket If this atom is defined as a bracket atom in the original SMILES, this object contains all the bracket information. Example: { hcount: {Number}, charge: ['--', '-', '+', '++'], isotope: {Number} }.\n * @property {Number} plane Specifies on which \"plane\" the atoms is in stereochemical deptictions (-1 back, 0 middle, 1 front).\n * @property {Object[]} attachedPseudoElements A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\n * @property {String} attachedPseudoElement[].element The element symbol.\n * @property {Number} attachedPseudoElement[].count The number of occurences that match the key.\n * @property {Number} attachedPseudoElement[].hyrogenCount The number of hydrogens attached to each atom matching the key.\n * @property {Boolean} hasAttachedPseudoElements A boolean indicating whether or not this attom will be drawn with an attached pseudo element or concatinated elements.\n * @property {Boolean} isDrawn A boolean indicating whether or not this atom is drawn. In contrast to drawExplicit, the bond is drawn neither.\n * @property {Boolean} isConnectedToRing A boolean indicating whether or not this atom is directly connected (but not a member of) a ring.\n * @property {String[]} neighbouringElements An array containing the element symbols of neighbouring atoms.\n * @property {Boolean} isPartOfAromaticRing A boolean indicating whether or not this atom is part of an explicitly defined aromatic ring. Example: c1ccccc1.\n * @property {Number} bondCount The number of bonds in which this atom is participating.\n * @property {String} chirality The chirality of this atom if it is a stereocenter (R or S).\n * @property {Number} priority The priority of this atom acording to the CIP rules, where 0 is the highest priority.\n * @property {Boolean} mainChain A boolean indicating whether or not this atom is part of the main chain (used for chirality).\n * @property {Number} subtreeDepth The depth of the subtree coming from a stereocenter.\n * @property {Number} class\n */\nexport default class Atom {\n    /**\n     * The constructor of the class Atom.\n     *\n     * @param {String} element The one-letter code of the element.\n     * @param {String} [bondType='-'] The type of the bond associated with this atom.\n     */\n    constructor(element, bondType = '-') {\n        this.idx = null;\n        this.element = element.length === 1 ? element.toUpperCase() : element;\n        this.drawExplicit = false;\n        this.ringbonds = [];\n        this.rings = [];\n        this.bondType = bondType;\n        this.branchBond = null;\n        this.isBridge = false;\n        this.isBridgeNode = false;\n        this.originalRings = [];\n        this.bridgedRing = null;\n        this.anchoredRings = [];\n        this.bracket = null;\n        this.plane = 0;\n        this.attachedPseudoElements = {};\n        this.hasAttachedPseudoElements = false;\n        this.isDrawn = true;\n        this.isConnectedToRing = false;\n        this.neighbouringElements = [];\n        this.isPartOfAromaticRing = element !== this.element;\n        this.bondCount = 0;\n        this.chirality = '';\n        this.isStereoCenter = false;\n        this.priority = 0;\n        this.mainChain = false;\n        this.subtreeDepth = 1;\n        this.class = undefined;\n    }\n\n    /**\n     * Adds a neighbouring element to this atom.\n     *\n     * @param {String} element A string representing an element.\n     */\n    addNeighbouringElement(element) {\n        this.neighbouringElements.push(element);\n    }\n\n    /**\n     * Attaches a pseudo element (e.g. Ac) to the atom.\n     * @param {String} element The element identifier (e.g. Br, C, ...).\n     * @param {String} previousElement The element that is part of the main chain (not the terminals that are converted to the pseudo element or concatinated).\n     * @param {Number} [hydrogenCount=0] The number of hydrogens for the element.\n     * @param {Number} [charge=0] The charge for the element.\n     */\n    attachPseudoElement(element, previousElement, hydrogenCount = 0, charge = 0) {\n        if (hydrogenCount === null) {\n            hydrogenCount = 0;\n        }\n\n        if (charge === null) {\n            charge = 0;\n        }\n\n        let key = hydrogenCount + element + charge;\n\n        if (this.attachedPseudoElements[key]) {\n            this.attachedPseudoElements[key].count += 1;\n        }\n        else {\n            this.attachedPseudoElements[key] = {\n                element:         element,\n                count:           1,\n                hydrogenCount:   hydrogenCount,\n                previousElement: previousElement,\n                charge:          charge,\n            };\n        }\n\n        this.hasAttachedPseudoElements = true;\n    }\n\n    /**\n     * Returns the attached pseudo elements sorted by hydrogen count (ascending).\n     *\n     * @returns {Object} The sorted attached pseudo elements.\n     */\n    getAttachedPseudoElements() {\n        let ordered = {};\n\n        Object.keys(this.attachedPseudoElements).sort().forEach((key) => {\n            ordered[key] = this.attachedPseudoElements[key];\n        });\n\n        return ordered;\n    }\n\n    /**\n     * Returns the number of attached pseudo elements.\n     *\n     * @returns {Number} The number of attached pseudo elements.\n     */\n    getAttachedPseudoElementsCount() {\n        return Object.keys(this.attachedPseudoElements).length;\n    }\n\n    /**\n     * Returns whether this atom is a heteroatom (not C and not H).\n     *\n     * @returns {Boolean} A boolean indicating whether this atom is a heteroatom.\n     */\n    isHeteroAtom() {\n        return this.element !== 'C' && this.element !== 'H';\n    }\n\n    /**\n     * Defines this atom as the anchor for a ring. When doing repositionings of the vertices and the vertex associated with this atom is moved, the center of this ring is moved as well.\n     *\n     * @param {Number} ringId A ring id.\n     */\n    addAnchoredRing(ringId) {\n        if (!ArrayHelper.contains(this.anchoredRings, {value: ringId})) {\n            this.anchoredRings.push(ringId);\n        }\n    }\n\n    /**\n     * Returns the number of ringbonds (breaks in rings to generate the MST of the smiles) within this atom is connected to.\n     *\n     * @returns {Number} The number of ringbonds this atom is connected to.\n     */\n    getRingbondCount() {\n        return this.ringbonds.length;\n    }\n\n    /**\n     * Backs up the current rings.\n     */\n    backupRings() {\n        this.originalRings = Array(this.rings.length);\n\n        for (let i = 0; i < this.rings.length; i++) {\n            this.originalRings[i] = this.rings[i];\n        }\n    }\n\n    /**\n     * Restores the most recent backed up rings.\n     */\n    restoreRings() {\n        this.rings = Array(this.originalRings.length);\n\n        for (let i = 0; i < this.originalRings.length; i++) {\n            this.rings[i] = this.originalRings[i];\n        }\n    }\n\n    /**\n     * Checks whether or not two atoms share a common ringbond id. A ringbond is a break in a ring created when generating the spanning tree of a structure.\n     *\n     * @param {Atom} atomA An atom.\n     * @param {Atom} atomB An atom.\n     * @returns {Boolean} A boolean indicating whether or not two atoms share a common ringbond.\n     */\n    haveCommonRingbond(atomA, atomB) {\n        for (let i = 0; i < atomA.ringbonds.length; i++) {\n            for (let j = 0; j < atomB.ringbonds.length; j++) {\n                if (atomA.ringbonds[i].id == atomB.ringbonds[j].id) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Check whether or not the neighbouring elements of this atom equal the supplied array.\n     *\n     * @param {String[]} arr An array containing all the elements that are neighbouring this atom. E.g. ['C', 'O', 'O', 'N']\n     * @returns {Boolean} A boolean indicating whether or not the neighbours match the supplied array of elements.\n     */\n    neighbouringElementsEqual(arr) {\n        if (arr.length !== this.neighbouringElements.length) {\n            return false;\n        }\n\n        arr.sort();\n        this.neighbouringElements.sort();\n\n        for (let i = 0; i < this.neighbouringElements.length; i++) {\n            if (arr[i] !== this.neighbouringElements[i]) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Get the atomic number of this atom.\n     *\n     * @returns {Number} The atomic number of this atom.\n     */\n    getAtomicNumber() {\n        return Atom.atomicNumbers[this.element];\n    }\n\n    /**\n     * Counts the implicit hydrogens attached to this atom.\n     *\n     * This function deals with hydrogens specified in SMILES brackets\n     * and inferred based on bond counts and normal valences (see the\n     * VALENCES constant below).  It does NOT count any hydrogens that\n     * are attached as separate atoms in the SMILES string ([H]Cl).\n     *\n     * @returns {number} The number of implicit hydrogens attached to this atom.\n     */\n    countImplicitHydrogens() {\n        if (this.bracket) {\n            if (this.bracket.chirality) {\n                // We add hydrogens to chiral atoms explicitly.\n                return 0;\n            }\n            else {\n                // But otherwise, the bracket count is accurate.\n                return this.bracket.hcount || 0;\n            }\n        }\n\n        let bonds = this.bondCount;\n        if (this.isPartOfAromaticRing) {\n            if (this.element !== 'C') {\n                // This is a HACK to set heteroatoms to a sensible default.\n                // TODO: The correct fix for this is kekulization.\n                return 0;\n            }\n\n            // This is also definitely a HACK for something...\n            // TODO: Figure out what and fix the real issue!\n            bonds += 1;\n        }\n\n        const valences = Atom.VALENCES[this.element];\n        if (valences === undefined) {\n            return 0;\n        }\n\n        const valence = valences.find(n => (n >= bonds));\n        if (valence !== undefined) {\n            return valence - bonds;\n        }\n\n        return 0;\n    }\n\n    // Possible valences according to OpenSMILES\n    // http://opensmiles.org/opensmiles.html#orgsbst\n    static VALENCES = {\n        H:  [1],\n        B:  [3],\n        C:  [4],\n        N:  [3, 5],\n        O:  [2],\n        F:  [1],\n        P:  [3, 5],\n        S:  [2, 4, 6],\n        Cl: [1],\n        Br: [1],\n        I:  [1],\n    };\n\n    /**\n     * A map mapping element symbols to the atomic number.\n     */\n    static get atomicNumbers() {\n        return {\n            H:   1,\n            He:  2,\n            Li:  3,\n            Be:  4,\n            B:   5,\n            b:   5,\n            C:   6,\n            c:   6,\n            N:   7,\n            n:   7,\n            O:   8,\n            o:   8,\n            F:   9,\n            Ne:  10,\n            Na:  11,\n            Mg:  12,\n            Al:  13,\n            Si:  14,\n            P:   15,\n            p:   15,\n            S:   16,\n            s:   16,\n            Cl:  17,\n            Ar:  18,\n            K:   19,\n            Ca:  20,\n            Sc:  21,\n            Ti:  22,\n            V:   23,\n            Cr:  24,\n            Mn:  25,\n            Fe:  26,\n            Co:  27,\n            Ni:  28,\n            Cu:  29,\n            Zn:  30,\n            Ga:  31,\n            Ge:  32,\n            As:  33,\n            Se:  34,\n            Br:  35,\n            Kr:  36,\n            Rb:  37,\n            Sr:  38,\n            Y:   39,\n            Zr:  40,\n            Nb:  41,\n            Mo:  42,\n            Tc:  43,\n            Ru:  44,\n            Rh:  45,\n            Pd:  46,\n            Ag:  47,\n            Cd:  48,\n            In:  49,\n            Sn:  50,\n            Sb:  51,\n            Te:  52,\n            I:   53,\n            Xe:  54,\n            Cs:  55,\n            Ba:  56,\n            La:  57,\n            Ce:  58,\n            Pr:  59,\n            Nd:  60,\n            Pm:  61,\n            Sm:  62,\n            Eu:  63,\n            Gd:  64,\n            Tb:  65,\n            Dy:  66,\n            Ho:  67,\n            Er:  68,\n            Tm:  69,\n            Yb:  70,\n            Lu:  71,\n            Hf:  72,\n            Ta:  73,\n            W:   74,\n            Re:  75,\n            Os:  76,\n            Ir:  77,\n            Pt:  78,\n            Au:  79,\n            Hg:  80,\n            Tl:  81,\n            Pb:  82,\n            Bi:  83,\n            Po:  84,\n            At:  85,\n            Rn:  86,\n            Fr:  87,\n            Ra:  88,\n            Ac:  89,\n            Th:  90,\n            Pa:  91,\n            U:   92,\n            Np:  93,\n            Pu:  94,\n            Am:  95,\n            Cm:  96,\n            Bk:  97,\n            Cf:  98,\n            Es:  99,\n            Fm:  100,\n            Md:  101,\n            No:  102,\n            Lr:  103,\n            Rf:  104,\n            Db:  105,\n            Sg:  106,\n            Bh:  107,\n            Hs:  108,\n            Mt:  109,\n            Ds:  110,\n            Rg:  111,\n            Cn:  112,\n            Uut: 113,\n            Uuq: 114,\n            Uup: 115,\n            Uuh: 116,\n            Uus: 117,\n            Uuo: 118,\n        };\n    }\n}\n", "// @ts-check\n\n/**\n * A class representing a 2D vector.\n *\n * @property {Number} x The x component of the vector.\n * @property {Number} y The y component of the vector.\n */\nexport default class Vector2 {\n    /**\n     * The constructor of the class Vector2.\n     *\n     * @param {(Number|Vector2)} x The initial x coordinate value or, if the single argument, a Vector2 object.\n     * @param {Number} y The initial y coordinate value.\n     */\n    constructor(x, y) {\n        if (arguments.length == 0) {\n            this.x = 0;\n            this.y = 0;\n        }\n        else if (x instanceof Vector2) {\n            this.x = x.x;\n            this.y = x.y;\n        }\n        else {\n            this.x = x;\n            this.y = y;\n        }\n    }\n\n    /**\n     * Clones this vector and returns the clone.\n     *\n     * @returns {Vector2} The clone of this vector.\n     */\n    clone() {\n        return new Vector2(this.x, this.y);\n    }\n\n    /**\n     * Returns a string representation of this vector.\n     *\n     * @returns {String} A string representation of this vector.\n     */\n    toString() {\n        return '(' + this.x + ',' + this.y + ')';\n    }\n\n    /**\n     * Add the x and y coordinate values of a vector to the x and y coordinate values of this vector.\n     *\n     * @param {Vector2} vec Another vector.\n     * @returns {Vector2} Returns itself.\n     */\n    add(vec) {\n        this.x += vec.x;\n        this.y += vec.y;\n\n        return this;\n    }\n\n    /**\n     * Subtract the x and y coordinate values of a vector from the x and y coordinate values of this vector.\n     *\n     * @param {Vector2} vec Another vector.\n     * @returns {Vector2} Returns itself.\n     */\n    subtract(vec) {\n        this.x -= vec.x;\n        this.y -= vec.y;\n\n        return this;\n    }\n\n    /**\n     * Divide the x and y coordinate values of this vector by a scalar.\n     *\n     * @param {Number} scalar The scalar.\n     * @returns {Vector2} Returns itself.\n     */\n    divide(scalar) {\n        this.x /= scalar;\n        this.y /= scalar;\n\n        return this;\n    }\n\n    /**\n     * Multiply the x and y coordinate values of this vector by the values of another vector.\n     *\n     * @param {Vector2} v A vector.\n     * @returns {Vector2} Returns itself.\n     */\n    multiply(v) {\n        this.x *= v.x;\n        this.y *= v.y;\n\n        return this;\n    }\n\n    /**\n     * Multiply the x and y coordinate values of this vector by a scalar.\n     *\n     * @param {Number} scalar The scalar.\n     * @returns {Vector2} Returns itself.\n     */\n    multiplyScalar(scalar) {\n        this.x *= scalar;\n        this.y *= scalar;\n\n        return this;\n    }\n\n    /**\n     * Inverts this vector. Same as multiply(-1.0).\n     *\n     * @returns {Vector2} Returns itself.\n     */\n    invert() {\n        this.x = -this.x;\n        this.y = -this.y;\n\n        return this;\n    }\n\n    /**\n     * Returns the angle of this vector in relation to the coordinate system.\n     *\n     * @returns {Number} The angle in radians.\n     */\n    angle() {\n        return Math.atan2(this.y, this.x);\n    }\n\n    /**\n     * Returns the euclidean distance between this vector and another vector.\n     *\n     * @param {Vector2} vec A vector.\n     * @returns {Number} The euclidean distance between the two vectors.\n     */\n    distance(vec) {\n        return Math.sqrt((vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y));\n    }\n\n    /**\n     * Returns the squared euclidean distance between this vector and another vector. When only the relative distances of a set of vectors are needed, this is is less expensive than using distance(vec).\n     *\n     * @param {Vector2} vec Another vector.\n     * @returns {Number} The squared euclidean distance of the two vectors.\n     */\n    distanceSq(vec) {\n        return (vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y);\n    }\n\n    /**\n     * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to the coordinate system.\n     *\n     * @param {Vector2} vec Another vector.\n     * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to the coordinate system.\n     */\n    clockwise(vec) {\n        let a = this.y * vec.x;\n        let b = this.x * vec.y;\n\n        if (a > b) {\n            return -1;\n        }\n        else if (a === b) {\n            return 0;\n        }\n\n        return 1;\n    }\n\n    /**\n     * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to an arbitrary third vector.\n     *\n     * @param {Vector2} center The central vector.\n     * @param {Vector2} vec Another vector.\n     * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to an arbitrary third vector.\n     */\n    relativeClockwise(center, vec) {\n        let a = (this.y - center.y) * (vec.x - center.x);\n        let b = (this.x - center.x) * (vec.y - center.y);\n\n        if (a > b) {\n            return -1;\n        }\n        else if (a === b) {\n            return 0;\n        }\n\n        return 1;\n    }\n\n    /**\n     * Rotates this vector by a given number of radians around the origin of the coordinate system.\n     *\n     * @param {Number} angle The angle in radians to rotate the vector.\n     * @returns {Vector2} Returns itself.\n     */\n    rotate(angle) {\n        let tmp = new Vector2(0, 0);\n        let cosAngle = Math.cos(angle);\n        let sinAngle = Math.sin(angle);\n\n        tmp.x = this.x * cosAngle - this.y * sinAngle;\n        tmp.y = this.x * sinAngle + this.y * cosAngle;\n\n        this.x = tmp.x;\n        this.y = tmp.y;\n\n        return this;\n    }\n\n    /**\n     * Rotates this vector around another vector.\n     *\n     * @param {Number} angle The angle in radians to rotate the vector.\n     * @param {Vector2} vec The vector which is used as the rotational center.\n     * @returns {Vector2} Returns itself.\n     */\n    rotateAround(angle, vec) {\n        let s = Math.sin(angle);\n        let c = Math.cos(angle);\n\n        this.x -= vec.x;\n        this.y -= vec.y;\n\n        let x = this.x * c - this.y * s;\n        let y = this.x * s + this.y * c;\n\n        this.x = x + vec.x;\n        this.y = y + vec.y;\n\n        return this;\n    }\n\n    /**\n     * Rotate a vector around a given center to the same angle as another vector (so that the two vectors and the center are in a line, with both vectors on one side of the center), keeps the distance from this vector to the center.\n     *\n     * @param {Vector2} vec The vector to rotate this vector to.\n     * @param {Vector2} center The rotational center.\n     * @param {Number} [offsetAngle=0.0] An additional amount of radians to rotate the vector.\n     * @returns {Vector2} Returns itself.\n     */\n    rotateTo(vec, center, offsetAngle = 0.0) {\n        // Problem if this is first position\n        this.x += 0.001;\n        this.y -= 0.001;\n\n        let a = Vector2.subtract(this, center);\n        let b = Vector2.subtract(vec, center);\n        let angle = Vector2.angle(b, a);\n\n        this.rotateAround(angle + offsetAngle, center);\n\n        return this;\n    }\n\n    /**\n     * Rotates the vector away from a specified vector around a center.\n     *\n     * @param {Vector2} vec The vector this one is rotated away from.\n     * @param {Vector2} center The rotational center.\n     * @param {Number} angle The angle by which to rotate.\n     */\n    rotateAwayFrom(vec, center, angle) {\n        this.rotateAround(angle, center);\n\n        let distSqA = this.distanceSq(vec);\n\n        this.rotateAround(-2.0 * angle, center);\n\n        let distSqB = this.distanceSq(vec);\n\n        // If it was rotated towards the other vertex, rotate in other direction by same amount.\n        if (distSqB < distSqA) {\n            this.rotateAround(2.0 * angle, center);\n        }\n    }\n\n    /**\n     * Returns the angle in radians used to rotate this vector away from a given vector.\n     *\n     * @param {Vector2} vec The vector this one is rotated away from.\n     * @param {Vector2} center The rotational center.\n     * @param {Number} angle The angle by which to rotate.\n     * @returns {Number} The angle in radians.\n     */\n    getRotateAwayFromAngle(vec, center, angle) {\n        let tmp = this.clone();\n\n        tmp.rotateAround(angle, center);\n\n        let distSqA = tmp.distanceSq(vec);\n\n        tmp.rotateAround(-2.0 * angle, center);\n\n        let distSqB = tmp.distanceSq(vec);\n\n        if (distSqB < distSqA) {\n            return angle;\n        }\n        else {\n            return -angle;\n        }\n    }\n\n    /**\n     * Returns the angle in radians used to rotate this vector towards a given vector.\n     *\n     * @param {Vector2} vec The vector this one is rotated towards to.\n     * @param {Vector2} center The rotational center.\n     * @param {Number} angle The angle by which to rotate.\n     * @returns {Number} The angle in radians.\n     */\n    getRotateTowardsAngle(vec, center, angle) {\n        let tmp = this.clone();\n\n        tmp.rotateAround(angle, center);\n\n        let distSqA = tmp.distanceSq(vec);\n\n        tmp.rotateAround(-2.0 * angle, center);\n\n        let distSqB = tmp.distanceSq(vec);\n\n        if (distSqB > distSqA) {\n            return angle;\n        }\n        else {\n            return -angle;\n        }\n    }\n\n    /**\n     * Gets the angles between this vector and another vector around a common center of rotation.\n     *\n     * @param {Vector2} vec Another vector.\n     * @param {Vector2} center The center of rotation.\n     * @returns {Number} The angle between this vector and another vector around a center of rotation in radians.\n     */\n    getRotateToAngle(vec, center) {\n        let a = Vector2.subtract(this, center);\n        let b = Vector2.subtract(vec, center);\n        let angle = Vector2.angle(b, a);\n\n        return Number.isNaN(angle) ? 0.0 : angle;\n    }\n\n    /**\n     * Checks whether a vector lies within a polygon spanned by a set of vectors.\n     *\n     * @param {Vector2[]} polygon An array of vectors spanning the polygon.\n     * @returns {Boolean} A boolean indicating whether or not this vector is within a polygon.\n     */\n    isInPolygon(polygon) {\n        let inside = false;\n\n        // Its not always a given, that the polygon is convex (-> sugars)\n        for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n            const a = polygon[i];\n            const b = polygon[j];\n            if (((a.y > this.y) != (b.y > this.y)) && (this.x < (b.x - a.x) * (this.y - a.y) / (b.y - a.y) + a.x)) {\n                inside = !inside;\n            }\n        }\n\n        return inside;\n    }\n\n    /**\n     * Returns the length of this vector.\n     *\n     * @returns {Number} The length of this vector.\n     */\n    length() {\n        return Math.sqrt((this.x * this.x) + (this.y * this.y));\n    }\n\n    /**\n     * Returns the square of the length of this vector.\n     *\n     * @returns {Number} The square of the length of this vector.\n     */\n    lengthSq() {\n        return (this.x * this.x) + (this.y * this.y);\n    }\n\n    /**\n     * Normalizes this vector.\n     *\n     * @returns {Vector2} Returns itself.\n     */\n    normalize() {\n        this.divide(this.length());\n\n        return this;\n    }\n\n    /**\n     * Returns a normalized copy of this vector.\n     *\n     * @returns {Vector2} A normalized copy of this vector.\n     */\n    normalized() {\n        return Vector2.divideScalar(this, this.length());\n    }\n\n    /**\n     * Calculates which side of a line spanned by two vectors this vector is.\n     *\n     * @param {Vector2} vecA A vector.\n     * @param {Vector2} vecB A vector.\n     * @returns {Number} A number indicating the side of this vector, given a line spanned by two other vectors.\n     */\n    whichSide(vecA, vecB) {\n        return (this.x - vecA.x) * (vecB.y - vecA.y) - (this.y - vecA.y) * (vecB.x - vecA.x);\n    }\n\n    /**\n     * Checks whether or not this vector is on the same side of a line spanned by two vectors as another vector.\n     *\n     * @param {Vector2} vecA A vector spanning the line.\n     * @param {Vector2} vecB A vector spanning the line.\n     * @param {Vector2} vecC A vector to check whether or not it is on the same side as this vector.\n     * @returns {Boolean} Returns a boolean indicating whether or not this vector is on the same side as another vector.\n     */\n    sameSideAs(vecA, vecB, vecC) {\n        let d    = this.whichSide(vecA, vecB);\n        let dRef = vecC.whichSide(vecA, vecB);\n\n        return (d < 0 && dRef < 0) || (d == 0 && dRef == 0) || (d > 0 && dRef > 0);\n    }\n\n    /**\n     * Adds two vectors and returns the result as a new vector.\n     *\n     * @static\n     * @param {Vector2} vecA A summand.\n     * @param {Vector2} vecB A summand.\n     * @returns {Vector2} Returns the sum of two vectors.\n     */\n    static add(vecA, vecB) {\n        return new Vector2(vecA.x + vecB.x, vecA.y + vecB.y);\n    }\n\n    /**\n     * Subtracts one vector from another and returns the result as a new vector.\n     *\n     * @static\n     * @param {Vector2} vecA The minuend.\n     * @param {Vector2} vecB The subtrahend.\n     * @returns {Vector2} Returns the difference of two vectors.\n     */\n    static subtract(vecA, vecB) {\n        return new Vector2(vecA.x - vecB.x, vecA.y - vecB.y);\n    }\n\n    /**\n     * Multiplies two vectors (value by value) and returns the result.\n     *\n     * @static\n     * @param {Vector2} vecA A vector.\n     * @param {Vector2} vecB A vector.\n     * @returns {Vector2} Returns the product of two vectors.\n     */\n    static multiply(vecA, vecB) {\n        return new Vector2(vecA.x * vecB.x, vecA.y * vecB.y);\n    }\n\n    /**\n     * Multiplies two vectors (value by value) and returns the result.\n     *\n     * @static\n     * @param {Vector2} vec A vector.\n     * @param {Number} scalar A scalar.\n     * @returns {Vector2} Returns the product of two vectors.\n     */\n    static multiplyScalar(vec, scalar) {\n        return new Vector2(vec.x, vec.y).multiplyScalar(scalar);\n    }\n\n    /**\n     * Returns the midpoint of a line spanned by two vectors.\n     *\n     * @static\n     * @param {Vector2} vecA A vector spanning the line.\n     * @param {Vector2} vecB A vector spanning the line.\n     * @returns {Vector2} The midpoint of the line spanned by two vectors.\n     */\n    static midpoint(vecA, vecB) {\n        return new Vector2((vecA.x + vecB.x) / 2, (vecA.y + vecB.y) / 2);\n    }\n\n    /**\n     * Returns the normals of a line spanned by two vectors.\n     *\n     * @static\n     * @param {Vector2} vecA A vector spanning the line.\n     * @param {Vector2} vecB A vector spanning the line.\n     * @returns {Vector2[]} An array containing the two normals, each represented by a vector.\n     */\n    static normals(vecA, vecB) {\n        let delta = Vector2.subtract(vecB, vecA);\n\n        return [\n            new Vector2(-delta.y, delta.x),\n            new Vector2(delta.y, -delta.x),\n        ];\n    }\n\n    /**\n     * Returns the unit (normalized normal) vectors of a line spanned by two vectors.\n     *\n     * @static\n     * @param {Vector2} vecA A vector spanning the line.\n     * @param {Vector2} vecB A vector spanning the line.\n     * @returns {Vector2[]} An array containing the two unit vectors.\n     */\n    static units(vecA, vecB) {\n        let delta = Vector2.subtract(vecB, vecA);\n\n        return [\n            (new Vector2(-delta.y, delta.x)).normalize(),\n            (new Vector2(delta.y, -delta.x)).normalize(),\n        ];\n    }\n\n    /**\n     * Divides a vector by another vector and returns the result as new vector.\n     *\n     * @static\n     * @param {Vector2} vecA The dividend.\n     * @param {Vector2} vecB The divisor.\n     * @returns {Vector2} The fraction of the two vectors.\n     */\n    static divide(vecA, vecB) {\n        return new Vector2(vecA.x / vecB.x, vecA.y / vecB.y);\n    }\n\n    /**\n     * Divides a vector by a scalar and returns the result as new vector.\n     *\n     * @static\n     * @param {Vector2} vecA The dividend.\n     * @param {Number} s The scalar.\n     * @returns {Vector2} The fraction of the two vectors.\n     */\n    static divideScalar(vecA, s) {\n        return new Vector2(vecA.x / s, vecA.y / s);\n    }\n\n    /**\n     * Returns the dot product of two vectors.\n     *\n     * @static\n     * @param {Vector2} vecA A vector.\n     * @param {Vector2} vecB A vector.\n     * @returns {Number} The dot product of two vectors.\n     */\n    static dot(vecA, vecB) {\n        return vecA.x * vecB.x + vecA.y * vecB.y;\n    }\n\n    /**\n     * Returns the angle between two vectors.\n     *\n     * @static\n     * @param {Vector2} vecA A vector.\n     * @param {Vector2} vecB A vector.\n     * @returns {Number} The angle between two vectors in radians.\n     */\n    static angle(vecA, vecB) {\n        let dot = Vector2.dot(vecA, vecB);\n\n        return Math.acos(dot / (vecA.length() * vecB.length()));\n    }\n\n    /**\n     * Returns the angle between two vectors based on a third vector in between.\n     *\n     * @static\n     * @param {Vector2} vecA A vector.\n     * @param {Vector2} vecB A (central) vector.\n     * @param {Vector2} vecC A vector.\n     * @returns {Number} The angle in radians.\n     */\n    static threePointangle(vecA, vecB, vecC) {\n        let ab = Vector2.subtract(vecB, vecA);\n        let bc = Vector2.subtract(vecC, vecB);\n        let abLength = vecA.distance(vecB);\n        let bcLength = vecB.distance(vecC);\n\n        return Math.acos(Vector2.dot(ab, bc) / (abLength * bcLength));\n    }\n\n    /**\n     * Returns the scalar projection of a vector on another vector.\n     *\n     * @static\n     * @param {Vector2} vecA The vector to be projected.\n     * @param {Vector2} vecB The vector to be projection upon.\n     * @returns {Number} The scalar component.\n     */\n    static scalarProjection(vecA, vecB) {\n        let unit = vecB.normalized();\n\n        return Vector2.dot(vecA, unit);\n    }\n\n    /**\n     * Returns the average vector (normalized) of the input vectors.\n     *\n     * @static\n     * @param {Array} vecs An array containing vectors.\n     * @returns {Vector2} The resulting vector (normalized).\n     */\n    static averageDirection(vecs) {\n        let avg = new Vector2(0.0, 0.0);\n\n        for (let i = 0; i < vecs.length; i++) {\n            let vec = vecs[i];\n            avg.add(vec);\n        }\n\n        return avg.normalize();\n    }\n}\n", "// @ts-check\nimport Vector2 from './Vector2';\n\n/**\n * A class representing a line.\n *\n * @property {Vector2} from The Vector2 defining the start of the line.\n * @property {Vector2} to The Vector2 defining the end of the line.\n * @property {String} elementFrom The element symbol associated with the start of the line.\n * @property {String} elementTo The element symbol associated with the end of the line.\n * @property {Boolean} chiralFrom A boolean indicating whether or not the source atom is a chiral center.\n * @property {Boolean} chiralTo A boolean indicating whether or tno the target atom is a chiral center.\n */\nexport default class Line {\n    /**\n     * The constructor for the class Line.\n     *\n     * @param {Vector2} [from=new Vector2(0, 0)] A vector marking the beginning of the line.\n     * @param {Vector2} [to=new Vector2(0, 0)] A vector marking the end of the line.\n     * @param {string} [elementFrom=null] A one-letter representation of the element associated with the vector marking the beginning of the line.\n     * @param {string} [elementTo=null] A one-letter representation of the element associated with the vector marking the end of the line.\n     * @param {Boolean} [chiralFrom=false] Whether or not the from atom is a chiral center.\n     * @param {Boolean} [chiralTo=false] Whether or not the to atom is a chiral center.\n     */\n    constructor(from = new Vector2(0, 0), to = new Vector2(0, 0), elementFrom = null, elementTo = null, chiralFrom = false, chiralTo = false) {\n        this.from = from;\n        this.to = to;\n        this.elementFrom = elementFrom;\n        this.elementTo = elementTo;\n        this.chiralFrom = chiralFrom;\n        this.chiralTo = chiralTo;\n    }\n\n    /**\n     * Clones this line and returns the clone.\n     *\n     * @returns {Line} A clone of this line.\n     */\n    clone() {\n        return new Line(this.from.clone(), this.to.clone(), this.elementFrom, this.elementTo);\n    }\n\n    /**\n     * Returns the length of this line.\n     *\n     * @returns {Number} The length of this line.\n     */\n    getLength() {\n        const dx = this.to.x - this.from.x;\n        const dy = this.to.y - this.from.y;\n        return Math.sqrt(dx * dx + dy * dy);\n    }\n\n    /**\n     * Returns the angle of the line in relation to the coordinate system (the x-axis).\n     *\n     * @returns {Number} The angle in radians.\n     */\n    getAngle() {\n        // Get the angle between the line and the x-axis\n        let diff = Vector2.subtract(this.getRightVector(), this.getLeftVector());\n        return diff.angle();\n    }\n\n    /**\n     * Returns the right vector (the vector with the larger x value).\n     *\n     * @returns {Vector2} The right vector.\n     */\n    getRightVector() {\n        // Return the vector with the larger x value (the right one)\n        if (this.from.x < this.to.x) {\n            return this.to;\n        }\n        else {\n            return this.from;\n        }\n    }\n\n    /**\n     * Returns the left vector (the vector with the smaller x value).\n     *\n     * @returns {Vector2} The left vector.\n     */\n    getLeftVector() {\n        // Return the vector with the smaller x value (the left one)\n        if (this.from.x < this.to.x) {\n            return this.from;\n        }\n        else {\n            return this.to;\n        }\n    }\n\n    /**\n     * Returns the element associated with the right vector (the vector with the larger x value).\n     *\n     * @returns {String} The element associated with the right vector.\n     */\n    getRightElement() {\n        if (this.from.x < this.to.x) {\n            return this.elementTo;\n        }\n        else {\n            return this.elementFrom;\n        }\n    }\n\n    /**\n     * Returns the element associated with the left vector (the vector with the smaller x value).\n     *\n     * @returns {String} The element associated with the left vector.\n     */\n    getLeftElement() {\n        if (this.from.x < this.to.x) {\n            return this.elementFrom;\n        }\n        else {\n            return this.elementTo;\n        }\n    }\n\n    /**\n     * Returns whether or not the atom associated with the right vector (the vector with the larger x value) is a chiral center.\n     *\n     * @returns {Boolean} Whether or not the atom associated with the right vector is a chiral center.\n     */\n    getRightChiral() {\n        if (this.from.x < this.to.x) {\n            return this.chiralTo;\n        }\n        else {\n            return this.chiralFrom;\n        }\n    }\n\n    /**\n     * Returns whether or not the atom associated with the left vector (the vector with the smaller x value) is a chiral center.\n     *\n     * @returns {Boolean} Whether or not the atom  associated with the left vector is a chiral center.\n     */\n    getLeftChiral() {\n        if (this.from.x < this.to.x) {\n            return this.chiralFrom;\n        }\n        else {\n            return this.chiralTo;\n        }\n    }\n\n    /**\n     * Set the value of the right vector.\n     *\n     * @param {Number} x The x value.\n     * @param {Number} y The y value.\n     * @returns {Line} This line.\n     */\n    setRightVector(x, y) {\n        if (this.from.x < this.to.x) {\n            this.to.x = x;\n            this.to.y = y;\n        }\n        else {\n            this.from.x = x;\n            this.from.y = y;\n        }\n\n        return this;\n    }\n\n    /**\n     * Set the value of the left vector.\n     *\n     * @param {Number} x The x value.\n     * @param {Number} y The y value.\n     * @returns {Line} This line.\n     */\n    setLeftVector(x, y) {\n        if (this.from.x < this.to.x) {\n            this.from.x = x;\n            this.from.y = y;\n        }\n        else {\n            this.to.x = x;\n            this.to.y = y;\n        }\n\n        return this;\n    }\n\n    /**\n     * Rotates this line to be aligned with the x-axis. The center of rotation is the left vector.\n     *\n     * @returns {Line} This line.\n     */\n    rotateToXAxis() {\n        let left = this.getLeftVector();\n\n        this.setRightVector(left.x + this.getLength(), left.y);\n\n        return this;\n    }\n\n    /**\n     * Rotate the line by a given value (in radians). The center of rotation is the left vector.\n     *\n     * @param {Number} theta The angle (in radians) to rotate the line.\n     * @returns {Line} This line.\n     */\n    rotate(theta) {\n        let l = this.getLeftVector();\n        let r = this.getRightVector();\n        let sinTheta = Math.sin(theta);\n        let cosTheta = Math.cos(theta);\n\n        let x = cosTheta * (r.x - l.x) - sinTheta * (r.y - l.y) + l.x;\n        let y = sinTheta * (r.x - l.x) - cosTheta * (r.y - l.y) + l.y;\n\n        this.setRightVector(x, y);\n\n        return this;\n    }\n\n    /**\n     * Shortens this line from the \"from\" direction by a given value (in pixels).\n     *\n     * @param {Number} by The length in pixels to shorten the vector by.\n     * @returns {Line} This line.\n     */\n    shortenFrom(by) {\n        let f = Vector2.subtract(this.to, this.from);\n\n        f.normalize();\n        f.multiplyScalar(by);\n\n        this.from.add(f);\n\n        return this;\n    }\n\n    /**\n     * Shortens this line from the \"to\" direction by a given value (in pixels).\n     *\n     * @param {Number} by The length in pixels to shorten the vector by.\n     * @returns {Line} This line.\n     */\n    shortenTo(by) {\n        let f = Vector2.subtract(this.from, this.to);\n\n        f.normalize();\n        f.multiplyScalar(by);\n\n        this.to.add(f);\n\n        return this;\n    }\n\n    /**\n     * Shorten the right side.\n     *\n     * @param {Number} by The length in pixels to shorten the vector by.\n     * @returns {Line} Returns itself.\n     */\n    shortenRight(by) {\n        if (this.from.x < this.to.x) {\n            this.shortenTo(by);\n        }\n        else {\n            this.shortenFrom(by);\n        }\n\n        return this;\n    }\n\n    /**\n     * Shorten the left side.\n     *\n     * @param {Number} by The length in pixels to shorten the vector by.\n     * @returns {Line} Returns itself.\n     */\n    shortenLeft(by) {\n        if (this.from.x < this.to.x) {\n            this.shortenFrom(by);\n        }\n        else {\n            this.shortenTo(by);\n        }\n\n        return this;\n    }\n\n    /**\n     * Shortens this line from both directions by a given value (in pixels).\n     *\n     * @param {Number} by The length in pixels to shorten the vector by.\n     * @returns {Line} This line.\n     */\n    shorten(by) {\n        let f = Vector2.subtract(this.from, this.to);\n\n        f.normalize();\n        f.multiplyScalar(by / 2.0);\n\n        this.to.add(f);\n        this.from.subtract(f);\n\n        return this;\n    }\n}\n", "/**\n * A static class containing helper functions for math-related tasks.\n */\nexport default class MathHelper {\n    /**\n     * Rounds a value to a given number of decimals.\n     *\n     * @static\n     * @param {Number} value A number.\n     * @param {Number} decimals The number of decimals.\n     * @returns {Number} A number rounded to a given number of decimals.\n     */\n    static round(value, decimals) {\n        if (decimals) {\n            const pow = Math.pow(10, decimals);\n            return Math.round(value * pow) / pow;\n        }\n        else {\n            return Math.round(value);\n        }\n    }\n\n    /**\n     * Returns the means of the angles contained in an array. In radians.\n     *\n     * @static\n     * @param {Number[]} arr An array containing angles (in radians).\n     * @returns {Number} The mean angle in radians.\n     */\n    static meanAngle(arr) {\n        let sin = 0.0;\n        let cos = 0.0;\n\n        for (let i = 0; i < arr.length; i++) {\n            sin += Math.sin(arr[i]);\n            cos += Math.cos(arr[i]);\n        }\n\n        return Math.atan2(sin / arr.length, cos / arr.length);\n    }\n\n    /**\n     * Returns the inner angle of a n-sided regular polygon.\n     *\n     * @static\n     * @param {Number} n Number of sides of a regular polygon.\n     * @returns {Number} The inner angle of a given regular polygon.\n     */\n    static innerAngle(n) {\n        return MathHelper.toRad((n - 2) * 180 / n);\n    }\n\n    /**\n     * Returns the circumradius of a n-sided regular polygon with a given side-length.\n     *\n     * @static\n     * @param {Number} s The side length of the regular polygon.\n     * @param {Number} n The number of sides.\n     * @returns {Number} The circumradius of the regular polygon.\n     */\n    static polyCircumradius(s, n) {\n        return s / (2 * Math.sin(Math.PI / n));\n    }\n\n    /**\n     * Returns the apothem of a regular n-sided polygon based on its radius.\n     *\n     * @static\n     * @param {Number} r The radius.\n     * @param {Number} n The number of edges of the regular polygon.\n     * @returns {Number} The apothem of a n-sided polygon based on its radius.\n     */\n    static apothem(r, n) {\n        return r * Math.cos(Math.PI / n);\n    }\n\n    static apothemFromSideLength(s, n) {\n        let r = MathHelper.polyCircumradius(s, n);\n\n        return MathHelper.apothem(r, n);\n    }\n\n    /**\n     * The central angle of a n-sided regular polygon. In radians.\n     *\n     * @static\n     * @param {Number} n The number of sides of the regular polygon.\n     * @returns {Number} The central angle of the n-sided polygon in radians.\n     */\n    static centralAngle(n) {\n        return MathHelper.toRad(360 / n);\n    }\n\n    /**\n     * Convertes radians to degrees.\n     *\n     * @static\n     * @param {Number} rad An angle in radians.\n     * @returns {Number} The angle in degrees.\n     */\n    static toDeg(rad) {\n        return rad * MathHelper.degFactor;\n    }\n\n    /**\n     * Converts degrees to radians.\n     *\n     * @static\n     * @param {Number} deg An angle in degrees.\n     * @returns {Number} The angle in radians.\n     */\n    static toRad(deg) {\n        return deg * MathHelper.radFactor;\n    }\n\n    /**\n     * Returns the parity of the permutation (1 or -1)\n     * @param {(Array|Uint8Array)} arr An array containing the permutation.\n     * @returns {Number} The parity of the permutation (1 or -1), where 1 means even and -1 means odd.\n     */\n    static parityOfPermutation(arr) {\n        let visited = new Uint8Array(arr.length);\n        let evenLengthCycleCount = 0;\n\n        let traverseCycle = function(i, cycleLength = 0) {\n            if (visited[i] === 1) {\n                return cycleLength;\n            }\n\n            cycleLength++;\n\n            visited[i] = 1;\n            return traverseCycle(arr[i], cycleLength);\n        };\n\n        for (let i = 0; i < arr.length; i++) {\n            if (visited[i] === 1) {\n                continue;\n            }\n\n            let cycleLength = traverseCycle(i);\n            evenLengthCycleCount += (1 - cycleLength % 2);\n        }\n\n        return evenLengthCycleCount % 2 ? -1 : 1;\n    }\n\n    /** The factor to convert degrees to radians. */\n    static get radFactor() {\n        return Math.PI / 180.0;\n    }\n\n    /** The factor to convert radians to degrees. */\n    static get degFactor() {\n        return 180.0 / Math.PI;\n    }\n\n    /** Two times PI. */\n    static get twoPI() {\n        return 2.0 * Math.PI;\n    }\n}\n", "// @ts-check\nimport ArrayHelper from './ArrayHelper';\nimport Atom        from './Atom';\nimport MathHelper  from './MathHelper';\nimport Vector2     from './Vector2';\n\n/**\n * A class representing a vertex.\n *\n * @property {Number} id The id of this vertex.\n * @property {Atom} value The atom associated with this vertex.\n * @property {Vector2} position The position of this vertex.\n * @property {Vector2} previousPosition The position of the previous vertex.\n * @property {Number|null} parentVertexId The id of the previous vertex.\n * @property {Number[]} children The ids of the children of this vertex.\n * @property {Number[]} spanningTreeChildren The ids of the children of this vertex as defined in the spanning tree defined by the SMILES.\n * @property {Number[]} edges The ids of edges associated with this vertex.\n * @property {Boolean} positioned A boolean indicating whether or not this vertex has been positioned.\n * @property {Number} angle The angle of this vertex.\n * @property {Number} dir The direction of this vertex.\n * @property {Number} neighbourCount The number of neighbouring vertices.\n * @property {Number[]} neighbours The vertex ids of neighbouring vertices.\n * @property {String[]} neighbouringElements The element symbols associated with neighbouring vertices.\n * @property {Boolean} forcePositioned A boolean indicating whether or not this vertex was positioned using a force-based approach.\n */\n\nexport default class Vertex {\n    /**\n     * The constructor for the class Vertex.\n     *\n     * @param {Atom} value The value associated with this vertex.\n     * @param {Number} [x=0] The initial x coordinate of the positional vector of this vertex.\n     * @param {Number} [y=0] The initial y coordinate of the positional vector of this vertex.\n     */\n    constructor(value, x = 0, y = 0) {\n        this.id = null;\n        this.value = value;\n        this.position = new Vector2(x ? x : 0, y ? y : 0);\n        this.previousPosition = new Vector2(0, 0);\n        this.parentVertexId = null;\n        this.children = [];\n        this.spanningTreeChildren = [];\n        this.edges = [];\n        this.positioned = false;\n        this.angle = null;\n        this.dir = 1.0;\n        this.neighbourCount = 0;\n        this.neighbours = [];\n        this.neighbouringElements = [];\n        this.forcePositioned = false;\n    }\n\n    /**\n     * Set the 2D coordinates of the vertex.\n     *\n     * @param {Number} x The x component of the coordinates.\n     * @param {Number} y The y component of the coordinates.\n     *\n     */\n    setPosition(x, y) {\n        this.position.x = x;\n        this.position.y = y;\n    }\n\n    /**\n     * Set the 2D coordinates of the vertex from a Vector2.\n     *\n     * @param {Vector2} v A 2D vector.\n     *\n     */\n    setPositionFromVector(v) {\n        this.position.x = v.x;\n        this.position.y = v.y;\n    }\n\n    /**\n     * Add a child vertex id to this vertex.\n     * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\n     */\n    addChild(vertexId) {\n        this.children.push(vertexId);\n        this.neighbours.push(vertexId);\n\n        this.neighbourCount++;\n    }\n\n    /**\n     * Add a child vertex id to this vertex as the second child of the neighbours array,\n     * except this vertex is the first vertex of the SMILE string, then it is added as the first.\n     * This is used to get the correct ordering of neighbours for parity calculations.\n     * If a hydrogen is implicitly attached to the chiral center, insert as the third child.\n     * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\n     * @param {Number} ringbondIndex The index of the ringbond.\n     */\n    addRingbondChild(vertexId, ringbondIndex) {\n        this.children.push(vertexId);\n\n        if (this.value.bracket) {\n            let index = 1;\n\n            if (this.id === 0 && this.value.bracket.hcount === 0) {\n                index = 0;\n            }\n\n            if (this.value.bracket.hcount === 1 && ringbondIndex === 0) {\n                index = 2;\n            }\n\n            if (this.value.bracket.hcount === 1 && ringbondIndex === 1) {\n                if (this.neighbours.length < 3) {\n                    index = 2;\n                }\n                else {\n                    index = 3;\n                }\n            }\n\n            if (this.value.bracket.hcount === null && ringbondIndex === 0) {\n                index = 1;\n            }\n\n            if (this.value.bracket.hcount === null && ringbondIndex === 1) {\n                if (this.neighbours.length < 3) {\n                    index = 1;\n                }\n                else {\n                    index = 2;\n                }\n            }\n\n            this.neighbours.splice(index, 0, vertexId);\n        }\n        else {\n            this.neighbours.push(vertexId);\n        }\n\n        this.neighbourCount++;\n    }\n\n    /**\n     * Set the vertex id of the parent.\n     *\n     * @param {Number} parentVertexId The parents vertex id.\n     */\n    setParentVertexId(parentVertexId) {\n        this.neighbourCount++;\n        this.parentVertexId = parentVertexId;\n        this.neighbours.push(parentVertexId);\n    }\n\n    /**\n     * Returns true if this vertex is terminal (has no parent or child vertices), otherwise returns false. Always returns true if associated value has property hasAttachedPseudoElements set to true.\n     *\n     * @returns {Boolean} A boolean indicating whether or not this vertex is terminal.\n     */\n    isTerminal() {\n        if (this.value.hasAttachedPseudoElements) {\n            return true;\n        }\n\n        return (this.parentVertexId === null && this.children.length < 2) || this.children.length === 0;\n    }\n\n    /**\n     * Clones this vertex and returns the clone.\n     *\n     * @returns {Vertex} A clone of this vertex.\n     */\n    clone() {\n        let clone = new Vertex(this.value, this.position.x, this.position.y);\n        clone.id = this.id;\n        clone.previousPosition = new Vector2(this.previousPosition.x, this.previousPosition.y);\n        clone.parentVertexId = this.parentVertexId;\n        clone.children = ArrayHelper.clone(this.children);\n        clone.spanningTreeChildren = ArrayHelper.clone(this.spanningTreeChildren);\n        clone.edges = ArrayHelper.clone(this.edges);\n        clone.positioned = this.positioned;\n        clone.angle = this.angle;\n        clone.forcePositioned = this.forcePositioned;\n        return clone;\n    }\n\n    /**\n     * Returns true if this vertex and the supplied vertex both have the same id, else returns false.\n     *\n     * @param {Vertex} vertex The vertex to check.\n     * @returns {Boolean} A boolean indicating whether or not the two vertices have the same id.\n     */\n    equals(vertex) {\n        return this.id === vertex.id;\n    }\n\n    /**\n     * Returns the angle of this vertexes positional vector. If a reference vector is supplied in relations to this vector, else in relations to the coordinate system.\n     *\n     * @param {Vector2} [referenceVector=null] - The reference vector.\n     * @param {Boolean} [returnAsDegrees=false] - If true, returns angle in degrees, else in radians.\n     * @returns {Number} The angle of this vertex.\n     */\n    getAngle(referenceVector = null, returnAsDegrees = false) {\n        let u = null;\n\n        if (!referenceVector) {\n            u = Vector2.subtract(this.position, this.previousPosition);\n        }\n        else {\n            u = Vector2.subtract(this.position, referenceVector);\n        }\n\n        if (returnAsDegrees) {\n            return MathHelper.toDeg(u.angle());\n        }\n\n        return u.angle();\n    }\n\n    /**\n     * Returns the suggested text direction when text is added at the position of this vertex.\n     *\n     * @param {Vertex[]} vertices The array of vertices for the current molecule.\n     * @param {Boolean} onlyHorizontal In case the text direction should be limited to either left or right.\n     * @returns {String} The suggested direction of the text.\n     */\n    getTextDirection(vertices, onlyHorizontal = false) {\n        let neighbours = this.getDrawnNeighbours(vertices);\n        let angles = [];\n\n        // If there is only one vertex in the graph, always draw to the right\n        if (vertices.length === 1) {\n            return 'right';\n        }\n\n        for (let i = 0; i < neighbours.length; i++) {\n            angles.push(this.getAngle(vertices[neighbours[i]].position));\n        }\n\n        let textAngle = MathHelper.meanAngle(angles);\n\n        if (this.isTerminal() || onlyHorizontal) {\n            // Round to 0 or 180 if terminal or only horizontal allowed\n            // With only this, text is written to the left if the angle is 90\u00B0/1.5708 rad (straight down).\n            // So if angle is ~1.5708, force it a bit anti-clock-wise\n            if (Math.round(textAngle * 100) / 100 === 1.57) {\n                textAngle = textAngle - 0.2;\n            }\n            textAngle = Math.round(Math.round(textAngle / Math.PI) * Math.PI);\n        }\n        else {\n            // Round to 0, 90, 180 or 270 degree if not terminal\n            let halfPi = Math.PI / 2.0;\n            textAngle = Math.round(Math.round(textAngle / halfPi) * halfPi);\n        }\n\n        if (textAngle === 2) {\n            return 'down';\n        }\n        else if (textAngle === -2) {\n            return 'up';\n        }\n        else if (textAngle === 0) {\n            return 'right';\n        }\n        else if (textAngle === 3 || textAngle === -3) {\n            return 'left';\n        }\n        else {\n            return 'down'; // default to down\n        }\n    }\n\n    /**\n     * Returns an array of ids of neighbouring vertices.\n     *\n     * @param {Number} [vertexId=null] If a value is supplied, the vertex with this id is excluded from the returned indices.\n     * @returns {Number[]} An array containing the ids of neighbouring vertices.\n     */\n    getNeighbours(vertexId = null) {\n        if (vertexId === null) {\n            return this.neighbours.slice();\n        }\n\n        let arr = [];\n\n        for (let i = 0; i < this.neighbours.length; i++) {\n            if (this.neighbours[i] !== vertexId) {\n                arr.push(this.neighbours[i]);\n            }\n        }\n\n        return arr;\n    }\n\n    /**\n     * Returns an array of ids of neighbouring vertices that will be drawn (vertex.value.isDrawn === true).\n     *\n     * @param {Vertex[]} vertices An array containing the vertices associated with the current molecule.\n     * @returns {Number[]} An array containing the ids of neighbouring vertices that will be drawn.\n     */\n    getDrawnNeighbours(vertices) {\n        let arr = [];\n\n        for (let i = 0; i < this.neighbours.length; i++) {\n            if (vertices[this.neighbours[i]].value.isDrawn) {\n                arr.push(this.neighbours[i]);\n            }\n        }\n\n        return arr;\n    }\n\n    /**\n     * Returns the number of neighbours of this vertex.\n     *\n     * @returns {Number} The number of neighbours.\n     */\n    getNeighbourCount() {\n        return this.neighbourCount;\n    }\n\n    /**\n     * Returns a list of ids of vertices neighbouring this one in the original spanning tree, excluding the ringbond connections.\n     *\n     * @param {Number} [vertexId=null] If supplied, the vertex with this id is excluded from the array returned.\n     * @returns {Number[]} An array containing the ids of the neighbouring vertices.\n     */\n    getSpanningTreeNeighbours(vertexId = null) {\n        let neighbours = [];\n\n        for (let i = 0; i < this.spanningTreeChildren.length; i++) {\n            if (vertexId === undefined || vertexId != this.spanningTreeChildren[i]) {\n                neighbours.push(this.spanningTreeChildren[i]);\n            }\n        }\n\n        if (this.parentVertexId != null) {\n            if (vertexId === undefined || vertexId != this.parentVertexId) {\n                neighbours.push(this.parentVertexId);\n            }\n        }\n\n        return neighbours;\n    }\n\n    /**\n     * Gets the next vertex in the ring in opposide direction to the supplied vertex id.\n     *\n     * @param {Vertex[]} vertices The array of vertices for the current molecule.\n     * @param {Number} ringId The id of the ring containing this vertex.\n     * @param {Number} previousVertexId The id of the previous vertex. The next vertex will be opposite from the vertex with this id as seen from this vertex.\n     * @returns {Number} The id of the next vertex in the ring.\n     */\n    getNextInRing(vertices, ringId, previousVertexId) {\n        let neighbours = this.getNeighbours();\n\n        for (let i = 0; i < neighbours.length; i++) {\n            if (ArrayHelper.contains(vertices[neighbours[i]].value.rings, {value: ringId}) && neighbours[i] != previousVertexId) {\n                return neighbours[i];\n            }\n        }\n\n        return null;\n    }\n}\n", "// @ts-check\nimport Ring   from './Ring';\nimport Vertex from './Vertex';\n\n/**\n * A class representing a ring connection.\n *\n * @property {Number} id The id of this ring connection.\n * @property {Number} firstRingId A ring id.\n * @property {Number} secondRingId A ring id.\n * @property {Set<Number>} vertices A set containing the vertex ids participating in the ring connection.\n */\nexport default class RingConnection {\n    /**\n     * The constructor for the class RingConnection.\n     *\n     * @param {Ring} firstRing A ring.\n     * @param {Ring} secondRing A ring.\n     */\n    constructor(firstRing, secondRing) {\n        this.id = null;\n        this.firstRingId = firstRing.id;\n        this.secondRingId = secondRing.id;\n        this.vertices = new Set();\n        this.isForcedBridge = false;\n\n        for (let m = 0; m < firstRing.members.length; m++) {\n            let c = firstRing.members[m];\n\n            for (let n = 0; n < secondRing.members.length; n++) {\n                let d = secondRing.members[n];\n\n                if (c === d) {\n                    this.addVertex(c);\n                }\n            }\n        }\n    }\n\n    /**\n     * Adding a vertex to the ring connection.\n     *\n     * @param {Number} vertexId A vertex id.\n     */\n    addVertex(vertexId) {\n        this.vertices.add(vertexId);\n    }\n\n    /**\n     * Update the ring id of this ring connection that is not the ring id supplied as the second argument.\n     *\n     * @param {Number} ringId A ring id. The new ring id to be set.\n     * @param {Number} otherRingId A ring id. The id that is NOT to be updated.\n     */\n    updateOther(ringId, otherRingId) {\n        if (this.firstRingId === otherRingId) {\n            this.secondRingId = ringId;\n        }\n        else {\n            this.firstRingId = ringId;\n        }\n    }\n\n    /**\n     * Returns a boolean indicating whether or not a ring with a given id is participating in this ring connection.\n     *\n     * @param {Number} ringId A ring id.\n     * @returns {Boolean} A boolean indicating whether or not a ring with a given id participates in this ring connection.\n     */\n    containsRing(ringId) {\n        return this.firstRingId === ringId || this.secondRingId === ringId;\n    }\n\n    /**\n     * Checks whether or not this ring connection is a bridge in a bridged ring.\n     *\n     * @param {Vertex[]} vertices The array of vertices associated with the current molecule.\n     * @returns {Boolean} A boolean indicating whether or not this ring connection is a bridge.\n     */\n    isBridge(vertices) {\n        if (this.isForcedBridge) {\n            return true;\n        }\n\n        if (this.vertices.size > 2) {\n            return true;\n        }\n\n        // For 2 shared atoms, check if they form a triangle with a common\n        // neighbor that's in one of the two rings. This detects bridged\n        // bicyclic systems (e.g. norbornane, oxanorbornane) where SSSR\n        // produces a small ring and a large ring sharing 2 bridgehead atoms.\n        if (this.vertices.size === 2) {\n            let [v1, v2] = [...this.vertices];\n            let v2NeighbourSet = new Set(vertices[v2].neighbours);\n\n            for (let n of vertices[v1].neighbours) {\n                if (n !== v2 && v2NeighbourSet.has(n)) {\n                    let nRings = vertices[n].value.rings;\n                    if (nRings.includes(this.firstRingId) || nRings.includes(this.secondRingId)) {\n                        return true;\n                    }\n                }\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Checks whether or not two rings are connected by a bridged bond.\n     *\n     * @static\n     * @param {RingConnection[]} ringConnections An array of ring connections containing the ring connections associated with the current molecule.\n     * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\n     * @param {Number} firstRingId A ring id.\n     * @param {Number} secondRingId A ring id.\n     * @returns {Boolean} A boolean indicating whether or not two rings ar connected by a bridged bond.\n     */\n    static isBridge(ringConnections, vertices, firstRingId, secondRingId) {\n        let ringConnection = null;\n\n        for (let i = 0; i < ringConnections.length; i++) {\n            ringConnection = ringConnections[i];\n\n            if ((ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId)\n                || (ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId)\n            ) {\n                return ringConnection.isBridge(vertices);\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Retruns the neighbouring rings of a given ring.\n     *\n     * @static\n     * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\n     * @param {Number} ringId A ring id.\n     * @returns {Number[]} An array of ring ids of neighbouring rings.\n     */\n    static getNeighbours(ringConnections, ringId) {\n        let neighbours = [];\n\n        for (let i = 0; i < ringConnections.length; i++) {\n            let ringConnection = ringConnections[i];\n\n            if (ringConnection.firstRingId === ringId) {\n                neighbours.push(ringConnection.secondRingId);\n            }\n            else if (ringConnection.secondRingId === ringId) {\n                neighbours.push(ringConnection.firstRingId);\n            }\n        }\n\n        return neighbours;\n    }\n\n    /**\n     * Returns an array of vertex ids associated with a given ring connection.\n     *\n     * @static\n     * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\n     * @param {Number} firstRingId A ring id.\n     * @param {Number} secondRingId A ring id.\n     * @returns {Number[]} An array of vertex ids associated with the ring connection.\n     */\n    static getVertices(ringConnections, firstRingId, secondRingId) {\n        for (let i = 0; i < ringConnections.length; i++) {\n            let ringConnection = ringConnections[i];\n            if ((ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId)\n                || (ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId)\n            ) {\n                return [...ringConnection.vertices];\n            }\n        }\n    }\n}\n", "// @ts-check\nimport ArrayHelper    from './ArrayHelper';\nimport RingConnection from './RingConnection';\nimport Vector2        from './Vector2';\nimport Vertex         from './Vertex';\n\n/**\n * A class representing a ring.\n *\n * @property {Number} id The id of this ring.\n * @property {Number[]} members An array containing the vertex ids of the ring members.\n * @property {Number[]} edges An array containing the edge ids of the edges between the ring members.\n * @property {Number[]} insiders An array containing the vertex ids of the vertices contained within the ring if it is a bridged ring.\n * @property {Number[]} neighbours An array containing the ids of neighbouring rings.\n * @property {Boolean} positioned A boolean indicating whether or not this ring has been positioned.\n * @property {Vector2} center The center of this ring.\n * @property {Ring[]} rings The rings contained within this ring if this ring is bridged.\n * @property {Boolean} isBridged A boolean whether or not this ring is bridged.\n * @property {Boolean} isPartOfBridged A boolean whether or not this ring is part of a bridge ring.\n * @property {Boolean} isSpiro A boolean whether or not this ring is part of a spiro.\n * @property {Boolean} isFused A boolean whether or not this ring is part of a fused ring.\n * @property {Number} centralAngle The central angle of this ring.\n * @property {Boolean} canFlip A boolean indicating whether or not this ring allows flipping of attached vertices to the inside of the ring.\n */\nexport default class Ring {\n    /**\n     * The constructor for the class Ring.\n     *\n     * @param {Number[]} members An array containing the vertex ids of the members of the ring to be created.\n     */\n    constructor(members) {\n        this.id = null;\n        this.members = members;\n        this.edges = [];\n        this.insiders = [];\n        this.neighbours = [];\n        this.positioned = false;\n        this.center = new Vector2(0, 0);\n        this.rings = [];\n        this.isBridged = false;\n        this.isPartOfBridged = false;\n        this.isSpiro = false;\n        this.isFused = false;\n        this.centralAngle = 0.0;\n        this.canFlip = true;\n    }\n\n    /**\n     * Clones this ring and returns the clone.\n     *\n     * @returns {Ring} A clone of this ring.\n     */\n    clone() {\n        let clone = new Ring(this.members);\n\n        clone.id = this.id;\n        clone.insiders = ArrayHelper.clone(this.insiders);\n        clone.neighbours = ArrayHelper.clone(this.neighbours);\n        clone.positioned = this.positioned;\n        clone.center = this.center.clone();\n        clone.rings = ArrayHelper.clone(this.rings);\n        clone.isBridged = this.isBridged;\n        clone.isPartOfBridged = this.isPartOfBridged;\n        clone.isSpiro = this.isSpiro;\n        clone.isFused = this.isFused;\n        clone.centralAngle = this.centralAngle;\n        clone.canFlip = this.canFlip;\n\n        return clone;\n    }\n\n    /**\n     * Returns the size (number of members) of this ring.\n     *\n     * @returns {Number} The size (number of members) of this ring.\n     */\n    getSize() {\n        return this.members.length;\n    }\n\n    /**\n     * Gets the polygon representation (an array of the ring-members positional vectors) of this ring.\n     *\n     * @param {Vertex[]} vertices An array of vertices representing the current molecule.\n     * @returns {Vector2[]} An array of the positional vectors of the ring members.\n     */\n    getPolygon(vertices) {\n        let polygon = [];\n\n        for (let i = 0; i < this.members.length; i++) {\n            polygon.push(vertices[this.members[i]].position);\n        }\n\n        return polygon;\n    }\n\n    /**\n     * Returns the angle of this ring in relation to the coordinate system.\n     *\n     * @returns {Number} The angle in radians.\n     */\n    getAngle() {\n        return Math.PI - this.centralAngle;\n    }\n\n    /**\n     * Loops over the members of this ring from a given start position in a direction opposite to the vertex id passed as the previousId.\n     *\n     * @param {Vertex[]} vertices The vertices associated with the current molecule.\n     * @param {Function} callback A callback with the current vertex id as a parameter.\n     * @param {Number} startVertexId The vertex id of the start vertex.\n     * @param {Number} previousVertexId The vertex id of the previous vertex (the loop calling the callback function will run in the opposite direction of this vertex).\n     */\n    eachMember(vertices, callback, startVertexId, previousVertexId) {\n        startVertexId = startVertexId || startVertexId === 0 ? startVertexId : this.members[0];\n        let current = startVertexId;\n        let max = 0;\n\n        while (current != null && max < 100) {\n            let prev = current;\n\n            callback(prev);\n            current = vertices[current].getNextInRing(vertices, this.id, previousVertexId);\n            previousVertexId = prev;\n\n            // Stop while loop when arriving back at the start vertex\n            if (current == startVertexId) {\n                current = null;\n            }\n\n            max++;\n        }\n    }\n\n    /**\n     * Returns an array containing the neighbouring rings of this ring ordered by ring size.\n     *\n     * @param {RingConnection[]} ringConnections An array of ring connections associated with the current molecule.\n     * @returns {Object[]} An array of neighbouring rings sorted by ring size. Example: { n: 5, neighbour: 1 }.\n     */\n    getOrderedNeighbours(ringConnections) {\n        let orderedNeighbours = Array(this.neighbours.length);\n\n        for (let i = 0; i < this.neighbours.length; i++) {\n            let vertices = RingConnection.getVertices(ringConnections, this.id, this.neighbours[i]);\n\n            orderedNeighbours[i] = {\n                n:         vertices.length,\n                neighbour: this.neighbours[i],\n            };\n        }\n\n        // Sort highest to lowest\n        orderedNeighbours.sort((a, b) => b.n - a.n);\n\n        return orderedNeighbours;\n    }\n\n    /**\n     * Check whether this ring is an implicitly defined benzene-like (e.g. C1=CC=CC=C1) with 6 members and 3 double bonds.\n     *\n     * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\n     * @returns {Boolean} A boolean indicating whether or not this ring is an implicitly defined benzene-like.\n     */\n    isBenzeneLike(vertices) {\n        let db = this.getDoubleBondCount(vertices);\n        let length = this.members.length;\n\n        return (db === 3 && length === 6) || (db === 2 && length === 5);\n    }\n\n    /**\n     * Get the number of double bonds inside this ring.\n     *\n     * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\n     * @returns {Number} The number of double bonds inside this ring.\n     */\n    getDoubleBondCount(vertices) {\n        let doubleBondCount = 0;\n\n        for (let i = 0; i < this.members.length; i++) {\n            let atom = vertices[this.members[i]].value;\n\n            if (atom.bondType === '=' || atom.branchBond === '=') {\n                doubleBondCount++;\n            }\n        }\n\n        return doubleBondCount;\n    }\n\n    /**\n     * Checks whether or not this ring contains a member with a given vertex id.\n     *\n     * @param {Number} vertexId A vertex id.\n     * @returns {Boolean} A boolean indicating whether or not this ring contains a member with the given vertex id.\n     */\n    contains(vertexId) {\n        for (let i = 0; i < this.members.length; i++) {\n            if (this.members[i] == vertexId) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n", "export default class ThemeManager {\n    constructor(colors, theme) {\n        this.colors = colors;\n        this.theme = this.colors[theme];\n    }\n\n    /**\n     * Returns the hex code of a color associated with a key from the current theme.\n     *\n     * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\n     * @returns {String} A color hex value.\n     */\n    getColor(key) {\n        if (key) {\n            key = key.toUpperCase();\n\n            if (key in this.theme) {\n                return this.theme[key];\n            }\n        }\n\n        return this.theme['C'];\n    }\n\n    /**\n     * Sets the theme to the specified string if it exists. If it does not, this\n     * does nothing.\n     *\n     * @param {String} theme the name of the theme to switch to\n     */\n    setTheme(theme) {\n        if (theme in this.colors) {\n            this.theme = this.colors[theme];\n        }\n\n    // TODO: this probably should notify those who are watching this theme\n    // manager that the theme has changed so that colors can be changed\n    // on the fly\n    }\n}\n", "// @ts-check\nimport Line         from './Line';\nimport MathHelper   from './MathHelper';\nimport Ring         from './Ring';\nimport ThemeManager from './ThemeManager';\nimport Vector2      from './Vector2';\nimport Vertex       from './Vertex';\n\n/**\n * Translate the integer indicating the charge to the appropriate text.\n * @param {Number} charge The integer indicating the charge.\n * @returns {String} A string representing a charge.\n */\nfunction getChargeText(charge) {\n    if (!charge) {\n        return '';\n    }\n    else if (charge === 1) {\n        return '+';\n    }\n    else if (charge === -1) {\n        return '-';\n    }\n    else if (charge > 0) {\n        return charge + '+';\n    }\n    else {\n        return charge + '-';\n    }\n}\n\n/**\n * A class wrapping a canvas element.\n *\n * @property {HTMLCanvasElement} canvas The HTML element for the canvas associated with this CanvasWrapper instance.\n * @property {CanvasRenderingContext2D} ctx The CanvasRenderingContext2D of the canvas associated with this CanvasWrapper instance.\n * @property {Object} colors The colors object as defined in the SmilesDrawer options.\n * @property {Object} opts The SmilesDrawer options.\n * @property {Number} drawingWidth The width of the canvas.\n * @property {Number} drawingHeight The height of the canvas.\n * @property {Number} offsetX The horizontal offset required for centering the drawing.\n * @property {Number} offsetY The vertical offset required for centering the drawing.\n * @property {Number} fontLarge The large font size in pt.\n * @property {Number} fontSmall The small font size in pt.\n */\nexport default class CanvasWrapper {\n    /**\n     * The constructor for the class CanvasWrapper.\n     *\n     * @param {string|String|HTMLCanvasElement} target The canvas id or the HTMLCanvasElement.\n     * @param {ThemeManager} themeManager Theme manager for setting proper colors.\n     * @param {Object} options The smiles drawer options object.\n     */\n    constructor(target, themeManager, options) {\n        let element = null;\n        if (target instanceof String) {\n            element = document.getElementById(target.valueOf());\n        }\n        else if (typeof target === 'string') {\n            element = document.getElementById(target);\n        }\n        else {\n            element = target;\n        }\n\n        if (element instanceof HTMLCanvasElement) {\n            this.canvas = element;\n        }\n        else {\n            throw Error('First argument was not a canvas or the ID of a canvas.');\n        }\n\n        this.ctx = this.canvas.getContext('2d');\n        this.themeManager = themeManager;\n        this.opts = options;\n        this.drawingWidth = 0.0;\n        this.drawingHeight = 0.0;\n        this.offsetX = 0.0;\n        this.offsetY = 0.0;\n\n        this.fontLarge = this.opts.fontSizeLarge + 'pt Helvetica, Arial, sans-serif';\n        this.fontSmall = this.opts.fontSizeSmall + 'pt Helvetica, Arial, sans-serif';\n\n        this.updateSize(this.opts.width, this.opts.height);\n\n        this.ctx.font = this.fontLarge;\n        this.hydrogenWidth = this.ctx.measureText('H').width;\n        this.halfHydrogenWidth = this.hydrogenWidth / 2.0;\n        this.halfBondThickness = this.opts.bondThickness / 2.0;\n\n        // TODO: Find out why clear was here.\n        // this.clear();\n    }\n\n    /**\n     * Update the width and height of the canvas\n     *\n     * @param {Number} width\n     * @param {Number} height\n     */\n    updateSize(width, height) {\n        this.ratio = window.devicePixelRatio || 1;\n\n        if (this.ratio !== 1) {\n            this.canvas.width = width * this.ratio;\n            this.canvas.height = height * this.ratio;\n            this.canvas.style.width = width + 'px';\n            this.canvas.style.height = height + 'px';\n            this.ctx.setTransform(this.ratio, 0, 0, this.ratio, 0, 0);\n        }\n        else {\n            this.canvas.width = width * this.ratio;\n            this.canvas.height = height * this.ratio;\n        }\n    }\n\n    /**\n     * Sets a provided theme.\n     *\n     * @param {Object} theme A theme from the smiles drawer options.\n     */\n    setTheme(theme) {\n        this.colors = theme;\n    }\n\n    /**\n     * Scale the canvas based on vertex positions.\n     *\n     * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\n     */\n    scale(vertices) {\n        // Figure out the final size of the image\n        let maxX = -Number.MAX_VALUE;\n        let maxY = -Number.MAX_VALUE;\n        let minX = Number.MAX_VALUE;\n        let minY = Number.MAX_VALUE;\n\n        for (let i = 0; i < vertices.length; i++) {\n            if (!vertices[i].value.isDrawn) {\n                continue;\n            }\n\n            let p = vertices[i].position;\n\n            if (maxX < p.x) maxX = p.x;\n            if (maxY < p.y) maxY = p.y;\n            if (minX > p.x) minX = p.x;\n            if (minY > p.y) minY = p.y;\n        }\n\n        // Add padding\n        let padding = this.opts.padding;\n        maxX += padding;\n        maxY += padding;\n        minX -= padding;\n        minY -= padding;\n\n        this.drawingWidth = maxX - minX;\n        this.drawingHeight = maxY - minY;\n\n        let scaleX = this.canvas.offsetWidth / this.drawingWidth;\n        let scaleY = this.canvas.offsetHeight / this.drawingHeight;\n\n        let scale = (scaleX < scaleY) ? scaleX : scaleY;\n\n        this.ctx.scale(scale, scale);\n\n        this.offsetX = -minX;\n        this.offsetY = -minY;\n\n        // Center\n        if (scaleX < scaleY) {\n            this.offsetY += this.canvas.offsetHeight / (2.0 * scale) - this.drawingHeight / 2.0;\n        }\n        else {\n            this.offsetX += this.canvas.offsetWidth / (2.0 * scale) - this.drawingWidth / 2.0;\n        }\n    }\n\n    /**\n     * Resets the transform of the canvas.\n     */\n    reset() {\n        this.ctx.setTransform(1, 0, 0, 1, 0, 0);\n    }\n\n    /**\n     * Returns the hex code of a color associated with a key from the current theme.\n     *\n     * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\n     * @returns {String} A color hex value.\n     */\n    getColor(key) {\n        key = key.toUpperCase();\n\n        if (key in this.colors) {\n            return this.colors[key];\n        }\n\n        return this.colors['C'];\n    }\n\n    /**\n     * Draws a circle to a canvas context.\n     * @param {Number} x The x coordinate of the circles center.\n     * @param {Number} y The y coordinate of the circles center.\n     * @param {Number} radius The radius of the circle\n     * @param {String} color A hex encoded color.\n     * @param {Boolean} [fill=true] Whether to fill or stroke the circle.\n     * @param {Boolean} [debug=false] Draw in debug mode.\n     * @param {String} [debugText=''] A debug message.\n     */\n    drawCircle(x, y, radius, color, fill = true, debug = false, debugText = '') {\n        let ctx = this.ctx;\n        let offsetX = this.offsetX;\n        let offsetY = this.offsetY;\n\n        ctx.save();\n        ctx.lineWidth = 1.5;\n        ctx.beginPath();\n        ctx.arc(x + offsetX, y + offsetY, radius, 0, MathHelper.twoPI, true);\n        ctx.closePath();\n\n        if (debug) {\n            if (fill) {\n                ctx.fillStyle = '#f00';\n                ctx.fill();\n            }\n            else {\n                ctx.strokeStyle = '#f00';\n                ctx.stroke();\n            }\n\n            this.drawDebugText(x, y, debugText);\n        }\n        else {\n            if (fill) {\n                ctx.fillStyle = color;\n                ctx.fill();\n            }\n            else {\n                ctx.strokeStyle = color;\n                ctx.stroke();\n            }\n        }\n\n        ctx.restore();\n    }\n\n    /**\n     * Draw a line to a canvas.\n     *\n     * @param {Line} line A line.\n     * @param {Boolean} [dashed=false] Whether or not the line is dashed.\n     * @param {Number} [alpha=1.0] The alpha value of the color.\n     */\n    drawLine(line, dashed = false, alpha = 1.0) {\n        let ctx = this.ctx;\n        let offsetX = this.offsetX;\n        let offsetY = this.offsetY;\n\n        // Add a shadow behind the line\n        let shortLine = line.clone().shorten(4.0);\n\n        let l = shortLine.getLeftVector().clone();\n        let r = shortLine.getRightVector().clone();\n\n        l.x += offsetX;\n        l.y += offsetY;\n\n        r.x += offsetX;\n        r.y += offsetY;\n\n        // Draw the \"shadow\"\n        if (!dashed) {\n            ctx.save();\n            ctx.globalCompositeOperation = 'destination-out';\n            ctx.beginPath();\n            ctx.moveTo(l.x, l.y);\n            ctx.lineTo(r.x, r.y);\n            ctx.lineCap = 'round';\n            ctx.lineWidth = this.opts.bondThickness + 1.2;\n            ctx.strokeStyle = this.themeManager.getColor('BACKGROUND');\n            ctx.stroke();\n            ctx.globalCompositeOperation = 'source-over';\n            ctx.restore();\n        }\n\n        l = line.getLeftVector().clone();\n        r = line.getRightVector().clone();\n\n        l.x += offsetX;\n        l.y += offsetY;\n\n        r.x += offsetX;\n        r.y += offsetY;\n\n        ctx.save();\n        ctx.beginPath();\n        ctx.moveTo(l.x, l.y);\n        ctx.lineTo(r.x, r.y);\n        ctx.lineCap = 'round';\n        ctx.lineWidth = this.opts.bondThickness;\n\n        let gradient = this.ctx.createLinearGradient(l.x, l.y, r.x, r.y);\n        gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement())\n        || this.themeManager.getColor('C'));\n        gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement())\n        || this.themeManager.getColor('C'));\n\n        if (dashed) {\n            ctx.setLineDash([1, 1.5]);\n            ctx.lineWidth = this.opts.bondThickness / 1.5;\n        }\n\n        if (alpha < 1.0) {\n            ctx.globalAlpha = alpha;\n        }\n\n        ctx.strokeStyle = gradient;\n\n        ctx.stroke();\n        ctx.restore();\n    }\n\n    /**\n     * Draw a wedge on the canvas.\n     *\n     * @param {Line} line A line.\n     * @param {Number} _width The wedge width (UNUSED).\n     */\n    drawWedge(line, _width = 1.0) {\n        if (isNaN(line.from.x) || isNaN(line.from.y) || isNaN(line.to.x) || isNaN(line.to.y)) {\n            return;\n        }\n\n        let ctx = this.ctx;\n        let offsetX = this.offsetX;\n        let offsetY = this.offsetY;\n\n        // Add a shadow behind the line\n        let shortLine = line.clone().shorten(5.0);\n\n        let l = shortLine.getLeftVector().clone();\n        let r = shortLine.getRightVector().clone();\n\n        l.x += offsetX;\n        l.y += offsetY;\n\n        r.x += offsetX;\n        r.y += offsetY;\n\n        l = line.getLeftVector().clone();\n        r = line.getRightVector().clone();\n\n        l.x += offsetX;\n        l.y += offsetY;\n\n        r.x += offsetX;\n        r.y += offsetY;\n\n        ctx.save();\n\n        let normals = Vector2.normals(l, r);\n\n        normals[0].normalize();\n        normals[1].normalize();\n\n        let isRightChiralCenter = line.getRightChiral();\n\n        let start = l;\n        let end = r;\n\n        if (isRightChiralCenter) {\n            start = r;\n            end = l;\n        }\n\n        let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness));\n        let u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness));\n        let v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness));\n        let w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\n\n        ctx.beginPath();\n        ctx.moveTo(t.x, t.y);\n        ctx.lineTo(u.x, u.y);\n        ctx.lineTo(v.x, v.y);\n        ctx.lineTo(w.x, w.y);\n\n        let gradient = this.ctx.createRadialGradient(r.x, r.y, this.opts.bondLength, r.x, r.y, 0);\n        gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement())\n        || this.themeManager.getColor('C'));\n        gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement())\n        || this.themeManager.getColor('C'));\n\n        ctx.fillStyle = gradient;\n\n        ctx.fill();\n        ctx.restore();\n    }\n\n    /**\n     * Draw a dashed wedge on the canvas.\n     *\n     * @param {Line} line A line.\n     */\n    drawDashedWedge(line) {\n        if (isNaN(line.from.x) || isNaN(line.from.y) || isNaN(line.to.x) || isNaN(line.to.y)) {\n            return;\n        }\n\n        let ctx = this.ctx;\n        let offsetX = this.offsetX;\n        let offsetY = this.offsetY;\n\n        let l = line.getLeftVector().clone();\n        let r = line.getRightVector().clone();\n\n        l.x += offsetX;\n        l.y += offsetY;\n\n        r.x += offsetX;\n        r.y += offsetY;\n\n        ctx.save();\n\n        let normals = Vector2.normals(l, r);\n\n        normals[0].normalize();\n        normals[1].normalize();\n\n        let isRightChiralCenter = line.getRightChiral();\n\n        let start;\n        let end;\n        let sStart;\n        let sEnd;\n\n        let shortLine = line.clone();\n\n        if (isRightChiralCenter) {\n            start = r;\n            end = l;\n\n            shortLine.shortenRight(1.0);\n\n            sStart = shortLine.getRightVector().clone();\n            sEnd = shortLine.getLeftVector().clone();\n        }\n        else {\n            start = l;\n            end = r;\n\n            shortLine.shortenLeft(1.0);\n\n            sStart = shortLine.getLeftVector().clone();\n            sEnd = shortLine.getRightVector().clone();\n        }\n\n        sStart.x += offsetX;\n        sStart.y += offsetY;\n        sEnd.x += offsetX;\n        sEnd.y += offsetY;\n\n        let dir = Vector2.subtract(end, start).normalize();\n        ctx.strokeStyle = this.themeManager.getColor('C');\n        ctx.lineCap = 'round';\n        ctx.lineWidth = this.opts.bondThickness;\n        ctx.beginPath();\n        let length = line.getLength();\n        let step = 1.25 / (length / (this.opts.bondThickness * 3.0));\n\n        let changed = false;\n        for (let t = 0.0; t < 1.0; t += step) {\n            let to = Vector2.multiplyScalar(dir, t * length);\n            let startDash = Vector2.add(start, to);\n            let width = 1.5 * t;\n            let dashOffset = Vector2.multiplyScalar(normals[0], width);\n\n            if (!changed && t > 0.5) {\n                ctx.stroke();\n                ctx.beginPath();\n                ctx.strokeStyle = this.themeManager.getColor(line.getRightElement()) || this.themeManager.getColor('C');\n                changed = true;\n            }\n\n            startDash.subtract(dashOffset);\n            ctx.moveTo(startDash.x, startDash.y);\n            startDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\n            ctx.lineTo(startDash.x, startDash.y);\n        }\n\n        ctx.stroke();\n        ctx.restore();\n    }\n\n    /**\n     * Draws a debug text message at a given position\n     *\n     * @param {Number} x The x coordinate.\n     * @param {Number} y The y coordinate.\n     * @param {String} text The debug text.\n     */\n    drawDebugText(x, y, text) {\n        let ctx = this.ctx;\n\n        ctx.save();\n        ctx.font = '5px Droid Sans, sans-serif';\n        ctx.textAlign = 'start';\n        ctx.textBaseline = 'top';\n        ctx.fillStyle = '#ff0000';\n        ctx.fillText(text, x + this.offsetX, y + this.offsetY);\n        ctx.restore();\n    }\n\n    /**\n     * Draw a ball to the canvas.\n     *\n     * @param {Number} x The x position of the text.\n     * @param {Number} y The y position of the text.\n     * @param {String} elementName The name of the element (single-letter).\n     */\n    drawBall(x, y, elementName) {\n        let ctx = this.ctx;\n\n        ctx.save();\n        ctx.beginPath();\n        ctx.arc(x + this.offsetX, y + this.offsetY, this.opts.bondLength / 4.5, 0, MathHelper.twoPI, false);\n        ctx.fillStyle = this.themeManager.getColor(elementName);\n        ctx.fill();\n        ctx.restore();\n    }\n\n    /**\n     * Draw a point to the canvas.\n     *\n     * @param {Number} x The x position of the point.\n     * @param {Number} y The y position of the point.\n     * @param {String} elementName The name of the element (single-letter).\n     */\n    drawPoint(x, y, elementName) {\n        let ctx = this.ctx;\n        let offsetX = this.offsetX;\n        let offsetY = this.offsetY;\n\n        ctx.save();\n        ctx.globalCompositeOperation = 'destination-out';\n        ctx.beginPath();\n        ctx.arc(x + offsetX, y + offsetY, 1.5, 0, MathHelper.twoPI, true);\n        ctx.closePath();\n        ctx.fill();\n        ctx.globalCompositeOperation = 'source-over';\n\n        ctx.beginPath();\n        ctx.arc(x + this.offsetX, y + this.offsetY, 0.75, 0, MathHelper.twoPI, false);\n        ctx.fillStyle = this.themeManager.getColor(elementName);\n        ctx.fill();\n        ctx.restore();\n    }\n\n    /**\n     * Draw a text to the canvas.\n     *\n     * @param {Number} x The x position of the text.\n     * @param {Number} y The y position of the text.\n     * @param {String} elementName The name of the element (single-letter).\n     * @param {Number} hydrogens The number of hydrogen atoms.\n     * @param {String} direction The direction of the text in relation to the associated vertex.\n     * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\n     * @param {Number} charge The charge of the atom.\n     * @param {Number} isotope The isotope number.\n     * @param {Number} vertexCount The number of vertices in the molecular graph.\n     * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\n     */\n    drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, vertexCount, attachedPseudoElement = {}) {\n        let ctx = this.ctx;\n        let offsetX = this.offsetX;\n        let offsetY = this.offsetY;\n\n        ctx.save();\n\n        ctx.textAlign = 'start';\n        ctx.textBaseline = 'alphabetic';\n\n        let pseudoElementHandled = false;\n\n        // Charge\n        let chargeText = '';\n        let chargeWidth = 0;\n\n        if (charge) {\n            chargeText = getChargeText(charge);\n\n            ctx.font = this.fontSmall;\n            chargeWidth = ctx.measureText(chargeText).width;\n        }\n\n        let isotopeText = '0';\n        let isotopeWidth = 0;\n\n        if (isotope > 0) {\n            isotopeText = isotope.toString();\n            ctx.font = this.fontSmall;\n            isotopeWidth = ctx.measureText(isotopeText).width;\n        }\n\n        // TODO: Better handle exceptions\n        // Exception for nitro (draw nitro as NO2 instead of N+O-O)\n        if (charge === 1 && elementName === 'N' && '0O' in attachedPseudoElement && '0O-1' in attachedPseudoElement) {\n            attachedPseudoElement = {'0O': {element: 'O', count: 2, hydrogenCount: 0, previousElement: 'C', charge: ''}};\n            charge = 0;\n        }\n\n        ctx.font = this.fontLarge;\n        ctx.fillStyle = this.themeManager.getColor('BACKGROUND');\n\n        let dim = ctx.measureText(elementName);\n\n        let r = (dim.width > this.opts.fontSizeLarge) ? dim.width : this.opts.fontSizeLarge;\n        r /= 1.5;\n\n        ctx.globalCompositeOperation = 'destination-out';\n        ctx.beginPath();\n        ctx.arc(x + offsetX, y + offsetY, r, 0, MathHelper.twoPI, true);\n        ctx.closePath();\n        ctx.fill();\n        ctx.globalCompositeOperation = 'source-over';\n\n        let cursorPos = -dim.width / 2.0;\n        let cursorPosLeft = -dim.width / 2.0;\n\n        ctx.fillStyle = this.themeManager.getColor(elementName);\n        ctx.fillText(elementName, x + offsetX + cursorPos, y + this.opts.halfFontSizeLarge + offsetY);\n        cursorPos += dim.width;\n\n        if (charge) {\n            ctx.font = this.fontSmall;\n            ctx.fillText(chargeText, x + offsetX + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\n            cursorPos += chargeWidth;\n        }\n\n        if (isotope > 0) {\n            ctx.font = this.fontSmall;\n            ctx.fillText(isotopeText, x + offsetX + cursorPosLeft - isotopeWidth, y - this.opts.fifthFontSizeSmall + offsetY);\n            cursorPosLeft -= isotopeWidth;\n        }\n\n        ctx.font = this.fontLarge;\n\n        let hydrogenWidth = 0;\n        let hydrogenCountWidth = 0;\n\n        if (hydrogens === 1) {\n            let hx = x + offsetX;\n            let hy = y + offsetY + this.opts.halfFontSizeLarge;\n\n            hydrogenWidth = this.hydrogenWidth;\n            cursorPosLeft -= hydrogenWidth;\n\n            if (direction === 'left') {\n                hx += cursorPosLeft;\n            }\n            else if (direction === 'right') {\n                hx += cursorPos;\n            }\n            else if (direction === 'up' && isTerminal) {\n                hx += cursorPos;\n            }\n            else if (direction === 'down' && isTerminal) {\n                hx += cursorPos;\n            }\n            else if (direction === 'up' && !isTerminal) {\n                hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\n                hx -= this.halfHydrogenWidth;\n            }\n            else if (direction === 'down' && !isTerminal) {\n                hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\n                hx -= this.halfHydrogenWidth;\n            }\n\n            ctx.fillText('H', hx, hy);\n\n            cursorPos += hydrogenWidth;\n        }\n        else if (hydrogens > 1) {\n            let hx = x + offsetX;\n            let hy = y + offsetY + this.opts.halfFontSizeLarge;\n\n            hydrogenWidth = this.hydrogenWidth;\n            ctx.font = this.fontSmall;\n            hydrogenCountWidth = ctx.measureText(hydrogens.toString()).width;\n            cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\n\n            if (direction === 'left') {\n                hx += cursorPosLeft;\n            }\n            else if (direction === 'right') {\n                hx += cursorPos;\n            }\n            else if (direction === 'up' && isTerminal) {\n                hx += cursorPos;\n            }\n            else if (direction === 'down' && isTerminal) {\n                hx += cursorPos;\n            }\n            else if (direction === 'up' && !isTerminal) {\n                hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\n                hx -= this.halfHydrogenWidth;\n            }\n            else if (direction === 'down' && !isTerminal) {\n                hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\n                hx -= this.halfHydrogenWidth;\n            }\n\n            ctx.font = this.fontLarge;\n            ctx.fillText('H', hx, hy);\n\n            ctx.font = this.fontSmall;\n            ctx.fillText(hydrogens.toString(), hx + this.halfHydrogenWidth + hydrogenCountWidth, hy + this.opts.fifthFontSizeSmall);\n\n            cursorPos += hydrogenWidth + this.halfHydrogenWidth + hydrogenCountWidth;\n        }\n\n        if (pseudoElementHandled) {\n            ctx.restore();\n            return;\n        }\n\n        for (const key of Object.keys(attachedPseudoElement)) {\n            let openParenthesisWidth = 0;\n            let closeParenthesisWidth = 0;\n\n            let element = attachedPseudoElement[key].element;\n            let elementCount = attachedPseudoElement[key].count;\n            let hydrogenCount = attachedPseudoElement[key].hydrogenCount;\n            let elementCharge = attachedPseudoElement[key].charge;\n\n            ctx.font = this.fontLarge;\n\n            if (elementCount > 1 && hydrogenCount > 0) {\n                openParenthesisWidth = ctx.measureText('(').width;\n                closeParenthesisWidth = ctx.measureText(')').width;\n            }\n\n            let elementWidth = ctx.measureText(element).width;\n            let elementCountWidth = 0;\n\n            let elementChargeText = '';\n            let elementChargeWidth = 0;\n\n            hydrogenWidth = 0;\n\n            if (hydrogenCount > 0) {\n                hydrogenWidth = this.hydrogenWidth;\n            }\n\n            ctx.font = this.fontSmall;\n\n            if (elementCount > 1) {\n                elementCountWidth = ctx.measureText(elementCount).width;\n            }\n\n            if (elementCharge !== 0) {\n                elementChargeText = getChargeText(elementCharge);\n                elementChargeWidth = ctx.measureText(elementChargeText).width;\n            }\n\n            hydrogenCountWidth = 0;\n\n            if (hydrogenCount > 1) {\n                hydrogenCountWidth = ctx.measureText(hydrogenCount).width;\n            }\n\n            ctx.font = this.fontLarge;\n\n            let hx = x + offsetX;\n            let hy = y + offsetY + this.opts.halfFontSizeLarge;\n\n            ctx.fillStyle = this.themeManager.getColor(element);\n\n            if (elementCount > 0) {\n                cursorPosLeft -= elementCountWidth;\n            }\n\n            if (elementCount > 1 && hydrogenCount > 0) {\n                if (direction === 'left') {\n                    cursorPosLeft -= closeParenthesisWidth;\n                    ctx.fillText(')', hx + cursorPosLeft, hy);\n                }\n                else {\n                    ctx.fillText('(', hx + cursorPos, hy);\n                    cursorPos += openParenthesisWidth;\n                }\n            }\n\n            if (direction === 'left') {\n                cursorPosLeft -= elementWidth;\n                ctx.fillText(element, hx + cursorPosLeft, hy);\n            }\n            else {\n                ctx.fillText(element, hx + cursorPos, hy);\n                cursorPos += elementWidth;\n            }\n\n            if (hydrogenCount > 0) {\n                if (direction === 'left') {\n                    cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\n                    ctx.fillText('H', hx + cursorPosLeft, hy);\n\n                    if (hydrogenCount > 1) {\n                        ctx.font = this.fontSmall;\n                        ctx.fillText(hydrogenCount, hx + cursorPosLeft + hydrogenWidth, hy + this.opts.fifthFontSizeSmall);\n                    }\n                }\n                else {\n                    ctx.fillText('H', hx + cursorPos, hy);\n                    cursorPos += hydrogenWidth;\n\n                    if (hydrogenCount > 1) {\n                        ctx.font = this.fontSmall;\n                        ctx.fillText(hydrogenCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\n                        cursorPos += hydrogenCountWidth;\n                    }\n                }\n            }\n\n            ctx.font = this.fontLarge;\n\n            if (elementCount > 1 && hydrogenCount > 0) {\n                if (direction === 'left') {\n                    cursorPosLeft -= openParenthesisWidth;\n                    ctx.fillText('(', hx + cursorPosLeft, hy);\n                }\n                else {\n                    ctx.fillText(')', hx + cursorPos, hy);\n                    cursorPos += closeParenthesisWidth;\n                }\n            }\n\n            ctx.font = this.fontSmall;\n\n            if (elementCount > 1) {\n                if (direction === 'left') {\n                    ctx.fillText(elementCount, hx + cursorPosLeft\n                    + openParenthesisWidth + closeParenthesisWidth + hydrogenWidth\n                    + hydrogenCountWidth + elementWidth, hy + this.opts.fifthFontSizeSmall);\n                }\n                else {\n                    ctx.fillText(elementCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\n                    cursorPos += elementCountWidth;\n                }\n            }\n\n            if (elementCharge !== 0) {\n                if (direction === 'left') {\n                    ctx.fillText(elementChargeText, hx + cursorPosLeft\n                    + openParenthesisWidth + closeParenthesisWidth + hydrogenWidth\n                    + hydrogenCountWidth + elementWidth, y - this.opts.fifthFontSizeSmall + offsetY);\n                }\n                else {\n                    ctx.fillText(elementChargeText, hx + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\n                    cursorPos += elementChargeWidth;\n                }\n            }\n        }\n\n        ctx.restore();\n    }\n\n    /**\n     * Draws a dubug dot at a given coordinate and adds text.\n     *\n     * @param {Number} x The x coordinate.\n     * @param {Number} y The y coordindate.\n     * @param {String} [debugText=''] A string.\n     * @param {String} [color='#f00'] A color in hex form.\n     */\n    drawDebugPoint(x, y, debugText = '', color = '#f00') {\n        this.drawCircle(x, y, 2, color, true, true, debugText);\n    }\n\n    /**\n     * Draws a ring inside a provided ring, indicating aromaticity.\n     *\n     * @param {Ring} ring A ring.\n     */\n    drawAromaticityRing(ring) {\n        let ctx = this.ctx;\n        let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\n\n        ctx.save();\n        ctx.strokeStyle = this.themeManager.getColor('C');\n        ctx.lineWidth = this.opts.bondThickness;\n        ctx.beginPath();\n        ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\n            radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\n        ctx.closePath();\n        ctx.stroke();\n        ctx.restore();\n    }\n\n    /**\n     * Clear the canvas.\n     *\n     */\n    clear() {\n        this.ctx.clearRect(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);\n    }\n}\n", "import Graph  from './Graph';\nimport Vertex from './Vertex';\n\n/**\n * The result of comparing two CIPTrees.\n *\n * The number is a standard JavaScript comparison result: negative means the\n * thing on the left was smaller, positive means the thing on the right was\n * smaller, and zero means the two were equal.  The boolean provides extra\n * information in the case of a tie: if the tie involved any stereocenters, it\n * is set to true (this is used to mimic RDKit; see CIPTree.sortChildren()).\n */\ntype CIPComparison = [number, boolean];\n\n/**\n * A lazily evaluated tree for determining CIP priority.\n *\n * This is optimized to delay recursion for as long as possible:\n * - Don't load children by default.  If a node might have children, initialize\n *   its children array to undefined.  Users who need the full list of children\n *   should call findChildren().\n * - When the children are initially loaded, only sort them based on their local\n *   attributes (this avoids recursion). Users who need the fully sorted list of\n *   children should call sortChildren() (after calling findChildren()).\n *\n * And a few minor optimizations to reduce copying / memory allocation:\n * - The visited map doesn't include the current node (so it can be shared among\n *   siblings) until the children are loaded.\n * - If a node has multiple copy or implicit children, a single instance is\n *   inserted into its children array multiple times.\n */\nexport class CIPTree {\n    // Stupid linter doesn't understand TypeScript...\n    /* eslint-disable @stylistic/key-spacing */\n    graph:  Graph;\n    vertex: Vertex | null;\n    parent: Vertex | null;\n\n    atomicNumber: number;\n    atomicWeight: number;\n    cloneDepth:   number | undefined;\n    stereocenter: boolean;\n\n    children: CIPTree[] | undefined;\n    visited: Map<Vertex, number> | null;\n    sorted: boolean;\n    /* eslint-enable @stylistic/key-spacing */\n\n    static build(graph: Graph, vertex: Vertex): CIPTree {\n        const root = new CIPTree(graph, vertex, null, new Map());\n        root.findChildren();\n        root.sortChildren();\n        return root;\n    }\n\n    /**\n     * Perform a non-recursive comparison between two CIPTrees.\n     *\n     * This performs any priority determination that can be done without looking\n     * at the children of the nodes in question.  Not all of the official CIP\n     * rules are currently implemented, but those that are are sufficient for\n     * the vast majority of molecules.\n     *\n     * @see https://iupac.qmul.ac.uk/BlueBook/P9.html\n     */\n    static compareAtoms(lhs: CIPTree, rhs: CIPTree): CIPComparison {\n        // CIP Rule 1a: Higher atomic number precedes lower.\n        if (lhs.atomicNumber !== rhs.atomicNumber) {\n            return [rhs.atomicNumber - lhs.atomicNumber, false];\n        }\n\n        // CIP Rule 1b: Clones of rootier atoms precede clones of leafier atoms.\n        if (lhs.cloneDepth && rhs.cloneDepth) {\n            const cmp = lhs.cloneDepth - rhs.cloneDepth;\n            if (cmp !== 0) return [cmp, false];\n        }\n\n        // CIP Rule 2: Higher atomic mass precedes lower.\n        if (lhs.atomicWeight !== rhs.atomicWeight) {\n            return [rhs.atomicWeight - lhs.atomicWeight, false];\n        }\n\n        // TODO: CIP Rule 3: seqcis/Z bonds precede seqtrans/E bonds precede other double bonds.\n\n        // TODO: CIP Rule 4: See the Blue Book P-92.1.3.4\n        // TODO: CIP Rule 4a: Chiral precedes pseudoasymmetric precedes nonstereogenic.\n        // TODO: CIP Rule 4b: Like precedes unlike.\n\n        // TODO: CIP Rule 5: See the Blue Book P-92.1.3.5\n\n        return [0, lhs.stereocenter || rhs.stereocenter];\n    }\n\n    static compareTrees(lhs: CIPTree, rhs: CIPTree): CIPComparison {\n        let cmp = this.compareAtoms(lhs, rhs);\n        if (cmp[0] !== 0) return cmp;\n\n        let lqueue = [lhs];\n        let rqueue = [rhs];\n        let stereo = false;\n\n        while (lqueue.length !== 0) {\n            for (let q = 0; q < lqueue.length; ++q) {\n                const ls  = lqueue[q].findChildren();\n                const rs  = rqueue[q].findChildren();\n                const len = Math.max(ls.length, rs.length);\n\n                for (let i = 0; i < len; ++i) {\n                    if (i >= ls.length) return [+1, false];\n                    if (i >= rs.length) return [-1, false];\n\n                    cmp = this.compareAtoms(ls[i], rs[i]);\n                    if (cmp[0] !== 0) return cmp;\n                    stereo ||= cmp[1];\n                }\n            }\n\n            lqueue = lqueue.flatMap(d => d.sortChildren());\n            rqueue = rqueue.flatMap(d => d.sortChildren());\n        }\n\n        return [0, stereo];\n    }\n\n    /**\n     * Create a new CIP tree node.\n     *\n     * This function signature is a mess - don't call it unless you absolutely\n     * know what you're getting into!  Fortunately, you shouldn't have to.\n     *\n     * There are three types of CIP node:\n     * - Real nodes correspond to real atoms in the graph.  Any atom can appear\n     *   in at most one real node; further appearances use clone nodes (below).\n     *   Real nodes can have children.\n     * - Clone nodes refer to real nodes that have already appeared in the tree.\n     *   They hold the same atom as the real node, but they never have children,\n     *   even though the real node might.\n     * - Implicit nodes correspond to atoms that don't appear in the graph. They\n     *   hold things like implicit hydrogens or \"aromatic\" phantom atoms.\n     *\n     * To create a new \"real\" node:\n     * - Pass the vertex in the `vertex` argument.\n     * - Pass the visited map in the `magic` argument.\n     * - The visited map should map previously seen vertices to their depths in\n     *   the CIP tree (the root is at depth 1, its children are at depth 2, and\n     *   so on).  This map should NOT contain a depth for this node.\n     *\n     * To create a new \"clone\" node:\n     * - Pass the vertex in the `vertex` argument.\n     * - Pass the depth of the real node being cloned in the `magic` argument.\n     *\n     * To create a new \"implicit\" node:\n     * - Pass the atomic number of the implicit atom in the `vertex` argument.\n     * - Don't pass anything in the `magic` argument.\n     *\n     * @param graph  - The graph layout that contains the vertices we care about.\n     * @param vertex - The vertex at this node, or the atomic number of an implicit atom.\n     * @param parent - The previous vertex in the CIP tree, or null if this is the root.\n     * @param magic  - A map of visited vertices to their depths, or the depth of a clone node.\n     *\n     * TODO: Eventually, this logic should work at the molecule level (on atoms\n     * and bonds) rather than at the layout level (on vertices and edges).\n     */\n    constructor(graph: Graph, vertex: Vertex | number, parent: Vertex | null, magic?: Map<Vertex, number> | number) {\n        this.graph  = graph;\n        this.parent = parent;\n\n        if (vertex instanceof Vertex) {\n            this.vertex       = vertex;\n            this.atomicNumber = vertex.value.getAtomicNumber();\n            this.atomicWeight = 0; // TODO!\n            this.stereocenter = !!(vertex.value.bracket && vertex.value.bracket.chirality);\n        }\n        else {\n            this.vertex       = null;\n            this.atomicNumber = vertex;\n            this.atomicWeight = 0; // TODO!\n            this.stereocenter = false;\n        }\n\n        if (magic instanceof Map) {\n            this.cloneDepth = undefined;\n            this.visited    = magic;\n            this.children   = undefined;\n            this.sorted     = false;\n        }\n        else {\n            this.cloneDepth = magic;\n            this.visited    = null;\n            this.children   = [];\n            this.sorted     = true;\n\n            // Only real nodes should contribute to stereo ties!\n            // This prevents a copy of an actually-not-chiral root node from\n            // incorrectly causing a stereo tie (e.g. C1CC[C@]2(CC1)CCCC2).\n            this.stereocenter = false;\n\n            // TODO: For full robustness, we may need a way to prevent OTHER (non-root)\n            // not-actually-stereocenters from reporting false stereo ties...\n        }\n    }\n\n    /**\n     * Load the children of this CIPTree.\n     *\n     * This function is only called when needed; by default, CIPTrees just have\n     * a placeholder indicating that they might have children.  This function\n     * does not perform a full CIP sort on the children once they're loaded; it\n     * only performs a non-recursive sort using CIPTree.compareAtoms().\n     *\n     * @returns The partially sorted list of children.\n     */\n    findChildren(): CIPTree[] {\n        if (this.children === undefined) {\n            this.children = [];\n\n            const mydepth = this.visited.size + 1;\n            const visited = new Map(this.visited);\n            visited.set(this.vertex, mydepth);\n            this.visited = null;\n\n            for (const index of this.vertex.neighbours) {\n                let links = this.graph.getEdge(this.vertex.id, index).weight;\n                if (!links) continue;\n\n                const neighbour = this.graph.vertices[index];\n                let   depth     = visited.get(neighbour);\n\n                if (Object.is(neighbour, this.parent)) {\n                    // Add one less link.\n                    links -= 1;\n                }\n                else if (depth === undefined) {\n                    // Add one real edge and one less link.\n                    const child = new CIPTree(this.graph, neighbour, this.vertex, visited);\n                    this.children.push(child);\n                    depth  = mydepth + 1;\n                    links -= 1;\n                }\n                else {\n                    // Add all links.\n                }\n\n                if (links > 0) {\n                    const child = new CIPTree(this.graph, neighbour, this.vertex, depth);\n                    while (links-- > 0) this.children.push(child);\n                }\n            }\n\n            if (this.vertex.value.isPartOfAromaticRing) {\n                // This is a HACK to get aromatic rings ordered correctly.\n                // TODO: Fix it!  The actual fix is still pretty hacky, though...\n                // See P-92.1.4.4 in the Blue Book.\n                const child = new CIPTree(this.graph, 6, this.vertex);\n                this.children.push(child);\n            }\n\n            let hydrogens = this.vertex.value.countImplicitHydrogens();\n            if (hydrogens > 0) {\n                const child = new CIPTree(this.graph, 1, this.vertex);\n                while (hydrogens-- > 0) this.children.push(child);\n            }\n\n            // Sort as well as possible without fetching children recursively.\n            this.children.sort((a, b) => CIPTree.compareAtoms(a, b)[0]);\n        }\n\n        return this.children;\n    }\n\n    /**\n     * Count the number of nodes in the (sub)tree rooted at this node.\n     *\n     * @returns The number of nodes in the tree.\n     */\n    size(): number {\n        if (this.children !== undefined) {\n            return this.children.reduce((sum, child) => sum + child.size(), 1);\n        }\n\n        return 1;\n    }\n\n    /**\n     * Perform a full recursive sort on this node's children.\n     *\n     * The children must already be loaded, or this will crash.  This function\n     * is normally called by CIPTree.compareTrees(), which is designed to make\n     * sure that isn't a problem.  If you call this function manually, make\n     * sure to call findChildren() first.\n     *\n     * @returns The fully sorted list of children.\n     */\n    sortChildren(): CIPTree[] {\n        if (!this.sorted) {\n            this.children.sort((a, b) => {\n                const [cmp, stereo] = CIPTree.compareTrees(a, b);\n\n                // This matches RDKit for unresolved stereo-containing ties.\n                // Keep original tie direction for @@, but invert it for @.\n                if (stereo && this.stereocenter) {\n                    if (this.vertex.value.bracket.chirality === '@') {\n                        return b.vertex.id - a.vertex.id;\n                    }\n                    else {\n                        return a.vertex.id - b.vertex.id;\n                    }\n                }\n\n                return cmp;\n            });\n\n            this.sorted = true;\n        }\n\n        return this.children;\n    }\n}\n\n/**\n * A namespace to hold the public CIP API.\n *\n * For more information on the Cahn-Ingold-Prelog priority system, see the links\n * below.  The Yale links give the best introduction; the Blue Book contains the\n * official specification.\n *\n * @see https://iupac.qmul.ac.uk/BlueBook/P9.html\n * @see https://en.wikipedia.org/wiki/Cahn%E2%80%93Ingold%E2%80%93Prelog_priority_rules\n * @see https://ursula.chem.yale.edu/~chem220/chem220js/STUDYAIDS/isomers/CIP%20rules%20NEW.html\n * @see https://ursula.chem.yale.edu/~chem220/chem220js/STUDYAIDS/isomers/RS14272/pinene.html\n */\nexport default class CIP {\n    static getOrderArray(graph: Graph, vertex: Vertex): Array<number> | undefined {\n        const root = CIPTree.build(graph, vertex);\n\n        // If there are any non-stereo ties, this isn't a stereocenter!\n        // TODO: Could we detect this quicker?\n        for (let i = 1; i < root.children.length; ++i) {\n            const cmp = CIPTree.compareTrees(root.children[i - 1], root.children[i]);\n            if (cmp[0] === 0 && !cmp[1]) return undefined;\n        }\n\n        // Build the ordering array expected by DrawerBase._computeWedgeDirection().\n        const nNeighbours = vertex.neighbours.length;\n        const order = new Array(nNeighbours);\n        for (let i = 0; i < nNeighbours; ++i) {\n            const vid = root.children[i].vertex.id;\n            order[i] = vertex.neighbours.findIndex(nid => nid === vid);\n        }\n\n        return order;\n    }\n}\n", "// @ts-check\n\n/**\n * A class representing an edge.\n *\n * @property {Number} id The id of this edge.\n * @property {Number} sourceId The id of the source vertex.\n * @property {Number} targetId The id of the target vertex.\n * @property {Number} weight The weight of this edge. That is, the degree of the bond (single bond = 1, double bond = 2, etc).\n * @property {String} [bondType='-'] The bond type of this edge.\n * @property {Boolean} [isPartOfAromaticRing=false] Whether or not this edge is part of an aromatic ring.\n * @property {Boolean} [center=false] Wheter or not the bond is centered. For example, this affects straight double bonds.\n * @property {String} [wedge=''] Wedge direction. Either '', 'up' or 'down'\n */\nexport default class Edge {\n    /**\n     * The constructor for the class Edge.\n     *\n     * @param {Number} sourceId A vertex id.\n     * @param {Number} targetId A vertex id.\n     * @param {Number} [weight=1] The weight of the edge.\n     */\n    constructor(sourceId, targetId, weight = 1) {\n        this.id = null;\n        this.sourceId = sourceId;\n        this.targetId = targetId;\n        this.weight = weight;\n        this.bondType = '-';\n        this.isPartOfAromaticRing = false;\n        this.center = false;\n        this.wedge = '';\n    }\n\n    /**\n     * Set the bond type of this edge. This also sets the edge weight.\n     * @param {String} bondType\n     */\n    setBondType(bondType) {\n        this.bondType = bondType;\n        this.weight = Edge.bonds[bondType];\n    }\n\n    /**\n     * An object mapping the bond type to the number of bonds.\n     *\n     * @returns {Object} The object containing the map.\n     */\n    static get bonds() {\n        return {\n            '.':  0,\n            '-':  1,\n            '/':  1,\n            '\\\\': 1,\n            '=':  2,\n            '#':  3,\n            '$':  4,\n        };\n    }\n}\n", "// @ts-check\nimport Atom       from './Atom';\nimport Edge       from './Edge';\nimport MathHelper from './MathHelper';\nimport Ring       from './Ring';\nimport Vector2    from './Vector2';\nimport Vertex     from './Vertex';\n\n/**\n * A class representing the molecular graph.\n *\n * @property {Vertex[]} vertices The vertices of the graph.\n * @property {Edge[]} edges The edges of this graph.\n * @property {Number[]} atomIdxToVertexId A map mapping atom indices to vertex ids.\n * @property {Object} vertexIdsToEdgeId A map mapping vertex ids to the edge between the two vertices. The key is defined as vertexAId + '_' + vertexBId.\n * @property {Boolean} isometric A boolean indicating whether or not the SMILES associated with this graph is isometric.\n */\nexport default class Graph {\n    /**\n     * The constructor of the class Graph.\n     *\n     * @param {Object} parseTree A SMILES parse tree.\n     * @param {Boolean} [isomeric=false] A boolean specifying whether or not the SMILES is isomeric.\n     */\n    constructor(parseTree, isomeric = false) {\n        this.vertices = [];\n        this.edges = [];\n        this.atomIdxToVertexId = [];\n        this.vertexIdsToEdgeId = {};\n        this.isomeric = isomeric;\n\n        // Used to assign indices to the heavy atoms.\n        this._atomIdx = 0;\n\n        // Used for the bridge detection algorithm\n        this._time = 0;\n        this._init(parseTree);\n    }\n\n    /**\n     * PRIVATE FUNCTION. Initializing the graph from the parse tree.\n     *\n     * @param {Object} node The current node in the parse tree.\n     * @param {Number} _order UNUSED\n     * @param {?Number} parentVertexId=null The id of the previous vertex.\n     * @param {Boolean} isBranch=false Whether or not the bond leading to this vertex is a branch bond. Branches are represented by parentheses in smiles (e.g. CC(O)C).\n     */\n    _init(node, _order = 0, parentVertexId = null, isBranch = false) {\n    // Create a new vertex object\n        const element = node.atom.element ? node.atom.element : node.atom;\n        let atom = new Atom(element, node.bond);\n\n        if (element !== 'H' || (!node.hasNext && parentVertexId === null)) {\n            atom.idx = this._atomIdx;\n            this._atomIdx++;\n        }\n\n        atom.branchBond = node.branchBond;\n        atom.ringbonds = node.ringbonds;\n        atom.bracket = node.atom.element ? node.atom : null;\n        atom.class = node.atom.class;\n\n        let vertex = new Vertex(atom);\n        let parentVertex = this.vertices[parentVertexId];\n\n        this.addVertex(vertex);\n\n        if (atom.idx !== null) {\n            this.atomIdxToVertexId.push(vertex.id);\n        }\n\n        // Add the id of this node to the parent as child\n        if (parentVertexId !== null) {\n            vertex.setParentVertexId(parentVertexId);\n            vertex.value.addNeighbouringElement(parentVertex.value.element);\n            parentVertex.addChild(vertex.id);\n            parentVertex.value.addNeighbouringElement(atom.element);\n\n            // In addition create a spanningTreeChildren property, which later will\n            // not contain the children added through ringbonds\n            parentVertex.spanningTreeChildren.push(vertex.id);\n\n            // Add edge between this node and its parent\n            let edge = new Edge(parentVertexId, vertex.id, 1);\n\n            if (isBranch) {\n                edge.setBondType(vertex.value.branchBond || '-');\n            }\n            else {\n                edge.setBondType(parentVertex.value.bondType || '-');\n            }\n\n            this.addEdge(edge);\n        }\n\n        let offset = node.ringbondCount + 1;\n\n        if (atom.bracket) {\n            offset += atom.bracket.hcount;\n        }\n\n        let stereoHydrogens = 0;\n        if (atom.bracket && atom.bracket.chirality) {\n            atom.isStereoCenter = true;\n            stereoHydrogens = atom.bracket.hcount;\n            for (let i = 0; i < stereoHydrogens; i++) {\n                this._init({\n                    atom:          'H',\n                    isBracket:     'false',\n                    branches:      [],\n                    branchCount:   0,\n                    ringbonds:     [],\n                    ringbondCount: false,\n                    next:          null,\n                    hasNext:       false,\n                    bond:          '-',\n                }, i, vertex.id, true);\n            }\n        }\n\n        for (let i = 0; i < node.branchCount; i++) {\n            this._init(node.branches[i], i + offset, vertex.id, true);\n        }\n\n        if (node.hasNext) {\n            this._init(node.next, node.branchCount + offset, vertex.id);\n        }\n    }\n\n    /**\n     * Clears all the elements in this graph (edges and vertices).\n     */\n    clear() {\n        this.vertices = [];\n        this.edges = [];\n        this.vertexIdsToEdgeId = {};\n    }\n\n    /**\n     * Add a vertex to the graph.\n     *\n     * @param {Vertex} vertex A new vertex.\n     * @returns {Number} The vertex id of the new vertex.\n     */\n    addVertex(vertex) {\n        vertex.id = this.vertices.length;\n        this.vertices.push(vertex);\n\n        return vertex.id;\n    }\n\n    /**\n     * Add an edge to the graph.\n     *\n     * @param {Edge} edge A new edge.\n     * @returns {Number} The edge id of the new edge.\n     */\n    addEdge(edge) {\n        let source = this.vertices[edge.sourceId];\n        let target = this.vertices[edge.targetId];\n\n        edge.id = this.edges.length;\n        this.edges.push(edge);\n\n        this.vertexIdsToEdgeId[edge.sourceId + '_' + edge.targetId] = edge.id;\n        this.vertexIdsToEdgeId[edge.targetId + '_' + edge.sourceId] = edge.id;\n        edge.isPartOfAromaticRing = source.value.isPartOfAromaticRing && target.value.isPartOfAromaticRing;\n\n        source.value.bondCount += edge.weight;\n        target.value.bondCount += edge.weight;\n\n        source.edges.push(edge.id);\n        target.edges.push(edge.id);\n\n        return edge.id;\n    }\n\n    /**\n     * Returns the edge between two given vertices.\n     *\n     * @param {Number} vertexIdA A vertex id.\n     * @param {Number} vertexIdB A vertex id.\n     * @returns {(Edge|null)} The edge or, if no edge can be found, null.\n     */\n    getEdge(vertexIdA, vertexIdB) {\n        let edgeId = this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB];\n\n        return edgeId === undefined ? null : this.edges[edgeId];\n    }\n\n    /**\n     * Returns the ids of edges connected to a vertex.\n     *\n     * @param {Number} vertexId A vertex id.\n     * @returns {Number[]} An array containing the ids of edges connected to the vertex.\n     */\n    getEdges(vertexId) {\n        let edgeIds = [];\n        let vertex = this.vertices[vertexId];\n\n        for (let i = 0; i < vertex.neighbours.length; i++) {\n            edgeIds.push(this.vertexIdsToEdgeId[vertexId + '_' + vertex.neighbours[i]]);\n        }\n\n        return edgeIds;\n    }\n\n    /**\n     * Check whether or not two vertices are connected by an edge.\n     *\n     * @param {Number} vertexIdA A vertex id.\n     * @param {Number} vertexIdB A vertex id.\n     * @returns {Boolean} A boolean indicating whether or not two vertices are connected by an edge.\n     */\n    hasEdge(vertexIdA, vertexIdB) {\n        return this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB] !== undefined;\n    }\n\n    /**\n     * Returns an array containing the vertex ids of this graph.\n     *\n     * @returns {Number[]} An array containing all vertex ids of this graph.\n     */\n    getVertexList() {\n        let arr = [this.vertices.length];\n\n        for (let i = 0; i < this.vertices.length; i++) {\n            arr[i] = this.vertices[i].id;\n        }\n\n        return arr;\n    }\n\n    /**\n     * Returns an array containing source, target arrays of this graphs edges.\n     *\n     * @returns {Array[]} An array containing source, target arrays of this graphs edges. Example: [ [ 2, 5 ], [ 6, 9 ] ].\n     */\n    getEdgeList() {\n        let arr = Array(this.edges.length);\n\n        for (let i = 0; i < this.edges.length; i++) {\n            arr[i] = [this.edges[i].sourceId, this.edges[i].targetId];\n        }\n\n        return arr;\n    }\n\n    /**\n     * Get the adjacency matrix of the graph.\n     *\n     * @returns {Array[]} The adjancency matrix of the molecular graph.\n     */\n    getAdjacencyMatrix() {\n        let length = this.vertices.length;\n        let adjacencyMatrix = Array(length);\n\n        for (let i = 0; i < length; i++) {\n            adjacencyMatrix[i] = new Array(length);\n            adjacencyMatrix[i].fill(0);\n        }\n\n        for (let i = 0; i < this.edges.length; i++) {\n            let edge = this.edges[i];\n\n            adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\n            adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\n        }\n\n        return adjacencyMatrix;\n    }\n\n    /**\n     * Get the adjacency matrix of the graph with all bridges removed (thus the components). Thus the remaining vertices are all part of ring systems.\n     *\n     * @returns {Array[]} The adjancency matrix of the molecular graph with all bridges removed.\n     */\n    getComponentsAdjacencyMatrix() {\n        let length = this.vertices.length;\n        let adjacencyMatrix = Array(length);\n        let bridges = this.getBridges();\n\n        for (let i = 0; i < length; i++) {\n            adjacencyMatrix[i] = new Array(length);\n            adjacencyMatrix[i].fill(0);\n        }\n\n        for (let i = 0; i < this.edges.length; i++) {\n            let edge = this.edges[i];\n\n            adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\n            adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\n        }\n\n        for (let i = 0; i < bridges.length; i++) {\n            adjacencyMatrix[bridges[i][0]][bridges[i][1]] = 0;\n            adjacencyMatrix[bridges[i][1]][bridges[i][0]] = 0;\n        }\n\n        return adjacencyMatrix;\n    }\n\n    /**\n     * Get the adjacency matrix of a subgraph.\n     *\n     * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\n     * @returns {Array[]} The adjancency matrix of the subgraph.\n     */\n    getSubgraphAdjacencyMatrix(vertexIds) {\n        let length = vertexIds.length;\n        let adjacencyMatrix = Array(length);\n\n        for (let i = 0; i < length; i++) {\n            adjacencyMatrix[i] = new Array(length);\n            adjacencyMatrix[i].fill(0);\n\n            for (let j = 0; j < length; j++) {\n                if (i === j) {\n                    continue;\n                }\n\n                if (this.hasEdge(vertexIds[i], vertexIds[j])) {\n                    adjacencyMatrix[i][j] = 1;\n                }\n            }\n        }\n\n        return adjacencyMatrix;\n    }\n\n    /**\n     * Get the distance matrix of the graph.\n     *\n     * @returns {Array[]} The distance matrix of the graph.\n     */\n    getDistanceMatrix() {\n        let length = this.vertices.length;\n        let adja = this.getAdjacencyMatrix();\n        let dist = Array(length);\n\n        for (let i = 0; i < length; i++) {\n            dist[i] = Array(length);\n            dist[i].fill(Infinity);\n        }\n\n        for (let i = 0; i < length; i++) {\n            for (let j = 0; j < length; j++) {\n                if (adja[i][j] === 1) {\n                    dist[i][j] = 1;\n                }\n            }\n        }\n\n        for (let k = 0; k < length; k++) {\n            for (let i = 0; i < length; i++) {\n                for (let j = 0; j < length; j++) {\n                    if (dist[i][j] > dist[i][k] + dist[k][j]) {\n                        dist[i][j] = dist[i][k] + dist[k][j];\n                    }\n                }\n            }\n        }\n\n        return dist;\n    }\n\n    /**\n     * Get the distance matrix of a subgraph.\n     *\n     * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\n     * @returns {Array[]} The distance matrix of the subgraph.\n     */\n    getSubgraphDistanceMatrix(vertexIds) {\n        let length = vertexIds.length;\n        let adja = this.getSubgraphAdjacencyMatrix(vertexIds);\n        let dist = Array(length);\n\n        for (let i = 0; i < length; i++) {\n            dist[i] = Array(length);\n            dist[i].fill(Infinity);\n            dist[i][i] = 0;\n        }\n\n        for (let i = 0; i < length; i++) {\n            for (let j = 0; j < length; j++) {\n                if (adja[i][j] === 1) {\n                    dist[i][j] = 1;\n                }\n            }\n        }\n\n        for (let k = 0; k < length; k++) {\n            for (let i = 0; i < length; i++) {\n                for (let j = 0; j < length; j++) {\n                    if (dist[i][j] > dist[i][k] + dist[k][j]) {\n                        dist[i][j] = dist[i][k] + dist[k][j];\n                    }\n                }\n            }\n        }\n\n        return dist;\n    }\n\n    /**\n     * Get the adjacency list of the graph.\n     *\n     * @returns {Array[]} The adjancency list of the graph.\n     */\n    getAdjacencyList() {\n        let length = this.vertices.length;\n        let adjacencyList = Array(length);\n\n        for (let i = 0; i < length; i++) {\n            adjacencyList[i] = [];\n\n            for (let j = 0; j < length; j++) {\n                if (i === j) {\n                    continue;\n                }\n\n                if (this.hasEdge(this.vertices[i].id, this.vertices[j].id)) {\n                    adjacencyList[i].push(j);\n                }\n            }\n        }\n\n        return adjacencyList;\n    }\n\n    /**\n     * Get the adjacency list of a subgraph.\n     *\n     * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\n     * @returns {Array[]} The adjancency list of the subgraph.\n     */\n    getSubgraphAdjacencyList(vertexIds) {\n        let length = vertexIds.length;\n        let adjacencyList = Array(length);\n\n        for (let i = 0; i < length; i++) {\n            adjacencyList[i] = [];\n\n            for (let j = 0; j < length; j++) {\n                if (i === j) {\n                    continue;\n                }\n\n                if (this.hasEdge(vertexIds[i], vertexIds[j])) {\n                    adjacencyList[i].push(j);\n                }\n            }\n        }\n\n        return adjacencyList;\n    }\n\n    /**\n     * Returns the perimeter order of a bridged ring after removing interior bridge atoms.\n     * Falls back to the unsorted perimeter vertices when the remaining subgraph is not a simple cycle.\n     *\n     * @param {Number[]} vertexIds The bridged-ring vertex ids.\n     * @param {Ring} ring The bridged ring.\n     * @param {Number} startVertexId A preferred starting vertex id.\n     * @returns {Number[]} The ordered perimeter vertex ids.\n     */\n    getBridgedRingPerimeter(vertexIds, ring, startVertexId) {\n        let insiderSet = new Set(ring.insiders || []);\n        let perimeter = vertexIds.filter(id => !insiderSet.has(id));\n\n        if (perimeter.length < 3) {\n            return perimeter;\n        }\n\n        let perimeterSet = new Set(perimeter);\n        let adjacency = new Map();\n\n        for (let i = 0; i < perimeter.length; i++) {\n            let id = perimeter[i];\n            let neighbours = this.vertices[id].neighbours.filter(neighbourId => perimeterSet.has(neighbourId));\n            adjacency.set(id, neighbours);\n\n            if (neighbours.length !== 2) {\n                return perimeter;\n            }\n        }\n\n        let start = perimeterSet.has(startVertexId) ? startVertexId : perimeter[0];\n        let ordered = [start];\n        let previous = null;\n        let current = start;\n\n        while (ordered.length < perimeter.length) {\n            let neighbours = adjacency.get(current).filter(neighbourId => neighbourId !== previous);\n\n            if (previous === null) {\n                neighbours.sort((a, b) => this.vertices[a].value.smilesOrder - this.vertices[b].value.smilesOrder);\n            }\n\n            if (neighbours.length === 0) {\n                return perimeter;\n            }\n\n            let next = neighbours[0];\n\n            if (next === start) {\n                return perimeter;\n            }\n\n            ordered.push(next);\n            previous = current;\n            current = next;\n        }\n\n        return adjacency.get(current).includes(start) ? ordered : perimeter;\n    }\n\n    /**\n     * Returns an array containing the edge ids of bridges. A bridge splits the graph into multiple components when removed.\n     *\n     * @returns {Number[]} An array containing the edge ids of the bridges.\n     */\n    getBridges() {\n        let length = this.vertices.length;\n        let visited = new Array(length);\n        let disc = new Array(length);\n        let low = new Array(length);\n        let parent = new Array(length);\n        let adj = this.getAdjacencyList();\n        let outBridges = [];\n\n        visited.fill(false);\n        parent.fill(null);\n        this._time = 0;\n\n        for (let i = 0; i < length; i++) {\n            if (!visited[i]) {\n                this._bridgeDfs(i, visited, disc, low, parent, adj, outBridges);\n            }\n        }\n\n        return outBridges;\n    }\n\n    /**\n     * Traverses the graph in breadth-first order.\n     *\n     * @param {Number} startVertexId The id of the starting vertex.\n     * @param {Function} callback The callback function to be called on every vertex.\n     */\n    traverseBF(startVertexId, callback) {\n        let length = this.vertices.length;\n        let visited = new Array(length);\n\n        visited.fill(false);\n\n        let queue = [startVertexId];\n\n        while (queue.length > 0) {\n            // JavaScripts shift() is O(n) ... bad JavaScript, bad!\n            let u = queue.shift();\n            let vertex = this.vertices[u];\n\n            callback(vertex);\n\n            for (let i = 0; i < vertex.neighbours.length; i++) {\n                let v = vertex.neighbours[i];\n                if (!visited[v]) {\n                    visited[v] = true;\n                    queue.push(v);\n                }\n            }\n        }\n    }\n\n    /**\n     * Get the depth of a subtree in the direction opposite to the vertex specified as the parent vertex.\n     *\n     * @param {Number} vertexId A vertex id.\n     * @param {Number} parentVertexId The id of a neighbouring vertex.\n     * @returns {Number} The depth of the sub-tree.\n     */\n    getTreeDepth(vertexId, parentVertexId) {\n        if (vertexId === null || parentVertexId === null) {\n            return 0;\n        }\n\n        let neighbours = this.vertices[vertexId].getSpanningTreeNeighbours(parentVertexId);\n        let max = 0;\n\n        for (let i = 0; i < neighbours.length; i++) {\n            let childId = neighbours[i];\n            let d = this.getTreeDepth(childId, vertexId);\n\n            if (d > max) {\n                max = d;\n            }\n        }\n\n        return max + 1;\n    }\n\n    /**\n     * Traverse a sub-tree in the graph.\n     *\n     * @param {Number} vertexId A vertex id.\n     * @param {Number} parentVertexId A neighbouring vertex.\n     * @param {Function} callback The callback function that is called with each visited as an argument.\n     * @param {Number} [maxDepth=999999] The maximum depth of the recursion.\n     * @param {Boolean} [ignoreFirst=false] Whether or not to ignore the starting vertex supplied as vertexId in the callback.\n     * @param {Number} [depth=1] The current depth in the tree.\n     * @param {Uint8Array} [visited=null] An array holding a flag on whether or not a node has been visited.\n     */\n    traverseTree(vertexId, parentVertexId, callback, maxDepth = 999999, ignoreFirst = false, depth = 1, visited = null) {\n        if (visited === null) {\n            visited = new Uint8Array(this.vertices.length);\n        }\n\n        if (depth > maxDepth + 1 || visited[vertexId] === 1) {\n            return;\n        }\n\n        visited[vertexId] = 1;\n\n        let vertex = this.vertices[vertexId];\n        let neighbours = vertex.getNeighbours(parentVertexId);\n\n        if (!ignoreFirst || depth > 1) {\n            callback(vertex);\n        }\n\n        for (let i = 0; i < neighbours.length; i++) {\n            this.traverseTree(neighbours[i], vertexId, callback, maxDepth, ignoreFirst, depth + 1, visited);\n        }\n    }\n\n    /**\n     * Positiones the (sub)graph using Kamada and Kawais algorithm for drawing general undirected graphs. https://pdfs.semanticscholar.org/b8d3/bca50ccc573c5cb99f7d201e8acce6618f04.pdf\n     * There are undocumented layout parameters. They are undocumented for a reason, so be very careful.\n     *\n     * @param {Number[]} vertexIds An array containing vertexIds to be placed using the force based layout.\n     * @param {Vector2} center The center of the layout.\n     * @param {Number} startVertexId A vertex id. Should be the starting vertex - e.g. the first to be positioned and connected to a previously place vertex.\n     * @param {Ring} ring The bridged ring associated with this force-based layout.\n     */\n    /**\n     * Compute 2D starting positions for a ring system from its graph-distance\n     * matrix using classical multidimensional scaling (MDS).\n     *\n     * Used by kkLayout to seed cage like ring systems where a plain\n     * circular start sends Kamada-Kawai into a local minimum. Classical\n     * MDS gives a single global answer in closed form, so KK starts somewhere\n     * sensible. A visual example of having MDS+KK vs only KK difference is on dodecahedrane\n     * check https://math.mit.edu/~urschel/publications/p2021e.pdf Figure 5 (last page) for\n     * a very close example of how KK vs MDS+KK looks like in dodecahedrane\n     *\n     * The algorithm is classical MDS, also called Torgerson scaling or\n     * Principal Coordinates Analysis (Torgerson, \"Multidimensional scaling: I.\n     * Theory and method\", Psychometrika 17, 1952). Given an n x n distance\n     * matrix D it returns the 2D point set whose pairwise Euclidean distances\n     * best match D in least-squares sense.\n     *\n     *   1. Square the distances element-wise:           D2[i][j] = D[i][j]^2\n     *   2. Double-centre to get a Gram-like matrix:     B = -1/2 H D2 H\n     *      with H = I - (1/n) 1 1^T (centres rows and columns on zero).\n     *   3. Take the top two eigenvectors of B.\n     *   4. Coordinates: x_i = sqrt(lambda_1) v_1[i],\n     *                   y_i = sqrt(lambda_2) v_2[i].\n     *\n     *  The final rescale (lines below) sizes the layout so that the largest\n     * pairwise distance is roughly bondLength * sqrt(n), which puts the result\n     * on the same scale as the rest of the drawing.\n     *\n     * @param {Array[]} matDist Graph-distance matrix (shortest paths in bonds).\n     * @param {number} n Number of vertices.\n     * @param {number} bondLength Target bond length, used as the output scale.\n     * @returns {{xs: Float32Array, ys: Float32Array}} 2D coordinates centred at 0.\n     */\n    static mdsLayout(matDist, n, bondLength) {\n        // Step 1: Compute B = -0.5 * H * D^2 * H (double-centered squared distances)\n        // H = I - (1/n) * 11^T\n        let dsq = new Array(n);\n        for (let i = 0; i < n; i++) {\n            dsq[i] = new Float64Array(n);\n            for (let j = 0; j < n; j++) {\n                dsq[i][j] = matDist[i][j] * matDist[i][j];\n            }\n        }\n\n        // Row means, column means, grand mean\n        let rowMean = new Float64Array(n);\n        let grandMean = 0;\n        for (let i = 0; i < n; i++) {\n            let s = 0;\n            for (let j = 0; j < n; j++) s += dsq[i][j];\n            rowMean[i] = s / n;\n            grandMean += s;\n        }\n        grandMean /= (n * n);\n\n        // B[i][j] = -0.5 * (D^2[i][j] - rowMean[i] - rowMean[j] + grandMean)\n        let B = new Array(n);\n        for (let i = 0; i < n; i++) {\n            B[i] = new Float64Array(n);\n            for (let j = 0; j < n; j++) {\n                B[i][j] = -0.5 * (dsq[i][j] - rowMean[i] - rowMean[j] + grandMean);\n            }\n        }\n\n        // Step 2: Power iteration to find top 2 eigenvectors of B\n        let eigvec1 = Graph._powerIteration(B, n, 200);\n        let eval1 = Graph._rayleigh(B, eigvec1, n);\n\n        // B' = B - eval1 * v1 * v1^T\n        for (let i = 0; i < n; i++) {\n            for (let j = 0; j < n; j++) {\n                B[i][j] -= eval1 * eigvec1[i] * eigvec1[j];\n            }\n        }\n\n        let eigvec2 = Graph._powerIteration(B, n, 200);\n        let eval2 = Graph._rayleigh(B, eigvec2, n);\n\n        // Step 3: Coordinates = eigvec * sqrt(eigenvalue) * bondLength\n        let scale1 = eval1 > 0 ? Math.sqrt(eval1) : 0;\n        let scale2 = eval2 > 0 ? Math.sqrt(eval2) : 0;\n\n        // Normalize so max distance between any pair ~= diameter of a polygon\n        // with this many vertices at bondLength spacing\n        let xs = new Float32Array(n);\n        let ys = new Float32Array(n);\n        for (let i = 0; i < n; i++) {\n            xs[i] = eigvec1[i] * scale1;\n            ys[i] = eigvec2[i] * scale2;\n        }\n\n        // Scale to match bondLength.\n        let maxDistSq = 0;\n        for (let i = 0; i < n; i++) {\n            for (let j = i + 1; j < n; j++) {\n                let dx = xs[i] - xs[j];\n                let dy = ys[i] - ys[j];\n                let dSq = dx * dx + dy * dy;\n                if (dSq > maxDistSq) maxDistSq = dSq;\n            }\n        }\n        let maxDist = Math.sqrt(maxDistSq);\n        if (maxDist > 0) {\n            let targetSize = bondLength * Math.max(2, Math.sqrt(n));\n            let s = targetSize / maxDist;\n            for (let i = 0; i < n; i++) {\n                xs[i] *= s;\n                ys[i] *= s;\n            }\n        }\n\n        return {xs, ys};\n    }\n\n    /**\n     * Power iteration to find the dominant eigenvector of a symmetric matrix.\n     * @param {Array[]} mat The matrix.\n     * @param {number} n Size.\n     * @param {number} maxIter Maximum iterations.\n     * @returns {Float64Array} The normalized eigenvector.\n     */\n    static _powerIteration(mat, n, maxIter) {\n        let v = new Float64Array(n);\n        // Seed with non-uniform vector to break symmetry\n        for (let i = 0; i < n; i++) {\n            v[i] = 1.0 + 0.1 * i;\n        }\n\n        let w = new Float64Array(n);\n        for (let iter = 0; iter < maxIter; iter++) {\n            for (let i = 0; i < n; i++) {\n                let s = 0;\n                for (let j = 0; j < n; j++) s += mat[i][j] * v[j];\n                w[i] = s;\n            }\n            // Normalize\n            let norm = 0;\n            for (let i = 0; i < n; i++) norm += w[i] * w[i];\n            norm = Math.sqrt(norm);\n            if (norm < 1e-12) break;\n            for (let i = 0; i < n; i++) v[i] = w[i] / norm;\n        }\n        return v;\n    }\n\n    /**\n     * Rayleigh quotient: v^T * A * v (for normalized v).\n     * @param {Array[]} mat The matrix.\n     * @param {Float64Array} v Normalized eigenvector.\n     * @param {number} n Size.\n     * @returns {number} The eigenvalue estimate.\n     */\n    static _rayleigh(mat, v, n) {\n        let r = 0;\n        for (let i = 0; i < n; i++) {\n            let s = 0;\n            for (let j = 0; j < n; j++) s += mat[i][j] * v[j];\n            r += v[i] * s;\n        }\n        return r;\n    }\n\n    kkLayout(vertexIds, center, startVertexId, ring, bondLength,\n        threshold = 0.1,\n        innerThreshold = 0.1,\n        maxIteration = 2000,\n        maxInnerIteration = 50,\n        maxEnergy = 1e9\n    ) {\n        let edgeStrength = bondLength;\n\n        let matDist = this.getSubgraphDistanceMatrix(vertexIds);\n        let length = vertexIds.length;\n\n        let arrPositionX = new Float32Array(length);\n        let arrPositionY = new Float32Array(length);\n        let arrPositioned = Array(length);\n\n        let radius = MathHelper.polyCircumradius(bondLength, length);\n        let angle = MathHelper.centralAngle(length);\n        let a = 0.0;\n\n        let insiderSet = new Set(ring.insiders || []);\n        let insiders = vertexIds.filter(id => insiderSet.has(id));\n\n        let anyPositioned = false;\n        for (let i = 0; i < length; i++) {\n            if (this.vertices[vertexIds[i]].positioned) {\n                anyPositioned = true;\n                break;\n            }\n        }\n\n        // Pick the starting positions for KK based on the shape of the ring system.\n        // KK refines from these positions, but it can only find a local minimum,\n        // so a bad start gives a poor output (see dodecahedrane); with MDS-based\n        // init it lays out as a better dodecahedron projection.\n        //\n        // Three cases:\n        // 1. A small bridged ring with 1-2 atoms in the interior. Place the outer\n        //    ring as a regular polygon, then drop the interior atom(s) at the\n        //    centroid of their neighbours on the perimeter. This is the original\n        //    SmilesDrawer strategy and still gives the best result for these\n        //    molecules.\n        //\n        // 2. A cage or a ring system with many interior atoms (cubane,\n        //    dodecahedrane, fullerenes, cyclophanes). The \"drop interior atoms at\n        //    the centroid\" trick from case 1 fails here because it stacks many\n        //    atoms on top of each other in the middle. Instead we use MDS to\n        //    compute a 2D layout from the graph-distance matrix in one shot. See\n        //    Graph.mdsLayout below for details.\n        //\n        // 3. Anything else: the system is too small for MDS to help, or some atoms\n        //    have already been placed by a previous layout stage. Fall back to a\n        //    simple circle as the starting guess and KK takes it from there.\n        if (insiders.length > 0 && insiders.length <= 2) {\n            let perimeter = this.getBridgedRingPerimeter(vertexIds, ring, startVertexId);\n            let perimeterSet = new Set(perimeter);\n            let perimeterCount = perimeter.length;\n            let perimeterRadius = perimeterCount > 2\n                ? MathHelper.polyCircumradius(bondLength, perimeterCount)\n                : radius;\n            let perimeterAngle = perimeterCount > 0\n                ? Math.PI * 2.0 / perimeterCount\n                : angle;\n            let perimeterOffset = 0.0;\n            let initialPositions = new Map();\n\n            if (perimeterSet.has(startVertexId)) {\n                let startVertexIndex = perimeter.indexOf(startVertexId);\n                let startVertex = this.vertices[startVertexId];\n\n                if (startVertex.positioned) {\n                    perimeterOffset = Vector2.subtract(startVertex.position, center).angle() - startVertexIndex * perimeterAngle;\n                }\n            }\n\n            for (let i = 0; i < perimeter.length; i++) {\n                let id = perimeter[i];\n                let vertex = this.vertices[id];\n\n                if (vertex.positioned) {\n                    initialPositions.set(id, vertex.position.clone());\n                }\n                else {\n                    let point = new Vector2(\n                        center.x + Math.cos(perimeterOffset + i * perimeterAngle) * perimeterRadius,\n                        center.y + Math.sin(perimeterOffset + i * perimeterAngle) * perimeterRadius\n                    );\n                    initialPositions.set(id, point);\n                }\n            }\n\n            let innerRadius = Math.max(bondLength * 0.35, perimeterRadius * 0.35);\n\n            for (let i = 0; i < insiders.length; i++) {\n                let id = insiders[i];\n                let vertex = this.vertices[id];\n\n                if (vertex.positioned) {\n                    initialPositions.set(id, vertex.position.clone());\n                    continue;\n                }\n\n                let neighbours = vertex.neighbours.filter(neighbourId => perimeterSet.has(neighbourId));\n                let point = new Vector2(center.x, center.y);\n\n                if (neighbours.length > 0) {\n                    point = new Vector2(0.0, 0.0);\n\n                    for (let j = 0; j < neighbours.length; j++) {\n                        point.add(initialPositions.get(neighbours[j]));\n                    }\n\n                    point.divide(neighbours.length);\n\n                    let direction = Vector2.subtract(point, center);\n                    if (direction.lengthSq() < 1e-4) {\n                        direction = new Vector2(Math.cos(i * perimeterAngle), Math.sin(i * perimeterAngle));\n                    }\n                    else {\n                        direction.normalize();\n                    }\n\n                    point = direction.multiplyScalar(innerRadius).add(center.clone());\n                }\n                else {\n                    point.x += Math.cos(i * perimeterAngle) * innerRadius;\n                    point.y += Math.sin(i * perimeterAngle) * innerRadius;\n                }\n\n                initialPositions.set(id, point);\n            }\n\n            var i = length;\n            while (i--) {\n                let vertex = this.vertices[vertexIds[i]];\n                if (!vertex.positioned) {\n                    let initial = initialPositions.get(vertex.id);\n                    if (initial) {\n                        arrPositionX[i] = initial.x;\n                        arrPositionY[i] = initial.y;\n                    }\n                    else {\n                        arrPositionX[i] = center.x + Math.cos(a) * radius;\n                        arrPositionY[i] = center.y + Math.sin(a) * radius;\n                    }\n                }\n                else {\n                    arrPositionX[i] = vertex.position.x;\n                    arrPositionY[i] = vertex.position.y;\n                }\n                arrPositioned[i] = vertex.positioned;\n                a += angle;\n            }\n        }\n        else if (!anyPositioned && length >= 6) {\n            let mds = Graph.mdsLayout(matDist, length, bondLength);\n            for (let idx = 0; idx < length; idx++) {\n                arrPositionX[idx] = center.x + mds.xs[idx];\n                arrPositionY[idx] = center.y + mds.ys[idx];\n                arrPositioned[idx] = false;\n            }\n        }\n        else {\n            var i = length;\n            while (i--) {\n                let vertex = this.vertices[vertexIds[i]];\n                if (!vertex.positioned) {\n                    arrPositionX[i] = center.x + Math.cos(a) * radius;\n                    arrPositionY[i] = center.y + Math.sin(a) * radius;\n                }\n                else {\n                    arrPositionX[i] = vertex.position.x;\n                    arrPositionY[i] = vertex.position.y;\n                }\n                arrPositioned[i] = vertex.positioned;\n                a += angle;\n            }\n        }\n\n        // Create the matrix containing the lengths\n        let matLength = Array(length);\n        i = length;\n        while (i--) {\n            matLength[i] = new Array(length);\n            let j = length;\n            while (j--) {\n                matLength[i][j] = bondLength * matDist[i][j];\n            }\n        }\n\n        // Create the matrix containing the spring strenghts\n        let matStrength = Array(length);\n        i = length;\n        while (i--) {\n            matStrength[i] = Array(length);\n            let j = length;\n            while (j--) {\n                matStrength[i][j] = edgeStrength * Math.pow(matDist[i][j], -2.0);\n            }\n        }\n\n        // Create the matrix containing the energies\n        let matEnergy = Array(length);\n        let arrEnergySumX = new Float32Array(length);\n        let arrEnergySumY = new Float32Array(length);\n        i = length;\n        while (i--) {\n            matEnergy[i] = Array(length);\n        }\n\n        i = length;\n\n        while (i--) {\n            let ux = arrPositionX[i];\n            let uy = arrPositionY[i];\n            let dEx = 0.0;\n            let dEy = 0.0;\n            let j = length;\n            while (j--) {\n                if (i === j) {\n                    continue;\n                }\n                let vx = arrPositionX[j];\n                let vy = arrPositionY[j];\n                let denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\n                matEnergy[i][j] = [\n                    matStrength[i][j] * ((ux - vx) - matLength[i][j] * (ux - vx) * denom),\n                    matStrength[i][j] * ((uy - vy) - matLength[i][j] * (uy - vy) * denom),\n                ];\n                matEnergy[j][i] = matEnergy[i][j];\n                dEx += matEnergy[i][j][0];\n                dEy += matEnergy[i][j][1];\n            }\n            arrEnergySumX[i] = dEx;\n            arrEnergySumY[i] = dEy;\n        }\n\n        // Utility functions, maybe inline them later\n        let energy = function(index) {\n            return [arrEnergySumX[index] * arrEnergySumX[index] + arrEnergySumY[index] * arrEnergySumY[index], arrEnergySumX[index], arrEnergySumY[index]];\n        };\n\n        let highestEnergy = function() {\n            let highEnergy = 0.0;\n            let highEnergyId = 0;\n            let highDEX = 0.0;\n            let highDEY = 0.0;\n\n            i = length;\n            while (i--) {\n                let [delta, dEX, dEY] = energy(i);\n\n                if (delta > highEnergy && arrPositioned[i] === false) {\n                    highEnergy = delta;\n                    highEnergyId = i;\n                    highDEX = dEX;\n                    highDEY = dEY;\n                }\n            }\n\n            return [highEnergyId, highEnergy, highDEX, highDEY];\n        };\n\n        let update = function(index, dEX, dEY) {\n            let dxx = 0.0;\n            let dyy = 0.0;\n            let dxy = 0.0;\n            let ux = arrPositionX[index];\n            let uy = arrPositionY[index];\n            let arrL = matLength[index];\n            let arrK = matStrength[index];\n\n            i = length;\n            while (i--) {\n                if (i === index) {\n                    continue;\n                }\n\n                let vx = arrPositionX[i];\n                let vy = arrPositionY[i];\n                let l = arrL[i];\n                let k = arrK[i];\n                let m = (ux - vx) * (ux - vx);\n                let denom = 1.0 / Math.pow(m + (uy - vy) * (uy - vy), 1.5);\n\n                dxx += k * (1 - l * (uy - vy) * (uy - vy) * denom);\n                dyy += k * (1 - l * m * denom);\n                dxy += k * (l * (ux - vx) * (uy - vy) * denom);\n            }\n\n            // Prevent division by zero\n            if (dxx === 0) {\n                dxx = 0.1;\n            }\n\n            if (dyy === 0) {\n                dyy = 0.1;\n            }\n\n            if (dxy === 0) {\n                dxy = 0.1;\n            }\n\n            let denom = (dxy / dxx - dyy / dxy);\n            let dy, dx;\n            if (Math.abs(denom) < 1e-6) {\n                // Degenerate case: fall back to simple gradient descent\n                dx = -dEX * 0.1;\n                dy = -dEY * 0.1;\n            }\n            else {\n                dy = (dEX / dxx + dEY / dxy) / denom;\n                dx = -(dxy * dy + dEX) / dxx;\n            }\n\n            // Clamp step size to prevent extreme jumps\n            let stepLen = Math.sqrt(dx * dx + dy * dy);\n            if (stepLen > bondLength) {\n                let scale = bondLength / stepLen;\n                dx *= scale;\n                dy *= scale;\n            }\n\n            arrPositionX[index] += dx;\n            arrPositionY[index] += dy;\n\n            // Update the energies\n            let arrE = matEnergy[index];\n            dEX = 0.0;\n            dEY = 0.0;\n\n            ux = arrPositionX[index];\n            uy = arrPositionY[index];\n\n            i = length;\n            while (i--) {\n                if (index === i) {\n                    continue;\n                }\n                let vx = arrPositionX[i];\n                let vy = arrPositionY[i];\n                // Store old energies\n                let prevEx = arrE[i][0];\n                let prevEy = arrE[i][1];\n                let invDist = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\n                dx = arrK[i] * ((ux - vx) - arrL[i] * (ux - vx) * invDist);\n                dy = arrK[i] * ((uy - vy) - arrL[i] * (uy - vy) * invDist);\n\n                arrE[i] = [dx, dy];\n                dEX += dx;\n                dEY += dy;\n                arrEnergySumX[i] += dx - prevEx;\n                arrEnergySumY[i] += dy - prevEy;\n            }\n            arrEnergySumX[index] = dEX;\n            arrEnergySumY[index] = dEY;\n        };\n\n        // Setting up variables for the while loops\n        let maxEnergyId = 0;\n        let dEX = 0.0;\n        let dEY = 0.0;\n        let delta = 0.0;\n        let iteration = 0;\n        let innerIteration = 0;\n\n        while (maxEnergy > threshold && maxIteration > iteration) {\n            iteration++;\n            [maxEnergyId, maxEnergy, dEX, dEY] = highestEnergy();\n            delta = maxEnergy;\n            innerIteration = 0;\n            while (delta > innerThreshold && maxInnerIteration > innerIteration) {\n                innerIteration++;\n                update(maxEnergyId, dEX, dEY);\n                [delta, dEX, dEY] = energy(maxEnergyId);\n            }\n        }\n\n        i = length;\n        while (i--) {\n            let index = vertexIds[i];\n            let vertex = this.vertices[index];\n            vertex.position.x = arrPositionX[i];\n            vertex.position.y = arrPositionY[i];\n            vertex.positioned = true;\n            vertex.forcePositioned = true;\n        }\n    }\n\n    /**\n     * PRIVATE FUNCTION used by getBridges().\n     */\n    _bridgeDfs(u, visited, disc, low, parent, adj, outBridges) {\n        visited[u] = true;\n        disc[u] = low[u] = ++this._time;\n\n        for (let i = 0; i < adj[u].length; i++) {\n            let v = adj[u][i];\n\n            if (!visited[v]) {\n                parent[v] = u;\n\n                this._bridgeDfs(v, visited, disc, low, parent, adj, outBridges);\n\n                low[u] = Math.min(low[u], low[v]);\n\n                // If low > disc, we have a bridge\n                if (low[v] > disc[u]) {\n                    outBridges.push([u, v]);\n                }\n            }\n            else if (v !== parent[u]) {\n                low[u] = Math.min(low[u], disc[v]);\n            }\n        }\n    }\n\n    /**\n     * Returns the connected components of the graph.\n     *\n     * @param {Array[]} adjacencyMatrix An adjacency matrix.\n     * @returns {number[][]} Connected components as arrays of vertex ids.\n     */\n    static getConnectedComponents(adjacencyMatrix) {\n        let length = adjacencyMatrix.length;\n        let visited = new Array(length);\n        let components = [];\n\n        visited.fill(false);\n\n        for (let u = 0; u < length; u++) {\n            if (!visited[u]) {\n                let component = [];\n                visited[u] = true;\n                component.push(u);\n                Graph._ccGetDfs(u, visited, adjacencyMatrix, component);\n                if (component.length > 1) {\n                    components.push(component);\n                }\n            }\n        }\n\n        return components;\n    }\n\n    /**\n     * Returns the number of connected components for the graph.\n     *\n     * @param {Array[]} adjacencyMatrix An adjacency matrix.\n     * @returns {Number} The number of connected components of the supplied graph.\n     */\n    static getConnectedComponentCount(adjacencyMatrix) {\n        let length = adjacencyMatrix.length;\n        let visited = new Array(length);\n        let count = 0;\n\n        visited.fill(false);\n\n        for (let u = 0; u < length; u++) {\n            if (!visited[u]) {\n                visited[u] = true;\n                count++;\n                Graph._ccCountDfs(u, visited, adjacencyMatrix);\n            }\n        }\n\n        return count;\n    }\n\n    /**\n     * PRIVATE FUNCTION used by getConnectedComponentCount().\n     */\n    static _ccCountDfs(u, visited, adjacencyMatrix) {\n        for (let v = 0; v < adjacencyMatrix[u].length; v++) {\n            let c = adjacencyMatrix[u][v];\n\n            if (!c || visited[v] || u === v) {\n                continue;\n            }\n\n            visited[v] = true;\n            Graph._ccCountDfs(v, visited, adjacencyMatrix);\n        }\n    }\n\n    /**\n     * PRIVATE FUNCTION used by getConnectedComponents().\n     */\n    static _ccGetDfs(u, visited, adjacencyMatrix, component) {\n        for (let v = 0; v < adjacencyMatrix[u].length; v++) {\n            let c = adjacencyMatrix[u][v];\n\n            if (!c || visited[v] || u === v) {\n                continue;\n            }\n\n            visited[v] = true;\n            component.push(v);\n            Graph._ccGetDfs(v, visited, adjacencyMatrix, component);\n        }\n    }\n}\n", "// @ts-check\n\nexport default class Options {\n    /**\n     * A helper method to extend the default options with user supplied ones.\n     */\n    static extend() {\n        let extended = {};\n        let deep = false;\n        let i = 0;\n        let length = arguments.length;\n\n        if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') {\n            deep = arguments[0];\n            i++;\n        }\n\n        let merge = function(obj) {\n            for (let prop in obj) {\n                if (Object.prototype.hasOwnProperty.call(obj, prop)) {\n                    if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {\n                        extended[prop] = Options.extend(true, extended[prop], obj[prop]);\n                    }\n                    else {\n                        extended[prop] = obj[prop];\n                    }\n                }\n            }\n        };\n\n        for (; i < length; i++) {\n            let obj = arguments[i];\n            merge(obj);\n        }\n\n        return extended;\n    }\n}\n", "// A fixed-size bit vector backed by a Uint32Array.\n//\n// Used by the Vismara cycle-perception pipeline (see CycleBasis), where every\n// BitSet represents a subset of the graph's edge set: cycle vectors and\n// basis-coverage vectors all live in the same coordinate system (size = nEdges),\n// so GF(2) addition is just an XOR of the word arrays.\n\n/**\n * A fixed-size bit vector backed by a Uint32Array.\n *\n * All binary operations (`xor`, `and`, `or`, `orWith`, `isSubsetOf`) require\n * both operands to have the same `size`. `_assertSameSize` throws on a mismatch,\n * so there is no silent truncation or zero-extension of the shorter operand.\n */\nexport default class BitSet {\n    size:  number;\n    words: Uint32Array;\n\n    /**\n     * @param size Number of bits this set can hold.\n     */\n    constructor(size: number) {\n        this.size = size;\n        // wordIndex = i >>> 5\n        const numWords = size === 0 ? 0 : ((size - 1) >>> 5) + 1;\n        this.words = new Uint32Array(numWords);\n    }\n\n    set(i: number): void {\n        // word |= (1 << n), where n = the bit position within the word (i & 31)\n        this.words[i >>> 5] |= (1 << (i & 31));\n    }\n\n    get(i: number): boolean {\n        return (this.words[i >>> 5] & (1 << (i & 31))) !== 0;\n    }\n\n    /**\n     * Throws unless `other` has the same bit length as `this`. We compare `size`\n     * (bits) rather than `words.length` (32-bit chunks) because two BitSets can\n     * share a word count while differing in bit length \u2014 e.g. size 33 and size 64\n     * both round up to 2 words, but mixing them would still be a coordinate\n     * mismatch in the cycle algorithm.\n     *\n     * @param op operation name, used in the error message\n     */\n    _assertSameSize(other: BitSet, op: string): void {\n        if (this.size !== other.size) {\n            throw new Error(\n                'BitSet.' + op + ': size mismatch (' + this.size + ' vs ' + other.size + '). '\n                + 'Operands must share the same bit length.'\n            );\n        }\n    }\n\n    /** @returns a new bitset = this XOR other (merge two cycles, cancelling shared edges). */\n    xor(other: BitSet): BitSet {\n        this._assertSameSize(other, 'xor');\n        const result = new BitSet(this.size);\n        for (let i = 0; i < this.words.length; i++) {\n            result.words[i] = this.words[i] ^ other.words[i];\n        }\n        return result;\n    }\n\n    /** @returns a new bitset = this AND other (the edges shared by two cycles). */\n    and(other: BitSet): BitSet {\n        this._assertSameSize(other, 'and');\n        const result = new BitSet(this.size);\n        for (let i = 0; i < this.words.length; i++) {\n            result.words[i] = this.words[i] & other.words[i];\n        }\n        return result;\n    }\n\n    /** @returns a new bitset = this OR other (the edges covered by either). */\n    or(other: BitSet): BitSet {\n        this._assertSameSize(other, 'or');\n        const result = new BitSet(this.size);\n        for (let i = 0; i < this.words.length; i++) {\n            result.words[i] = this.words[i] | other.words[i];\n        }\n        return result;\n    }\n\n    /**\n     * Mutating union: this |= other. Used to accumulate the basis's edge coverage\n     * without allocating a new BitSet each time.\n     */\n    orWith(other: BitSet): void {\n        this._assertSameSize(other, 'orWith');\n        for (let i = 0; i < this.words.length; i++) {\n            this.words[i] |= other.words[i];\n        }\n    }\n\n    /**\n     * @returns true iff every bit set in `this` is also set in `other` (this \u2286 other).\n     * Single pass with an early exit, no allocation.\n     */\n    isSubsetOf(other: BitSet): boolean {\n        this._assertSameSize(other, 'isSubsetOf');\n        for (let i = 0; i < this.words.length; i++) {\n            // A bit set in `this` but not in `other` breaks the subset.\n            // We test `this & ~other` instead of comparing `this & other` to\n            // `this`: JS `&` returns a *signed* int32 (negative once bit 31 is\n            // set), while a Uint32Array read is unsigned, so that comparison\n            // would wrongly report a non-subset for any word with bit 31/63/...\n            // set. Comparing against 0 sidesteps the signedness entirely.\n            if ((this.words[i] & ~other.words[i]) !== 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /** @returns a deep copy. */\n    clone(): BitSet {\n        const result = new BitSet(this.size);\n        for (let i = 0; i < this.words.length; i++) {\n            result.words[i] = this.words[i];\n        }\n        return result;\n    }\n\n    /** @returns true iff no bits are set. */\n    isEmpty(): boolean {\n        for (let i = 0; i < this.words.length; i++) {\n            if (this.words[i] !== 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /** @returns the number of set bits (population count). */\n    popcount(): number {\n        let count = 0;\n        for (let i = 0; i < this.words.length; i++) {\n            // Brian Kernighan's bit count: clearing the lowest set bit each step\n            // runs once per set bit. Kept inline because this is a hot loop.\n            let word = this.words[i];\n            while (word !== 0) {\n                word &= (word - 1);\n                count++;\n            }\n        }\n        return count;\n    }\n\n    /**\n     * @returns the count of leading zeros: the number of zero bits above the\n     * highest set bit (mirrors `Math.clz32`). Returns `size` when no bit is set.\n     * The \"index of the highest set bit + 1\" value is `size - clz()`.\n     */\n    clz(): number {\n        for (let i = this.words.length - 1; i >= 0; i--) {\n            if (this.words[i] !== 0) {\n                const highestSetBit = i * 32 + (31 - Math.clz32(this.words[i]));\n                return this.size - 1 - highestSetBit;\n            }\n        }\n        return this.size;\n    }\n}\n", "//\n// Vismara-based cycle perception for molecular graphs.\n//\n// Reference: P. Vismara, \"Union of all the minimum cycle bases of a graph\",\n//            The Electronic Journal of Combinatorics, Vol. 4, No. 1, R9, 1997.\n// This is an independent implementation written directly from Vismara's paper.\n\nimport BitSet from './BitSet';\n\nconst MAX_INT = 0x7FFFFFFF; // not reachable (for BFS)\n\n/** A cycle: a closed vertex path together with its edge-set bit vector. */\ntype Cycle = {path: number[], edgeVector: BitSet};\n\n/**\n * A node in a BFS route tree, used to reconstruct shortest paths lazily: a\n * `source` root, a `seq` step that points back at its parent, or a `branch`\n * recording two equally-short alternative routes to the same vertex.\n */\ntype SourceRoute = {type: 'source', vertex: number};\ntype SeqRoute = {type: 'seq', parent: Route, vertex: number, dist: number};\ntype BranchRoute = {type: 'branch', left: Route, right: Route};\ntype Route = SourceRoute | SeqRoute | BranchRoute;\n\n/** Distances from a BFS source plus lazy path reconstructors (see shortestPaths). */\nexport interface ShortestPaths {\n    distTo:   Int32Array\n    nPathsTo: Int32Array\n    precedes: boolean[]\n    pathTo(end: number): number[]\n    pathsTo(end: number): number[][]\n    isPrecedingPathTo(end: number): boolean\n}\n\n/**\n * BFS shortest paths from a single source vertex, with the vertex-ordering\n * constraint for Vismara's algorithm.\n *\n * Routes are stored as a tree of Route nodes for lazy path reconstruction\n * (source root / sequential step / branch).\n *\n * @param graph adjacency list\n * @param start source vertex\n * @param limit maximum BFS depth\n * @param ordering vertex ordering (\u03C0)\n */\nexport function shortestPaths(graph: number[][], start: number, limit: number, ordering: number[]): ShortestPaths {\n    const n = graph.length;\n    const distTo = new Int32Array(n).fill(MAX_INT);\n    const precedes = new Array(n).fill(false);\n    const routeTo: (Route | null)[] = new Array(n).fill(null);\n    const nPathsTo = new Int32Array(n);\n\n    distTo[start] = 0;\n    precedes[start] = true;\n    nPathsTo[start] = 1;\n    routeTo[start] = {type: 'source', vertex: start};\n\n    const queue = [start];\n    let qLen = 1; // qLen method is faster than queue.shift() method (O(n))\n\n    for (let i = 0; i < qLen; i++) {\n        const v = queue[i];\n        const dist = distTo[v] + 1;\n        if (dist > limit) continue;\n\n        // iterate through v neighbors\n        for (let k = 0; k < graph[v].length; k++) {\n            const w = graph[v][k];\n\n            if (dist < distTo[w]) { // if shortest path append\n                distTo[w] = dist;\n                // each seq stores v (which vertex), dist (vertex distance from start), parent (route)\n                routeTo[w] = {type:   'seq',\n                    parent: routeTo[v]!,  // point at route to v and not v itself. necessary to walk backwards through the tree\n                    vertex: w, dist:   dist};\n                // Definition 4: check Vismara paper (is there a shortest path passing\n                // only through vertices with \u03C0 < \u03C0(r)?)\n                precedes[w] = precedes[v] && ordering[w] < ordering[start];\n                nPathsTo[w] = nPathsTo[v];\n                queue[qLen++] = w;\n            }\n            else if (dist === distTo[w]) { // if same dist (alterantive path), keep this is part of Vismara algorithm\n                // if respects pi priority  skip ties whose new path violates the \u03C0 constraint\n                if (!(precedes[v] && ordering[w] < ordering[start])) continue;\n\n                const newSeq: Route = {type: 'seq', parent: routeTo[v]!, vertex: w, dist: dist};\n\n                if (precedes[w]) {\n                    // merge: w already had a low-\u03C0 witness; record this as an alternative\n                    routeTo[w] = {type: 'branch', left: routeTo[w]!, right: newSeq};\n                    nPathsTo[w] += nPathsTo[v];\n                }\n                else {\n                    // upgrade: this is the first low-\u03C0 witness reaching w (we know because precedes was False)\n                    precedes[w] = true;\n                    routeTo[w] = newSeq;\n                    nPathsTo[w] = nPathsTo[v];\n                }\n            }\n        }\n    }\n    /**\n     * Walk a route tree backwards to one shortest path.\n     * @param route route-tree node\n     * @param len length of the path to allocate\n     */\n    function routeToPath(route: Route, len: number): number[] {\n        if (!route) return [];\n        const path = new Array(len);\n        let cur: Route = route;\n        while (cur) {\n            if (cur.type === 'source') {\n                path[0] = cur.vertex;\n                break;\n            }\n            else if (cur.type === 'seq') {\n                path[cur.dist] = cur.vertex;\n                cur = cur.parent;\n            }\n            else {\n                // branch: use left as first path\n                cur = cur.left;\n            }\n        }\n        return path;\n    }\n\n    /**\n     * Walk a route tree backwards to all shortest paths (cartesian over branches).\n     * @param route route-tree node\n     * @param len length of each path to allocate\n     */\n    function routeToPaths(route: Route, len: number): number[][] {\n        if (!route) return [];\n        if (route.type === 'source') {\n            const path = new Array(len);\n            path[0] = route.vertex;\n            return [path];\n        }\n        else if (route.type === 'seq') {\n            const parentPaths = routeToPaths(route.parent, len);\n            for (let j = 0; j < parentPaths.length; j++) {\n                parentPaths[j][route.dist] = route.vertex;\n            }\n            return parentPaths;\n        }\n        else {\n            // branch: both sides are equally short, so concatenate their paths\n            const leftPaths = routeToPaths(route.left, len);\n            const rightPaths = routeToPaths(route.right, len);\n            return leftPaths.concat(rightPaths);\n        }\n    }\n\n    return {\n        distTo:   distTo,\n        nPathsTo: nPathsTo,\n        precedes: precedes,\n        pathTo(end) {\n            if (end < 0 || end >= n || !routeTo[end]) return [];\n            return routeToPath(routeTo[end]!, distTo[end] + 1);\n        },\n        pathsTo(end) {\n            if (end < 0 || end >= n || !routeTo[end]) return [];\n            return routeToPaths(routeTo[end]!, distTo[end] + 1);\n        },\n        isPrecedingPathTo(end) {\n            return end >= 0 && end < n && precedes[end];\n        },\n    };\n}\n\n/**\n * Check if two paths from a common root only intersect at the root.\n * Paths are BFS shortest paths so vertex at index i is at distance i.\n * Used in Vismara;s Algorithm 1 Line 8\n * @param p first path\n * @param q second path\n */\nfunction singletonIntersect(p: number[], q: number[]): boolean {\n    const n = p.length;\n    for (let i = 1; i < n; i++) {\n        if (p[i] === q[i]) return false;\n    }\n    return true;\n}\n\n/**\n * translates a vertex-path representation of a cycle into a bit-vector representation\n * over the edge set, which is the form Gaussian elimination needs\n *\n * @param path vertex path where path[0] connects to path[last]\n * @param edgeIndex edge index map\n * @param nEdges total number of edges\n */\nfunction pathToEdgeVector(path: number[], edgeIndex: Map<string, number>, nEdges: number): BitSet {\n    const bs = new BitSet(nEdges);\n    const len = path.length - 1;\n    for (let i = 0; i < len; i++) {\n        const u = path[i], v = path[i + 1];\n\n        // normalize key = (u < v) ? \"u,v\" : \"v,u\" because edges are undirected,\n        // so the algorithm might traverse (0, 9) or (9, 0) depending on which way around\n        // the cycle you walk.\n        //   Normalizing to lower-vertex-first guarantees both encodings hit the same bit\n        const key = (u < v) ? u + ',' + v : v + ',' + u;\n        bs.set(edgeIndex.get(key)!);\n        // Input:  path = [9, 0, 1, 2, 3, 4, 9]    closed cycle, first==last\n        // edgeIndex = { \"0,1\":0, \"1,2\":1, \"2,3\":2, \"3,4\":3, ... }\n        // nEdges = 11\n\n        //   Process:\n        //     bs = empty BitSet of length 11\n        //     len = path.length - 1 = 6   (number of edges)\n        //     iterate i = 0..5:\n        //       i=0: u=9, v=0 \u2192 key \"0,9\"  \u2192 set bit edgeIndex[\"0,9\"]\n        //       i=1: u=0, v=1 \u2192 key \"0,1\"  \u2192 set bit edgeIndex[\"0,1\"]\n        //       ...\n        //       i=5: u=4, v=9 \u2192 key \"4,9\"  \u2192 set bit edgeIndex[\"4,9\"]\n    }\n    return bs;\n}\n\n/**\n * Index all edges in the graph. Each undirected edge (u,v) with u < v\n * gets a unique integer index.\n *\n * @param graph adjacency list\n */\nfunction indexEdges(graph: number[][]): Map<string, number> {\n    const toIndex = new Map<string, number>();\n    const n = graph.length;\n\n    for (let v = 0; v < n; v++) {\n        for (let k = 0; k < graph[v].length; k++) {\n            const w = graph[v][k];\n            // Only key each undirected edge from its lower-numbered endpoint, so\n            // every edge is seen exactly once (the adjacency list is derived from\n            // a 0/1 matrix, so there are no duplicate neighbours).\n            if (w > v) {\n                toIndex.set(v + ',' + w, toIndex.size);\n            }\n        }\n    }\n\n    return toIndex;\n}\n\n/**\n * Compute vertex ordering by degree (ascending), using counting sort.\n * \u03C0(x) < \u03C0(y) => deg(x) \u2264 deg(y).\n *\n *\n * @param graph adjacency list\n * @returns ordering[v] = rank of vertex v\n */\nexport function computeOrdering(graph: number[][]): number[] {\n    const n = graph.length;\n    let maxDeg = 0;\n    // fill() so we start from a packed (non-sparse) array; every slot is then\n    // overwritten with the vertex's rank below.\n    const order = new Array(n).fill(0);\n\n    // get max degree\n    for (let i = 0; i < n; i++) {\n        if (graph[i].length > maxDeg) maxDeg = graph[i].length;\n    }\n    // create buckets (one per degree)\n    const buckets = new Array(maxDeg + 1);\n    for (let d = 0; d <= maxDeg; d++) buckets[d] = [];\n\n    // populate buckets\n    for (let v = 0; v < n; v++) {\n        buckets[graph[v].length].push(v);\n    }\n    let rank = 0;\n    // rank\n    for (let d = 0; d <= maxDeg; d++) {\n        for (const v of buckets[d])\n            order[v] = rank++;\n    }\n    return order;\n}\n// An example of what computeOrdering is supposed to be doing:\n// let this graph be the example\n//     0\n//    / \\\n//   1--\u25002\n//   |   |\n//   3--\u25004\n\n// graph = [[1,2], [0,2,3], [0,1,4], [1,4], [2,3]] adjacency list\n// degrees: [2, 3, 3, 2, 2] (i.e number of bonds)\n// ordering = [0, 3, 4, 1, 2]  (output: rank (\u03C0))\n// first assign rank to the ones with lower degree (0, 3 and 4)\n// then assign rank by index number  (lower first) 0 -> 0; 3 -> 1; 4 -> 2\n// follow with vertex with higher degree (vertex 1 and 2)\n// assign rank again by index order (1 -> 3; 2 -> 4)\n// result vertex 0,1,2,3,4 get rank (0, 3, 4, 1, 2)\n\n/**\n * Compute the initial cycle set C'_I using Vismara's algorithm (Algorithm 1).\n *\n * @param graph adjacency list\n */\nexport function computeInitialCycles(graph: number[][]): {cycles: Map<number, Cycle[]>, edgeIndex: Map<string, number>, nEdges: number} {\n    const n = graph.length;\n    const ordering = computeOrdering(graph); // assign pi rank\n\n    // cycles grouped by length\n    const cycles = new Map<number, Cycle[]>();\n\n    const edgeIndex = indexEdges(graph);\n    const nEdges = edgeIndex.size;\n\n    const vertices = new Array(n);\n    for (let v = 0; v < n; v++) {\n        vertices[ordering[v]] = v;\n    }\n\n    function addCycle(path: number[]) {\n        const edgeVector = pathToEdgeVector(path, edgeIndex, nEdges);\n        const len = path.length - 1; // number of edges = cycle length\n        let group = cycles.get(len);\n        if (!group) {\n            group = [];\n            cycles.set(len, group);\n        }\n        group.push({path, edgeVector});\n    }\n\n    // Set 'S' (Vismara line 4): for each y, the neighbours z of y with\n    // d(r,z) + 1 == d(r,y). Allocated once and refilled per y (via sizeOfS)\n    // to avoid re-allocating inside the loop.\n    const s = new Array(n);\n\n    const first = 2; // smllest cycle is 3 vertices, we can skip first 2 ordered vertices\n\n    for (let i = first; i < n; i++) { // for all vertices\n        const r = vertices[i];\n        // compute Vr (subset of shortest paths from vertex to r)\n        // limit to n/2 is simply because the shortest path for any relevant cycle\n        // can be at most n/2  (Vismara Lemma 2)\n        const paths = shortestPaths(graph, r, Math.floor(n / 2), ordering);\n\n        // for all y /in Vr do:\n        for (let j = 0; j < i; j++) {\n            const y = vertices[j];\n            if (!paths.isPrecedingPathTo(y)) continue; // only those respecting pi order\n\n            let sizeOfS = 0;\n\n            // for all z in Vr...\n            for (let k = 0; k < graph[y].length; k++) {\n                const z = graph[y][k]; // ...such that z is adjacent to y (i.e. neighbor)\n                if (!paths.isPrecedingPathTo(z)) continue;\n\n                // if d(r,z) + d(z,y) = d(r,y) (line 6)\n                // here we write d(z,y) instead of w(z,y) because weight is always 1 for our case\n                const distToZ = paths.distTo[z];\n                const distToY = paths.distTo[y];\n                // d(z,y) = 1 because they are adjacent\n\n                if (distToZ + 1 === distToY) {\n                    s[sizeOfS++] = z;\n                }\n                // elseif d(r, z) != d(r, y) + d(z, y) and \u03C0(z) < \u03C0(y) and P(r, y) \u2229 P(r, z) = {r}\n                // Line 8\n                else if (distToZ === distToY && ordering[z] < ordering[y]) {\n                    const pathToY = paths.pathTo(y);\n                    const pathToZ = paths.pathTo(z);\n                    if (singletonIntersect(pathToZ, pathToY)) {\n                        // odd cycle: [r..y] then reversed [r..z], closed by the y-z edge\n                        addCycle(pathToY.concat(pathToZ.reverse()));\n                    }\n                }\n            }\n\n            // Check pairs in s for even cycles\n            for (let k = 0; k < sizeOfS; k++) {\n                for (let l = k + 1; l < sizeOfS; l++) {\n                    const pathToP = paths.pathTo(s[k]);\n                    const pathToQ = paths.pathTo(s[l]);\n                    if (singletonIntersect(pathToP, pathToQ)) {\n                        // even cycle: [r..p] then y then reversed [r..q]\n                        addCycle(pathToP.concat([y], pathToQ.reverse()));\n                    }\n                }\n            }\n        }\n    }\n\n    return {cycles, edgeIndex, nEdges};\n}\n\n// BitMatrix (GF(2) elimination)\n// GF(2) is essentially the same as the Gauss-Jordan over the real numbers from linear algebra\n// The algorithm can be summarize as\n//   for each column x = 0, 1, 2, ... (the pivot column):\n//       find the first row at-or-below current row y whose bit x is 1\n//       if none: move to next column, same y\n//       else:    swap that row up to position y (it's the pivot row)\n//                for every row below y that has bit x set:  row ^= pivot_row\n//                y += 1   (move to next row)\n\n// BitMatrix helps to keep independence between cycle basis. Let's say we already have\n// two bases c1 and c2 and now Vismara hands a candidate cycle c3\n// question becomes if we should add c3 to the basis. Only if it's linearly independent of {c1, c2}.\n// again, very similar to linear algebra with vector basis\n// to see what cycle basis are check vismara page 5\n//\n\n// For example for graph formed by two fused triangles\n//   0 --- 1\n//   | \\   |\n//   |   \\ |\n//   2  -- 3\n//  edges: e0=(0,1), e1=(0,2), e2=(0,3), e3=(1,3), e4=(2,3)\n// The bit matrix is\n//                     e0 e1 e2 e3 e4   original index\n//   row 0 (c1):        1  0  1  1  0   j=0\n//   row 1 (c2):        0  1  1  0  1   j=1\n//   row 2 (c3):        1  1  0  1  1   j=2\n// rank=2 and by GF(2) elimination we realize c3 is dependent\n\nexport class BitMatrix {\n    _n:       number;\n    _max:     number;\n    _rows:    BitSet[];\n    _indices: Int32Array;\n    _m:       number;\n\n    /**\n     * @param columns number of columns (edges)\n     * @param maxRows maximum number of rows (cycles)\n     */\n    constructor(columns: number, maxRows: number) {\n        this._n = columns;\n        this._max = maxRows;\n        this._rows = new Array(maxRows);\n        this._indices = new Int32Array(maxRows);\n        this._m = 0;\n    }\n\n    /** @param row a cycle's edge vector */\n    add(row: BitSet) {\n        this._rows[this._m] = row;\n        // we need _indices to keep track after swaping rows\n        // otherwise we cannot track if our added basis is eliminiated\n        // or not\n        this._indices[this._m] = this._m;\n        this._m++;\n    }\n\n    /**\n     * Swap rows i and j, tracking original indices.\n     * @param i row index\n     * @param j row index\n     */\n    swap(i: number, j: number) {\n        const tmpRow = this._rows[i];\n        const tmpIdx = this._indices[i];\n        this._rows[i] = this._rows[j];\n        this._indices[i] = this._indices[j];\n        this._rows[j] = tmpRow;\n        this._indices[j] = tmpIdx;\n    }\n\n    /**\n     * Find current position of original row j.\n     * @param j original row index\n     */\n    _rowIndex(j: number): number {\n        for (let i = 0; i < this._m; i++) {\n            if (this._indices[i] === j) return i;\n        }\n        return -1;\n    }\n\n    /**\n     * Check if the row originally added at index j was eliminated to zero.\n     * @param j original row index\n     */\n    eliminated(j: number): boolean {\n        return this._rows[this._rowIndex(j)].isEmpty();\n    }\n\n    /**\n     * Gaussian elimination over GF(2). Returns the rank.\n     */\n    eliminate(): number {\n        return this._eliminate(0, 0);\n    }\n\n    /**\n     * @param x column index\n     * @param y row index\n     * @returns rank\n     */\n    _eliminate(x: number, y: number): number {\n        while (x < this._n && y < this._m) {\n            // Find first row >= y with bit x set\n            let i = -1;\n            for (let j = y; j < this._m; j++) {\n                if (this._rows[j].get(x)) {\n                    i = j;\n                    break;\n                }\n            }\n\n            if (i < 0) return this._eliminate(x + 1, y);\n\n            if (i !== y) this.swap(i, y);\n\n            // XOR row y into all rows below that have bit x set\n            for (let j = y + 1; j < this._m; j++) {\n                if (this._rows[j].get(x)) {\n                    this._rows[j] = this._rows[j].xor(this._rows[y]);\n                }\n            }\n\n            y++;\n        }\n        return y;\n    }\n}\n\n// sort cycles by lenght, ascending\n// for each cycle c (in that order):\n//  if c is independent of the basis so far:\n//    add c\n// if basis is full (E - V + 1):\n//    stop\nexport class GreedyBasis {\n    _members:      Cycle[];\n    _edgesOfBasis: BitSet;\n    _nEdges:       number;\n\n    /**\n     * @param nEdges number of edges in the graph\n     */\n    constructor(nEdges: number) {\n        this._members = [];\n        this._edgesOfBasis = new BitSet(nEdges);\n        this._nEdges = nEdges;\n    }\n\n    /** @param cycle a cycle to add to the basis */\n    add(cycle: Cycle) {\n        this._members.push(cycle);\n        // Add what edges are covered by the basis so far\n        this._edgesOfBasis.orWith(cycle.edgeVector); // orWith is a union\n    }\n\n    members(): Cycle[] {\n        return this._members;\n    }\n\n    size(): number {\n        return this._members.length;\n    }\n\n    /**\n     * Check whether all edges of the cycle are already covered by the basis.\n     * @param cycle candidate cycle\n     */\n    isSubsetOfBasis(cycle: Cycle): boolean {\n        // c.edges subset of edgesOfBasis? single pass with early-exit, no allocation.\n        return cycle.edgeVector.isSubsetOf(this._edgesOfBasis);\n    }\n\n    /**\n     * Full independence check via GF(2) Gaussian elimination.\n     * @param candidate candidate cycle\n     */\n    isIndependent(candidate: Cycle): boolean {\n        // cheap path\n        // if the candidate has any edge outside union, it cannot possibly be\n        // a XOR  (addition) of basis cycles (because XOR can never invent an edge that none of the basis has)\n        // So it's independent - faster than doing the full GF(2) eliminitatino which requires building the matrix etc.\n\n        if (this._members.length === 0 || !this.isSubsetOfBasis(candidate)) {\n            return true;\n        }\n\n        // expensive path, check via GF(2)\n        const matrix = new BitMatrix(this._nEdges, this._members.length + 1);\n        for (let i = 0; i < this._members.length; i++) {\n            matrix.add(this._members[i].edgeVector.clone());\n        }\n        matrix.add(candidate.edgeVector.clone());\n        matrix.eliminate();\n        // After eliminate(), check whether the row originally added at index members.length got removed\n        // If it did, candidate is dependent. If not, independent.\n\n        return !matrix.eliminated(this._members.length); // check last row\n        // it is important to add candidate last because that way we now its index is members length!\n    }\n}\n\n// ----------- Public API ----------\n// Compute Minicum Cycle Basis and RelevantCycle\n// To understand why we need both see end of this file\n\n/**\n * Compute the Minimum Cycle Basis (MCB a.k.a SSSR) of a graph.\n * Returns exactly E - V + 1 linearly independent cycles per connected component.\n *\n * This is Horton's algorithm (1987) which extracts a cycle basis from an inital set of cycles (C_I)\n * which we get from Algorithm 1 (computeInitialCycles)\n * @param adjList adjacency list (adjList[v] = array of neighbor vertex indices)\n * @returns array of cycles, each cycle is a closed vertex path [v0, v1, ..., vn, v0]\n */\nexport function minimumCycleBasis(adjList: number[][]): number[][] {\n    // MCB (\"smallest set of smallest rings\", SSSR):\n    // give me ANY linearly independent set of nSssr = E - V + 1 cycles,\n    // picked greedily by length. arbitrary ties are broken by input order.\n\n    const n = adjList.length;\n    if (n < 3) return []; // minimum cycle is 3\n\n    const {cycles: initialCycles, nEdges} = computeInitialCycles(adjList);\n    const basis = new GreedyBasis(nEdges);\n\n    // Compute the expected number of independent cycles\n    const nSssr = nEdges - n + 1;\n    // patching nSssr for disconnected graphs (is done in SSSR.js)\n    // this assumes connected graph,\n    // for a graph with C connected components its nEdges - n + C\n\n    // sort initialCycles by lengths in ascending order (shortest cycles first)\n    const sortedCycles = [...initialCycles.keys()].sort((a, b) => a - b);\n\n    for (let li = 0; li < sortedCycles.length; li++) {\n        const group = initialCycles.get(sortedCycles[li])!;\n\n        for (let ci = 0; ci < group.length; ci++) {\n            if (basis.size() >= nSssr)\n                break;\n            if (basis.isIndependent(group[ci])) {\n                basis.add(group[ci]);\n            }\n        }\n    }\n\n    return basis.members().map(c => c.path);\n}\n\n/**\n * Compute the Relevant Cycles of a graph: i.e. the union of all possible MCBs.\n * This set is unique and contains all minimum-weight cycles needed for\n * unambiguous depiction of symmetric ring systems.\n *\n * @param adjList adjacency list\n * @returns array of cycles, each cycle is a closed vertex path [v0, v1, ..., vn, v0]\n */\nexport function relevantCycles(adjList: number[][]): number[][] {\n    // RC (\"relevant cycles\"):\n    // give me the UNION of all MCBs i.e. every cycle that some MCB\n    // could legitimately have chosen. always unique, always a superset\n    // of any single MCB.\n\n    const n = adjList.length;\n    if (n < 3) return []; // minimum cycle is 3\n\n    const {cycles: initialCycles, nEdges} = computeInitialCycles(adjList);\n    const basis = new GreedyBasis(nEdges);\n\n    // accumulate the relevant cycles separately;\n    const relevant: number[][] = [];\n\n    // sort initialCycles by lengths in ascending order (shortest cycles first).\n    // RC, like MCB, is greedy in length\n    const sortedCycles = [...initialCycles.keys()].sort((a, b) => a - b);\n\n    // process one length class at a time. the key invariant: when we test a\n    // cycle C of length L, the basis must contain ONLY cycles strictly shorter\n    // than L. that is what makes \"independent\" mean \"not a sum of strictly\n    // shorter cycles\"  which is the definition of relevant. see vismara\n    for (let li = 0; li < sortedCycles.length; li++) {\n        const group = initialCycles.get(sortedCycles[li])!;\n\n        // pending = the cycles of THIS length that turn out to be relevant.\n        // we collect them all before touching the basis, because we do NOT\n        // want adding the first relevant cycle of length L to disqualify a\n        // sibling cycle of the same length L. equal-length cycles can be\n        // pairwise dependent on each other modulo shorter cycles, and RC\n        // keeps them all (this is exactly where RC differs from MCB\n        // MCB picks one while RC keeps both).\n        const pending: Cycle[] = [];\n\n        for (let ci = 0; ci < group.length; ci++) {\n            // independence is checked against the basis as it stands right\n            // now, which only contains cycles of length < L. so this is\n            // really asking: \"is C expressible as a XOR-sum of strictly\n            // shorter cycles?\" if not C is relevant.\n            // note: NO early-exit on basis.size() here. unlike MCB we don't\n            // know the final size of RC up front (it can exceed nSssr), and\n            // stopping early would silently drop relevant cycles.\n            if (basis.isIndependent(group[ci])) {\n                pending.push(group[ci]);\n                relevant.push(group[ci].path);\n            }\n        }\n\n        // bulk-commit AFTER the length class is fully scanned. now the basis\n        // grows by all relevant cycles of length L at once, so that the next\n        // length class (L+1) sees them as \"shorter\". any subsequent same-length\n        // dependencies among them are irrelevant and we already decided they\n        // were all relevant against the strictly-shorter basis, which is the\n        // only check that matters for RC.\n        for (let ci = 0; ci < pending.length; ci++) {\n            basis.add(pending[ci]);\n        }\n    }\n\n    return relevant;\n}\n\n/**\n * Convert an adjacency matrix to an adjacency list.\n *\n * @param matrix square adjacency matrix\n * @returns adjacency list\n */\nexport function matrixToAdjList(matrix: number[][]): number[][] {\n    const n = matrix.length;\n    const adj: number[][] = new Array(n);\n    for (let i = 0; i < n; i++) {\n        adj[i] = [];\n        for (let j = 0; j < n; j++) {\n            if (matrix[i][j] === 1) adj[i].push(j);\n        }\n    }\n    return adj;\n}\n", "// SSSR.js is the adapter layer between DrawerBase and CycleBasis (Vismara's algortihm) instead of\n// a full implementation on its own (previously was Floyd-Warshall algorihtm).\n\n// In short, CycleBasis.js takes an adjacency list indexed for one connected component and returns\n// cycles as closed vertex paths [v0, v1, ..., vn, V0].\n// This is essentially a shim and could probably be dropped. Since DrawerBase calls SSSR.getRings\n// in a dozen places keeping this is probably more stable for now and thus avoiding changing those callers\n// TODO: Remove complete SSSR.js and adapt DrawerBase\n\n// To understand why we need both getRings(MCB) and getRingsForLayout(Relevant Cycles) check\n// `CycleBasis.js`\n\n// @ts-check\nimport Graph from './Graph';\nimport {minimumCycleBasis, relevantCycles, matrixToAdjList} from './CycleBasis';\n\n/** A class encapsulating the functionality to find the smallest set of smallest rings in a graph. */\nexport default class SSSR {\n    /**\n     * Returns an array containing arrays, each representing a ring from the\n     * minimum cycle basis (MCB / SSSR) of the graph.\n     *\n     * @param {Graph} graph A Graph object.\n     * @param {Boolean} [_experimental=false] Whether or not to use experimental SSSR (UNUSED).\n     * @returns {Array[]} An array containing arrays, each representing a ring.\n     */\n    static getRings(graph, _experimental = false) {\n        return SSSR._findRings(graph, false);\n    }\n\n    /**\n     * Returns a layout-oriented ring set (relevant cycles).\n     *\n     * This is the union of all minimum cycle bases \u2014 a unique, complete set of\n     * minimum-weight cycles that includes all symmetric faces. Use this for\n     * depiction; use getRings() for chemistry (aromaticity, ring membership).\n     *\n     * @param {Graph} graph A Graph object.\n     * @param {Boolean} [_experimental=false] Whether or not to use experimental SSSR (UNUSED).\n     * @returns {Array[]} An array containing arrays, each representing a ring.\n     */\n    static getRingsForLayout(graph, _experimental = false) {\n        return SSSR._findRings(graph, true);\n    }\n\n    /**\n     * Internal ring finder shared by getRings and getRingsForLayout.\n     *\n     * @param {Graph} graph A Graph object.\n     * @param {Boolean} forLayout If true, return relevant cycles; otherwise MCB.\n     * @returns {Array[]} An array of rings (each ring is an array of vertex ids).\n     */\n    static _findRings(graph, forLayout) {\n        // Get the adjacency matrix of the graph with all bridges removed\n        // this returns one set per connected component (e.g. 1 for benzene and 2 for [Na+].[Cl-])\n        let adjacencyMatrix = graph.getComponentsAdjacencyMatrix();\n        if (adjacencyMatrix.length === 0) {\n            return [];\n        }\n\n        // Note: We get the matrix and not a list because that's what Graph.js exposes\n        // if (or when) we rewrite Graph we could change it as this code is\n        // essentially transforming matrix -> list\n        let connectedComponents = Graph.getConnectedComponents(adjacencyMatrix);\n        let rings = [];\n\n        for (let i = 0; i < connectedComponents.length; i++) {\n            let connectedComponent = connectedComponents[i];\n            // extracts kxk submatrix for just the k vertices in i component\n            // the index will be local (0 to N) and not global vertex IDs\n            // this becomes relevant later on because DrawerBase cosumes global vertex Ids\n            let ccAdjacencyMatrix = graph.getSubgraphAdjacencyMatrix([...connectedComponent]);\n\n            // Convert adjacency matrix to adjacency list for Vismara algorithm\n            // (neighbor list per vertex)\n            let adjList = matrixToAdjList(ccAdjacencyMatrix);\n\n            // Run the appropriate cycle finder\n            let cyclePaths = forLayout\n                ? relevantCycles(adjList)\n                : minimumCycleBasis(adjList);\n\n            // Convert closed paths to vertex ID arrays, mapping local\n            // component indices back to global vertex IDs (DrawerBase needs it)\n            for (let j = 0; j < cyclePaths.length; j++) {\n                let path = cyclePaths[j];\n                // path is closed: [v0, v1, ..., vn, v0]. Extract unique vertices.\n                // path is closed because Vismara needs it\n                let ring = [];\n                for (let k = 0; k < path.length - 1; k++) {\n                    ring.push(connectedComponent[path[k]]);\n                }\n                rings.push(ring);\n            }\n        }\n\n        return rings;\n    }\n\n    /**\n     * Creates a printable string from a matrix (2D array).\n     *\n     * @param {Array[]} matrix A 2D array.\n     * @returns {String} A string representing the matrix.\n     */\n    static matrixToString(matrix) {\n        let str = '';\n\n        for (let i = 0; i < matrix.length; i++) {\n            for (let j = 0; j < matrix[i].length; j++) {\n                str += matrix[i][j] + ' ';\n            }\n\n            str += '\\n';\n        }\n\n        return str;\n    }\n\n    /**\n     * Checks whether or not two sets are equal (contain the same elements).\n     *\n     * @param {Set<Number>} setA A set.\n     * @param {Set<Number>} setB A set.\n     * @returns {Boolean} A boolean indicating whether or not the two sets are equal.\n     */\n    static areSetsEqual(setA, setB) {\n        if (setA.size !== setB.size) {\n            return false;\n        }\n\n        for (let element of setA) {\n            if (!setB.has(element)) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Checks whether or not a set (setA) is a superset of another set (setB).\n     *\n     * @param {Set<Number>} setA A set.\n     * @param {Set<Number>} setB A set.\n     * @returns {Boolean} A boolean indicating whether or not setB is a superset of setA.\n     */\n    static isSupersetOf(setA, setB) {\n        for (let element of setB) {\n            if (!setA.has(element)) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n}\n", "// @ts-check\nimport ArrayHelper    from './ArrayHelper';\nimport Atom           from './Atom';\nimport CanvasWrapper  from './CanvasWrapper';\nimport CIP            from './CIP';\nimport Edge           from './Edge';\nimport Graph          from './Graph';\nimport Line           from './Line';\nimport MathHelper     from './MathHelper';\nimport Options        from './Options';\nimport Ring           from './Ring';\nimport RingConnection from './RingConnection';\nimport SSSR           from './SSSR';\nimport ThemeManager   from './ThemeManager';\nimport Vector2        from './Vector2';\nimport Vertex         from './Vertex';\n\n/**\n * The main class of the application representing the smiles drawer\n *\n * @property {Graph} graph The graph associated with this SmilesDrawer.Drawer instance.\n * @property {Number} ringIdCounter An internal counter to keep track of ring ids.\n * @property {Number} ringConnectionIdCounter An internal counter to keep track of ring connection ids.\n * @property {CanvasWrapper} canvasWrapper The CanvasWrapper associated with this SmilesDrawer.Drawer instance.\n * @property {Number} totalOverlapScore The current internal total overlap score.\n * @property {Object} defaultOptions The default options.\n * @property {Object} opts The merged options.\n * @property {Object} theme The current theme.\n */\nexport default class DrawerBase {\n    /**\n     * The constructor for the class SmilesDrawer.\n     *\n     * @param {Object} options An object containing custom values for different options. It is merged with the default options.\n     */\n    constructor(options) {\n        this.graph = null;\n        this.doubleBondConfigCount = 0;\n        this.doubleBondConfig = null;\n        this.ringIdCounter = 0;\n        this.ringConnectionIdCounter = 0;\n        this.canvasWrapper = null;\n        this.totalOverlapScore = 0;\n\n        this.defaultOptions = {\n            width:                       500,\n            height:                      500,\n            scale:                       0.0,\n            bondThickness:               1.0,\n            bondLength:                  30,\n            shortBondLength:             0.8,\n            bondSpacing:                 0.17 * 30,\n            atomVisualization:           'default',\n            isomeric:                    true,\n            debug:                       false,\n            terminalCarbons:             false,\n            showCarbons:                 'default',\n            explicitHydrogens:           true,\n            overlapSensitivity:          0.42,\n            overlapResolutionIterations: 1,\n            compactDrawing:              true,\n            fontFamily:                  'Arial, Helvetica, sans-serif',\n            fontSizeLarge:               11,\n            fontSizeSmall:               3,\n            padding:                     10.0,\n            experimentalSSSR:            false,\n            experimentalWeights:         false,\n            kkThreshold:                 0.1,\n            kkInnerThreshold:            0.1,\n            kkMaxIteration:              20000,\n            kkMaxInnerIteration:         50,\n            kkMaxEnergy:                 1e9,\n\n            weights: {\n                colormap:          null,\n                additionalPadding: 20.0,\n                sigma:             10,\n                interval:          0.0,\n                opacity:           1.0,\n            },\n\n            themes: {\n                'dark': {\n                    FOREGROUND: '#ffffff',\n                    BACKGROUND: '#141414',\n\n                    C:  '#ffffff',\n                    O:  '#e74c3c',\n                    N:  '#3498db',\n                    F:  '#27ae60',\n                    CL: '#16a085',\n                    BR: '#d35400',\n                    I:  '#8e44ad',\n                    P:  '#d35400',\n                    S:  '#f1c40f',\n                    B:  '#e67e22',\n                    SI: '#e67e22',\n                    H:  '#aaaaaa',\n                },\n                'light': {\n                    FOREGROUND: '#222222',\n                    BACKGROUND: '#ffffff',\n\n                    C:  '#222222',\n                    O:  '#e74c3c',\n                    N:  '#3498db',\n                    F:  '#27ae60',\n                    CL: '#16a085',\n                    BR: '#d35400',\n                    I:  '#8e44ad',\n                    P:  '#d35400',\n                    S:  '#f1c40f',\n                    B:  '#e67e22',\n                    SI: '#e67e22',\n                    H:  '#666666',\n                },\n                'oldschool': {\n                    FOREGROUND: '#000000',\n                    BACKGROUND: '#ffffff',\n\n                    C:  '#000000',\n                    O:  '#000000',\n                    N:  '#000000',\n                    F:  '#000000',\n                    CL: '#000000',\n                    BR: '#000000',\n                    I:  '#000000',\n                    P:  '#000000',\n                    S:  '#000000',\n                    B:  '#000000',\n                    SI: '#000000',\n                    H:  '#000000',\n                },\n                'solarized': {\n                    FOREGROUND: '#586e75',\n                    BACKGROUND: '#eee8d5',\n\n                    C:  '#586e75',\n                    O:  '#dc322f',\n                    N:  '#268bd2',\n                    F:  '#859900',\n                    CL: '#16a085',\n                    BR: '#cb4b16',\n                    I:  '#6c71c4',\n                    P:  '#d33682',\n                    S:  '#b58900',\n                    B:  '#2aa198',\n                    SI: '#2aa198',\n                    H:  '#657b83',\n                },\n                'solarized-dark': {\n                    FOREGROUND: '#93a1a1',\n                    BACKGROUND: '#073642',\n\n                    C:  '#93a1a1',\n                    O:  '#dc322f',\n                    N:  '#268bd2',\n                    F:  '#859900',\n                    CL: '#16a085',\n                    BR: '#cb4b16',\n                    I:  '#6c71c4',\n                    P:  '#d33682',\n                    S:  '#b58900',\n                    B:  '#2aa198',\n                    SI: '#2aa198',\n                    H:  '#839496',\n                },\n                'matrix': {\n                    FOREGROUND: '#678c61',\n                    BACKGROUND: '#ffffff',\n\n                    C:  '#678c61',\n                    O:  '#2fc079',\n                    N:  '#4f7e7e',\n                    F:  '#90d762',\n                    CL: '#82d967',\n                    BR: '#23755a',\n                    I:  '#409931',\n                    P:  '#c1ff8a',\n                    S:  '#faff00',\n                    B:  '#50b45a',\n                    SI: '#409931',\n                    H:  '#426644',\n                },\n                'github': {\n                    FOREGROUND: '#24292f',\n                    BACKGROUND: '#ffffff',\n\n                    C:  '#24292f',\n                    O:  '#cf222e',\n                    N:  '#0969da',\n                    F:  '#2da44e',\n                    CL: '#6fdd8b',\n                    BR: '#bc4c00',\n                    I:  '#8250df',\n                    P:  '#bf3989',\n                    S:  '#d4a72c',\n                    B:  '#fb8f44',\n                    SI: '#bc4c00',\n                    H:  '#57606a',\n                },\n                'carbon': {\n                    FOREGROUND: '#161616',\n                    BACKGROUND: '#ffffff',\n\n                    C:  '#161616',\n                    O:  '#da1e28',\n                    N:  '#0f62fe',\n                    F:  '#198038',\n                    CL: '#007d79',\n                    BR: '#fa4d56',\n                    I:  '#8a3ffc',\n                    P:  '#ff832b',\n                    S:  '#f1c21b',\n                    B:  '#8a3800',\n                    SI: '#e67e22',\n                    H:  '#525252',\n                },\n                'cyberpunk': {\n                    FOREGROUND: '#ea00d9',\n                    BACKGROUND: '#ffffff',\n\n                    C:  '#ea00d9',\n                    O:  '#ff3131',\n                    N:  '#0abdc6',\n                    F:  '#00ff9f',\n                    CL: '#00fe00',\n                    BR: '#fe9f20',\n                    I:  '#ff00ff',\n                    P:  '#fe7f00',\n                    S:  '#fcee0c',\n                    B:  '#ff00ff',\n                    SI: '#ffffff',\n                    H:  '#913cb1',\n                },\n                'gruvbox': {\n                    FOREGROUND: '#665c54',\n                    BACKGROUND: '#fbf1c7',\n\n                    C:  '#665c54',\n                    O:  '#cc241d',\n                    N:  '#458588',\n                    F:  '#98971a',\n                    CL: '#79740e',\n                    BR: '#d65d0e',\n                    I:  '#b16286',\n                    P:  '#af3a03',\n                    S:  '#d79921',\n                    B:  '#689d6a',\n                    SI: '#427b58',\n                    H:  '#7c6f64',\n                },\n                'gruvbox-dark': {\n                    FOREGROUND: '#ebdbb2',\n                    BACKGROUND: '#282828',\n\n                    C:  '#ebdbb2',\n                    O:  '#cc241d',\n                    N:  '#458588',\n                    F:  '#98971a',\n                    CL: '#b8bb26',\n                    BR: '#d65d0e',\n                    I:  '#b16286',\n                    P:  '#fe8019',\n                    S:  '#d79921',\n                    B:  '#8ec07c',\n                    SI: '#83a598',\n                    H:  '#bdae93',\n                },\n                'custom': {\n                    FOREGROUND: '#222222',\n                    BACKGROUND: '#ffffff',\n\n                    C:  '#222222',\n                    O:  '#e74c3c',\n                    N:  '#3498db',\n                    F:  '#27ae60',\n                    CL: '#16a085',\n                    BR: '#d35400',\n                    I:  '#8e44ad',\n                    P:  '#d35400',\n                    S:  '#f1c40f',\n                    B:  '#e67e22',\n                    SI: '#e67e22',\n                    H:  '#666666',\n                },\n            },\n        };\n\n        this.opts = Options.extend(true, this.defaultOptions, options);\n\n        const allowedShowCarbons = ['none', 'default', 'terminal', 'acyclic', 'all'];\n        if (allowedShowCarbons.indexOf(this.opts.showCarbons) === -1) {\n            this.opts.showCarbons = 'default';\n        }\n\n        this.opts.halfBondSpacing = this.opts.bondSpacing / 2.0;\n        this.opts.bondLengthSq = this.opts.bondLength * this.opts.bondLength;\n        this.opts.halfFontSizeLarge = this.opts.fontSizeLarge / 2.0;\n        this.opts.quarterFontSizeLarge = this.opts.fontSizeLarge / 4.0;\n        this.opts.fifthFontSizeSmall = this.opts.fontSizeSmall / 5.0;\n\n        // Set the default theme.\n        this.theme = this.opts.themes.dark;\n    }\n\n    /**\n     * Resolves carbon label display mode, including legacy `terminalCarbons` when `showCarbons` is `'default'`.\n     *\n     * @param {Object} opts Merged drawer options.\n     * @returns {'none'|'default'|'terminal'|'acyclic'|'all'}\n     */\n    static getEffectiveShowCarbonsMode(opts) {\n        const allowed = ['none', 'default', 'terminal', 'acyclic', 'all'];\n        let mode = opts.showCarbons;\n        if (mode === undefined || mode === null || allowed.indexOf(mode) === -1) {\n            mode = 'default';\n        }\n        if (mode === 'default' && opts.terminalCarbons) {\n            return 'terminal';\n        }\n        return mode;\n    }\n\n    /**\n     * Draws the parsed smiles data to a canvas element.\n     *\n     * @param {Object} data The tree returned by the smiles parser.\n     * @param {(String|HTMLCanvasElement)} target The id of the HTML canvas element the structure is drawn to - or the element itself.\n     * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\n     * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\n     */\n    draw(data, target, themeName = 'light', infoOnly = false) {\n        this.initDraw(data, themeName, infoOnly);\n\n        if (!this.infoOnly) {\n            this.themeManager = new ThemeManager(this.opts.themes, themeName);\n            this.canvasWrapper = new CanvasWrapper(target, this.themeManager, this.opts);\n        }\n\n        if (!infoOnly) {\n            this.processGraph();\n\n            // Set the canvas to the appropriate size\n            this.canvasWrapper.scale(this.graph.vertices);\n\n            // Do the actual drawing\n            this.drawEdges(this.opts.debug);\n            this.drawVertices(this.opts.debug);\n            this.canvasWrapper.reset();\n\n            if (this.opts.debug) {\n                console.debug('DrawerBase::draw()', {\n                    graph:           this.graph,\n                    rings:           this.rings,\n                    ringConnections: this.ringConnections,\n                });\n            }\n        }\n    }\n\n    /**\n     * Returns the number of rings this edge is a part of.\n     *\n     * @param {Number} edgeId The id of an edge.\n     * @returns {Number} The number of rings the provided edge is part of.\n     */\n    edgeRingCount(edgeId) {\n        let edge = this.graph.edges[edgeId];\n        let a = this.graph.vertices[edge.sourceId];\n        let b = this.graph.vertices[edge.targetId];\n\n        return Math.min(a.value.rings.length, b.value.rings.length);\n    }\n\n    /**\n     * Returns an array containing the bridged rings associated with this  molecule.\n     *\n     * @returns {Ring[]} An array containing all bridged rings associated with this molecule.\n     */\n    getBridgedRings() {\n        return this.rings.filter(ring => ring.isBridged);\n    }\n\n    /**\n     * Returns an array containing all fused rings associated with this molecule.\n     *\n     * @returns {Ring[]} An array containing all fused rings associated with this molecule.\n     */\n    getFusedRings() {\n        return this.rings.filter(ring => ring.isFused);\n    }\n\n    /**\n     * Returns an array containing all spiros associated with this molecule.\n     *\n     * @returns {Ring[]} An array containing all spiros associated with this molecule.\n     */\n    getSpiros() {\n        return this.rings.filter(ring => ring.isSpiro);\n    }\n\n    /**\n     * Returns a string containing a semicolon and new-line separated list of ring properties: Id; Members Count; Neighbours Count; IsSpiro; IsFused; IsBridged; Ring Count (subrings of bridged rings)\n     *\n     * @returns {String} A string as described in the method description.\n     */\n    printRingInfo() {\n        let result = '';\n        for (let i = 0; i < this.rings.length; i++) {\n            const ring = this.rings[i];\n\n            result += ring.id + ';';\n            result += ring.members.length + ';';\n            result += ring.neighbours.length + ';';\n            result += ring.isSpiro ? 'true;' : 'false;';\n            result += ring.isFused ? 'true;' : 'false;';\n            result += ring.isBridged ? 'true;' : 'false;';\n            result += ring.rings.length + ';';\n            result += '\\n';\n        }\n\n        return result;\n    }\n\n    /**\n     * Rotates the drawing to make the widest dimension horizontal.\n     */\n    rotateDrawing() {\n    // Rotate the vertices to make the molecule align horizontally\n    // Find the longest distance\n        let a = 0;\n        let b = 0;\n        let maxDist = 0;\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            let vertexA = this.graph.vertices[i];\n\n            if (!vertexA.value.isDrawn) {\n                continue;\n            }\n\n            for (let j = i + 1; j < this.graph.vertices.length; j++) {\n                let vertexB = this.graph.vertices[j];\n\n                if (!vertexB.value.isDrawn) {\n                    continue;\n                }\n\n                let dist = vertexA.position.distanceSq(vertexB.position);\n\n                if (dist > maxDist) {\n                    maxDist = dist;\n                    a = i;\n                    b = j;\n                }\n            }\n        }\n\n        let angle = -Vector2.subtract(this.graph.vertices[a].position, this.graph.vertices[b].position).angle();\n\n        if (!isNaN(angle)) {\n            // Round to 30 degrees\n            let remainder = angle % 0.523599;\n\n            // Round either up or down in 30 degree steps\n            if (remainder < 0.2617995) {\n                angle = angle - remainder;\n            }\n            else {\n                angle += 0.523599 - remainder;\n            }\n\n            // Finally, rotate everything\n            for (let i = 0; i < this.graph.vertices.length; i++) {\n                if (i === b) {\n                    continue;\n                }\n\n                this.graph.vertices[i].position.rotateAround(angle, this.graph.vertices[b].position);\n            }\n\n            for (let i = 0; i < this.rings.length; i++) {\n                this.rings[i].center.rotateAround(angle, this.graph.vertices[b].position);\n            }\n        }\n    }\n\n    /**\n     * Returns the total overlap score of the current molecule.\n     *\n     * @returns {Number} The overlap score.\n     */\n    getTotalOverlapScore() {\n        return this.totalOverlapScore;\n    }\n\n    /**\n     * Returns the ring count of the current molecule.\n     *\n     * @returns {Number} The ring count.\n     */\n    getRingCount() {\n        return this.rings.length;\n    }\n\n    /**\n     * Checks whether or not the current molecule  a bridged ring.\n     *\n     * @returns {Boolean} A boolean indicating whether or not the current molecule  a bridged ring.\n     */\n    hasBridgedRing() {\n        return this.bridgedRing;\n    }\n\n    /**\n     * Returns the number of heavy atoms (non-hydrogen) in the current molecule.\n     *\n     * @returns {Number} The heavy atom count.\n     */\n    getHeavyAtomCount() {\n        let hac = 0;\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            if (this.graph.vertices[i].value.element !== 'H') {\n                hac++;\n            }\n        }\n\n        return hac;\n    }\n\n    /**\n     * Returns the molecular formula of the loaded molecule as a string.\n     *\n     * @returns {String} The molecular formula.\n     */\n    getMolecularFormula(data = null) {\n        let molecularFormula = '';\n        let counts = new Map();\n\n        let graph = data === null ? this.graph : new Graph(data, this.opts.isomeric);\n\n        // Initialize element count\n        for (let i = 0; i < graph.vertices.length; i++) {\n            let atom = graph.vertices[i].value;\n\n            const a = counts.get(atom.element) || 0;\n            counts.set(atom.element, a + 1);\n\n            const hydrogens = atom.countImplicitHydrogens();\n            if (hydrogens) {\n                const h = counts.get('H') || 0;\n                counts.set('H', h + hydrogens);\n            }\n        }\n\n        if (counts.has('C')) {\n            let count = counts.get('C');\n            molecularFormula += 'C' + (count > 1 ? count : '');\n            counts.delete('C');\n        }\n\n        if (counts.has('H')) {\n            let count = counts.get('H');\n            molecularFormula += 'H' + (count > 1 ? count : '');\n            counts.delete('H');\n        }\n\n        // TODO: Can we not get keys from counts instead?\n        let elements = Object.keys(Atom.atomicNumbers).sort();\n\n        elements.map((e) => {\n            if (counts.has(e)) {\n                let count = counts.get(e);\n                molecularFormula += e + (count > 1 ? count : '');\n            }\n        });\n\n        return molecularFormula;\n    }\n\n    /**\n     * Returns the type of the ringbond (e.g. '=' for a double bond). The ringbond represents the break in a ring introduced when creating the MST. If the two vertices supplied as arguments are not part of a common ringbond, the method returns null.\n     *\n     * @param {Vertex} vertexA A vertex.\n     * @param {Vertex} vertexB A vertex.\n     * @returns {(String|null)} Returns the ringbond type or null, if the two supplied vertices are not connected by a ringbond.\n     */\n    getRingbondType(vertexA, vertexB) {\n    // Checks whether the two vertices are the ones connecting the ring\n    // and what the bond type should be.\n        if (vertexA.value.getRingbondCount() < 1 || vertexB.value.getRingbondCount() < 1) {\n            return null;\n        }\n\n        for (let i = 0; i < vertexA.value.ringbonds.length; i++) {\n            for (let j = 0; j < vertexB.value.ringbonds.length; j++) {\n                // if(i != j) continue;\n                if (vertexA.value.ringbonds[i].id === vertexB.value.ringbonds[j].id) {\n                    // If the bonds are equal, it doesn't matter which bond is returned.\n                    // if they are not equal, return the one that is not the default ('-')\n                    if (vertexA.value.ringbonds[i].bondType === '-') {\n                        return vertexB.value.ringbonds[j].bond;\n                    }\n                    else {\n                        return vertexA.value.ringbonds[i].bond;\n                    }\n                }\n            }\n        }\n\n        return null;\n    }\n\n    initDraw(data, themeName, infoOnly, highlight_atoms) {\n        this.data = data;\n        this.infoOnly = infoOnly;\n\n        this.ringIdCounter = 0;\n        this.ringConnectionIdCounter = 0;\n\n        this.graph = new Graph(data, this.opts.isomeric);\n        this.rings = [];\n        this.ringConnections = [];\n\n        this.originalRings = [];\n        this.originalRingConnections = [];\n\n        this.bridgedRing = false;\n\n        // Reset those, in case the previous drawn SMILES had a dangling \\ or /\n        this.doubleBondConfigCount = null;\n        this.doubleBondConfig = null;\n\n        this.highlight_atoms = highlight_atoms;\n\n        this.initRings();\n        this.initHydrogens();\n    }\n\n    processGraph() {\n        this.position();\n        this.fixDoubleBondStereo();\n\n        // Restore the ring information (removes bridged rings and replaces them with the original, multiple, rings)\n        this.restoreRingInformation();\n\n        // Atoms bonded to the same ring atom\n        this.resolvePrimaryOverlaps();\n\n        let overlapScore = this.getOverlapScore();\n\n        this.totalOverlapScore = this.getOverlapScore().total;\n\n        for (let o = 0; o < this.opts.overlapResolutionIterations; o++) {\n            for (let i = 0; i < this.graph.edges.length; i++) {\n                let edge = this.graph.edges[i];\n                if (this.isEdgeRotatable(edge)) {\n                    let subTreeDepthA = this.graph.getTreeDepth(edge.sourceId, edge.targetId);\n                    let subTreeDepthB = this.graph.getTreeDepth(edge.targetId, edge.sourceId);\n\n                    // Only rotate the shorter subtree\n                    let a = edge.targetId;\n                    let b = edge.sourceId;\n\n                    if (subTreeDepthA > subTreeDepthB) {\n                        a = edge.sourceId;\n                        b = edge.targetId;\n                    }\n\n                    let subTreeOverlap = this.getSubtreeOverlapScore(b, a, overlapScore.vertexScores);\n                    if (subTreeOverlap.value > this.opts.overlapSensitivity) {\n                        let vertexA = this.graph.vertices[a];\n                        let vertexB = this.graph.vertices[b];\n                        let neighboursB = vertexB.getNeighbours(a);\n\n                        if (neighboursB.length === 1) {\n                            let neighbour = this.graph.vertices[neighboursB[0]];\n                            let angle = neighbour.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\n\n                            this.rotateSubtree(neighbour.id, vertexB.id, angle, vertexB.position);\n                            // If the new overlap is bigger, undo change\n                            let newTotalOverlapScore = this.getOverlapScore().total;\n\n                            if (newTotalOverlapScore > this.totalOverlapScore) {\n                                this.rotateSubtree(neighbour.id, vertexB.id, -angle, vertexB.position);\n                            }\n                            else {\n                                this.totalOverlapScore = newTotalOverlapScore;\n                            }\n                        }\n                        else if (neighboursB.length === 2) {\n                            // Switch places / sides\n                            // Here we only try to rotate a simple ring substituent.\n                            // If both ends of the bond are already inside rings, this code gives up.\n                            // That means it will not help with a ring attached to another ring\n                            // layouts, which is why a later dedicated pass was added\n                            if (vertexB.value.rings.length !== 0 && vertexA.value.rings.length !== 0) {\n                                continue;\n                            }\n\n                            let neighbourA = this.graph.vertices[neighboursB[0]];\n                            let neighbourB = this.graph.vertices[neighboursB[1]];\n\n                            if (neighbourA.value.rings.length === 1 && neighbourB.value.rings.length === 1) {\n                                // We only want the case where these two neighbours belong to the same ring.\n                                // In practice, this means vertexB is acting like the attachment point for one ring.\n                                if (neighbourA.value.rings[0] !== neighbourB.value.rings[0]) {\n                                    continue;\n                                }\n\n                                let ringId = neighbourA.value.rings[0];\n                                // only handle rings that have a single\n                                // connection to the rest of the structure. If the ring has multiple exits,\n                                // rotating it here becomes much less predictable\n                                if (this.getRingExternalConnectionCount(ringId) !== 1) {\n                                    continue;\n                                }\n\n                                let bestAngle = 0.0;\n                                let bestOverlap = this.totalOverlapScore;\n                                let ring = this.getRing(ringId);\n                                let stepAngle = MathHelper.centralAngle(ring.getSize());\n                                let maxSteps = Math.max(1, Math.floor(ring.getSize() / 2));\n\n                                // TODO: speedup by rotating by stepAngle each iteration instead\n                                // of resetting to origin and rotating by step*stepAngle. Then do\n                                // one final rotation to the best position. (See PR #237 review.)\n                                for (let step = 1; step <= maxSteps; step++) {\n                                    let angle = stepAngle * step;\n\n                                    // Try roatation in one direction\n                                    this.rotateSubtree(vertexB.id, vertexA.id, angle, vertexB.position);\n\n                                    let newTotalOverlapScore = this.getOverlapScore().total;\n                                    if (newTotalOverlapScore < bestOverlap) {\n                                        bestOverlap = newTotalOverlapScore;\n                                        bestAngle = angle;\n                                    }\n\n                                    // Try in the other direction (twice to revert previous one)\n                                    this.rotateSubtree(vertexB.id, vertexA.id, -angle, vertexB.position);\n                                    this.rotateSubtree(vertexB.id, vertexA.id, -angle, vertexB.position);\n\n                                    newTotalOverlapScore = this.getOverlapScore().total;\n                                    if (newTotalOverlapScore < bestOverlap) {\n                                        bestOverlap = newTotalOverlapScore;\n                                        bestAngle = -angle;\n                                    }\n\n                                    // restore the original before testing the next angle.\n                                    this.rotateSubtree(vertexB.id, vertexA.id, angle, vertexB.position);\n                                }\n\n                                // only keep a rotation if we actually found an orientation that improved\n                                // the global overlap score\n                                if (bestAngle !== 0.0) {\n                                    this.rotateSubtree(vertexB.id, vertexA.id, bestAngle, vertexB.position);\n                                    this.totalOverlapScore = bestOverlap;\n                                }\n                            }\n                            else if (neighbourA.value.rings.length !== 0 || neighbourB.value.rings.length !== 0) {\n                                continue;\n                            }\n                            else {\n                                let angleA = neighbourA.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\n                                let angleB = neighbourB.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\n\n                                this.rotateSubtree(neighbourA.id, vertexB.id, angleA, vertexB.position);\n                                this.rotateSubtree(neighbourB.id, vertexB.id, angleB, vertexB.position);\n\n                                let newTotalOverlapScore = this.getOverlapScore().total;\n\n                                if (newTotalOverlapScore > this.totalOverlapScore) {\n                                    this.rotateSubtree(neighbourA.id, vertexB.id, -angleA, vertexB.position);\n                                    this.rotateSubtree(neighbourB.id, vertexB.id, -angleB, vertexB.position);\n                                }\n                                else {\n                                    this.totalOverlapScore = newTotalOverlapScore;\n                                }\n                            }\n                        }\n\n                        overlapScore = this.getOverlapScore();\n                    }\n                }\n            }\n        }\n\n        this.resolveSecondaryOverlaps(overlapScore.scores);\n        this.resolveRigidRingOverlaps();\n        overlapScore = this.getOverlapScore();\n        this.resolveSecondaryOverlaps(overlapScore.scores);\n\n        if (this.opts.isomeric) {\n            this.annotateStereochemistry();\n        }\n\n        // Initialize pseudo elements or shortcuts\n        if (this.opts.compactDrawing && this.opts.atomVisualization === 'default') {\n            this.initPseudoElements();\n        }\n\n        this.rotateDrawing();\n    }\n\n    /**\n     * Inverts an E/Z bond marker; leaves other bonds unchanged.\n     *\n     * @param {?string} bond - The bond marker to invert.\n     * @returns The bond marker, inverted if it was an E/Z bond.\n     */\n    static flipEZ(bond) {\n        if (bond === '/')  return '\\\\';\n        if (bond === '\\\\') return '/';\n        return bond;\n    }\n\n    /**\n     * Gets the bond type of a ringbond given the bond markers at either end.\n     *\n     * This is necessary because some code elsewhere (Graph?) sets these markers\n     * to '-' if they aren't specified.  This returns the first bond that differs\n     * from the default.  It flips E/Z specification of the reverse bond (if any)\n     * to make sure the stereochemistry is correct.\n     *\n     * @param {?string} fwd - The forward bond marker.\n     * @param {?string} rev - The reverse bond marker.\n     * @returns A bond marker, with correct E/Z stereochemistry.\n     */\n    static getRingbondType(fwd, rev) {\n        if (fwd && fwd !== '-') return fwd;\n        if (rev && rev !== '-') return DrawerBase.flipEZ(rev);\n        return '-';\n    }\n\n    /**\n     * Initializes rings and ringbonds for the current molecule.\n     */\n    initRings() {\n        let openBonds = new Map();\n\n        // Close the open ring bonds (spanning tree -> graph)\n        for (let i = this.graph.vertices.length - 1; i >= 0; i--) {\n            let vertex = this.graph.vertices[i];\n\n            if (vertex.value.ringbonds.length === 0) {\n                continue;\n            }\n\n            for (let j = 0; j < vertex.value.ringbonds.length; j++) {\n                let ringbondId = vertex.value.ringbonds[j].id;\n                let ringbondBond = vertex.value.ringbonds[j].bond;\n\n                // If the other ringbond id has not been discovered,\n                // add it to the open bonds map and continue.\n                // if the other ringbond id has already been discovered,\n                // create a bond between the two atoms.\n                if (!openBonds.has(ringbondId)) {\n                    openBonds.set(ringbondId, [vertex.id, ringbondBond]);\n                }\n                else {\n                    let sourceVertexId = vertex.id;\n                    let targetVertexId = openBonds.get(ringbondId)[0];\n                    let targetRingbondBond = openBonds.get(ringbondId)[1];\n                    let edge = new Edge(sourceVertexId, targetVertexId, 1);\n\n                    // The new edge goes from this vertex to the other vertex,\n                    // so the bond from openBonds is the \"reverse\" bond.\n                    edge.setBondType(DrawerBase.getRingbondType(ringbondBond, targetRingbondBond));\n\n                    let edgeId = this.graph.addEdge(edge);\n                    let targetVertex = this.graph.vertices[targetVertexId];\n\n                    vertex.addRingbondChild(targetVertexId, j);\n                    vertex.value.addNeighbouringElement(targetVertex.value.element);\n\n                    // Find the ringbond index on the TARGET vertex (not the source)\n                    let targetRingbondIdx = 0;\n                    for (let k = 0; k < targetVertex.value.ringbonds.length; k++) {\n                        if (targetVertex.value.ringbonds[k].id === ringbondId) {\n                            targetRingbondIdx = k;\n                            break;\n                        }\n                    }\n                    targetVertex.addRingbondChild(sourceVertexId, targetRingbondIdx);\n                    targetVertex.value.addNeighbouringElement(vertex.value.element);\n                    vertex.edges.push(edgeId);\n                    targetVertex.edges.push(edgeId);\n\n                    openBonds.delete(ringbondId);\n                }\n            }\n        }\n\n        // Get the rings in the graph (the SSSR)\n        let rings = SSSR.getRings(this.graph, this.opts.experimentalSSSR);\n\n        if (rings === null || rings.length === 0) {\n            return;\n        }\n\n        for (let i = 0; i < rings.length; i++) {\n            let ringVertices = [...rings[i]];\n            let ringId = this.addRing(new Ring(ringVertices));\n\n            // Add the ring to the atoms\n            for (let j = 0; j < ringVertices.length; j++) {\n                this.graph.vertices[ringVertices[j]].value.rings.push(ringId);\n            }\n        }\n\n        // Find connection between rings\n        // Check for common vertices and create ring connections. This is a bit\n        // ugly, but the ringcount is always fairly low (< 100)\n        for (let i = 0; i < this.rings.length - 1; i++) {\n            for (let j = i + 1; j < this.rings.length; j++) {\n                let a = this.rings[i];\n                let b = this.rings[j];\n                let ringConnection = new RingConnection(a, b);\n\n                // If there are no vertices in the ring connection, then there\n                // is no ring connection\n                if (ringConnection.vertices.size > 0) {\n                    this.addRingConnection(ringConnection);\n                }\n            }\n        }\n\n        // Add neighbours to the rings\n        for (let i = 0; i < this.rings.length; i++) {\n            let ring = this.rings[i];\n            ring.neighbours = RingConnection.getNeighbours(this.ringConnections, ring.id);\n        }\n\n        // Anchor the ring to one of it's members, so that the ring center will always\n        // be tied to a single vertex when doing repositionings\n        for (let i = 0; i < this.rings.length; i++) {\n            let ring = this.rings[i];\n            this.graph.vertices[ring.members[0]].value.addAnchoredRing(ring.id);\n        }\n\n        this.markCageRingSystems();\n\n        // Backup the ring information to restore after placing the bridged ring.\n        // This is needed in order to identify aromatic rings and stuff like this in\n        // rings that are member of the superring.\n        this.backupRingInformation();\n\n        // Replace rings contained by a larger bridged ring with a bridged ring\n        while (this.rings.length > 0) {\n            let id = -1;\n            for (let i = 0; i < this.rings.length; i++) {\n                let ring = this.rings[i];\n\n                if (this.isPartOfBridgedRing(ring.id) && !ring.isBridged) {\n                    id = ring.id;\n                }\n            }\n\n            if (id === -1) {\n                break;\n            }\n\n            let ring = this.getRing(id);\n\n            let involvedRings = this.getBridgedRingRings(ring.id);\n\n            this.bridgedRing = true;\n            this.createBridgedRing(involvedRings, ring.members[0]);\n            this.bridgedRing = false;\n\n            // Remove the rings\n            for (let i = 0; i < involvedRings.length; i++) {\n                this.removeRing(involvedRings[i]);\n            }\n        }\n    }\n\n    initHydrogens() {\n        if (this.opts.explicitHydrogens) {\n            return;\n        }\n\n        for (const vertex of this.graph.vertices) {\n            if (vertex.value.element !== 'H' || vertex.neighbours.length !== 1) {\n                continue;\n            }\n\n            const neighbour = this.graph.vertices[vertex.neighbours[0]];\n            if (!neighbour.value.isStereoCenter\n                || (neighbour.value.rings.length < 2 && !neighbour.value.bridgedRing)\n                || (neighbour.value.bridgedRing && neighbour.value.originalRings.length < 2)\n            ) {\n                // This vertex can be safely hidden.\n                vertex.value.isDrawn = false;\n            }\n        }\n    }\n\n    /**\n     * Returns all rings connected by bridged bonds starting from the ring with the supplied ring id.\n     *\n     * @param {Number} ringId A ring id.\n     * @returns {Number[]} An array containing all ring ids of rings part of a bridged ring system.\n     */\n    getBridgedRingRings(ringId) {\n        let involvedRings = [];\n\n        let recurse = (r) => {\n            let ring = this.getRing(r);\n\n            involvedRings.push(r);\n\n            for (let i = 0; i < ring.neighbours.length; i++) {\n                let n = ring.neighbours[i];\n\n                if (involvedRings.indexOf(n) === -1 && n !== r && RingConnection.isBridge(this.ringConnections, this.graph.vertices, r, n)) {\n                    recurse(n);\n                }\n            }\n        };\n\n        recurse(ringId);\n\n        // recurse() is only used for BRIDGED connections (rings that share 3+ atoms)\n        // but FUSED rings (exactly 2 shared atoms, like in naphtahlene) are left out.\n        // THis causes issues if the bridged system is laid out by KK. If a fused ring\n        // shares 2 atoms with the bridges system but isn't included, those 2 atoms\n        // get positioned by KK, while the rest of the fused rings gets positioned by the\n        // normal layout algorithm. Both algos fight producing distored drawings\n        // TODO: change recurse() by making it always recurse when there are two or more\n        // shared vertices and use a Set instead of indexOf on an array.\n        // (See PR#237 review)\n        let changed = true;\n        while (changed) {\n            changed = false;\n            for (let i = 0; i < this.ringConnections.length; i++) {\n                let rc = this.ringConnections[i];\n                if (rc.vertices.size < 2) continue;\n                let hasFirst = involvedRings.indexOf(rc.firstRingId) !== -1;\n                let hasSecond = involvedRings.indexOf(rc.secondRingId) !== -1;\n\n                if (hasFirst && !hasSecond) {\n                    involvedRings.push(rc.secondRingId);\n                    changed = true;\n                }\n                else if (hasSecond && !hasFirst) {\n                    involvedRings.push(rc.firstRingId);\n                    changed = true;\n                }\n            }\n        }\n\n        return ArrayHelper.unique(involvedRings);\n    }\n\n    /**\n     * Checks whether or not a ring is part of a bridged ring.\n     *\n     * @param {Number} ringId A ring id.\n     * @returns {Boolean} A boolean indicating whether or not the supplied ring (by id) is part of a bridged ring system.\n     */\n    isPartOfBridgedRing(ringId) {\n        for (let i = 0; i < this.ringConnections.length; i++) {\n            if (this.ringConnections[i].containsRing(ringId) && this.ringConnections[i].isBridge(this.graph.vertices)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Detect cage-like fused ring systems and route them through bridged-ring\n     * layout.\n     *\n     * logic:\n     * Check one fused ring component at a time. Rings are fused when they\n     * share two or more atoms.\n     *  A cage should have several rings fused on three or more sides.\n     * Every atom in the cage skeleton should have three neighbours inside\n     * the same fused component.\n     * Most ring edges should be shared by two rings. A small boundary is\n     *allowed because the SSSR can miss one face of a cage (see cubane example)\n     * This rejects polycyclic aromatic hydrocarbons (PAHs) which are an exception to the rule\n     *  check https://en.wikipedia.org/wiki/Polycyclic_aromatic_hydrocarbon\n     * PAHs have outer atoms with only two neighbours inside the fused system.\n     */\n    markCageRingSystems() {\n        // Count fused connections (vertices.size >= 2) per ring and build a\n        // ring -> fused-neighbour adjacency list.\n        let fusedCount = new Map();\n        let fusedNeighbours = new Map();\n        for (let i = 0; i < this.rings.length; i++) {\n            fusedCount.set(this.rings[i].id, 0);\n            fusedNeighbours.set(this.rings[i].id, []);\n        }\n\n        for (let i = 0; i < this.ringConnections.length; i++) {\n            let rc = this.ringConnections[i];\n            if (rc.vertices.size < 2) continue;\n            fusedCount.set(rc.firstRingId, fusedCount.get(rc.firstRingId) + 1);\n            fusedCount.set(rc.secondRingId, fusedCount.get(rc.secondRingId) + 1);\n            fusedNeighbours.get(rc.firstRingId).push(rc.secondRingId);\n            fusedNeighbours.get(rc.secondRingId).push(rc.firstRingId);\n        }\n\n        let visited = new Set();\n        let cagedRings = new Set();\n\n        for (let i = 0; i < this.rings.length; i++) {\n            let rootId = this.rings[i].id;\n            if (visited.has(rootId)) continue;\n\n            let component = [];\n            let queue = [rootId];\n            visited.add(rootId);\n            while (queue.length > 0) {\n                let cur = queue.shift();\n                component.push(cur);\n                let neighbours = fusedNeighbours.get(cur);\n                for (let j = 0; j < neighbours.length; j++) {\n                    let n = neighbours[j];\n                    if (!visited.has(n)) {\n                        visited.add(n);\n                        queue.push(n);\n                    }\n                }\n            }\n\n            if (this.isCageRingComponent(component, fusedCount)) {\n                for (let j = 0; j < component.length; j++) {\n                    cagedRings.add(component[j]);\n                }\n            }\n        }\n\n        if (cagedRings.size === 0) return;\n\n        // Force every fused connection internal to a caged component to act\n        // as a bridge so RingConnection.isBridge() reports true and the\n        // bridged-ring collapse picks it up.\n        for (let i = 0; i < this.ringConnections.length; i++) {\n            let rc = this.ringConnections[i];\n            if (rc.vertices.size < 2) continue;\n            if (cagedRings.has(rc.firstRingId) && cagedRings.has(rc.secondRingId)) {\n                rc.isForcedBridge = true;\n            }\n        }\n    }\n\n    /**\n     * Check whether a fused ring component looks like a closed cage.\n     *\n     * @param {Number[]} ringIds Ring ids in one fused component.\n     * @param {Map<Number, Number>} fusedCount Number of fused neighbours per ring.\n     * @returns {Boolean} Whether this component should use bridged-ring layout.\n     */\n    isCageRingComponent(ringIds, fusedCount) {\n        let seedCount = 0;\n        for (let i = 0; i < ringIds.length; i++) {\n            if (fusedCount.get(ringIds[i]) >= 3) {\n                seedCount++;\n            }\n        }\n\n        if (seedCount < 2) {\n            return false;\n        }\n\n        let stats = this.getRingSystemStats(ringIds);\n\n        return (\n            stats.atomCount > 0\n            && stats.edgeCount > 0\n            && stats.nonCageAtomCount === 0\n            && stats.boundaryEdgeRatio <= 0.5\n        );\n    }\n\n    /**\n     * Collect simple graph stats for a fused ring component.\n     *\n     * @param {Number[]} ringIds Ring ids in one fused component.\n     * @returns {Object} Ring-system atom and edge stats.\n     */\n    getRingSystemStats(ringIds) {\n        let ringMemberSets = new Map();\n        let atoms = new Set();\n        let degreeByAtom = new Map();\n\n        for (let i = 0; i < ringIds.length; i++) {\n            let ring = this.getRing(ringIds[i]);\n            let members = new Set(ring.members);\n            ringMemberSets.set(ringIds[i], members);\n\n            for (let j = 0; j < ring.members.length; j++) {\n                atoms.add(ring.members[j]);\n                degreeByAtom.set(ring.members[j], 0);\n            }\n        }\n\n        let edgeCount = 0;\n        let boundaryEdgeCount = 0;\n\n        for (let i = 0; i < this.graph.edges.length; i++) {\n            let edge = this.graph.edges[i];\n            if (!atoms.has(edge.sourceId) || !atoms.has(edge.targetId)) {\n                continue;\n            }\n\n            let ringCount = 0;\n            for (let j = 0; j < ringIds.length; j++) {\n                let members = ringMemberSets.get(ringIds[j]);\n                if (members.has(edge.sourceId) && members.has(edge.targetId)) {\n                    ringCount++;\n                }\n            }\n\n            if (ringCount === 0) {\n                continue;\n            }\n\n            edgeCount++;\n            degreeByAtom.set(edge.sourceId, degreeByAtom.get(edge.sourceId) + 1);\n            degreeByAtom.set(edge.targetId, degreeByAtom.get(edge.targetId) + 1);\n\n            if (ringCount === 1) {\n                boundaryEdgeCount++;\n            }\n        }\n\n        let nonCageAtomCount = 0;\n        for (let degree of degreeByAtom.values()) {\n            if (degree !== 3) {\n                nonCageAtomCount++;\n            }\n        }\n\n        return {\n            atomCount:         atoms.size,\n            edgeCount:         edgeCount,\n            nonCageAtomCount:  nonCageAtomCount,\n            boundaryEdgeRatio: edgeCount === 0 ? 1 : boundaryEdgeCount / edgeCount,\n        };\n    }\n\n    /**\n     * Creates a bridged ring.\n     *\n     * @param {Number[]} ringIds An array of ids of rings involved in the bridged ring.\n     * @param {Number} _sourceVertexId The vertex id to start the bridged ring discovery from (UNUSED).\n     * @returns {Ring} The bridged ring.\n     */\n    createBridgedRing(ringIds, _sourceVertexId) {\n        let ringMembers = new Set();\n        let vertices = new Set();\n        let neighbours = new Set();\n\n        for (let i = 0; i < ringIds.length; i++) {\n            let ring = this.getRing(ringIds[i]);\n            ring.isPartOfBridged = true;\n\n            for (let j = 0; j < ring.members.length; j++) {\n                vertices.add(ring.members[j]);\n            }\n\n            for (let j = 0; j < ring.neighbours.length; j++) {\n                let id = ring.neighbours[j];\n\n                if (ringIds.indexOf(id) === -1) {\n                    neighbours.add(ring.neighbours[j]);\n                }\n            }\n        }\n\n        // A vertex is part of the bridged ring if it only belongs to\n        // one of the rings (or to another ring\n        // which is not part of the bridged ring).\n        let leftovers = new Set();\n\n        for (let id of vertices) {\n            let vertex = this.graph.vertices[id];\n            let intersection = ArrayHelper.intersection(ringIds, vertex.value.rings);\n\n            if (vertex.value.rings.length === 1 || intersection.length === 1) {\n                ringMembers.add(vertex.id);\n            }\n            else {\n                leftovers.add(vertex.id);\n            }\n        }\n\n        // Vertices can also be part of multiple rings and lay on the bridged ring,\n        // however, they have to have at least two neighbours that are not part of\n        // two rings\n        let insideRing = [];\n\n        for (let id of leftovers) {\n            let vertex = this.graph.vertices[id];\n            let onRing = false;\n\n            for (let j = 0; j < vertex.edges.length; j++) {\n                if (this.edgeRingCount(vertex.edges[j]) === 1) {\n                    onRing = true;\n                }\n            }\n\n            if (onRing) {\n                vertex.value.isBridgeNode = true;\n                ringMembers.add(vertex.id);\n            }\n            else {\n                vertex.value.isBridge = true;\n                insideRing.push(vertex.id);\n                ringMembers.add(vertex.id);\n            }\n        }\n\n        // Create the ring\n        let ring = new Ring([...ringMembers]);\n        this.addRing(ring);\n\n        ring.isBridged = true;\n        ring.insiders = insideRing;\n        ring.neighbours = [...neighbours];\n\n        for (let i = 0; i < ringIds.length; i++) {\n            ring.rings.push(this.getRing(ringIds[i]).clone());\n        }\n\n        for (let i = 0; i < ring.members.length; i++) {\n            this.graph.vertices[ring.members[i]].value.bridgedRing = ring.id;\n        }\n\n        // Atoms inside the ring are no longer part of a ring but are now\n        // associated with the bridged ring\n        for (let i = 0; i < insideRing.length; i++) {\n            let vertex = this.graph.vertices[insideRing[i]];\n            vertex.value.rings = [];\n        }\n\n        // Remove former rings from members of the bridged ring and add the bridged ring\n        for (let id of ringMembers) {\n            let vertex = this.graph.vertices[id];\n            vertex.value.rings = ArrayHelper.removeAll(vertex.value.rings, ringIds);\n            vertex.value.rings.push(ring.id);\n        }\n\n        // Remove all the ring connections no longer used\n        for (let i = 0; i < ringIds.length; i++) {\n            for (let j = i + 1; j < ringIds.length; j++) {\n                this.removeRingConnectionsBetween(ringIds[i], ringIds[j]);\n            }\n        }\n\n        // Update the ring connections and add this ring to the neighbours neighbours\n        for (let id of neighbours) {\n            let connections = this.getRingConnections(id, ringIds);\n\n            for (let j = 0; j < connections.length; j++) {\n                this.getRingConnection(connections[j]).updateOther(ring.id, id);\n            }\n\n            this.getRing(id).neighbours.push(ring.id);\n        }\n\n        return ring;\n    }\n\n    /**\n     * Checks whether or not two vertices are in the same ring.\n     *\n     * @param {Vertex} vertexA A vertex.\n     * @param {Vertex} vertexB A vertex.\n     * @returns {Boolean} A boolean indicating whether or not the two vertices are in the same ring.\n     */\n    areVerticesInSameRing(vertexA, vertexB) {\n    // This is a little bit lighter (without the array and push) than\n    // getCommonRings().length > 0\n        for (let i = 0; i < vertexA.value.rings.length; i++) {\n            for (let j = 0; j < vertexB.value.rings.length; j++) {\n                if (vertexA.value.rings[i] === vertexB.value.rings[j]) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Returns an array of ring ids shared by both vertices.\n     *\n     * @param {Vertex} vertexA A vertex.\n     * @param {Vertex} vertexB A vertex.\n     * @returns {Number[]} An array of ids of rings shared by the two vertices.\n     */\n    getCommonRings(vertexA, vertexB) {\n        let commonRings = [];\n\n        for (let i = 0; i < vertexA.value.rings.length; i++) {\n            for (let j = 0; j < vertexB.value.rings.length; j++) {\n                if (vertexA.value.rings[i] == vertexB.value.rings[j]) {\n                    commonRings.push(vertexA.value.rings[i]);\n                }\n            }\n        }\n\n        return commonRings;\n    }\n\n    /**\n     * Returns the aromatic or largest ring shared by the two vertices.\n     *\n     * @param {Vertex} vertexA A vertex.\n     * @param {Vertex} vertexB A vertex.\n     * @returns {(Ring|null)} If an aromatic common ring exists, that ring, else the largest (non-aromatic) ring, else null.\n     */\n    getLargestOrAromaticCommonRing(vertexA, vertexB) {\n        let commonRings = this.getCommonRings(vertexA, vertexB);\n        let maxSize = 0;\n        let largestCommonRing = null;\n\n        for (let i = 0; i < commonRings.length; i++) {\n            let ring = this.getRing(commonRings[i]);\n            let size = ring.getSize();\n\n            if (ring.isBenzeneLike(this.graph.vertices)) {\n                return ring;\n            }\n            else if (size > maxSize) {\n                maxSize = size;\n                largestCommonRing = ring;\n            }\n        }\n\n        return largestCommonRing;\n    }\n\n    /**\n     * Returns an array of vertices positioned at a specified location.\n     *\n     * @param {Vector2} position The position to search for vertices.\n     * @param {Number} radius The radius within to search.\n     * @param {Number} excludeVertexId A vertex id to be excluded from the search results.\n     * @returns {Number[]} An array containing vertex ids in a given location.\n     */\n    getVerticesAt(position, radius, excludeVertexId) {\n        let locals = [];\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            let vertex = this.graph.vertices[i];\n\n            if (vertex.id === excludeVertexId || !vertex.positioned) {\n                continue;\n            }\n\n            let distance = position.distanceSq(vertex.position);\n\n            if (distance <= radius * radius) {\n                locals.push(vertex.id);\n            }\n        }\n\n        return locals;\n    }\n\n    /**\n     * Returns the closest vertex (connected as well as unconnected).\n     *\n     * @param {Vertex} vertex The vertex of which to find the closest other vertex.\n     * @returns {Vertex} The closest vertex.\n     */\n    getClosestVertex(vertex) {\n        let minDist = 99999;\n        let minVertex = null;\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            let v = this.graph.vertices[i];\n\n            if (v.id === vertex.id) {\n                continue;\n            }\n\n            let distSq = vertex.position.distanceSq(v.position);\n\n            if (distSq < minDist) {\n                minDist = distSq;\n                minVertex = v;\n            }\n        }\n\n        return minVertex;\n    }\n\n    /**\n     * Add a ring to this representation of a molecule.\n     *\n     * @param {Ring} ring A new ring.\n     * @returns {Number} The ring id of the new ring.\n     */\n    addRing(ring) {\n        ring.id = this.ringIdCounter++;\n        this.rings.push(ring);\n\n        return ring.id;\n    }\n\n    /**\n     * Removes a ring from the array of rings associated with the current molecule.\n     *\n     * @param {Number} ringId A ring id.\n     */\n    removeRing(ringId) {\n        this.rings = this.rings.filter(function(item) {\n            return item.id !== ringId;\n        });\n\n        // Also remove ring connections involving this ring\n        this.ringConnections = this.ringConnections.filter(function(item) {\n            return item.firstRingId !== ringId && item.secondRingId !== ringId;\n        });\n\n        // Remove the ring as neighbour of other rings\n        for (let i = 0; i < this.rings.length; i++) {\n            let r = this.rings[i];\n            r.neighbours = r.neighbours.filter(function(item) {\n                return item !== ringId;\n            });\n        }\n    }\n\n    /**\n     * Gets a ring object from the array of rings associated with the current molecule by its id. The ring id is not equal to the index, since rings can be added and removed when processing bridged rings.\n     *\n     * @param {Number} ringId A ring id.\n     * @returns {Ring} A ring associated with the current molecule.\n     */\n    getRing(ringId) {\n        for (let i = 0; i < this.rings.length; i++) {\n            if (this.rings[i].id == ringId) {\n                return this.rings[i];\n            }\n        }\n    }\n\n    /**\n     * Add a ring connection to this representation of a molecule.\n     *\n     * @param {RingConnection} ringConnection A new ringConnection.\n     * @returns {Number} The ring connection id of the new ring connection.\n     */\n    addRingConnection(ringConnection) {\n        ringConnection.id = this.ringConnectionIdCounter++;\n        this.ringConnections.push(ringConnection);\n\n        return ringConnection.id;\n    }\n\n    /**\n     * Removes a ring connection from the array of rings connections associated with the current molecule.\n     *\n     * @param {Number} ringConnectionId A ring connection id.\n     */\n    removeRingConnection(ringConnectionId) {\n        this.ringConnections = this.ringConnections.filter(function(item) {\n            return item.id !== ringConnectionId;\n        });\n    }\n\n    /**\n     * Removes all ring connections between two vertices.\n     *\n     * @param {Number} vertexIdA A vertex id.\n     * @param {Number} vertexIdB A vertex id.\n     */\n    removeRingConnectionsBetween(vertexIdA, vertexIdB) {\n        let toRemove = [];\n        for (let i = 0; i < this.ringConnections.length; i++) {\n            let ringConnection = this.ringConnections[i];\n\n            if  ((ringConnection.firstRingId === vertexIdA && ringConnection.secondRingId === vertexIdB)\n                || (ringConnection.firstRingId === vertexIdB && ringConnection.secondRingId === vertexIdA)\n            ) {\n                toRemove.push(ringConnection.id);\n            }\n        }\n\n        for (let i = 0; i < toRemove.length; i++) {\n            this.removeRingConnection(toRemove[i]);\n        }\n    }\n\n    /**\n     * Get a ring connection with a given id.\n     *\n     * @param {Number} id\n     * @returns {RingConnection} The ring connection with the specified id.\n     */\n    getRingConnection(id) {\n        for (let i = 0; i < this.ringConnections.length; i++) {\n            if (this.ringConnections[i].id == id) {\n                return this.ringConnections[i];\n            }\n        }\n    }\n\n    /**\n     * Get the ring connections between a ring and a set of rings.\n     *\n     * @param {Number} ringId A ring id.\n     * @param {Number[]} ringIds An array of ring ids.\n     * @returns {Number[]} An array of ring connection ids.\n     */\n    getRingConnections(ringId, ringIds) {\n        let ringConnections = [];\n\n        for (let i = 0; i < this.ringConnections.length; i++) {\n            let rc = this.ringConnections[i];\n\n            for (let j = 0; j < ringIds.length; j++) {\n                let id = ringIds[j];\n\n                if ((rc.firstRingId === ringId && rc.secondRingId === id) || (rc.firstRingId === id && rc.secondRingId === ringId)) {\n                    ringConnections.push(rc.id);\n                }\n            }\n        }\n\n        return ringConnections;\n    }\n\n    /**\n     * Returns the overlap score of the current molecule based on its positioned vertices. The higher the score, the more overlaps occur in the structure drawing.\n     *\n     * @returns {Object} Returns the total overlap score and the overlap score of each vertex sorted by score (higher to lower). Example: { total: 99, scores: [ { id: 0, score: 22 }, ... ]  }\n     */\n    getOverlapScore() {\n        let total = 0.0;\n        let overlapScores = new Float32Array(this.graph.vertices.length);\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            overlapScores[i] = 0;\n        }\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            let j = this.graph.vertices.length;\n            while (--j > i) {\n                let a = this.graph.vertices[i];\n                let b = this.graph.vertices[j];\n\n                if (!a.value.isDrawn || !b.value.isDrawn) {\n                    continue;\n                }\n\n                let dist = Vector2.subtract(a.position, b.position).lengthSq();\n\n                if (dist < this.opts.bondLengthSq) {\n                    let weighted = (this.opts.bondLength - Math.sqrt(dist)) / this.opts.bondLength;\n                    total += weighted;\n                    overlapScores[i] += weighted;\n                    overlapScores[j] += weighted;\n                }\n            }\n        }\n\n        let sortable = [];\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            sortable.push({id: i, score: overlapScores[i]});\n        }\n\n        sortable.sort(function(a, b) {\n            return b.score - a.score;\n        });\n\n        return {\n            total:        total,\n            scores:       sortable,\n            vertexScores: overlapScores,\n        };\n    }\n\n    /**\n     * When drawing a double bond, choose the side to place the double bond. E.g. a double bond should always been drawn inside a ring.\n     *\n     * @param {Vertex} vertexA A vertex.\n     * @param {Vertex} vertexB A vertex.\n     * @param {Vector2[]} sides An array containing the two normals of the line spanned by the two provided vertices.\n     * @returns {Object} Returns an object containing the following information: {\n          totalSideCount: Counts the sides of each vertex in the molecule, is an array [ a, b ],\n          totalPosition: Same as position, but based on entire molecule,\n          sideCount: Counts the sides of each neighbour, is an array [ a, b ],\n          position: which side to position the second bond, is 0 or 1, represents the index in the normal array. This is based on only the neighbours\n          anCount: the number of neighbours of vertexA,\n          bnCount: the number of neighbours of vertexB\n      }\n     */\n    chooseSide(vertexA, vertexB, sides) {\n    // Check which side has more vertices\n    // Get all the vertices connected to the both ends\n        let an = vertexA.getNeighbours(vertexB.id);\n        let bn = vertexB.getNeighbours(vertexA.id);\n        let anCount = an.length;\n        let bnCount = bn.length;\n\n        // All vertices connected to the edge vertexA to vertexB\n        let tn = ArrayHelper.merge(an, bn);\n\n        // Only considering the connected vertices\n        let sideCount = [0, 0];\n\n        for (let i = 0; i < tn.length; i++) {\n            let v = this.graph.vertices[tn[i]].position;\n\n            if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\n                sideCount[0]++;\n            }\n            else {\n                sideCount[1]++;\n            }\n        }\n\n        // Considering all vertices in the graph, this is to resolve ties\n        // from the above side counts\n        let totalSideCount = [0, 0];\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            let v = this.graph.vertices[i].position;\n\n            if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\n                totalSideCount[0]++;\n            }\n            else {\n                totalSideCount[1]++;\n            }\n        }\n\n        return {\n            totalSideCount: totalSideCount,\n            totalPosition:  totalSideCount[0] > totalSideCount[1] ? 0 : 1,\n            sideCount:      sideCount,\n            position:       sideCount[0] > sideCount[1] ? 0 : 1,\n            anCount:        anCount,\n            bnCount:        bnCount,\n        };\n    }\n\n    /**\n     * Sets the center for a ring.\n     *\n     * @param {Ring} ring A ring.\n     */\n    setRingCenter(ring) {\n        let ringSize = ring.getSize();\n        let total = new Vector2(0, 0);\n\n        for (let i = 0; i < ringSize; i++) {\n            total.add(this.graph.vertices[ring.members[i]].position);\n        }\n\n        ring.center = total.divide(ringSize);\n    }\n\n    /**\n     * Gets the center of a ring contained within a bridged ring and containing a given vertex.\n     *\n     * @param {Ring} ring A bridged ring.\n     * @param {Vertex} vertex A vertex.\n     * @returns {Vector2} The center of the subring that containing the vertex.\n     */\n    getSubringCenter(ring, vertex) {\n        let rings = vertex.value.originalRings;\n        let center = ring.center;\n        let smallest = Number.MAX_VALUE;\n\n        // Always get the smallest ring.\n        for (let i = 0; i < rings.length; i++) {\n            for (let j = 0; j < ring.rings.length; j++) {\n                if (rings[i] === ring.rings[j].id) {\n                    if (ring.rings[j].getSize() < smallest) {\n                        center = ring.rings[j].center;\n                        smallest = ring.rings[j].getSize();\n                    }\n                }\n            }\n        }\n\n        return center;\n    }\n\n    /**\n     * Draw the actual edges as bonds to the canvas.\n     *\n     * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\n     */\n    drawEdges(debug) {\n        let drawn = Array(this.graph.edges.length);\n        drawn.fill(false);\n\n        this.graph.traverseBF(0, (vertex) => {\n            let edges = this.graph.getEdges(vertex.id);\n            for (let i = 0; i < edges.length; i++) {\n                let edgeId = edges[i];\n                if (!drawn[edgeId]) {\n                    drawn[edgeId] = true;\n                    this.drawEdge(edgeId, debug);\n                }\n            }\n        });\n\n        // Draw the aromatic-ring circle. Bridged aromatic rings still get\n        // a circle as long as their 2D projection is close to a regular\n        // polygon (e.g. a flat pyrrole on a bridged bicyclic). Distorted\n        // ones (paracyclophane, triptycene) are skipped here and fall\n        // back to dashed bonds in drawEdge. Mirrors SvgDrawer.drawEdges.\n        for (let i = 0; i < this.rings.length; i++) {\n            let ring = this.rings[i];\n\n            if (!this.isRingAromatic(ring)) continue;\n\n            if (ring.isPartOfBridged && !this.isRingRegularPolygon(ring)) {\n                continue;\n            }\n\n            this.canvasWrapper.drawAromaticityRing(ring);\n        }\n    }\n\n    /**\n     * Draw the an edge as a bonds to the canvas.\n     *\n     * @param {Number} edgeId An edge id.\n     * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\n     */\n    drawEdge(edgeId, debug) {\n        let edge = this.graph.edges[edgeId];\n        let vertexA = this.graph.vertices[edge.sourceId];\n        let vertexB = this.graph.vertices[edge.targetId];\n        let elementA = vertexA.value.element;\n        let elementB = vertexB.value.element;\n\n        if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && this.opts.atomVisualization === 'default') {\n            return;\n        }\n\n        let a = vertexA.position;\n        let b = vertexB.position;\n        let normals = this.getEdgeNormals(edge);\n\n        // Create a point on each side of the line\n        let sides = ArrayHelper.clone(normals);\n\n        sides[0].multiplyScalar(10).add(a);\n        sides[1].multiplyScalar(10).add(a);\n\n        // The third condition handles aromatic bonds inside a bridged ring\n        // system wher the 2D projection is too distorted for the\n        // aromatic circle too look good (e.g triptycene). Those bonds\n        // get drawn as a solid line with a dashed parallel inside the ring\n        // If the aromatic ring is still close to a regular polygon (e.g.\n        // a flat pyrrole on a bridged bicyclic) we skip this branch and\n        // let drawEdges draw the circle as usual becuase it looks better.\n        // the long term fix is to kekulise aromatic input for bridged systems in\n        // the parser (explicit single/double) Mirrors SvgDrawer.drawEdge.\n        let aromaticRing = (edge.isPartOfAromaticRing\n            && vertexA.value.bridgedRing !== null\n            && vertexB.value.bridgedRing !== null)\n            ? this.getLargestOrAromaticCommonRing(vertexA, vertexB)\n            : null;\n\n        if (edge.bondType === '=' || this.getRingbondType(vertexA, vertexB) === '=' || (aromaticRing && !this.isRingRegularPolygon(aromaticRing))) {\n            // Always draw double bonds inside the ring\n            let inRing = this.areVerticesInSameRing(vertexA, vertexB);\n            let s = this.chooseSide(vertexA, vertexB, sides);\n\n            if (inRing) {\n                // Always draw double bonds inside a ring\n                // if the bond is shared by two rings, it is drawn in the larger\n                // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\n                let lcr = this.getLargestOrAromaticCommonRing(vertexA, vertexB);\n                let center = lcr.center;\n\n                normals[0].multiplyScalar(this.opts.bondSpacing);\n                normals[1].multiplyScalar(this.opts.bondSpacing);\n\n                // Choose the normal that is on the same side as the center\n                let line = null;\n\n                if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\n                    line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\n                }\n                else {\n                    line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\n                }\n\n                line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\n\n                // The shortened edge\n                if (edge.isPartOfAromaticRing) {\n                    this.canvasWrapper.drawLine(line, true);\n                }\n                else {\n                    this.canvasWrapper.drawLine(line);\n                }\n\n                // The normal edge\n                this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB));\n            }\n            else if (edge.center || (vertexA.isTerminal() && vertexB.isTerminal())) {\n                normals[0].multiplyScalar(this.opts.halfBondSpacing);\n                normals[1].multiplyScalar(this.opts.halfBondSpacing);\n\n                let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\n                let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\n\n                this.canvasWrapper.drawLine(lineA);\n                this.canvasWrapper.drawLine(lineB);\n            }\n            else if ((s.anCount == 0 && s.bnCount > 1) || (s.bnCount == 0 && s.anCount > 1)) {\n                // Both lines are the same length here\n                // Add the spacing to the edges (which are of unit length)\n                normals[0].multiplyScalar(this.opts.halfBondSpacing);\n                normals[1].multiplyScalar(this.opts.halfBondSpacing);\n\n                let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\n                let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\n\n                this.canvasWrapper.drawLine(lineA);\n                this.canvasWrapper.drawLine(lineB);\n            }\n            else if (s.sideCount[0] > s.sideCount[1]) {\n                normals[0].multiplyScalar(this.opts.bondSpacing);\n                normals[1].multiplyScalar(this.opts.bondSpacing);\n\n                let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\n\n                line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\n                this.canvasWrapper.drawLine(line);\n                this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB));\n            }\n            else if (s.sideCount[0] < s.sideCount[1]) {\n                normals[0].multiplyScalar(this.opts.bondSpacing);\n                normals[1].multiplyScalar(this.opts.bondSpacing);\n\n                let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\n\n                line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\n                this.canvasWrapper.drawLine(line);\n                this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB));\n            }\n            else if (s.totalSideCount[0] > s.totalSideCount[1]) {\n                normals[0].multiplyScalar(this.opts.bondSpacing);\n                normals[1].multiplyScalar(this.opts.bondSpacing);\n\n                let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\n\n                line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\n                this.canvasWrapper.drawLine(line);\n                this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB));\n            }\n            else if (s.totalSideCount[0] <= s.totalSideCount[1]) {\n                normals[0].multiplyScalar(this.opts.bondSpacing);\n                normals[1].multiplyScalar(this.opts.bondSpacing);\n\n                let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\n\n                line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\n                this.canvasWrapper.drawLine(line);\n                this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB));\n            }\n        }\n        else if (edge.bondType === '#') {\n            normals[0].multiplyScalar(this.opts.bondSpacing / 1.5);\n            normals[1].multiplyScalar(this.opts.bondSpacing / 1.5);\n\n            let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\n            let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\n\n            this.canvasWrapper.drawLine(lineA);\n            this.canvasWrapper.drawLine(lineB);\n\n            this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB));\n        }\n        else if (edge.bondType === '.') {\n            // TODO: Something... maybe... version 2?\n        }\n        else {\n            let isChiralCenterA = vertexA.value.isStereoCenter;\n            let isChiralCenterB = vertexB.value.isStereoCenter;\n\n            if (edge.wedge === 'up') {\n                this.canvasWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\n            }\n            else if (edge.wedge === 'down') {\n                this.canvasWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\n            }\n            else {\n                this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\n            }\n        }\n\n        if (debug) {\n            let midpoint = Vector2.midpoint(a, b);\n            this.canvasWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\n        }\n    }\n\n    /**\n     * Draws the vertices representing atoms to the canvas.\n     *\n     * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\n     */\n    drawVertices(debug) {\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            let vertex = this.graph.vertices[i];\n            let atom = vertex.value;\n            let charge = 0;\n            let isotope = 0;\n            let element = atom.element;\n            let hydrogens = atom.countImplicitHydrogens();\n            let dir = vertex.getTextDirection(this.graph.vertices);\n            const showCarbonsMode = DrawerBase.getEffectiveShowCarbonsMode(this.opts);\n            let isTerminal = (showCarbonsMode === 'terminal' || element !== 'C' || atom.hasAttachedPseudoElements) ? vertex.isTerminal() : false;\n            let isCarbon = atom.element === 'C';\n\n            if (element === 'C') {\n                const isRingCarbon = atom.rings && atom.rings.length > 0;\n                if (showCarbonsMode === 'none') {\n                    isCarbon = true;\n                    isTerminal = false;\n                }\n                else if (showCarbonsMode === 'all') {\n                    isCarbon = false;\n                    isTerminal = true;\n                }\n                else if (showCarbonsMode === 'acyclic' && !isRingCarbon) {\n                    isCarbon = false;\n                    isTerminal = true;\n                }\n            }\n            // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\n            // should be the most common state. This has to be fixed by kekulization\n            if (atom.element === 'N' && atom.isPartOfAromaticRing) {\n                hydrogens = 0;\n            }\n\n            if (atom.bracket) {\n                hydrogens = atom.bracket.hcount;\n                charge = atom.bracket.charge;\n                isotope = atom.bracket.isotope;\n            }\n\n            // If the molecule has less than 3 elements, always write the 'C' for carbon\n            // Likewise, if the carbon has a charge or an isotope, always draw it\n            if (charge || isotope || this.graph.vertices.length < 3) {\n                isCarbon = false;\n            }\n\n            if (this.opts.atomVisualization === 'allballs') {\n                this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\n            }\n            else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || this.graph.vertices.length === 1) {\n                if (this.opts.atomVisualization === 'default') {\n                    this.canvasWrapper.drawText(vertex.position.x, vertex.position.y,\n                        element, hydrogens, dir, isTerminal, charge, isotope, this.graph.vertices.length, atom.getAttachedPseudoElements());\n                }\n                else if (this.opts.atomVisualization === 'balls') {\n                    this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\n                }\n            }\n            else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\n                // If there is a carbon which bonds are in a straight line, draw a dot\n                let a = this.graph.vertices[vertex.neighbours[0]].position;\n                let b = this.graph.vertices[vertex.neighbours[1]].position;\n                let angle = Vector2.threePointangle(vertex.position, a, b);\n\n                if (Math.abs(Math.PI - angle) < 0.1) {\n                    this.canvasWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\n                }\n            }\n\n            if (debug) {\n                let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\n                this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\n            }\n            else {\n                // this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\n            }\n        }\n\n        // Draw the ring centers for debug purposes\n        if (this.opts.debug) {\n            for (let i = 0; i < this.rings.length; i++) {\n                let center = this.rings[i].center;\n                this.canvasWrapper.drawDebugPoint(center.x, center.y, 'r: ' + this.rings[i].id);\n            }\n        }\n    }\n\n    /**\n     * Position the vertices according to their bonds and properties.\n     */\n    position() {\n        let startVertex = null;\n\n        // Always start drawing at a bridged ring if there is one\n        // If not, start with a ring\n        // else, start with 0\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            if (this.graph.vertices[i].value.bridgedRing !== null) {\n                startVertex = this.graph.vertices[i];\n                break;\n            }\n        }\n\n        for (let i = 0; i < this.rings.length; i++) {\n            if (this.rings[i].isBridged) {\n                startVertex = this.graph.vertices[this.rings[i].members[0]];\n            }\n        }\n\n        if (this.rings.length > 0 && startVertex === null) {\n            startVertex = this.graph.vertices[this.rings[0].members[0]];\n        }\n\n        if (startVertex === null) {\n            startVertex = this.graph.vertices[0];\n        }\n\n        this.createNextBond(startVertex, null, 0.0);\n    }\n\n    /**\n     * Stores the current information associated with rings.\n     */\n    backupRingInformation() {\n        this.originalRings = [];\n        this.originalRingConnections = [];\n\n        for (let i = 0; i < this.rings.length; i++) {\n            this.originalRings.push(this.rings[i]);\n        }\n\n        for (let i = 0; i < this.ringConnections.length; i++) {\n            this.originalRingConnections.push(this.ringConnections[i]);\n        }\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            this.graph.vertices[i].value.backupRings();\n        }\n    }\n\n    /**\n     * Restores the most recently backed up information associated with rings.\n     */\n    restoreRingInformation() {\n    // Get the subring centers from the bridged rings\n        let bridgedRings = this.getBridgedRings();\n\n        this.rings = [];\n        this.ringConnections = [];\n\n        for (let i = 0; i < bridgedRings.length; i++) {\n            let bridgedRing = bridgedRings[i];\n\n            for (let j = 0; j < bridgedRing.rings.length; j++) {\n                let ring = bridgedRing.rings[j];\n                this.originalRings[ring.id].center = ring.center;\n            }\n        }\n\n        for (let i = 0; i < this.originalRings.length; i++) {\n            this.rings.push(this.originalRings[i]);\n        }\n\n        for (let i = 0; i < this.originalRingConnections.length; i++) {\n            this.ringConnections.push(this.originalRingConnections[i]);\n        }\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            this.graph.vertices[i].value.restoreRings();\n        }\n    }\n\n    // TODO: This needs some cleaning up\n\n    /**\n     * Creates a new ring, that is, positiones all the vertices inside a ring.\n     *\n     * @param {Ring} ring The ring to position.\n     * @param {(Vector2|null)} [center=null] The center of the ring to be created.\n     * @param {(Vertex|null)} [startVertex=null] The first vertex to be positioned inside the ring.\n     * @param {(Vertex|null)} [previousVertex=null] The last vertex that was positioned.\n     * @param {Boolean} [previousVertex=false] A boolean indicating whether or not this ring was force positioned already - this is needed after force layouting a ring, in order to draw rings connected to it.\n     */\n    createRing(ring, center = null, startVertex = null, previousVertex = null) {\n        if (ring.positioned) {\n            return;\n        }\n\n        center = center ? center : new Vector2(0, 0);\n\n        let orderedNeighbours = ring.getOrderedNeighbours(this.ringConnections);\n        let startingAngle = startVertex ? Vector2.subtract(startVertex.position, center).angle() : 0;\n\n        let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\n        let angle = MathHelper.centralAngle(ring.getSize());\n\n        ring.centralAngle = angle;\n\n        let a = startingAngle;\n        let startVertexId = (startVertex) ? startVertex.id : null;\n\n        if (ring.members.indexOf(startVertexId) === -1) {\n            if (startVertex) {\n                startVertex.positioned = false;\n            }\n\n            startVertexId = ring.members[0];\n        }\n\n        // If the ring is bridged, then draw the vertices inside the ring\n        // using a force based approach\n        if (ring.isBridged) {\n            this.graph.kkLayout(ring.members.slice(), center, startVertex.id, ring, this.opts.bondLength,\n                this.opts.kkThreshold, this.opts.kkInnerThreshold, this.opts.kkMaxIteration,\n                this.opts.kkMaxInnerIteration, this.opts.kkMaxEnergy);\n            ring.positioned = true;\n\n            // Update the center of the bridged ring\n            this.setRingCenter(ring);\n            center = ring.center;\n\n            // Setting the centers for the subrings\n            for (let i = 0; i < ring.rings.length; i++) {\n                this.setRingCenter(ring.rings[i]);\n            }\n        }\n        else {\n            ring.eachMember(this.graph.vertices, (v) => {\n                let vertex = this.graph.vertices[v];\n\n                if (!vertex.positioned) {\n                    vertex.setPosition(center.x + Math.cos(a) * radius, center.y + Math.sin(a) * radius);\n                }\n\n                a += angle;\n\n                if (!ring.isBridged || ring.rings.length < 3) {\n                    vertex.angle = a;\n                    vertex.positioned = true;\n                }\n            }, startVertexId, (previousVertex) ? previousVertex.id : null);\n        }\n\n        ring.positioned = true;\n        ring.center = center;\n\n        // Draw neighbours in decreasing order of connectivity\n        for (let i = 0; i < orderedNeighbours.length; i++) {\n            let neighbour = this.getRing(orderedNeighbours[i].neighbour);\n\n            if (neighbour.positioned) {\n                continue;\n            }\n\n            let vertices = RingConnection.getVertices(this.ringConnections, ring.id, neighbour.id);\n\n            if (vertices.length === 2) {\n                // This ring is a fused ring\n                ring.isFused = true;\n                neighbour.isFused = true;\n\n                let vertexA = this.graph.vertices[vertices[0]];\n                let vertexB = this.graph.vertices[vertices[1]];\n\n                // Get middle between vertex A and B\n                let midpoint = Vector2.midpoint(vertexA.position, vertexB.position);\n\n                // Get the normals to the line between A and B\n                let normals = Vector2.normals(vertexA.position, vertexB.position);\n\n                // Normalize the normals\n                normals[0].normalize();\n                normals[1].normalize();\n\n                // Set length from middle of side to center (the apothem)\n                let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\n                let apothem = MathHelper.apothem(r, neighbour.getSize());\n\n                normals[0].multiplyScalar(apothem).add(midpoint);\n                normals[1].multiplyScalar(apothem).add(midpoint);\n\n                // Pick the normal which results in a larger distance to the previous center\n                // Also check whether it's inside another ring\n                let nextCenter = normals[0];\n                if (Vector2.subtract(center, normals[1]).lengthSq() > Vector2.subtract(center, normals[0]).lengthSq()) {\n                    nextCenter = normals[1];\n                }\n\n                // Get the vertex (A or B) which is in clock-wise direction of the other\n                let posA = Vector2.subtract(vertexA.position, nextCenter);\n                let posB = Vector2.subtract(vertexB.position, nextCenter);\n\n                if (posA.clockwise(posB) === -1) {\n                    if (!neighbour.positioned) {\n                        this.createRing(neighbour, nextCenter, vertexA, vertexB);\n                    }\n                }\n                else {\n                    if (!neighbour.positioned) {\n                        this.createRing(neighbour, nextCenter, vertexB, vertexA);\n                    }\n                }\n            }\n            else if (vertices.length === 1) {\n                // This ring is a spiro\n                ring.isSpiro = true;\n                neighbour.isSpiro = true;\n\n                let vertexA = this.graph.vertices[vertices[0]];\n\n                // Get the vector pointing from the shared vertex to the new centpositioner\n                let nextCenter = Vector2.subtract(center, vertexA.position);\n\n                nextCenter.invert();\n                nextCenter.normalize();\n\n                // Get the distance from the vertex to the center\n                let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\n\n                nextCenter.multiplyScalar(r);\n                nextCenter.add(vertexA.position);\n\n                if (!neighbour.positioned) {\n                    this.createRing(neighbour, nextCenter, vertexA);\n                }\n            }\n        }\n\n        // Next, draw atoms that are not part of a ring that are directly attached to this ring\n        for (let i = 0; i < ring.members.length; i++) {\n            let ringMember = this.graph.vertices[ring.members[i]];\n            let ringMemberNeighbours = ringMember.neighbours;\n\n            // If there are multiple, the ovlerap will be resolved in the appropriate step\n            for (let j = 0; j < ringMemberNeighbours.length; j++) {\n                let v = this.graph.vertices[ringMemberNeighbours[j]];\n\n                if (v.positioned) {\n                    continue;\n                }\n\n                v.value.isConnectedToRing = true;\n                this.createNextBond(v, ringMember, 0.0);\n            }\n        }\n    }\n\n    /**\n     * Post-processing fix for E/Z double bond stereochemistry.\n     * After position(), checks all stereo double bonds and corrects any\n     * where the visual geometry doesn't match the SMILES encoding.\n     *\n     * The SMILES edge source\u2192target preserves reading order, so we can\n     * determine the intended side for each substituent independent of\n     * the graph traversal order used during position().\n     */\n    fixDoubleBondStereo() {\n        const graph = this.graph;\n\n        for (let i = 0; i < graph.edges.length; i++) {\n            const edge = graph.edges[i];\n            if (edge.bondType !== '=') continue;\n\n            const vA = edge.sourceId;\n            const vB = edge.targetId;\n\n            if (this.areVerticesInSameRing(graph.vertices[vA], graph.vertices[vB])) {\n                // These had better be in the right place by default,\n                // because there's no clean fix if they're not...\n                continue;\n            }\n\n            // Find stereo-marked (/ or \\) bonds on each side\n            let stereoA = null, stereoB = null;\n\n            for (const nid of graph.vertices[vA].getNeighbours()) {\n                if (nid === vB) continue;\n                const e = graph.getEdge(vA, nid);\n                if (e && (e.bondType === '/' || e.bondType === '\\\\')) {\n                    // '/' means source is below, target is above\n                    // So neighbor's side depends on whether it's source or target\n                    let neighborAbove = (e.sourceId === vA)\n                        ? (e.bondType === '/')    // B=A/N: N above\n                        : (e.bondType === '\\\\');  // N\\A=B: N above\n                    stereoA = {nid, above: neighborAbove};\n                    break;\n                }\n            }\n\n            for (const nid of graph.vertices[vB].getNeighbours()) {\n                if (nid === vA) continue;\n                const e = graph.getEdge(vB, nid);\n                if (e && (e.bondType === '/' || e.bondType === '\\\\')) {\n                    let neighborAbove = (e.sourceId === vB)\n                        ? (e.bondType === '/')\n                        : (e.bondType === '\\\\');\n                    stereoB = {nid, above: neighborAbove};\n                    break;\n                }\n            }\n\n            if (!stereoA || !stereoB) continue;\n\n            // Expected: same above \u2192 same side \u2192 Z; different \u2192 opposite \u2192 E\n            const expectedSameSide = (stereoA.above === stereoB.above);\n\n            // Actual geometry via cross products\n            const posA = graph.vertices[vA].position;\n            const posB = graph.vertices[vB].position;\n            const posS1 = graph.vertices[stereoA.nid].position;\n            const posS2 = graph.vertices[stereoB.nid].position;\n\n            const ax = posB.x - posA.x;\n            const ay = posB.y - posA.y;\n\n            const cross1 = ax * (posS1.y - posA.y) - ay * (posS1.x - posA.x);\n            const cross2 = ax * (posS2.y - posB.y) - ay * (posS2.x - posB.x);\n            const actualSameSide = (cross1 > 0) === (cross2 > 0);\n\n            if (expectedSameSide === actualSameSide) continue;\n\n            // Geometry is wrong \u2014 reflect a subtree across the double bond axis.\n            // Prefer to flip from the side with fewer stereo bonds to avoid\n            // disrupting other stereo constraints at the same carbon.\n            let countA = 0, countB = 0;\n            for (const nid of graph.vertices[vA].getNeighbours()) {\n                if (nid === vB) continue;\n                const e = graph.getEdge(vA, nid);\n                if (e && (e.bondType === '/' || e.bondType === '\\\\')) countA++;\n            }\n            for (const nid of graph.vertices[vB].getNeighbours()) {\n                if (nid === vA) continue;\n                const e = graph.getEdge(vB, nid);\n                if (e && (e.bondType === '/' || e.bondType === '\\\\')) countB++;\n            }\n\n            const flipId  = (countA <= countB) ? vA : vB;\n            const pivotId = (countA <= countB) ? vB : vA;\n\n            // Reflect subtree across the line through pivot in direction (ax, ay)\n            const pivot = graph.vertices[pivotId].position;\n            const len2 = ax * ax + ay * ay;\n            if (len2 < 0.001) continue;\n\n            graph.traverseTree(flipId, pivotId, (vertex) => {\n                const dx = vertex.position.x - pivot.x;\n                const dy = vertex.position.y - pivot.y;\n                const dot = dx * ax + dy * ay;\n\n                vertex.position.x = pivot.x + (2 * dot * ax / len2) - dx;\n                vertex.position.y = pivot.y + (2 * dot * ay / len2) - dy;\n\n                // Also reflect anchored ring centers\n                for (let j = 0; j < vertex.value.anchoredRings.length; j++) {\n                    let ring = this.rings[vertex.value.anchoredRings[j]];\n                    if (ring) {\n                        const rdx = ring.center.x - pivot.x;\n                        const rdy = ring.center.y - pivot.y;\n                        const rdot = rdx * ax + rdy * ay;\n                        ring.center.x = pivot.x + (2 * rdot * ax / len2) - rdx;\n                        ring.center.y = pivot.y + (2 * rdot * ay / len2) - rdy;\n                    }\n                }\n            });\n        }\n    }\n\n    /**\n     * Rotate an entire subtree by an angle around a center.\n     *\n     * @param {Number} vertexId A vertex id (the root of the sub-tree).\n     * @param {Number} parentVertexId A vertex id in the previous direction of the subtree that is to rotate.\n     * @param {Number} angle An angle in radians.\n     * @param {Vector2} center The rotational center.\n     */\n    rotateSubtree(vertexId, parentVertexId, angle, center) {\n        let rotationCenter = center.clone();\n\n        this.graph.traverseTree(vertexId, parentVertexId, (vertex) => {\n            vertex.position.rotateAround(angle, rotationCenter);\n\n            for (let i = 0; i < vertex.value.anchoredRings.length; i++) {\n                let ring = this.rings[vertex.value.anchoredRings[i]];\n\n                if (ring) {\n                    ring.center.rotateAround(angle, rotationCenter);\n                }\n            }\n        });\n    }\n\n    /**\n     * Gets the overlap score of a subtree.\n     *\n     * @param {Number} vertexId A vertex id (the root of the sub-tree).\n     * @param {Number} parentVertexId A vertex id in the previous direction of the subtree.\n     * @param {Number[]} vertexOverlapScores An array containing the vertex overlap scores indexed by vertex id.\n     * @returns {Object} An object containing the total overlap score and the center of mass of the subtree weighted by overlap score { value: 0.2, center: new Vector2() }.\n     */\n    getSubtreeOverlapScore(vertexId, parentVertexId, vertexOverlapScores) {\n        let score = 0;\n        let center = new Vector2(0, 0);\n        let count = 0;\n\n        this.graph.traverseTree(vertexId, parentVertexId, (vertex) => {\n            if (!vertex.value.isDrawn) {\n                return;\n            }\n\n            let s = vertexOverlapScores[vertex.id];\n            if (s > this.opts.overlapSensitivity) {\n                score += s;\n                count++;\n            }\n\n            let position = this.graph.vertices[vertex.id].position.clone();\n            position.multiplyScalar(s);\n            center.add(position);\n        });\n\n        center.divide(score);\n\n        return {\n            value:  score / count,\n            center: center,\n        };\n    }\n\n    /**\n     * Returns the current (positioned vertices so far) center of mass.\n     *\n     * @returns {Vector2} The current center of mass.\n     */\n    getCurrentCenterOfMass() {\n        let total = new Vector2(0, 0);\n        let count = 0;\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            let vertex = this.graph.vertices[i];\n\n            if (vertex.positioned) {\n                total.add(vertex.position);\n                count++;\n            }\n        }\n\n        return total.divide(count);\n    }\n\n    /**\n     * Returns the current (positioned vertices so far) center of mass in the neighbourhood of a given position.\n     *\n     * @param {Vector2} vec The point at which to look for neighbours.\n     * @param {Number} [r=currentBondLength*2.0] The radius of vertices to include.\n     * @returns {Vector2} The current center of mass.\n     */\n    getCurrentCenterOfMassInNeigbourhood(vec, r = this.opts.bondLength * 2.0) {\n        let total = new Vector2(0, 0);\n        let count = 0;\n        let rSq = r * r;\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            let vertex = this.graph.vertices[i];\n\n            if (vertex.positioned && vec.distanceSq(vertex.position) < rSq) {\n                total.add(vertex.position);\n                count++;\n            }\n        }\n\n        return total.divide(count);\n    }\n\n    /**\n     * Resolve primary (exact) overlaps, such as two vertices that are connected to the same ring vertex.\n     */\n    resolvePrimaryOverlaps() {\n        let overlaps = [];\n        let done = Array(this.graph.vertices.length);\n\n        // Looking for overlaps created by two bonds coming out of a ring atom, which both point straight\n        // away from the ring and are thus perfectly overlapping.\n        for (let i = 0; i < this.rings.length; i++) {\n            let ring = this.rings[i];\n\n            for (let j = 0; j < ring.members.length; j++) {\n                let vertex = this.graph.vertices[ring.members[j]];\n\n                if (done[vertex.id]) {\n                    continue;\n                }\n\n                done[vertex.id] = true;\n\n                let nonRingNeighbours = this.getNonRingNeighbours(vertex.id);\n\n                if (nonRingNeighbours.length > 1) {\n                    // Look for rings where there are atoms with two bonds outside the ring (overlaps)\n                    let rings = [];\n\n                    for (let k = 0; k < vertex.value.rings.length; k++) {\n                        rings.push(vertex.value.rings[k]);\n                    }\n\n                    overlaps.push({\n                        common:   vertex,\n                        rings:    rings,\n                        vertices: nonRingNeighbours,\n                    });\n                }\n                else if (nonRingNeighbours.length === 1 && vertex.value.rings.length === 2) {\n                    // Look for bonds coming out of joined rings to adjust the angle, an example is: C1=CC(=CC=C1)[C@]12SCCN1CC1=CC=CC=C21\n                    // where the angle has to be adjusted to account for fused ring\n                    let rings = [];\n\n                    for (let k = 0; k < vertex.value.rings.length; k++) {\n                        rings.push(vertex.value.rings[k]);\n                    }\n\n                    overlaps.push({\n                        common:   vertex,\n                        rings:    rings,\n                        vertices: nonRingNeighbours,\n                    });\n                }\n            }\n        }\n\n        for (let i = 0; i < overlaps.length; i++) {\n            let overlap = overlaps[i];\n\n            if (overlap.vertices.length === 2) {\n                let a = overlap.vertices[0];\n                let b = overlap.vertices[1];\n\n                if (!a.value.isDrawn || !b.value.isDrawn) {\n                    continue;\n                }\n\n                let angle = (2 * Math.PI - this.getRing(overlap.rings[0]).getAngle()) / 6.0;\n\n                this.rotateSubtree(a.id, overlap.common.id, angle, overlap.common.position);\n                this.rotateSubtree(b.id, overlap.common.id, -angle, overlap.common.position);\n\n                // Decide which way to rotate the vertices depending on the effect it has on the overlap score\n                let overlapScore = this.getOverlapScore();\n                let subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\n                let subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\n                let total = subTreeOverlapA.value + subTreeOverlapB.value;\n\n                this.rotateSubtree(a.id, overlap.common.id, -2.0 * angle, overlap.common.position);\n                this.rotateSubtree(b.id, overlap.common.id, 2.0 * angle, overlap.common.position);\n\n                overlapScore = this.getOverlapScore();\n                subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\n                subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\n\n                if (subTreeOverlapA.value + subTreeOverlapB.value > total) {\n                    this.rotateSubtree(a.id, overlap.common.id, 2.0 * angle, overlap.common.position);\n                    this.rotateSubtree(b.id, overlap.common.id, -2.0 * angle, overlap.common.position);\n                }\n            }\n            else if (overlap.vertices.length === 1) {\n                if (overlap.rings.length === 2) {\n                    // TODO: Implement for more overlap resolution\n                    // console.log(overlap);\n                }\n            }\n        }\n    }\n\n    /**\n     * Resolve secondary overlaps. Those overlaps are due to the structure turning back on itself.\n     *\n     * @param {Object[]} scores An array of objects sorted descending by score.\n     * @param {Number} scores[].id A vertex id.\n     * @param {Number} scores[].score The overlap score associated with the vertex id.\n     */\n    resolveSecondaryOverlaps(scores) {\n        for (let i = 0; i < scores.length; i++) {\n            if (scores[i].score > this.opts.overlapSensitivity) {\n                let vertex = this.graph.vertices[scores[i].id];\n\n                if (vertex.isTerminal()) {\n                    let closest = this.getClosestVertex(vertex);\n\n                    if (closest) {\n                        // If one of the vertices is the first one, the previous vertex is not the central vertex but the dummy\n                        // so take the next rather than the previous, which is vertex 1\n                        let closestPosition = null;\n\n                        if (closest.isTerminal()) {\n                            closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.previousPosition;\n                        }\n                        else {\n                            closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.position;\n                        }\n\n                        let vertexPreviousPosition = vertex.id === 0 ? this.graph.vertices[1].position : vertex.previousPosition;\n\n                        vertex.position.rotateAwayFrom(closestPosition, vertexPreviousPosition, MathHelper.toRad(20));\n                    }\n                }\n            }\n        }\n    }\n\n    /**\n     * Get the last non-null or 0 angle.\n     * @param {Number} vertexId A vertex id.\n     * @returns {Number} The last angle that was not 0 or null.\n     */\n    getLastAngle(vertexId) {\n        while (vertexId) {\n            let vertex = this.graph.vertices[vertexId];\n            if (vertex.value.rings.length > 0) {\n                // Angles from rings aren't useful to us...\n                return 0;\n            }\n            if (vertex.angle) {\n                return vertex.angle;\n            }\n\n            vertexId = vertex.parentVertexId;\n        }\n\n        return 0;\n    }\n\n    /**\n     * Positiones the next vertex thus creating a bond.\n     *\n     * @param {Vertex} vertex A vertex.\n     * @param {Vertex} [previousVertex=null] The previous vertex which has been positioned.\n     * @param {Number} [angle=0.0] The (global) angle of the vertex.\n     * @param {Boolean} [originShortest=false] Whether the origin is the shortest subtree in the branch.\n     * @param {Boolean} [skipPositioning=false] Whether or not to skip positioning and just check the neighbours.\n     */\n    createNextBond(vertex, previousVertex = null, angle = 0.0, originShortest = false, skipPositioning = false) {\n        if (vertex.positioned && !skipPositioning) {\n            return;\n        }\n\n        // If the double bond config was set on this vertex, do not check later\n        let doubleBondConfigSet = false;\n\n        // Keeping track of configurations around double bonds\n        if (previousVertex) {\n            let edge = this.graph.getEdge(vertex.id, previousVertex.id);\n\n            if ((edge.bondType === '/' || edge.bondType === '\\\\') && ++this.doubleBondConfigCount % 2 === 1) {\n                if (this.doubleBondConfig === null) {\n                    this.doubleBondConfig = edge.bondType;\n                    doubleBondConfigSet = true;\n\n                    // Switch if the bond is a branch bond and previous vertex is the first\n                    // TODO: Why is it different with the first vertex?\n                    if (previousVertex.parentVertexId === null && vertex.value.branchBond) {\n                        if (this.doubleBondConfig === '/') {\n                            this.doubleBondConfig = '\\\\';\n                        }\n                        else if (this.doubleBondConfig === '\\\\') {\n                            this.doubleBondConfig = '/';\n                        }\n                    }\n                }\n            }\n        }\n\n        // If the current node is the member of one ring, then point straight away\n        // from the center of the ring. However, if the current node is a member of\n        // two rings, point away from the middle of the centers of the two rings\n        if (!skipPositioning) {\n            if (!previousVertex) {\n                // Add a (dummy) previous position if there is no previous vertex defined\n                // Since the first vertex is at (0, 0), create a vector at (bondLength, 0)\n                // and rotate it by 90\u00B0\n\n                let dummy = new Vector2(this.opts.bondLength, 0);\n                dummy.rotate(MathHelper.toRad(-60));\n\n                vertex.previousPosition = dummy;\n                vertex.setPosition(this.opts.bondLength, 0);\n                vertex.angle = MathHelper.toRad(-60);\n\n                // Do not position the vertex if it belongs to a bridged ring that is positioned using a layout algorithm.\n                if (vertex.value.bridgedRing === null) {\n                    vertex.positioned = true;\n                }\n            }\n            else if (previousVertex.value.rings.length > 0) {\n                let neighbours = previousVertex.neighbours;\n                let joinedVertex = null;\n                let pos = new Vector2(0.0, 0.0);\n\n                if (previousVertex.value.bridgedRing === null && previousVertex.value.rings.length > 1) {\n                    for (let i = 0; i < neighbours.length; i++) {\n                        let neighbour = this.graph.vertices[neighbours[i]];\n                        if (ArrayHelper.containsAll(neighbour.value.rings, previousVertex.value.rings)) {\n                            joinedVertex = neighbour;\n                            break;\n                        }\n                    }\n                }\n\n                if (joinedVertex === null) {\n                    for (let i = 0; i < neighbours.length; i++) {\n                        let v = this.graph.vertices[neighbours[i]];\n\n                        if (v.positioned && this.areVerticesInSameRing(v, previousVertex)) {\n                            pos.add(Vector2.subtract(v.position, previousVertex.position));\n                        }\n                    }\n\n                    // When ring neighbors cancel out (e.g. bridgehead with 3\n                    // neighbors at ~120\u00B0), the sum is near-zero and normalize()\n                    // would produce Infinity. Fall back to pointing away from\n                    // the ring center.\n                    if (pos.lengthSq() < 1.0) {\n                        let ring = null;\n                        if (previousVertex.value.bridgedRing !== null) {\n                            ring = this.getRing(previousVertex.value.bridgedRing);\n                        }\n                        else {\n                            ring = this.getRing(previousVertex.value.rings[0]);\n                        }\n                        if (ring && ring.center) {\n                            // Vector from center to vertex (away from ring), then\n                            // invert below makes it toward center \u2014 but we want\n                            // away, so use center-to-vertex AFTER invert:\n                            // pos = center - vertex \u2192 invert \u2192 vertex - center = away \u2713\n                            pos = Vector2.subtract(ring.center, previousVertex.position);\n                        }\n                        else {\n                            pos = new Vector2(1.0, 0.0);\n                        }\n                    }\n\n                    pos.invert().normalize().multiplyScalar(this.opts.bondLength).add(previousVertex.position);\n                }\n                else {\n                    pos = joinedVertex.position.clone().rotateAround(Math.PI, previousVertex.position);\n                }\n\n                vertex.previousPosition = previousVertex.position;\n                vertex.setPositionFromVector(pos);\n                vertex.positioned = true;\n            }\n            else {\n                // If the previous vertex was not part of a ring, draw a bond based\n                // on the global angle of the previous bond\n                let v = new Vector2(this.opts.bondLength, 0);\n\n                v.rotate(angle);\n                v.add(previousVertex.position);\n\n                vertex.setPositionFromVector(v);\n                vertex.previousPosition = previousVertex.position;\n                vertex.positioned = true;\n            }\n        }\n\n        // Go to next vertex\n        // If two rings are connected by a bond ...\n        if (vertex.value.bridgedRing !== null) {\n            let nextRing = this.getRing(vertex.value.bridgedRing);\n\n            if (!nextRing.positioned) {\n                let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\n\n                nextCenter.invert();\n                nextCenter.normalize();\n\n                let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.members.length);\n                nextCenter.multiplyScalar(r);\n                nextCenter.add(vertex.position);\n\n                this.createRing(nextRing, nextCenter, vertex);\n            }\n        }\n        else if (vertex.value.rings.length > 0) {\n            let nextRing = this.getRing(vertex.value.rings[0]);\n\n            if (!nextRing.positioned) {\n                let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\n\n                nextCenter.invert();\n                nextCenter.normalize();\n\n                let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.getSize());\n\n                nextCenter.multiplyScalar(r);\n                nextCenter.add(vertex.position);\n\n                this.createRing(nextRing, nextCenter, vertex);\n            }\n        }\n        else {\n            // Draw the non-ring vertices connected to this one\n            let tmpNeighbours = vertex.getNeighbours();\n            let neighbours = [];\n\n            // Remove neighbours that are not drawn\n            for (let i = 0; i < tmpNeighbours.length; i++) {\n                if (this.graph.vertices[tmpNeighbours[i]].value.isDrawn) {\n                    neighbours.push(tmpNeighbours[i]);\n                }\n            }\n\n            // Remove the previous vertex (which has already been drawn)\n            if (previousVertex) {\n                neighbours = ArrayHelper.remove(neighbours, previousVertex.id);\n            }\n\n            let previousAngle = vertex.getAngle();\n\n            if (neighbours.length === 1) {\n                let nextVertex = this.graph.vertices[neighbours[0]];\n\n                let prevEdge = previousVertex ? this.graph.getEdge(vertex.id, previousVertex.id) : null;\n                let nextEdge = this.graph.getEdge(vertex.id, nextVertex.id);\n\n                // Make a single chain always cis except when there's a tribble (yes, this is a Star Trek reference) bond\n                // or if there are successive double bonds (or some other bond-heavy combo).\n                if (prevEdge && nextEdge && prevEdge.weight + nextEdge.weight >= 4) {\n                    prevEdge.center = true;\n                    nextEdge.center = true;\n                    nextVertex.angle = 0.0;\n\n                    if (prevEdge.weight === nextEdge.weight) {\n                        vertex.value.drawExplicit = true;\n                    }\n\n                    this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\n                }\n                else if (previousVertex && previousVertex.value.rings.length > 0) {\n                    // If coming out of a ring, always draw away from the center of mass\n                    let proposedAngleA = MathHelper.toRad(60);\n                    let proposedAngleB = -proposedAngleA;\n\n                    let proposedVectorA = new Vector2(this.opts.bondLength, 0);\n                    let proposedVectorB = new Vector2(this.opts.bondLength, 0);\n\n                    proposedVectorA.rotate(proposedAngleA).add(vertex.position);\n                    proposedVectorB.rotate(proposedAngleB).add(vertex.position);\n\n                    // let centerOfMass = this.getCurrentCenterOfMassInNeigbourhood(vertex.position, 100);\n                    let centerOfMass = this.getCurrentCenterOfMass();\n                    let distanceA = proposedVectorA.distanceSq(centerOfMass);\n                    let distanceB = proposedVectorB.distanceSq(centerOfMass);\n\n                    nextVertex.angle = distanceA < distanceB ? proposedAngleB : proposedAngleA;\n\n                    this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\n                }\n                else {\n                    let a = this.getLastAngle(vertex.id);\n                    a = (a >= 0) ? 1.0472 : -1.0472;\n\n                    // Handle configuration around double bonds\n                    if (previousVertex && !doubleBondConfigSet) {\n                        let bondType = this.graph.getEdge(vertex.id, nextVertex.id).bondType;\n\n                        if (bondType === '/') {\n                            if (this.doubleBondConfig === '/') {\n                                // Nothing to do since it will be trans per default\n                            }\n                            else if (this.doubleBondConfig === '\\\\') {\n                                a = -a;\n                            }\n                            this.doubleBondConfig = null;\n                        }\n                        else if (bondType === '\\\\') {\n                            if (this.doubleBondConfig === '/') {\n                                a = -a;\n                            }\n                            else if (this.doubleBondConfig === '\\\\') {\n                                // Nothing to do since it will be trans per default\n                            }\n                            this.doubleBondConfig = null;\n                        }\n                    }\n\n                    if (originShortest) {\n                        nextVertex.angle = a;\n                    }\n                    else {\n                        nextVertex.angle = -a;\n                    }\n\n                    this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\n                }\n            }\n            else if (neighbours.length === 2) {\n                // If the previous vertex comes out of a ring, it doesn't have an angle set\n                let a = vertex.angle;\n                if (!a) {\n                    a = 1.0472;\n                }\n\n                // Check for the longer subtree - always go with cis for the longer subtree\n                let subTreeDepthA = this.graph.getTreeDepth(neighbours[0], vertex.id);\n                let subTreeDepthB = this.graph.getTreeDepth(neighbours[1], vertex.id);\n\n                let l = this.graph.vertices[neighbours[0]];\n                let r = this.graph.vertices[neighbours[1]];\n\n                l.value.subtreeDepth = subTreeDepthA;\n                r.value.subtreeDepth = subTreeDepthB;\n\n                // Also get the subtree for the previous direction (this is important when\n                // the previous vertex is the shortest path)\n                let subTreeDepthC = this.graph.getTreeDepth(previousVertex ? previousVertex.id : null, vertex.id);\n                if (previousVertex) {\n                    previousVertex.value.subtreeDepth = subTreeDepthC;\n                }\n\n                let cis = 0;\n                let trans = 1;\n\n                // Carbons go always cis\n                if (r.value.element === 'C' && l.value.element !== 'C' && subTreeDepthB > 1 && subTreeDepthA < 5) {\n                    cis = 1;\n                    trans = 0;\n                }\n                else if (r.value.element !== 'C' && l.value.element === 'C' && subTreeDepthA > 1 && subTreeDepthB < 5) {\n                    cis = 0;\n                    trans = 1;\n                }\n                else if (subTreeDepthB > subTreeDepthA) {\n                    cis = 1;\n                    trans = 0;\n                }\n\n                let cisVertex = this.graph.vertices[neighbours[cis]];\n                let transVertex = this.graph.vertices[neighbours[trans]];\n\n                // If the origin tree (from the previous vertex) is the shortest, make them the main chain\n                let prevShortest = (subTreeDepthC < subTreeDepthA && subTreeDepthC < subTreeDepthB);\n\n                transVertex.angle = a;\n                cisVertex.angle = -a;\n\n                if (this.doubleBondConfig === '\\\\') {\n                    if (transVertex.value.branchBond === '\\\\') {\n                        transVertex.angle = -a;\n                        cisVertex.angle = a;\n                    }\n                }\n                else if (this.doubleBondConfig === '/') {\n                    if (transVertex.value.branchBond === '/') {\n                        transVertex.angle = -a;\n                        cisVertex.angle = a;\n                    }\n                }\n\n                this.createNextBond(transVertex, vertex, previousAngle + transVertex.angle, prevShortest);\n                this.createNextBond(cisVertex,   vertex, previousAngle + cisVertex.angle,   prevShortest);\n            }\n            else if (neighbours.length > 0) {\n                // Create vertices for all drawn neighbors...\n                const vertices = neighbours.map((neighbour) => {\n                    let newvertex    = this.graph.vertices[neighbour];\n                    let subtreedepth = this.graph.getTreeDepth(neighbour, vertex.id);\n                    newvertex.value.subtreeDepth = subtreedepth;\n                    return newvertex;\n                });\n\n                // This puts all the longest subtrees on the far side...\n                // TODO: Maybe try to balance this better?\n                vertices.sort((a, b) => (b.value.subtreeDepth - a.value.subtreeDepth));\n\n                if (neighbours.length === 3\n                    && previousVertex\n                    && previousVertex.parentVertexId !== null\n                    && previousVertex.value.rings.length < 1\n                    && vertices[2].value.rings.length < 1\n                    && vertices[1].value.rings.length < 1\n                    && vertices[0].value.rings.length < 1\n                    && vertices[2].value.subtreeDepth === 1\n                    && vertices[1].value.subtreeDepth === 1\n                    && vertices[0].value.subtreeDepth > 1\n                ) {\n                    // Special logic for adding pinched pairs...\n                    // For example: CCS(=O)(=O)CC(F)(F)NC\n                    if (vertex.angle >= 0) {\n                        vertices[0].angle = -1.0472;\n                        vertices[1].angle = MathHelper.toRad(30);\n                        vertices[2].angle = MathHelper.toRad(90);\n                    }\n                    else {\n                        vertices[0].angle = +1.0472;\n                        vertices[1].angle = -MathHelper.toRad(30);\n                        vertices[2].angle = -MathHelper.toRad(90);\n                    }\n\n                    this.createNextBond(vertices[0], vertex, previousAngle + vertices[0].angle);\n                    this.createNextBond(vertices[1], vertex, previousAngle + vertices[1].angle);\n                    this.createNextBond(vertices[2], vertex, previousAngle + vertices[2].angle);\n                }\n                else {\n                    // Divide the remaining space evenly among all neighbors...\n                    const totalNeighbors = neighbours.length + (previousVertex ? 1 : 0);\n                    const angleDelta = 2 * Math.PI / totalNeighbors;\n                    let a = angleDelta; // Current angle\n                    let i = 0;          // Current index\n\n                    // We don't set vertices[x].angle here because these angles aren't useful\n                    // when alternating between cis and trans in the main chain.\n                    if (neighbours.length % 2 !== 0) {\n                        // If there are an even number, the longest neighbor goes directly across.\n                        this.createNextBond(vertices[0], vertex, previousAngle);\n                        i = 1;\n                    }\n                    else {\n                        // Otherwise, the two longest neighbors split the difference.\n                        a /= 2;\n                    }\n\n                    while (i < neighbours.length) {\n                        this.createNextBond(vertices[i + 0], vertex, previousAngle + a);\n                        this.createNextBond(vertices[i + 1], vertex, previousAngle - a);\n                        a += angleDelta;\n                        i += 2;\n                    }\n                }\n            }\n        }\n    }\n\n    /**\n     * Gets the vetex sharing the edge that is the common bond of two rings.\n     *\n     * @param {Vertex} vertex A vertex.\n     * @returns {(Number|null)} The id of a vertex sharing the edge that is the common bond of two rings with the vertex provided or null, if none.\n     */\n    getCommonRingbondNeighbour(vertex) {\n        let neighbours = vertex.neighbours;\n\n        for (let i = 0; i < neighbours.length; i++) {\n            let neighbour = this.graph.vertices[neighbours[i]];\n\n            if (ArrayHelper.containsAll(neighbour.value.rings, vertex.value.rings)) {\n                return neighbour;\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * Check if a vector is inside any ring.\n     *\n     * @param {Vector2} vec A vector.\n     * @returns {Boolean} A boolean indicating whether or not the point (vector) is inside any of the rings associated with the current molecule.\n     */\n    isPointInRing(vec) {\n        for (let i = 0; i < this.rings.length; i++) {\n            let ring = this.rings[i];\n\n            if (!ring.positioned) {\n                continue;\n            }\n\n            let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\n            let radiusSq = radius * radius;\n\n            if (vec.distanceSq(ring.center) < radiusSq) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Check whether or not an edge is part of a ring.\n     *\n     * @param {Edge} edge An edge.\n     * @returns {Boolean} A boolean indicating whether or not the edge is part of a ring.\n     */\n    isEdgeInRing(edge) {\n        let source = this.graph.vertices[edge.sourceId];\n        let target = this.graph.vertices[edge.targetId];\n\n        return this.areVerticesInSameRing(source, target);\n    }\n\n    /**\n     * Check whether or not an edge is rotatable.\n     *\n     * @param {Edge} edge An edge.\n     * @returns {Boolean} A boolean indicating whether or not the edge is rotatable.\n     */\n    isEdgeRotatable(edge) {\n        let vertexA = this.graph.vertices[edge.sourceId];\n        let vertexB = this.graph.vertices[edge.targetId];\n\n        // Only single bonds are rotatable\n        if (edge.bondType !== '-') {\n            return false;\n        }\n\n        // Do not rotate edges that have a further single bond to each side - do that!\n        // If the bond is terminal, it doesn't make sense to rotate it\n        // if (vertexA.getNeighbourCount() + vertexB.getNeighbourCount() < 5) {\n        //   return false;\n        // }\n\n        if (vertexA.isTerminal() || vertexB.isTerminal()) {\n            return false;\n        }\n\n        // Ringbonds are not rotatable\n        if (vertexA.value.rings.length > 0 && vertexB.value.rings.length > 0 && this.areVerticesInSameRing(vertexA, vertexB)) {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * Check whether or not a ring is an implicitly defined aromatic ring (lower case smiles).\n     *\n     * @param {Ring} ring A ring.\n     * @returns {Boolean} A boolean indicating whether or not a ring is implicitly defined as aromatic.\n     */\n    isRingAromatic(ring) {\n        for (let i = 0; i < ring.members.length; i++) {\n            let vertex = this.graph.vertices[ring.members[i]];\n\n            if (!vertex.value.isPartOfAromaticRing) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Check whether the ring's 2D projection is close enough to a regular\n     * polygon that the aromatic-circle indicator will sit correctly inside\n     * it. Used to decide whether an aromatic ring that has been absorbed\n     * into a bridged super-ring can still use a circle, or needs the\n     * dashed-bond fallback.\n     *\n     * Heuristic: every vertex of a regular N-gon is the same distance\n     * from the centre. We accept the ring as regular when the longest\n     * radius is no more than `tolerance` times the shortest.\n     *\n     * @param {Ring}   ring             A ring.\n     * @param {Number} [tolerance=1.15] Max acceptable max/min radius ratio.\n     * @returns {Boolean}\n     */\n    isRingRegularPolygon(ring, tolerance = 1.15) {\n        if (ring.members.length < 3) {\n            return false;\n        }\n\n        let positions = ring.getPolygon(this.graph.vertices);\n        let center    = ring.center;\n        let minR      = Infinity;\n        let maxR      = -Infinity;\n\n        for (let i = 0; i < positions.length; i++) {\n            let r = positions[i].distance(center);\n            if (r < minR) minR = r;\n            if (r > maxR) maxR = r;\n        }\n\n        if (minR < 1e-6) {\n            return false;\n        }\n\n        return (maxR / minR) < tolerance;\n    }\n\n    /**\n     * Get the normals of an edge.\n     *\n     * @param {Edge} edge An edge.\n     * @returns {Vector2[]} An array containing two vectors, representing the normals.\n     */\n    getEdgeNormals(edge) {\n        let v1 = this.graph.vertices[edge.sourceId].position;\n        let v2 = this.graph.vertices[edge.targetId].position;\n\n        // Get the normalized normals for the edge\n        let normals = Vector2.units(v1, v2);\n\n        return normals;\n    }\n\n    /**\n     * Returns an array of vertices that are neighbouring a vertix but are not members of a ring (including bridges).\n     *\n     * @param {Number} vertexId A vertex id.\n     * @returns {Vertex[]} An array of vertices.\n     */\n    getNonRingNeighbours(vertexId) {\n        let nrneighbours = [];\n        let vertex = this.graph.vertices[vertexId];\n        let neighbours = vertex.neighbours;\n\n        for (let i = 0; i < neighbours.length; i++) {\n            let neighbour = this.graph.vertices[neighbours[i]];\n            let nIntersections = ArrayHelper.intersection(vertex.value.rings, neighbour.value.rings).length;\n\n            if (nIntersections === 0 && neighbour.value.isBridge == false) {\n                nrneighbours.push(neighbour);\n            }\n        }\n\n        return nrneighbours;\n    }\n\n    /**\n     * Returns the minimum distance between any pair of non-bonded drawn atoms.\n     *\n     * @returns {Number} The minimum non-bonded distance.\n     */\n    getMinimumNonBondedDistance() {\n        let minimumDistance = Number.POSITIVE_INFINITY;\n\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            let vertexA = this.graph.vertices[i];\n\n            if (!vertexA.value.isDrawn) {\n                continue;\n            }\n\n            for (let j = i + 1; j < this.graph.vertices.length; j++) {\n                if (this.graph.hasEdge(i, j)) {\n                    continue;\n                }\n\n                let vertexB = this.graph.vertices[j];\n                if (!vertexB.value.isDrawn) {\n                    continue;\n                }\n\n                let distance = vertexA.position.distance(vertexB.position);\n                if (distance < minimumDistance) {\n                    minimumDistance = distance;\n                }\n            }\n        }\n\n        return minimumDistance;\n    }\n\n    /**\n     * Returns the number of external ring connections, counting bonds from ring members\n     * to atoms outside the ring.\n     *\n     * @param {Number} ringId A ring id.\n     * @returns {Number} The number of external connections.\n     */\n    getRingExternalConnectionCount(ringId) {\n        let ring = this.getRing(ringId);\n\n        if (!ring) {\n            return 0;\n        }\n\n        let members = new Set(ring.members);\n        let externalConnections = new Set();\n\n        for (let i = 0; i < ring.members.length; i++) {\n            let memberId = ring.members[i];\n            let vertex = this.graph.vertices[memberId];\n\n            for (let j = 0; j < vertex.neighbours.length; j++) {\n                let neighbourId = vertex.neighbours[j];\n\n                if (!members.has(neighbourId)) {\n                    externalConnections.add(`${memberId}:${neighbourId}`);\n                }\n            }\n        }\n\n        return externalConnections.size;\n    }\n\n    /**\n     * Try rigid rotations for ring systems attached through a rotatable bond after the\n     * main overlap passes have settled. This catches ring-on-ring stacking that is only\n     * obvious in the final geometry.\n     */\n    resolveRigidRingOverlaps() {\n        let currentOverlap = this.getOverlapScore().total; // total overlap score\n        let currentMinimumDistance = this.getMinimumNonBondedDistance(); // to make sure we are\n        // not creating a collision elsewhere\n        let minimumAllowedDistance = this.opts.bondLength * 0.3;\n\n        for (let i = 0; i < this.graph.edges.length; i++) {\n            let edge = this.graph.edges[i];\n            // Only single, non-terminal, non-ring bonds can be rotated.\n            if (!this.isEdgeRotatable(edge)) {\n                continue;\n            }\n\n            let subTreeDepthA = this.graph.getTreeDepth(edge.sourceId, edge.targetId);\n            let subTreeDepthB = this.graph.getTreeDepth(edge.targetId, edge.sourceId);\n            let a = edge.targetId;\n            let b = edge.sourceId;\n\n            // Rotate the shorter side of the bond.\n            // This changes less of the drawing and is less likely to disturb the rest of the layout\n            if (subTreeDepthA > subTreeDepthB) {\n                a = edge.sourceId;\n                b = edge.targetId;\n            }\n\n            let vertexA = this.graph.vertices[a];\n            let vertexB = this.graph.vertices[b];\n            let neighboursB = vertexB.getNeighbours(a);\n\n            // We only handle a very specific shape here:\n            // after removing the pivot bond to vertexA, vertexB must connect to exactly two atoms.\n            // That makes vertexB look like the entry point into one ring.\n            if (neighboursB.length !== 2) {\n                continue;\n            }\n\n            let neighbourA = this.graph.vertices[neighboursB[0]];\n            let neighbourB = this.graph.vertices[neighboursB[1]];\n\n            // Both neighbours must belong to exactly one ring.\n            // If either atom is in no ring or in multiple rings, this is not the clean rigid-ring case.\n            if (neighbourA.value.rings.length !== 1 || neighbourB.value.rings.length !== 1) {\n                continue;\n            }\n\n            // The two neighbours must belong to the same ring.\n            // This confirms that rotating around A-B will rotate one attached ring system as a rigid unit.\n            if (neighbourA.value.rings[0] !== neighbourB.value.rings[0]) {\n                continue;\n            }\n\n            let ring = this.getRing(neighbourA.value.rings[0]);\n            if (!ring) {\n                continue;\n            }\n\n            let bestAngle = 0.0;\n            let bestOverlap = currentOverlap;\n            let bestMinimumDistance = currentMinimumDistance;\n            let stepAngle = MathHelper.centralAngle(ring.getSize());\n            let maxSteps = Math.max(1, Math.floor(ring.getSize() / 2));\n\n            // TODO: same 2x speedup as the rotation loop in processGraph().\n            // Rotate incrementally instead of resetting each iteration. (See PR#237 review.)\n            for (let step = 1; step <= maxSteps; step++) {\n                let baseAngle = stepAngle * step;\n\n                for (let direction = 0; direction < 2; direction++) {\n                    let angle = direction === 0 ? baseAngle : -baseAngle;\n\n                    // rotate first by angle\n                    this.rotateSubtree(vertexB.id, vertexA.id, angle, vertexB.position);\n\n                    let newOverlap = this.getOverlapScore().total;\n                    let newMinimumDistance = this.getMinimumNonBondedDistance();\n\n                    // undo rotation once we got the score\n                    this.rotateSubtree(vertexB.id, vertexA.id, -angle, vertexB.position);\n\n                    // reject if two non-bonded atoms come too close together\n                    if (newMinimumDistance <= minimumAllowedDistance) {\n                        continue;\n                    }\n\n                    // prefer the one with a lower overlap score\n                    // and if two candidates tie, select one with more clearance between atoms\n                    if (newOverlap < bestOverlap - 1e-6\n                        || (Math.abs(newOverlap - bestOverlap) <= 1e-6 && newMinimumDistance > bestMinimumDistance + 1e-6)\n                    ) {\n                        bestAngle = angle;\n                        bestOverlap = newOverlap;\n                        bestMinimumDistance = newMinimumDistance;\n                    }\n                }\n            }\n\n            // apply the best rigid rotation if we found one\n            // Then update the \"current best\" baseline so later edges are judged against the improved layout.\n            if (bestAngle !== 0.0) {\n                this.rotateSubtree(vertexB.id, vertexA.id, bestAngle, vertexB.position);\n                currentOverlap = bestOverlap;\n                currentMinimumDistance = bestMinimumDistance;\n            }\n        }\n\n        // keep the stored total overlap score in sync with the final geometry after this pass.\n        this.totalOverlapScore = currentOverlap;\n    }\n\n    /**\n     * Annotated stereochemistry information for visualization.\n     */\n    annotateStereochemistry() {\n        // For each stereo-center\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            const vertex = this.graph.vertices[i];\n            if (!vertex.value.isStereoCenter) {\n                continue;\n            }\n\n            const neighbours = vertex.neighbours;\n            // Validate: a tetrahedral stereocenter needs exactly 4 bonds.\n            if (neighbours.length + vertex.value.countImplicitHydrogens() !== 4) {\n                vertex.value.isStereoCenter = false;\n                continue;\n            }\n\n            // This will return undefined if two branches are exactly equal.\n            const order = CIP.getOrderArray(this.graph, vertex);\n            if (order === undefined) {\n                vertex.value.isStereoCenter = false;\n                continue;\n            }\n\n            const parity   = MathHelper.parityOfPermutation(order);\n            const rotation = vertex.value.bracket.chirality === '@' ? -1 : 1;\n            const rs       = (parity === rotation) ? 'R' : 'S';\n            vertex.value.chirality = rs;\n\n            // Pick the best neighbor to draw a wedge to.\n            // Priority: non-stereocenter > not in same ring > visible > heteroatom > shortest subtree\n            // Note that the sort order is reversed, so higher scores get priority.\n            const wedgeOrder = order.map((o) => {\n                const nid       = neighbours[o];\n                const neighbour = this.graph.vertices[nid];\n\n                let rank = 0;\n                rank -= neighbour.value.isStereoCenter ? 1000000 : 0;\n                rank -= this.areVerticesInSameRing(neighbour, vertex) ? 100000 : 0;\n                rank += neighbour.value.isDrawn ? 10000 : 0;\n                // rank += neighbour.isTerminal() ? 1000 : 0;\n                rank += neighbour.value.element !== 'C' ? 100 : 0;\n                rank -= this.graph.getTreeDepth(nid, vertex.id);\n\n                return [rank, nid];\n            }).sort((a, b) => {\n                return b[0] - a[0];\n            });\n\n            // Set the wedge direction.\n            const wedgeId = wedgeOrder[0][1];\n            const wedge = this._computeWedgeDirection(vertex, wedgeId, order, neighbours, rs);\n            this.graph.getEdge(vertex.id, wedgeId).wedge = wedge;\n            this.graph.vertices[wedgeId].value.isDrawn = true;\n        }\n    }\n\n    /**\n     * Compute the correct wedge direction ('up' or 'down') for a bond from\n     * a stereocenter to a given neighbor, using the 3D determinant approach.\n     *\n     * The signed area of the triangle formed by the other 3 neighbors (in CIP\n     * order) determines the spatial orientation. Combined with the CIP rank\n     * parity of the wedged atom, this gives the correct solid/dashed assignment.\n     *\n     * @param {Vertex} vertex The stereocenter vertex.\n     * @param {Number} wedgeTargetId The vertex id of the neighbor being wedged.\n     * @param {number[] | Uint8Array} order CIP priority order (index\u2192original neighbor index).\n     * @param {Number[]} neighbours The neighbor vertex ids.\n     * @param {String} rs 'R' or 'S' designation.\n     * @returns {String} 'up' (solid wedge) or 'down' (dashed wedge).\n     */\n    _computeWedgeDirection(vertex, wedgeTargetId, order, neighbours, rs) {\n        let nNeighbours = neighbours.length;\n\n        // Find CIP rank of the wedged neighbor\n        let wedgeCipRank = 0;\n        for (let j = 0; j < nNeighbours; j++) {\n            if (neighbours[order[j]] === wedgeTargetId) {\n                wedgeCipRank = j;\n                break;\n            }\n        }\n\n        // Collect 2D positions of the other neighbors in CIP order\n        let others = [];\n        for (let j = 0; j < nNeighbours; j++) {\n            if (neighbours[order[j]] !== wedgeTargetId) {\n                others.push(this.graph.vertices[neighbours[order[j]]].position);\n            }\n        }\n\n        // For 3-neighbor stereocenters (implicit H), synthesize the H position.\n        // H is lowest CIP priority and sits roughly opposite the other 3 ligands.\n        if (others.length === 2) {\n            let wedgePos = this.graph.vertices[wedgeTargetId].position;\n            let cx = (wedgePos.x + others[0].x + others[1].x) / 3;\n            let cy = (wedgePos.y + others[0].y + others[1].y) / 3;\n            others.push({\n                x: 2 * vertex.position.x - cx,\n                y: 2 * vertex.position.y - cy,\n            });\n            // H is always lowest CIP priority, so wedgeCipRank doesn't shift\n        }\n\n        // Signed area of the triangle (others[0], others[1], others[2]).\n        // In SVG coordinates (y-axis down), positive = clockwise winding.\n        let sa = (others[1].x - others[0].x) * (others[2].y - others[0].y)\n            - (others[2].x - others[0].x) * (others[1].y - others[0].y);\n\n        // When the wedged atom has even CIP rank (0, 2), solid wedge gives R\n        // when the remaining triangle winds CW (sa > 0). For odd rank (1, 3),\n        // the relationship is inverted.\n        let solidGivesR = (wedgeCipRank % 2 === 0) ? (sa > 0) : (sa < 0);\n\n        return (solidGivesR === (rs === 'R')) ? 'up' : 'down';\n    }\n\n    /**\n     * Creates pseudo-elements (such as Et, Me, Ac, Bz, ...) at the position of the carbon sets\n     * the involved atoms not to be displayed.\n     */\n    initPseudoElements() {\n        for (let i = 0; i < this.graph.vertices.length; i++) {\n            const vertex = this.graph.vertices[i];\n            const neighbourIds = vertex.neighbours;\n            let neighbours = Array(neighbourIds.length);\n\n            for (let j = 0; j < neighbourIds.length; j++) {\n                neighbours[j] = this.graph.vertices[neighbourIds[j]];\n            }\n\n            // Ignore atoms that have less than 3 neighbours, except if\n            // the vertex is connected to a ring and has two neighbours\n            if (vertex.getNeighbourCount() < 3 || vertex.value.rings.length > 0) {\n                continue;\n            }\n\n            // TODO: This exceptions should be handled more elegantly (via config file?)\n\n            // Ignore phosphates (especially for triphosphates)\n            if (vertex.value.element === 'P') {\n                continue;\n            }\n\n            // Ignore also guanidine\n            if (vertex.value.element === 'C'\n                && neighbours.length === 3\n                && neighbours[0].value.element === 'N'\n                && neighbours[1].value.element === 'N'\n                && neighbours[2].value.element === 'N'\n            ) {\n                continue;\n            }\n\n            // Continue if there are less than two heteroatoms\n            // or if a neighbour has more than 1 neighbour\n            let heteroAtomCount = 0;\n            let ctn = 0;\n\n            for (let j = 0; j < neighbours.length; j++) {\n                let neighbour = neighbours[j];\n                let neighbouringElement = neighbour.value.element;\n                let neighbourCount = neighbour.getNeighbourCount();\n\n                if (neighbouringElement !== 'C' && neighbouringElement !== 'H' && neighbourCount === 1) {\n                    heteroAtomCount++;\n                }\n\n                if (neighbourCount > 1) {\n                    ctn++;\n                }\n            }\n\n            if (ctn > 1 || heteroAtomCount < 2) {\n                continue;\n            }\n\n            // Get the previous atom (the one which is not terminal)\n            let previous = null;\n\n            for (let j = 0; j < neighbours.length; j++) {\n                let neighbour = neighbours[j];\n\n                if (neighbour.getNeighbourCount() > 1) {\n                    previous = neighbour;\n                }\n            }\n\n            for (let j = 0; j < neighbours.length; j++) {\n                let neighbour = neighbours[j];\n\n                if (neighbour.getNeighbourCount() > 1) {\n                    continue;\n                }\n\n                neighbour.value.isDrawn = false;\n\n                let hydrogens = neighbour.value.countImplicitHydrogens();\n                let charge = '';\n\n                if (neighbour.value.bracket) {\n                    charge = neighbour.value.bracket.charge || 0;\n                }\n\n                vertex.value.attachPseudoElement(neighbour.value.element, previous ? previous.value.element : null, hydrogens, charge);\n            }\n        }\n\n    /*\n    // The second pass\n    for (let i = 0; i < this.graph.vertices.length; i++) {\n      const vertex = this.graph.vertices[i];\n      const atom = vertex.value;\n      const element = atom.element;\n\n      if (element === 'C' || element === 'H' || !atom.isDrawn) {\n        continue;\n      }\n\n      const neighbourIds = vertex.neighbours;\n      let neighbours = Array(neighbourIds.length);\n\n      for (let j = 0; j < neighbourIds.length; j++) {\n        neighbours[j] = this.graph.vertices[neighbourIds[j]];\n      }\n\n      for (let j = 0; j < neighbours.length; j++) {\n        let neighbour = neighbours[j].value;\n\n        if (!neighbour.hasAttachedPseudoElements || neighbour.getAttachedPseudoElementsCount() !== 2) {\n          continue;\n        }\n\n        const pseudoElements = neighbour.getAttachedPseudoElements();\n\n        if (neighbour.element === 'C' && pseudoElements.hasOwnProperty('0O') && pseudoElements.hasOwnProperty('3C')) {\n          if (pseudoElements['0O'].count === 1 && pseudoElements['3C'].count === 1) {\n            neighbour.isDrawn = false;\n            vertex.value.attachPseudoElement('Ac', '', 0);\n          }\n        }\n        else if (neighbour.element === 'S' && pseudoElements.hasOwnProperty('0O') && pseudoElements.hasOwnProperty('3C')) {\n          if (pseudoElements['0O'].count === 2 && pseudoElements['3C'].count === 1) {\n            neighbour.isDrawn = false;\n            vertex.value.attachPseudoElement('Ms', '', 0);\n          }\n        }\n      }\n    }\n      */\n    }\n}\n", "// Adapted from https://codepen.io/shshaw/pen/XbxvNj by\n\nexport default function convertImage(img) {\n    'use strict';\n\n    function each(obj, fn) {\n        let length = obj.length,\n            likeArray = (length === 0 || (length > 0 && (length - 1) in obj));\n\n        if (likeArray) {\n            for (let i = 0; i < length; i++) {\n                if (fn.call(obj[i], i, obj[i]) === false) {\n                    break;\n                }\n            }\n        }\n        else {\n            for (const i in obj) {\n                if (fn.call(obj[i], i, obj[i]) === false) {\n                    break;\n                }\n            }\n        }\n    }\n\n    function componentToHex(c) {\n        let hex = parseInt(c).toString(16);\n        return hex.length == 1 ? '0' + hex : hex;\n    }\n\n    function getColor(r, g, b, a) {\n        a = parseInt(a);\n        if (a === undefined || a === 255) {\n            return '#' + componentToHex(r) + componentToHex(g) + componentToHex(b);\n        }\n        if (a === 0) {\n            return false;\n        }\n\n        return 'rgba(' + r + ',' + g + ',' + b + ',' + (a / 255) + ')';\n    }\n\n    // Optimized for horizontal lines\n    function makePathData(x, y, w) {\n        return ('M' + x + ' ' + y + 'h' + w + '');\n    }\n\n    function makePath(color, data) {\n        return '<path stroke=\"' + color + '\" d=\"' + data + '\" />\\n';\n    }\n\n    function colorsToPaths(colors) {\n        let output = '';\n\n        // Loop through each color to build paths\n        each(colors, function(color, values) {\n            color = getColor.apply(null, color.split(','));\n\n            if (color === false) {\n                return;\n            }\n\n            let paths = [];\n            let curPath;\n            let w = 1;\n\n            // Loops through each color's pixels to optimize paths\n            each(values, function(index, value) {\n                if (curPath && value[1] === curPath[1] && value[0] === (curPath[0] + w)) {\n                    w++;\n                }\n                else {\n                    if (curPath) {\n                        paths.push(makePathData(curPath[0], curPath[1], w));\n                        w = 1;\n                    }\n                    curPath = value;\n                }\n            });\n\n            paths.push(makePathData(curPath[0], curPath[1], w)); // Finish last path\n            output += makePath(color, paths.join(''));\n        });\n\n        return output;\n    }\n\n    function getColors(image) {\n        let colors = {},\n            data = image.data,\n            len = data.length,\n            w = image.width,\n            x = 0,\n            y = 0,\n            color;\n\n        for (let i = 0; i < len; i += 4) {\n            if (data[i + 3] > 0) {\n                color = data[i] + ',' + data[i + 1] + ',' + data[i + 2] + ',' + data[i + 3];\n                colors[color] = colors[color] || [];\n                x = (i / 4) % w;\n                y = Math.floor((i / 4) / w);\n                colors[color].push([x, y]);\n            }\n        }\n\n        return colors;\n    }\n\n    let colors = getColors(img);\n    let paths = colorsToPaths(colors);\n    let output = '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -0.5 ' + img.width + ' ' + img.height + '\" shape-rendering=\"crispEdges\"><g shape-rendering=\"crispEdges\">' + paths + '</g></svg>';\n\n    let dummyDiv = document.createElement('div');\n    dummyDiv.innerHTML = output;\n\n    return dummyDiv.firstElementChild;\n}\n", "import convertImage from './PixelsToSvg';\nimport Vector2      from './Vector2';\n\nimport chroma from 'chroma-js';\n\nexport default class GaussDrawer {\n    /**\n     * The constructor of the class Graph.\n     *\n     * @param {Vector2[]} points The centres of the gaussians.\n     * @param {Number[]} weights The weights / amplitudes for each gaussian.\n     */\n    constructor(points, weights, width, height, sigma = 0.3, interval = 0, colormap = null, opacity = 1.0, normalized = false) {\n        this.points = points;\n        this.weights = weights;\n        this.width = width;\n        this.height = height;\n        this.sigma = sigma;\n        this.interval = interval;\n        this.opacity = opacity;\n        this.normalized = normalized;\n\n        if (colormap === null) {\n            let piyg11 = [\n                '#c51b7d', '#de77ae', '#f1b6da', '#fde0ef',\n                '#ffffff',\n                '#e6f5d0', '#b8e186', '#7fbc41', '#4d9221'];\n            colormap = piyg11;\n        }\n        this.colormap = colormap;\n\n        this.canvas = document.createElement('canvas');\n        this.context = this.canvas.getContext('2d');\n        this.canvas.width = this.width;\n        this.canvas.height = this.height;\n    }\n\n    setFromArray(arr_points, arr_weights) {\n        this.points = [];\n        arr_points.forEach((a) => {\n            this.points.push(new Vector2(a[0], a[1]));\n        });\n\n        this.weights = [];\n        arr_weights.forEach((w) => {\n            this.weights.push(w);\n        });\n    }\n\n    /**\n       * Compute and draw the gaussians.\n       */\n    draw() {\n        let m = [];\n\n        for (let x = 0; x < this.width; x++) {\n            let row = [];\n            for (let y = 0; y < this.height; y++) {\n                row.push(0.0);\n            }\n            m.push(row);\n        }\n\n        // It looks like in some common js engines, multiplication by a\n        // fraction is faster than division ...\n        let divisor = 1.0 / (2 * this.sigma * this.sigma);\n\n        for (let i = 0; i < this.points.length; i++) {\n            let v = this.points[i];\n            let a = this.weights[i];\n\n            for (let x = 0; x < this.width; x++) {\n                for (let y = 0; y < this.height; y++) {\n                    // let v_x = (x - v.x) ** 2 / (2 * this.sigma ** 2);\n                    // let v_y = (y - v.y) ** 2 / (2 * this.sigma ** 2);\n                    let dx = x - v.x;\n                    let dy = y - v.y;\n                    let v_xy = (dx * dx + dy * dy) * divisor;\n                    let val = a * Math.exp(-v_xy);\n\n                    m[x][y] += val;\n                }\n            }\n        }\n\n        let abs_max = 1.0;\n\n        if (!this.normalized) {\n            let max = -Number.MAX_SAFE_INTEGER;\n            let min = Number.MAX_SAFE_INTEGER;\n\n            for (let x = 0; x < this.width; x++) {\n                for (let y = 0; y < this.height; y++) {\n                    if (m[x][y] < min) {\n                        min = m[x][y];\n                    }\n\n                    if (m[x][y] > max) {\n                        max = m[x][y];\n                    }\n                }\n            }\n\n            abs_max = Math.max(Math.abs(min), Math.abs(max));\n        }\n\n        const scale = chroma.scale(this.colormap).domain([-1.0, 1.0]);\n\n        for (let x = 0; x < this.width; x++) {\n            for (let y = 0; y < this.height; y++) {\n                if (!this.normalized) {\n                    m[x][y] = m[x][y] / abs_max;\n                }\n\n                if (this.interval !== 0) {\n                    m[x][y] = Math.round(m[x][y] / this.interval) * this.interval;\n                }\n\n                let [r, g, b] = scale(m[x][y]).rgb();\n                this.setPixel(new Vector2(x, y), r, g, b);\n            }\n        }\n    }\n\n    /**\n       * Get the canvas as an HTML image.\n       *\n       * @param {CallableFunction} callback\n       */\n    getImage(callback) {\n        let image = new Image();\n        image.onload = () => {\n            this.context.imageSmoothingEnabled = false;\n            this.context.drawImage(image, 0, 0, this.width, this.height);\n\n            if (callback) {\n                callback(image);\n            }\n        };\n\n        image.onerror = (err) => {\n            console.log(err);\n        };\n\n        image.src = this.canvas.toDataURL();\n    }\n\n    /**\n       * Get the canvas as an SVG element.\n       */\n    getSVG() {\n        return convertImage(this.context.getImageData(0, 0, this.width, this.height));\n    }\n\n    /**\n       * Set the colour at a specific point on the canvas.\n       *\n       * @param {Vector2} vec The pixel position on the canvas.\n       * @param {Number} r The red colour-component.\n       * @param {Number} g The green colour-component.\n       * @param {Number} b The blue colour-component.\n       */\n    setPixel(vec, r, g, b) {\n        this.context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + this.opacity + ')';\n        this.context.fillRect(vec.x, vec.y, 1, 1);\n    }\n}\n", "import Line       from './Line';\nimport MathHelper from './MathHelper';\nimport Vector2    from './Vector2';\n\nfunction makeid(length) {\n    let result = '';\n    let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n    let charactersLength = characters.length;\n    for (let i = 0; i < length; i++) {\n        result += characters.charAt(Math.floor(Math.random() * charactersLength));\n    }\n    return result;\n}\n\nexport default class SvgWrapper {\n    constructor(themeManager, target, options, clear = true) {\n        if (typeof target === 'string' || target instanceof String) {\n            this.svg = document.getElementById(target);\n        }\n        else {\n            this.svg = target;\n        }\n\n        this.container = null;\n        this.opts = options;\n        this.uid = makeid(5);\n        this.gradientId = 0;\n\n        this.defaultGradients = new Map();\n\n        // maintain a list of line elements and their corresponding gradients\n        // maintain a list of vertex elements\n        // maintain a list of highlighting elements\n        this.backgroundItems = [];\n        this.paths = [];\n        this.vertices = [];\n        this.gradients = [];\n        this.highlights = [];\n\n        // maintain the dimensions\n        this.drawingWidth = 0;\n        this.drawingHeight = 0;\n        this.halfBondThickness = this.opts.bondThickness / 2.0;\n\n        // for managing color schemes\n        this.themeManager = themeManager;\n\n        // create the mask\n        this.maskElements = [];\n\n        // min and max values of the coordinates\n        this.maxX = -Number.MAX_VALUE;\n        this.maxY = -Number.MAX_VALUE;\n        this.minX = Number.MAX_VALUE;\n        this.minY = Number.MAX_VALUE;\n\n        // clear the svg element\n        if (clear) {\n            while (this.svg.firstChild) {\n                this.svg.removeChild(this.svg.firstChild);\n            }\n        }\n\n        // Create styles here as text measurement is done before constructSvg\n        this.style = document.createElementNS('http://www.w3.org/2000/svg', 'style');\n\n        // create the css styles\n        this.style.appendChild(document.createTextNode(`\n                .element {\n                    font: ${this.opts.fontSizeLarge}pt ${this.opts.fontFamily};\n                }\n                .sub {\n                    font: ${this.opts.fontSizeSmall}pt ${this.opts.fontFamily};\n                }\n            `));\n\n        if (this.svg) {\n            this.svg.appendChild(this.style);\n        }\n        else {\n            this.container = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n            this.container.appendChild(this.style);\n        }\n    }\n\n    constructSvg() {\n    // TODO: add the defs element to put gradients in\n        let defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'),\n            masks = document.createElementNS('http://www.w3.org/2000/svg', 'mask'),\n            background = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\n            highlights = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\n            paths = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\n            vertices = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\n            pathChildNodes = this.paths;\n\n        { // Set up the basic masking layer...\n            let mask = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n            mask.setAttributeNS(null, 'x', this.minX);\n            mask.setAttributeNS(null, 'y', this.minY);\n            mask.setAttributeNS(null, 'width', this.maxX - this.minX);\n            mask.setAttributeNS(null, 'height', this.maxY - this.minY);\n            mask.setAttributeNS(null, 'fill', 'white');\n\n            masks.appendChild(mask);\n        }\n\n        // give the mask an id and set bounds explicitly for userSpaceOnUse\n        masks.setAttributeNS(null, 'id', this.uid + '-text-mask');\n        masks.setAttributeNS(null, 'maskUnits', 'userSpaceOnUse');\n        masks.setAttributeNS(null, 'x', this.minX);\n        masks.setAttributeNS(null, 'y', this.minY);\n        masks.setAttributeNS(null, 'width', this.maxX - this.minX);\n        masks.setAttributeNS(null, 'height', this.maxY - this.minY);\n\n        for (let path of pathChildNodes) {\n            paths.appendChild(path);\n        }\n\n        for (let backgroundItem of this.backgroundItems) {\n            background.appendChild(backgroundItem);\n        }\n        for (let highlight of this.highlights) {\n            highlights.appendChild(highlight);\n        }\n        for (let vertex of this.vertices) {\n            vertices.appendChild(vertex);\n        }\n        for (let mask of this.maskElements) {\n            masks.appendChild(mask);\n        }\n        for (let gradient of this.gradients) {\n            defs.appendChild(gradient);\n        }\n\n        paths.setAttributeNS(null, 'mask', 'url(#' + this.uid + '-text-mask)');\n\n        this.updateViewbox(this.opts.scale);\n\n        if (this.svg) {\n            this.svg.appendChild(defs);\n            this.svg.appendChild(masks);\n            this.svg.appendChild(background);\n            this.svg.appendChild(highlights);\n            this.svg.appendChild(paths);\n            this.svg.appendChild(vertices);\n        }\n        else {\n            this.container.appendChild(defs);\n            this.container.appendChild(masks);\n            this.container.appendChild(background);\n            this.container.appendChild(paths);\n            this.container.appendChild(vertices);\n            return this.container;\n        }\n    }\n\n    /**\n     * Add a background to the svg.\n     */\n    addLayer(svg) {\n        this.backgroundItems.push(svg.firstChild);\n    }\n\n    /**\n     * Get the color or gradient URL for a line.\n     *\n     * @param {Vertex} vertex1 - The vertex on one end of the bond.\n     * @param {Vertex} vertex2 - The vertex on the other end of the bond.\n     * @returns {string} A string that can be used as a stroke or fill.\n     */\n    getBondColor(vertex1, vertex2) {\n        const c1 = this.themeManager.getColor(vertex1.value.element);\n        const c2 = this.themeManager.getColor(vertex2.value.element);\n\n        if (c1 === c2) {\n            return c1;\n        }\n\n        const cc = this.themeManager.getColor('C');\n        const d  = vertex1.position.distance(vertex2.position) / this.opts.bondLength;\n\n        if (d > 0.9 && d < 1.1) {\n            // Bonds of a typical length with carbon on one end can share a radial gradient.\n            if (c1 === cc) return this.getDefaultGradient(vertex2, c2, cc);\n            if (c2 === cc) return this.getDefaultGradient(vertex1, c1, cc);\n        }\n\n        return this.createLinearGradient(vertex1.position, vertex2.position, [\n            ['20%', c1],\n            ['80%', c2],\n        ]);\n    }\n\n    /**\n     * Gets or creates a defaut atom-to-carbon radial gradient around a vertex.\n     *\n     * @param {Vertex}  vertex - The vertex.\n     * @param {?string} color1 - The color of the vertex (uses the color of the atom by default).\n     * @param {?string} color2 - The color at the radiuis (uses the color of carbon by default).\n     * @returns {string} A \"url(#gradient-id)\" string that can be used as a stroke or fill.\n     */\n    getDefaultGradient(vertex, color1, color2) {\n        let gradientUrl = this.defaultGradients.get(vertex);\n        if (gradientUrl) return gradientUrl;\n\n        gradientUrl = this.createRadialGradient(vertex.position, this.opts.bondLength, [\n            ['20%', color1 || this.themeManager.getColor(vertex.value.element)],\n            ['80%', color2 || this.themeManager.getColor('C')],\n        ]);\n\n        this.defaultGradients.set(vertex, gradientUrl);\n        return gradientUrl;\n    }\n\n    /**\n     * Create a radial gradient around a point.\n     *\n     * @param {Vector2} point  - The central point.\n     * @param {number}  radius - A radius around that point.\n     * @param {Array}   stops  - An array of (offset, color) pairs.\n     * @returns {string} A \"url(#gradient-id)\" string that can be used as a stroke or fill.\n     */\n    createRadialGradient(point, radius, stops) {\n        const gradient = document.createElementNS('http://www.w3.org/2000/svg', 'radialGradient');\n        const gradientId = this.uid + `-atom-${this.gradientId++}`;\n\n        gradient.setAttributeNS(null, 'id', gradientId);\n        gradient.setAttributeNS(null, 'gradientUnits', 'userSpaceOnUse');\n        gradient.setAttributeNS(null, 'cx', point.x);\n        gradient.setAttributeNS(null, 'cy', point.y);\n        gradient.setAttributeNS(null, 'r',  radius);\n\n        for (const [offset, color] of stops) {\n            const stop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\n            stop.setAttributeNS(null, 'offset',     offset);\n            stop.setAttributeNS(null, 'stop-color', color);\n            gradient.appendChild(stop);\n        }\n\n        this.gradients.push(gradient);\n        return `url(#${gradientId})`;\n    }\n\n    /**\n     * Create a linear gradient between two points.\n     *\n     * @param {Vector2} point1 - The first point.\n     * @param {Vector2} point2 - The second point.\n     * @param {Array}   stops  - An array of (offset, color) pairs.\n     * @returns {string} A \"url(#gradient-id)\" string that can be used as a stroke or fill.\n     */\n    createLinearGradient(point1, point2, stops) {\n        const gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient');\n        const gradientId = this.uid + `-bond-${this.gradientId++}`;\n\n        gradient.setAttributeNS(null, 'id', gradientId);\n        gradient.setAttributeNS(null, 'gradientUnits', 'userSpaceOnUse');\n        gradient.setAttributeNS(null, 'x1', point1.x);\n        gradient.setAttributeNS(null, 'y1', point1.y);\n        gradient.setAttributeNS(null, 'x2', point2.x);\n        gradient.setAttributeNS(null, 'y2', point2.y);\n\n        for (const [offset, color] of stops) {\n            const stop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\n            stop.setAttributeNS(null, 'offset',     offset);\n            stop.setAttributeNS(null, 'stop-color', color);\n            gradient.appendChild(stop);\n        }\n\n        this.gradients.push(gradient);\n        return `url(#${gradientId})`;\n    }\n\n    /**\n     * Create a tspan element for sub or super scripts that styles the text\n     * appropriately as one of those text types.\n     *\n     * @param {String} text the actual text\n     * @param {String} shift the type of text, either 'sub', or 'super'\n     */\n    createSubSuperScripts(text, shift) {\n        let elem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\n        elem.setAttributeNS(null, 'baseline-shift', shift);\n        elem.appendChild(document.createTextNode(text));\n        elem.setAttributeNS(null, 'class', 'sub');\n\n        return elem;\n    }\n\n    static createUnicodeCharge(n) {\n        if (n === 1) {\n            return '\u207A';\n        }\n\n        if (n === -1) {\n            return '\u207B';\n        }\n\n        if (n > 1) {\n            return SvgWrapper.createUnicodeSuperscript(n) + '\u207A';\n        }\n\n        if (n < -1) {\n            return SvgWrapper.createUnicodeSuperscript(n) + '\u207B';\n        }\n\n        return '';\n    }\n\n    /**\n     * Determine drawing dimensiosn based on vertex positions.\n     *\n     * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\n     */\n    determineDimensions(vertices) {\n        for (let i = 0; i < vertices.length; i++) {\n            if (!vertices[i].value.isDrawn) {\n                continue;\n            }\n\n            let p = vertices[i].position;\n\n            if (this.maxX < p.x) this.maxX = p.x;\n            if (this.maxY < p.y) this.maxY = p.y;\n            if (this.minX > p.x) this.minX = p.x;\n            if (this.minY > p.y) this.minY = p.y;\n        }\n\n        // Add padding\n        let padding = this.opts.padding;\n        this.maxX += padding;\n        this.maxY += padding;\n        this.minX -= padding;\n        this.minY -= padding;\n\n        this.drawingWidth = this.maxX - this.minX;\n        this.drawingHeight = this.maxY - this.minY;\n    }\n\n    updateViewbox(scale) {\n        let x = this.minX;\n        let y = this.minY;\n        let width = this.maxX - this.minX;\n        let height = this.maxY - this.minY;\n\n        if (scale <= 0.0) {\n            if (width > height) {\n                let diff = width - height;\n                height = width;\n                y -= diff / 2.0;\n            }\n            else {\n                let diff = height - width;\n                width = height;\n                x -= diff / 2.0;\n            }\n        }\n        else {\n            if (this.svg) {\n                this.svg.style.width = scale * width + 'px';\n                this.svg.style.height = scale * height + 'px';\n            }\n        }\n\n        this.svg.setAttributeNS(null, 'viewBox', `${x} ${y} ${width} ${height}`);\n    }\n\n    /**\n     * Draw an svg ellipse as a ball.\n     *\n     * @param {Number} x The x position of the text.\n     * @param {Number} y The y position of the text.\n     * @param {String} elementName The name of the element (single-letter).\n     */\n    drawBall(x, y, elementName) {\n        let r = this.opts.bondLength / 4.5;\n\n        if (x - r < this.minX) {\n            this.minX = x - r;\n        }\n\n        if (x + r > this.maxX) {\n            this.maxX = x + r;\n        }\n\n        if (y - r < this.minY) {\n            this.minY = y - r;\n        }\n\n        if (y + r > this.maxY) {\n            this.maxY = y + r;\n        }\n\n        let ball = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n        ball.setAttributeNS(null, 'cx', x);\n        ball.setAttributeNS(null, 'cy', y);\n        ball.setAttributeNS(null, 'r', r);\n        ball.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\n\n        this.vertices.push(ball);\n    }\n\n    /**\n     * @param {Line}   line  - The line object to create the wedge from.\n     * @param {string} color - A CSS color or url(#gradient-id) (defaults to black).\n     */\n    drawWedge(line, color = '#000') {\n        let l = line.getLeftVector().clone(),\n            r = line.getRightVector().clone();\n\n        let normals = Vector2.normals(l, r);\n\n        normals[0].normalize();\n        normals[1].normalize();\n\n        let isRightChiralCenter = line.getRightChiral();\n\n        let start = l,\n            end = r;\n\n        if (isRightChiralCenter) {\n            start = r;\n            end = l;\n        }\n\n        let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness)),\n            u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 3.0 + this.opts.fontSizeLarge / 4.0)),\n            v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 3.0 + this.opts.fontSizeLarge / 4.0)),\n            w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\n\n        const polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');\n        polygon.setAttributeNS(null, 'points', `${t.x},${t.y} ${u.x},${u.y} ${v.x},${v.y} ${w.x},${w.y}`);\n        polygon.setAttributeNS(null, 'fill',   color);\n        this.paths.push(polygon);\n    }\n\n    /* Draw a highlight for an atom\n     *\n     *  @param {Number} x The x position of the highlight\n     *  @param {Number} y The y position of the highlight\n     *  @param {string} color The color of the highlight, default #03fc9d\n     */\n    drawAtomHighlight(x, y, color = '#03fc9d') {\n        let ball = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n        ball.setAttributeNS(null, 'cx', x);\n        ball.setAttributeNS(null, 'cy', y);\n        ball.setAttributeNS(null, 'r', this.opts.bondLength / 3);\n        ball.setAttributeNS(null, 'fill', color);\n\n        this.highlights.push(ball);\n    }\n\n    /**\n     * Draw a dashed wedge on the canvas.\n     *\n     * @param {Line}   line  - A line.\n     * @param {string} color - A CSS color or url(#gradient-id) (defaults to black).\n     */\n    drawDashedWedge(line, color = '#000') {\n        if (isNaN(line.from.x) || isNaN(line.from.y) || isNaN(line.to.x) || isNaN(line.to.y)) {\n            console.error('Invalid line passed to SvgWrapper.drawDashedWedge()!', line);\n            return;\n        }\n\n        let l = line.getLeftVector().clone(),\n            r = line.getRightVector().clone(),\n            normals = Vector2.normals(l, r);\n\n        normals[0].normalize();\n        normals[1].normalize();\n\n        let isRightChiralCenter = line.getRightChiral(),\n            start,\n            end;\n\n        if (isRightChiralCenter) {\n            start = r;\n            end = l;\n        }\n        else {\n            start = l;\n            end = r;\n        }\n\n        let dir = Vector2.subtract(end, start).normalize(),\n            length = line.getLength(),\n            step = 1.25 / (length / (this.opts.bondLength / 10.0));\n\n        for (let t = 0.0; t < 1.0; t += step) {\n            let to = Vector2.multiplyScalar(dir, t * length),\n                startDash = Vector2.add(start, to),\n                width = this.opts.fontSizeLarge / 2.0 * t,\n                dashOffset = Vector2.multiplyScalar(normals[0], width);\n\n            startDash.subtract(dashOffset);\n            let endDash = startDash.clone();\n            endDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\n\n            this.drawLine(new Line(startDash, endDash), false, color);\n        }\n    }\n\n    /**\n     * Draws a debug dot at a given coordinate and adds text.\n     *\n     * @param {Number} x The x coordinate.\n     * @param {Number} y The y coordindate.\n     * @param {String} [debugText=''] A string.\n     * @param {String} [color='#f00'] A color in hex form.\n     */\n    drawDebugPoint(x, y, debugText = '', color = '#f00') {\n        let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n        point.setAttributeNS(null, 'cx', x);\n        point.setAttributeNS(null, 'cy', y);\n        point.setAttributeNS(null, 'r', '2');\n        point.setAttributeNS(null, 'fill', color);\n        this.vertices.push(point);\n        this.drawDebugText(x + 2, y - 2, debugText, color);\n    }\n\n    /**\n     * Draws a debug text message at a given position\n     *\n     * @param {Number} x The x coordinate.\n     * @param {Number} y The y coordinate.\n     * @param {String} text The debug text.\n     */\n    drawDebugText(x, y, text, color = '#f00') {\n        let textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');\n        textElem.setAttributeNS(null, 'x', x);\n        textElem.setAttributeNS(null, 'y', y);\n        textElem.setAttributeNS(null, 'class', 'debug');\n        textElem.setAttributeNS(null, 'fill', color);\n        textElem.setAttributeNS(null, 'style', 'font: 5px sans-serif');\n        textElem.appendChild(document.createTextNode(text));\n\n        this.vertices.push(textElem);\n    }\n\n    /**\n     * Draws a ring.\n     *\n     * @param {x} x The x coordinate of the ring.\n     * @param {y} r The y coordinate of the ring.\n     * @param {s} s The size of the ring.\n     */\n    drawRing(x, y, s) {\n        let circleElem = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n        let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, s);\n        circleElem.setAttributeNS(null, 'cx', x);\n        circleElem.setAttributeNS(null, 'cy', y);\n        circleElem.setAttributeNS(null, 'r', radius - this.opts.bondSpacing);\n        circleElem.setAttributeNS(null, 'stroke', this.themeManager.getColor('C'));\n        circleElem.setAttributeNS(null, 'stroke-width', this.opts.bondThickness);\n        circleElem.setAttributeNS(null, 'fill', 'none');\n        this.paths.push(circleElem);\n    }\n\n    /**\n     * Draws a line.\n     *\n     * @param {Line}    line    - A line.\n     * @param {boolean} dashed  - Defaults to false.\n     * @param {string}  color   - A CSS color or url(#gradient-id).\n     * @param {string}  linecap - Defaults to round.\n     *\n     * TODO: Promote `color` to be the second argument, and maybe make it required.\n     * If we make it required, we should do that for other drawing functions as well.\n     * This is API-changing, so save it for v3.0...\n     */\n    drawLine(line, dashed = false, color = '#000', linecap = 'round') {\n        const l = line.getLeftVector();\n        const r = line.getRightVector();\n\n        const lineElem = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n        lineElem.setAttributeNS(null, 'x1', l.x);\n        lineElem.setAttributeNS(null, 'y1', l.y);\n        lineElem.setAttributeNS(null, 'x2', r.x);\n        lineElem.setAttributeNS(null, 'y2', r.y);\n\n        lineElem.setAttributeNS(null, 'stroke',         color);\n        lineElem.setAttributeNS(null, 'stroke-width',   this.opts.bondThickness);\n        lineElem.setAttributeNS(null, 'stroke-linecap', linecap);\n        if (dashed) {\n            lineElem.setAttributeNS(null, 'stroke-dasharray', '5,5');\n        }\n\n        this.paths.push(lineElem);\n    }\n\n    /**\n     * Draw a point.\n     *\n     * @param {Number} x The x position of the point.\n     * @param {Number} y The y position of the point.\n     * @param {String} elementName The name of the element (single-letter).\n     */\n    drawPoint(x, y, elementName) {\n        let r = 0.75;\n\n        if (x - r < this.minX) {\n            this.minX = x - r;\n        }\n\n        if (x + r > this.maxX) {\n            this.maxX = x + r;\n        }\n\n        if (y - r < this.minY) {\n            this.minY = y - r;\n        }\n\n        if (y + r > this.maxY) {\n            this.maxY = y + r;\n        }\n\n        // first create a mask\n        let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n        mask.setAttributeNS(null, 'cx', x);\n        mask.setAttributeNS(null, 'cy', y);\n        mask.setAttributeNS(null, 'r', '1.5');\n        mask.setAttributeNS(null, 'fill', 'black');\n        this.maskElements.push(mask);\n\n        // now create the point\n        let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n        point.setAttributeNS(null, 'cx', x);\n        point.setAttributeNS(null, 'cy', y);\n        point.setAttributeNS(null, 'r', r);\n        point.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\n        this.vertices.push(point);\n    }\n\n    /**\n     * Draw a text to the canvas.\n     *\n     * @param {Number} x The x position of the text.\n     * @param {Number} y The y position of the text.\n     * @param {String} elementName The name of the element (single-letter).\n     * @param {Number} hydrogens The number of hydrogen atoms.\n     * @param {String} direction The direction of the text in relation to the associated vertex.\n     * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\n     * @param {Number} charge The charge of the atom.\n     * @param {Number} isotope The isotope number.\n     * @param {Number} totalVertices The total number of vertices in the graph.\n     * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\n     * @param {String} attachedPseudoElement.element The element symbol.\n     * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\n     * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\n     */\n    drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, totalVertices, attachedPseudoElement = {}) {\n        let text = [];\n        let display = elementName;\n\n        if (charge !== 0 && charge !== null) {\n            display += SvgWrapper.createUnicodeCharge(charge);\n        }\n\n        if (isotope !== 0 && isotope !== null) {\n            display = SvgWrapper.createUnicodeSuperscript(isotope) + display;\n        }\n\n        text.push([display, elementName]);\n\n        if (hydrogens === 1) {\n            text.push(['H', 'H']);\n        }\n        else if (hydrogens > 1) {\n            text.push(['H' + SvgWrapper.createUnicodeSubscript(hydrogens), 'H']);\n        }\n\n        // TODO: Better handle exceptions\n        // Exception for nitro (draw nitro as NO2 instead of N+O-O)\n        if (charge === 1 && elementName === 'N' && '0O' in attachedPseudoElement && '0O-1' in attachedPseudoElement) {\n            attachedPseudoElement = {'0O': {element: 'O', count: 2, hydrogenCount: 0, previousElement: 'C', charge: ''}};\n            charge = 0;\n        }\n\n        for (let key of Object.keys(attachedPseudoElement)) {\n            let pe = attachedPseudoElement[key];\n            let pe_display = pe.element;\n\n            if (pe.count > 1) {\n                pe_display += SvgWrapper.createUnicodeSubscript(pe.count);\n            }\n\n            if (pe.charge) {\n                pe_display += SvgWrapper.createUnicodeCharge(pe.charge);\n            }\n\n            text.push([pe_display, pe.element]);\n\n            const hcount = pe.hydrogenCount * pe.count;\n            if (hcount === 1) {\n                text.push(['H', 'H']);\n            }\n            else if (hcount > 1) {\n                text.push(['H' + SvgWrapper.createUnicodeSubscript(hcount), 'H']);\n            }\n        }\n\n        this.write(text, direction, x, y, totalVertices === 1);\n    }\n\n    /**\n     * Draw highlights under the heavy atoms (blurred using a CSS filter).\n     *\n     * @param {number[]}  weights - An array of weights, one for each heavy atom.\n     * @param {Vector2[]} points  - An array of points, one for each heavy atom.\n     * @param {number}    scale   - A multiplier used to normalize the weights (typically 1/max(abs(weights))).\n     */\n    drawWeights(weights, points, scale) {\n        // NOTE: This calculates the highlight circle radius and the blur radius\n        // based on opts.weights.sigma and tries to mimic the existing (GaussDrawer)\n        // output.  We'll eventually want dedicated options for those instead.\n        const sigma = this.opts.weights.sigma;\n\n        // Use the first and last colors in the color map, if given.\n        // Default to the same values as GaussDrawer (https://loading.io/color/feature/PiYG-11/).\n        // TODO: Suport a full color map and the option to disable opacity scaling.\n        const cmap = this.opts.weights.colormap;\n        const pos  = (cmap == null) ? '#4d9221' : cmap[cmap.length - 1];\n        const neg  = (cmap == null) ? '#c51b7d' : cmap[0];\n\n        // This uses a CSS blur because it's simple and because different browsers\n        // interpret feGaussianBlur's stdDeviation attribute differently (\u03C3 vs 2\u03C3).\n        // TODO: Test this in other rendering engines, and if they can't handle it,\n        // add feGaussianBlur back as a fallback / configuration option.\n        const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n        g.setAttributeNS(null, 'style', `filter:blur(${sigma / 2}px)`);\n        this.backgroundItems.push(g);\n\n        for (let i = 0; i < weights.length; ++i) {\n            const weight = weights[i];\n            const point  = points[i];\n            if (!weight) continue;\n\n            let color = (weight > 0) ? pos : neg;\n            color = `rgb(from ${color} r g b / ${Math.abs(weight) * scale})`;\n\n            const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n            circle.setAttributeNS(null, 'cx',   point.x);\n            circle.setAttributeNS(null, 'cy',   point.y);\n            circle.setAttributeNS(null, 'r',    sigma);\n            circle.setAttributeNS(null, 'fill', color);\n            g.appendChild(circle);\n        }\n    }\n\n    write(text, direction, x, y, singleVertex) {\n        // Measure element name only, without charge or isotope ...\n        let bbox = SvgWrapper.measureText(text[0][1], this.opts.fontSizeLarge, this.opts.fontFamily);\n\n        // For left-direction text with charges/isotopes, account for\n        // the extra width from decorations without inflating the bbox\n        if (direction === 'left' && text[0][0] !== text[0][1]) {\n            let fullBbox = SvgWrapper.measureText(text[0][0], this.opts.fontSizeLarge, this.opts.fontFamily);\n            bbox.width = fullBbox.width;\n        }\n\n        // Get the approximate width and height of text and add update max/min\n        // to allow for narrower paddings\n        if (singleVertex) {\n            if (x + bbox.width * text.length > this.maxX) {\n                this.maxX = x + bbox.width * text.length;\n            }\n            if (x - bbox.width / 2.0 < this.minX) {\n                this.minX = x - bbox.width / 2.0;\n            }\n            if (y - bbox.height < this.minY) {\n                this.minY = y - bbox.height;\n            }\n            if (y + bbox.height > this.maxY) {\n                this.maxY = y + bbox.height;\n            }\n        }\n        else {\n            if (direction !== 'right') {\n                if (x + bbox.width * text.length > this.maxX) {\n                    this.maxX = x + bbox.width * text.length;\n                }\n                if (x - bbox.width * text.length < this.minX) {\n                    this.minX = x - bbox.width * text.length;\n                }\n            }\n            else if (direction !== 'left') {\n                if (x + bbox.width * text.length > this.maxX) {\n                    this.maxX = x + bbox.width * text.length;\n                }\n                if (x - bbox.width / 2.0 < this.minX) {\n                    this.minX = x - bbox.width / 2.0;\n                }\n            }\n\n            if (y - bbox.height < this.minY) {\n                this.minY = y - bbox.height;\n            }\n\n            if (y + bbox.height > this.maxY) {\n                this.maxY = y + bbox.height;\n            }\n\n            if (direction === 'down') {\n                if (y + 0.8 * bbox.height * text.length > this.maxY) {\n                    this.maxY = y + 0.8 * bbox.height * text.length;\n                }\n            }\n\n            if (direction === 'up') {\n                if (y - 0.8 * bbox.height * text.length < this.minY) {\n                    this.minY = y - 0.8 * bbox.height * text.length;\n                }\n            }\n        }\n\n        let cx = x;\n        let cy = y;\n\n        // Draw the text\n        let textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');\n        textElem.setAttributeNS(null, 'class', 'element');\n        let g = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n\n        textElem.setAttributeNS(null, 'fill', '#ffffff');\n\n        if (direction === 'left') {\n            text = text.reverse();\n        }\n\n        if (direction === 'right' || direction === 'down' || direction === 'up') {\n            x -= bbox.width / 2.0;\n        }\n\n        if (direction === 'left') {\n            x += bbox.width / 2.0;\n        }\n\n        text.forEach((part, i) => {\n            const display = part[0];\n            const elementName = part[1];\n            let tspanElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\n            tspanElem.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\n            tspanElem.textContent = display;\n\n            if (direction === 'up' || direction === 'down') {\n                tspanElem.setAttributeNS(null, 'x', '0px');\n                if (direction === 'up') {\n                    tspanElem.setAttributeNS(null, 'y', `-${0.9 * i}em`);\n                }\n                else {\n                    tspanElem.setAttributeNS(null, 'y', `${0.9 * i}em`);\n                }\n            }\n\n            textElem.appendChild(tspanElem);\n        });\n\n        textElem.setAttributeNS(null, 'data-direction', direction);\n\n        if (direction === 'left' || direction === 'right') {\n            textElem.setAttributeNS(null, 'dominant-baseline', 'alphabetic');\n            textElem.setAttributeNS(null, 'y', '0.36em');\n        }\n        else {\n            textElem.setAttributeNS(null, 'dominant-baseline', 'central');\n        }\n\n        if (direction === 'left') {\n            textElem.setAttributeNS(null, 'text-anchor', 'end');\n        }\n\n        g.appendChild(textElem);\n\n        g.setAttributeNS(null, 'style', `transform: translateX(${x}px) translateY(${y}px)`);\n\n        let maskRadius = this.opts.fontSizeLarge * 0.75;\n        if (text[0][1].length > 1) {\n            maskRadius = this.opts.fontSizeLarge * 1.1;\n        }\n\n        let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\n        mask.setAttributeNS(null, 'cx', cx);\n        mask.setAttributeNS(null, 'cy', cy);\n        mask.setAttributeNS(null, 'r', maskRadius);\n        mask.setAttributeNS(null, 'fill', 'black');\n\n        this.maskElements.push(mask);\n\n        this.vertices.push(g);\n    }\n\n    /**\n     * Draw the wrapped SVG to a canvas.\n     * @param {HTMLCanvasElement} canvas The canvas element to draw the svg to.\n     */\n    toCanvas(canvas, width, height) {\n        if (typeof canvas === 'string' || canvas instanceof String) {\n            canvas = document.getElementById(canvas);\n        }\n\n        let image = new Image();\n\n        image.onload = function() {\n            canvas.width = width;\n            canvas.height = height;\n            canvas.getContext('2d').drawImage(image, 0, 0, width, height);\n        };\n\n        image.src = 'data:image/svg+xml;charset-utf-8,' + encodeURIComponent(this.svg.outerHTML);\n    }\n\n    static createUnicodeSubscript(n) {\n        let result = '';\n\n        n.toString().split('').forEach((d) => {\n            result += ['\u2080', '\u2081', '\u2082', '\u2083', '\u2084', '\u2085', '\u2086', '\u2087', '\u2088', '\u2089'][parseInt(d)];\n        });\n\n        return result;\n    }\n\n    static createUnicodeSuperscript(n) {\n        let result = '';\n\n        n.toString().split('').forEach((d) => {\n            let parsed = parseInt(d);\n            if (Number.isFinite(parsed)) {\n                result += ['\u2070', '\u00B9', '\u00B2', '\u00B3', '\u2074', '\u2075', '\u2076', '\u2077', '\u2078', '\u2079'][parsed];\n            }\n        });\n\n        return result;\n    }\n\n    static replaceNumbersWithSubscript(text) {\n        let subscriptNumbers = {0: '\u2080', 1: '\u2081', 2: '\u2082', 3: '\u2083', 4: '\u2084', 5: '\u2085', 6: '\u2086', 7: '\u2087', 8: '\u2088', 9: '\u2089'};\n\n        for (const [key, value] of Object.entries(subscriptNumbers)) {\n            text = text.replaceAll(key, value);\n        }\n\n        return text;\n    }\n\n    static measureText(text, fontSize, fontFamily) {\n        const element = document.createElement('canvas');\n        const ctx = element.getContext('2d');\n        // In some environments (Node.js, JSDOM, CI runners) the canvas element\n        // exists but there is no graphics backend behind it causing getContext('2d')\n        // to return null\n        // Fall back to arithmetic estimation so the layout doesn't break\n        if (!ctx) {\n            return SvgWrapper.estimateTextSize(text, fontSize);\n        }\n\n        // In Firefox, the measureText() function is inconsistent at small font sizes.\n        // So measure a large(ish) font, then scale the measurements later.\n        const scale = fontSize / 16;\n        ctx.font = `16pt ${fontFamily}`;\n        const textMetrics = ctx.measureText(text);\n\n        const w = Math.abs(textMetrics.actualBoundingBoxLeft)   + Math.abs(textMetrics.actualBoundingBoxRight);\n        const h = Math.abs(textMetrics.actualBoundingBoxAscent) + Math.abs(textMetrics.actualBoundingBoxDescent);\n\n        return {\n            width:  w * scale,\n            height: h * scale,\n        };\n    }\n\n    static estimateTextSize(text, fontSize) {\n        let width = 0;\n\n        for (const char of String(text)) {\n            if (char === ' ') {\n                width += 0.35;\n            }\n            else if (/[A-Z]/.test(char)) {\n                width += 0.68;\n            }\n            else if (/[a-z]/.test(char)) {\n                width += 0.56;\n            }\n            else if (/[0-9]/.test(char)) {\n                width += 0.55;\n            }\n            else {\n                width += 0.45;\n            }\n        }\n\n        return {\n            width:  fontSize * width,\n            height: fontSize,\n        };\n    }\n\n    /**\n     * Convert an SVG to a canvas. Warning: This happens async!\n     *\n     * @param {SVGElement} svg\n     * @param {HTMLCanvasElement} canvas\n     * @param {Number} width\n     * @param {Number} height\n     * @param {CallableFunction} callback\n     * @returns {HTMLCanvasElement} The input html canvas element after drawing to.\n     */\n    static svgToCanvas(svg, canvas, width, height, callback = null) {\n        svg.setAttributeNS(null, 'width', width);\n        svg.setAttributeNS(null, 'height', height);\n\n        let image = document.createElement('img');\n        image.onload = function() {\n            canvas.width = width;\n            canvas.height = height;\n\n            let context = canvas.getContext('2d');\n            context.imageSmoothingEnabled = false;\n            context.drawImage(image, 0, 0, width, height);\n\n            if (callback) {\n                callback(canvas);\n            }\n        };\n\n        image.onerror = function(err) {\n            console.log(err);\n        };\n\n        image.src = 'data:image/svg+xml;charset-utf-8,' + encodeURIComponent(svg.outerHTML);\n        return canvas;\n    }\n\n    /**\n     * Convert an SVG to a canvas. Warning: This happens async!\n     *\n     * @param {SVGElement} svg\n     * @param {HTMLImageElement} canvas\n     * @param {Number} width\n     * @param {Number} height\n     */\n    static svgToImg(svg, img, width, height) {\n        let canvas = document.createElement('canvas');\n        this.svgToCanvas(svg, canvas, width, height, () => {\n            img.src = canvas.toDataURL('image/png');\n        });\n    }\n\n    /**\n     * Create an SVG element containing text.\n     * @param {String} text\n     * @param {*} themeManager\n     * @param {*} options\n     * @returns {{svg: SVGElement, width: Number, height: Number}} The SVG element containing the text and its dimensions.\n     */\n    static writeText(text, themeManager, fontSize, fontFamily, maxWidth = Number.MAX_SAFE_INTEGER) {\n        let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n        let style = document.createElementNS('http://www.w3.org/2000/svg', 'style');\n        style.appendChild(document.createTextNode(`\n            .text {\n                font: ${fontSize}pt ${fontFamily};\n                dominant-baseline: alphabetic;\n            }\n        `));\n        svg.appendChild(style);\n\n        let textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');\n        textElem.setAttributeNS(null, 'class', 'text');\n\n        let lines = [];\n        text.split('\\n').forEach((line) => {\n            let dims = SvgWrapper.measureText(line, fontSize, fontFamily);\n            if (dims.width >= maxWidth) {\n                const words  = line.split(' ');\n                let   offset = 0;\n\n                for (let i = 0; i < words.length; i++) {\n                    const part     = words.slice(offset, i + 1).join(' ');\n                    const partDims = SvgWrapper.measureText(part, fontSize, fontFamily);\n\n                    if (partDims.width > maxWidth && i > offset) {\n                        lines.push(words.slice(offset, i).join(' '));\n                        offset = i;\n                    }\n                }\n\n                if (offset < words.length) {\n                    lines.push(words.slice(offset, words.length).join(' '));\n                }\n            }\n            else {\n                lines.push(line);\n            }\n        });\n\n        let maxLineWidth = 0.0;\n        lines.forEach((line, i) => {\n            let tspanElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\n            tspanElem.setAttributeNS(null, 'fill', themeManager.getColor('C'));\n            tspanElem.textContent = line;\n            tspanElem.setAttributeNS(null, 'x', '0px');\n            tspanElem.setAttributeNS(null, 'y', `${i + 1}em`);\n            textElem.appendChild(tspanElem);\n\n            const dims = SvgWrapper.measureText(line, fontSize, fontFamily);\n            maxLineWidth = Math.max(maxLineWidth, dims.width);\n        });\n\n        textElem.setAttributeNS(null, 'transform',   `translate(${maxLineWidth / 2}, 0)`);\n        textElem.setAttributeNS(null, 'text-anchor', 'middle');\n\n        svg.appendChild(textElem);\n\n        // The extra 0.4 here is to account for any subscripts on the bottom line.\n        // The factor of 4 / 3 is to convert from points to CSS pixels (1in = 72pt = 96px).\n        return {svg: svg, width: maxLineWidth, height: (lines.length + 0.4) * fontSize * 4 / 3};\n    }\n}\n", "// @ts-check\n// we use the drawer to do all the preprocessing. then we take over the drawing\n// portion to output to svg\nimport ArrayHelper  from './ArrayHelper';\nimport Atom         from './Atom';\nimport DrawerBase   from './DrawerBase';\nimport GaussDrawer  from './GaussDrawer';\nimport Line         from './Line';\nimport Ring         from './Ring';\nimport SvgWrapper   from './SvgWrapper';\nimport ThemeManager from './ThemeManager';\nimport Vector2      from './Vector2';\n\nexport default class SvgDrawer {\n    constructor(options, clear = true) {\n        this.preprocessor = new DrawerBase(options);\n        this.opts = this.preprocessor.opts;\n        this.clear = clear;\n        this.svgWrapper = null;\n    }\n\n    /**\n     * Draws the parsed smiles data to an svg element.\n     *\n     * @param {Object} data The tree returned by the smiles parser.\n     * @param {?(string|String|Element)} target The id of the HTML svg element the structure is drawn to - or the element itself.\n     * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\n     * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\n     *\n     * @returns {SVGSVGElement} The (possibly new) SVG element that was drawn to.\n     */\n    draw(data, target, themeName = 'light', weights = null, infoOnly = false, highlight_atoms = [], weightsNormalized = false) {\n        let svg = null;\n\n        if (target === null || target === 'svg') {\n            svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n            svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n            svg.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');\n            svg.setAttributeNS(null, 'width', this.opts.width);\n            svg.setAttributeNS(null, 'height', this.opts.height);\n        }\n        else if (target instanceof String) {\n            svg = document.getElementById(target.valueOf());\n        }\n        else if (typeof target === 'string') {\n            svg = document.getElementById(target);\n        }\n        else {\n            svg = target;\n        }\n\n        if (!(svg instanceof SVGSVGElement)) {\n            throw Error('Second argument was not an SVG or the ID of an SVG.');\n        }\n\n        let optionBackup = {\n            padding:        this.opts.padding,\n            compactDrawing: this.opts.compactDrawing,\n        };\n\n        // Overwrite options when weights are added\n        if (weights !== null) {\n            this.opts.padding += this.opts.weights.additionalPadding;\n            this.opts.compactDrawing = false;\n        }\n\n        let preprocessor = this.preprocessor;\n\n        preprocessor.initDraw(data, themeName, infoOnly, highlight_atoms);\n\n        if (!infoOnly) {\n            this.themeManager = new ThemeManager(this.opts.themes, themeName);\n            if (this.svgWrapper === null || this.clear) {\n                this.svgWrapper = new SvgWrapper(this.themeManager, svg, this.opts, this.clear);\n            }\n        }\n\n        preprocessor.processGraph();\n\n        // Set the canvas to the appropriate size\n        this.svgWrapper.determineDimensions(preprocessor.graph.vertices);\n\n        // Do the actual drawing\n        this.drawAtomHighlights(preprocessor.opts.debug);\n        this.drawEdges(preprocessor.opts.debug);\n        this.drawVertices(preprocessor.opts.debug);\n\n        if (weights !== null) {\n            this.drawWeights(weights, weightsNormalized);\n        }\n\n        if (preprocessor.opts.debug) {\n            console.debug('SvgDrawer::draw()', {\n                graph:           preprocessor.graph,\n                rings:           preprocessor.rings,\n                ringConnections: preprocessor.ringConnections,\n            });\n        }\n\n        this.svgWrapper.constructSvg();\n\n        // Reset options in case weights were added.\n        if (weights !== null) {\n            this.opts.padding = optionBackup.padding;\n            this.opts.compactDrawing = optionBackup.padding;\n        }\n\n        return svg;\n    }\n\n    /**\n     * Draws the parsed smiles data to a canvas element.\n     *\n     * @param {Object} data The tree returned by the smiles parser.\n     * @param {(string|String|HTMLCanvasElement)} target The id of the HTML canvas element the structure is drawn to - or the element itself.\n     * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\n     * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\n     */\n    drawCanvas(data, target, themeName = 'light', infoOnly = false) {\n        let canvas = null;\n        if (target instanceof String) {\n            canvas = document.getElementById(target.valueOf());\n        }\n        else if (typeof target === 'string') {\n            canvas = document.getElementById(target);\n        }\n        else {\n            canvas = target;\n        }\n\n        if (!(canvas instanceof HTMLCanvasElement)) {\n            throw Error('Second argument was not a canvas or the ID of a canvas.');\n        }\n\n        let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n        svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n        // 500 as a size is arbritrary, but the canvas is scaled when drawn to the canvas anyway\n        svg.setAttributeNS(null, 'viewBox', '0 0 ' + 500 + ' ' + 500);\n        svg.setAttributeNS(null, 'width', 500 + '');\n        svg.setAttributeNS(null, 'height', 500 + '');\n        svg.setAttributeNS(null, 'style', 'visibility: hidden: position: absolute; left: -1000px');\n        document.body.appendChild(svg);\n        this.draw(data, svg, themeName, infoOnly);\n        this.svgWrapper.toCanvas(canvas, this.opts.width, this.opts.height);\n        document.body.removeChild(svg);\n        return target;\n    }\n\n    /**\n     * Draws a ring inside a provided ring, indicating aromaticity.\n     *\n     * @param {Ring} ring A ring.\n     */\n    drawAromaticityRing(ring) {\n        let svgWrapper = this.svgWrapper;\n        svgWrapper.drawRing(ring.center.x, ring.center.y, ring.getSize());\n    }\n\n    /**\n     * Draw the actual edges as bonds.\n     *\n     * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\n     */\n    drawEdges(debug) {\n        let preprocessor = this.preprocessor,\n            graph = preprocessor.graph,\n            rings = preprocessor.rings,\n            drawn = Array(this.preprocessor.graph.edges.length);\n\n        drawn.fill(false);\n\n        graph.traverseBF(0, (vertex) => {\n            let edges = graph.getEdges(vertex.id);\n            for (let i = 0; i < edges.length; i++) {\n                let edgeId = edges[i];\n                if (!drawn[edgeId]) {\n                    drawn[edgeId] = true;\n                    this.drawEdge(edgeId, debug);\n                }\n            }\n        });\n\n        // Draw the inner circle that marks an aromatic ring (benzene as\n        // hexagon + circle) rings that are part of a bridged system still\n        // get the circle as long as their 2D projection is close enough to\n        // a regular polygon (e.g a flat pyrrole face of a bridged bicyclic).\n        // If the projection is distorted (i.e. not close to a regular polygone), we\n        // skip the circle here and let drawEdge fall back to dashed bonds\n        // long term fix is to kekulise aromatic input for bridged systems in\n        // the parser so the fallback is no longer needed\n        for (let i = 0; i < rings.length; i++) {\n            let ring = rings[i];\n\n            if (!preprocessor.isRingAromatic(ring)) continue;\n\n            if (ring.isPartOfBridged && !preprocessor.isRingRegularPolygon(ring)) {\n                continue;\n            }\n\n            this.drawAromaticityRing(ring);\n        }\n    }\n\n    /**\n     * Draw the an edge as a bond.\n     *\n     * @param {Number} edgeId An edge id.\n     * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\n     */\n    drawEdge(edgeId, debug) {\n        let preprocessor = this.preprocessor,\n            opts = preprocessor.opts,\n            svgWrapper = this.svgWrapper,\n            edge = preprocessor.graph.edges[edgeId],\n            vertexA = preprocessor.graph.vertices[edge.sourceId],\n            vertexB = preprocessor.graph.vertices[edge.targetId],\n            elementA = vertexA.value.element,\n            elementB = vertexB.value.element;\n\n        if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && preprocessor.opts.atomVisualization === 'default') {\n            return;\n        }\n\n        const color = svgWrapper.getBondColor(vertexA, vertexB);\n\n        let a = vertexA.position,\n            b = vertexB.position,\n            normals = preprocessor.getEdgeNormals(edge),\n            // Create a point on each side of the line\n            sides = ArrayHelper.clone(normals);\n\n        sides[0].multiplyScalar(10).add(a);\n        sides[1].multiplyScalar(10).add(a);\n\n        // The third condition handles aromatic bonds inside a bridged ring\n        // system whose 2D projection is too distorted for the usual\n        // aromatic circle (e.g. paracyclophane, triptycene). Those bonds\n        // get drawn as a solid line with a dashed parallel inside the ring.\n        // If the aromatic ring is still close to a regular polygon (e.g.\n        // a flat pyrrole on a bridged bicyclic) we skip this branch and let\n        // drawEdges draw the circle as usual.\n        // The long-term fix is to kekulise aromatic input for bridged\n        // systems in the parser (explicit single/double) so the fallback\n        // is no longer needed.\n        let aromaticRing = (edge.isPartOfAromaticRing\n            && vertexA.value.bridgedRing !== null\n            && vertexB.value.bridgedRing !== null)\n            ? preprocessor.getLargestOrAromaticCommonRing(vertexA, vertexB)\n            : null;\n\n        if (edge.bondType === '='\n            || preprocessor.getRingbondType(vertexA, vertexB) === '='\n            || (aromaticRing && !preprocessor.isRingRegularPolygon(aromaticRing))\n        ) {\n            // Always draw double bonds inside the ring\n            let inRing = preprocessor.areVerticesInSameRing(vertexA, vertexB);\n            let s = preprocessor.chooseSide(vertexA, vertexB, sides);\n\n            if (inRing) {\n                // Always draw double bonds inside a ring\n                // if the bond is shared by two rings, it is drawn in the larger\n                // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\n                let lcr = preprocessor.getLargestOrAromaticCommonRing(vertexA, vertexB);\n                let center = lcr.center;\n\n                normals[0].multiplyScalar(opts.bondSpacing);\n                normals[1].multiplyScalar(opts.bondSpacing);\n\n                // Choose the normal that is on the same side as the center\n                let line = null;\n\n                if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\n                    line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\n                }\n                else {\n                    line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\n                }\n\n                line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\n\n                // Set dashed to true if the edge is part of an aromatic ring:\n                svgWrapper.drawLine(line, edge.isPartOfAromaticRing, color);\n                svgWrapper.drawLine(new Line(a, b, elementA, elementB), false, color);\n            }\n            else if (edge.center\n                || (vertexA.isTerminal() && vertexB.isTerminal())\n                || (s.anCount == 0 && s.bnCount > 1)\n                || (s.bnCount == 0 && s.anCount > 1)\n            ) {\n                this.multiplyNormals(normals, opts.halfBondSpacing);\n\n                let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB),\n                    lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\n\n                svgWrapper.drawLine(lineA, false, color);\n                svgWrapper.drawLine(lineB, false, color);\n            }\n            else if ((s.sideCount[0] > s.sideCount[1]) || (s.totalSideCount[0] > s.totalSideCount[1])) {\n                this.multiplyNormals(normals, opts.bondSpacing);\n\n                let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\n\n                line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\n\n                svgWrapper.drawLine(line, false, color);\n                svgWrapper.drawLine(new Line(a, b, elementA, elementB), false, color);\n            }\n            else if ((s.sideCount[0] < s.sideCount[1]) || (s.totalSideCount[0] <= s.totalSideCount[1])) {\n                this.multiplyNormals(normals, opts.bondSpacing);\n\n                let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\n\n                line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\n                svgWrapper.drawLine(line, false, color);\n                svgWrapper.drawLine(new Line(a, b, elementA, elementB), false, color);\n            }\n        }\n        else if (edge.bondType === '#') {\n            normals[0].multiplyScalar(opts.bondSpacing / 1.5);\n            normals[1].multiplyScalar(opts.bondSpacing / 1.5);\n\n            let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\n            let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\n\n            svgWrapper.drawLine(lineA, false, color);\n            svgWrapper.drawLine(lineB, false, color);\n            svgWrapper.drawLine(new Line(a, b, elementA, elementB), false, color);\n        }\n        else if (edge.bondType === '.') {\n            // TODO: Something... maybe... version 2?\n        }\n        else {\n            let isChiralCenterA = vertexA.value.isStereoCenter;\n            let isChiralCenterB = vertexB.value.isStereoCenter;\n\n            if (edge.wedge === 'up') {\n                svgWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB), color);\n            }\n            else if (edge.wedge === 'down') {\n                svgWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB), color);\n            }\n            else {\n                svgWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB), false, color);\n            }\n        }\n\n        if (debug) {\n            let midpoint = Vector2.midpoint(a, b);\n            svgWrapper.drawDebugText(midpoint.x, midpoint.y, 'e' + edgeId, '#0c0');\n        }\n    }\n\n    /**\n     * Draw the highlights for atoms to the canvas.\n     *\n     * @param {Boolean} _debug UNUSED\n     */\n    drawAtomHighlights(_debug) {\n        let preprocessor = this.preprocessor;\n        let graph = preprocessor.graph;\n        let svgWrapper = this.svgWrapper;\n\n        for (let i = 0; i < graph.vertices.length; i++) {\n            let vertex = graph.vertices[i];\n            let atom = vertex.value;\n\n            for (let j = 0; j < preprocessor.highlight_atoms.length; j++) {\n                let highlight = preprocessor.highlight_atoms[j];\n                if (atom.class === highlight[0]) {\n                    svgWrapper.drawAtomHighlight(vertex.position.x, vertex.position.y, highlight[1]);\n                }\n            }\n        }\n    }\n\n    /**\n     * Draws the vertices representing atoms to the canvas.\n     *\n     * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\n     */\n    drawVertices(debug) {\n        let preprocessor = this.preprocessor,\n            opts = preprocessor.opts,\n            graph = preprocessor.graph,\n            rings = preprocessor.rings,\n            svgWrapper = this.svgWrapper;\n\n        for (let i = 0; i < graph.vertices.length; i++) {\n            let vertex = graph.vertices[i];\n            let atom = vertex.value;\n            let charge = 0;\n            let isotope = 0;\n            let element = atom.element;\n            let hydrogens = atom.countImplicitHydrogens();\n            let dir = vertex.getTextDirection(graph.vertices, atom.hasAttachedPseudoElements);\n            const showCarbonsMode = DrawerBase.getEffectiveShowCarbonsMode(opts);\n            let isTerminal = (showCarbonsMode === 'terminal' || element !== 'C' || atom.hasAttachedPseudoElements) ? vertex.isTerminal() : false;\n            let isCarbon = atom.element === 'C';\n\n            if (element === 'C') {\n                const isRingCarbon = atom.rings && atom.rings.length > 0;\n                if (showCarbonsMode === 'none') {\n                    isCarbon = true;\n                    isTerminal = false;\n                }\n                else if (showCarbonsMode === 'all') {\n                    isCarbon = false;\n                    isTerminal = true;\n                }\n                else if (showCarbonsMode === 'acyclic' && !isRingCarbon) {\n                    isCarbon = false;\n                    isTerminal = true;\n                }\n            }\n\n            if (atom.bracket) {\n                charge = atom.bracket.charge;\n                isotope = atom.bracket.isotope;\n            }\n\n            // If the molecule has less than 3 elements, always write the \"C\" for carbon\n            // Likewise, if the carbon has a charge or an isotope, always draw it\n            if (charge || isotope || graph.vertices.length < 3) {\n                isCarbon = false;\n            }\n\n            if (opts.atomVisualization === 'allballs') {\n                svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\n            }\n            else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || graph.vertices.length === 1) {\n                if (opts.atomVisualization === 'default') {\n                    let attachedPseudoElements = atom.getAttachedPseudoElements();\n\n                    // Draw to the right if the whole molecule is concatenated into one string\n                    if (atom.hasAttachedPseudoElements && graph.vertices.length === Object.keys(attachedPseudoElements).length + 1) {\n                        dir = 'right';\n                    }\n\n                    svgWrapper.drawText(vertex.position.x, vertex.position.y,\n                        element, hydrogens, dir, isTerminal, charge, isotope, graph.vertices.length, attachedPseudoElements);\n                }\n                else if (opts.atomVisualization === 'balls') {\n                    svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\n                }\n            }\n            else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\n                // If there is a carbon which bonds are in a straight line, draw a dot\n                let a = graph.vertices[vertex.neighbours[0]].position;\n                let b = graph.vertices[vertex.neighbours[1]].position;\n                let angle = Vector2.threePointangle(vertex.position, a, b);\n\n                if (Math.abs(Math.PI - angle) < 0.1) {\n                    svgWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\n                }\n            }\n\n            if (debug) {\n                const value = 'v' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\n                svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\n            }\n        }\n\n        // Draw the ring centers for debug purposes\n        if (opts.debug) {\n            for (let i = 0; i < rings.length; i++) {\n                let center = rings[i].center;\n                svgWrapper.drawDebugPoint(center.x, center.y, 'r' + rings[i].id, '#00f');\n            }\n        }\n    }\n\n    /**\n     * Draw the weights on a background image.\n     * @param {Number[]} weights The weights assigned to each atom.\n     */\n    drawWeights(weights, weightsNormalized) {\n        if (!weights) {\n            return;\n        }\n\n        let vertex_ids = this.preprocessor.graph.atomIdxToVertexId;\n        if (weights.length < vertex_ids.length) {\n            vertex_ids = vertex_ids.slice(0, weights.length);\n        }\n        else if (weights.length > vertex_ids.length) {\n            console.warn(`More weights (${weights.length}) than heavy atoms (${vertex_ids.length}); truncating.`);\n            weights = weights.slice(0, vertex_ids.length);\n        }\n\n        let min = 0;\n        let max = 0;\n        for (let i = 0; i < weights.length; ++i) {\n            const weight = weights[i];\n            if (!weight) continue;\n\n            if (weight < min) min = weight;\n            if (weight > max) max = weight;\n        }\n\n        if (min === 0 && max === 0) {\n            return;\n        }\n\n        if (this.opts.experimentalWeights) {\n            const points = vertex_ids.map((vid) => {\n                return this.preprocessor.graph.vertices[vid].position;\n            });\n\n            let scale = this.opts.weights.opacity;\n            if (!weightsNormalized) {\n                scale /= Math.max(-min, max);\n            }\n\n            return this.svgWrapper.drawWeights(weights, points, scale);\n        }\n\n        const minX = this.svgWrapper.minX;\n        const minY = this.svgWrapper.minY;\n        const points = vertex_ids.map((vid) => {\n            const vertex = this.preprocessor.graph.vertices[vid];\n            return new Vector2(vertex.position.x - minX, vertex.position.y - minY);\n        });\n\n        let gd = new GaussDrawer(\n            points, weights, this.svgWrapper.drawingWidth, this.svgWrapper.drawingHeight,\n            this.opts.weights.sigma, this.opts.weights.interval, this.opts.weights.colormap,\n            this.opts.weights.opacity, weightsNormalized\n        );\n\n        gd.draw();\n        const background = gd.getSVG();\n        background.firstElementChild.setAttributeNS(null, 'transform', `translate(${minX},${minY})`);\n        this.svgWrapper.addLayer(background);\n    }\n\n    /**\n     * Returns the total overlap score of the current molecule.\n     *\n     * @returns {Number} The overlap score.\n     */\n    getTotalOverlapScore() {\n        return this.preprocessor.getTotalOverlapScore();\n    }\n\n    /**\n     * Returns the molecular formula of the loaded molecule as a string.\n     *\n     * @returns {String} The molecular formula.\n     */\n    getMolecularFormula(graph = null) {\n        return this.preprocessor.getMolecularFormula(graph);\n    }\n\n    /**\n     * @param {Array} normals list of normals to multiply\n     * @param {Number} spacing value to multiply normals by\n     */\n    multiplyNormals(normals, spacing) {\n        normals[0].multiplyScalar(spacing);\n        normals[1].multiplyScalar(spacing);\n    }\n}\n", "// @ts-check\nimport SvgDrawer from './SvgDrawer';\n\n/**\n * The main class of the application representing the smiles drawer\n *\n * @property {Graph} graph The graph associated with this SmilesDrawer.Drawer instance.\n * @property {Number} ringIdCounter An internal counter to keep track of ring ids.\n * @property {Number} ringConnectionIdCounter An internal counter to keep track of ring connection ids.\n * @property {CanvasWrapper} canvasWrapper The CanvasWrapper associated with this SmilesDrawer.Drawer instance.\n * @property {Number} totalOverlapScore The current internal total overlap score.\n * @property {Object} defaultOptions The default options.\n * @property {Object} opts The merged options.\n * @property {Object} theme The current theme.\n */\nexport default class Drawer {\n    /**\n     * The constructor for the class SmilesDrawer.\n     *\n     * @param {Object} options An object containing custom values for different options. It is merged with the default options.\n     */\n    constructor(options) {\n        this.svgDrawer = new SvgDrawer(options);\n    }\n\n    /**\n     * Draws the parsed smiles data to a canvas element.\n     *\n     * @param {Object} data The tree returned by the smiles parser.\n     * @param {string|String|HTMLCanvasElement} target The id of the HTML canvas element the structure is drawn to - or the element itself.\n     * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\n     * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\n     */\n    draw(data, target, themeName = 'light', infoOnly = false, highlight_atoms = []) {\n        let element = null;\n        let canvas  = null;\n        if (target instanceof String) {\n            element = document.getElementById(target.valueOf());\n        }\n        else if (typeof target === 'string') {\n            element = document.getElementById(target);\n        }\n        else {\n            element = target;\n        }\n\n        if (element instanceof HTMLCanvasElement) {\n            canvas = element;\n        }\n        else {\n            throw Error('Second argument was not a canvas or the ID of a canvas.');\n        }\n\n        let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n        svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n        svg.setAttributeNS(null, 'viewBox', '0 0 ' + this.svgDrawer.opts.width + ' ' + this.svgDrawer.opts.height);\n        svg.setAttributeNS(null, 'width', this.svgDrawer.opts.width + '');\n        svg.setAttributeNS(null, 'height', this.svgDrawer.opts.height + '');\n        this.svgDrawer.draw(data, svg, themeName, null, infoOnly, highlight_atoms);\n        this.svgDrawer.svgWrapper.toCanvas(canvas, this.svgDrawer.opts.width, this.svgDrawer.opts.height);\n    }\n\n    /**\n     * Returns the total overlap score of the current molecule.\n     *\n     * @returns {Number} The overlap score.\n     */\n    getTotalOverlapScore() {\n        return this.svgDrawer.getTotalOverlapScore();\n    }\n\n    /**\n     * Returns the molecular formula of the loaded molecule as a string.\n     *\n     * @returns {String} The molecular formula.\n     */\n    getMolecularFormula() {\n        return this.svgDrawer.getMolecularFormula();\n    }\n}\n", "// WHEN REPLACING, CHECK FOR:\n// KEEP THIS WHEN REGENERATING THE PARSER !!\n\nexport default (function () {\n  \"use strict\";\n\n  /*\n   * Generated by PEG.js 0.10.0.\n   *\n   * http://pegjs.org/\n   */\n\n  function peg$subclass(child, parent) {\n    function ctor() {\n      this.constructor = child;\n    }\n    ctor.prototype = parent.prototype;\n    child.prototype = new ctor();\n  }\n\n  function peg$SyntaxError(message, expected, found, location) {\n    this.message = message;\n    this.expected = expected;\n    this.found = found;\n    this.location = location;\n    this.name = \"SyntaxError\";\n\n    if (typeof Error.captureStackTrace === \"function\") {\n      Error.captureStackTrace(this, peg$SyntaxError);\n    }\n  }\n\n  peg$subclass(peg$SyntaxError, Error);\n\n  peg$SyntaxError.buildMessage = function (expected, found) {\n    var DESCRIBE_EXPECTATION_FNS = {\n      literal: function (expectation) {\n        return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";\n      },\n\n      \"class\": function (expectation) {\n        var escapedParts = \"\",\n          i;\n\n        for (i = 0; i < expectation.parts.length; i++) {\n          escapedParts += expectation.parts[i] instanceof Array ?\n            classEscape(expectation.parts[i][0]) + \"-\" + classEscape(expectation.parts[i][1]) :\n            classEscape(expectation.parts[i]);\n        }\n\n        return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts + \"]\";\n      },\n\n      any: function (expectation) {\n        return \"any character\";\n      },\n\n      end: function (expectation) {\n        return \"end of input\";\n      },\n\n      other: function (expectation) {\n        return expectation.description;\n      }\n    };\n\n    function hex(ch) {\n      return ch.charCodeAt(0).toString(16).toUpperCase();\n    }\n\n    function literalEscape(s) {\n      return s\n        .replace(/\\\\/g, '\\\\\\\\')\n        .replace(/\"/g, '\\\\\"')\n        .replace(/\\0/g, '\\\\0')\n        .replace(/\\t/g, '\\\\t')\n        .replace(/\\n/g, '\\\\n')\n        .replace(/\\r/g, '\\\\r')\n        .replace(/[\\x00-\\x0F]/g, function (ch) {\n          return '\\\\x0' + hex(ch);\n        })\n        .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\n          return '\\\\x' + hex(ch);\n        });\n    }\n\n    function classEscape(s) {\n      return s\n        .replace(/\\\\/g, '\\\\\\\\')\n        .replace(/\\]/g, '\\\\]')\n        .replace(/\\^/g, '\\\\^')\n        .replace(/-/g, '\\\\-')\n        .replace(/\\0/g, '\\\\0')\n        .replace(/\\t/g, '\\\\t')\n        .replace(/\\n/g, '\\\\n')\n        .replace(/\\r/g, '\\\\r')\n        .replace(/[\\x00-\\x0F]/g, function (ch) {\n          return '\\\\x0' + hex(ch);\n        })\n        .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\n          return '\\\\x' + hex(ch);\n        });\n    }\n\n    function describeExpectation(expectation) {\n      return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);\n    }\n\n    function describeExpected(expected) {\n      var descriptions = new Array(expected.length),\n        i, j;\n\n      for (i = 0; i < expected.length; i++) {\n        descriptions[i] = describeExpectation(expected[i]);\n      }\n\n      descriptions.sort();\n\n      if (descriptions.length > 0) {\n        for (i = 1, j = 1; i < descriptions.length; i++) {\n          if (descriptions[i - 1] !== descriptions[i]) {\n            descriptions[j] = descriptions[i];\n            j++;\n          }\n        }\n        descriptions.length = j;\n      }\n\n      switch (descriptions.length) {\n        case 1:\n          return descriptions[0];\n\n        case 2:\n          return descriptions[0] + \" or \" + descriptions[1];\n\n        default:\n          return descriptions.slice(0, -1).join(\", \") +\n            \", or \" +\n            descriptions[descriptions.length - 1];\n      }\n    }\n\n    function describeFound(found) {\n      return found ? \"\\\"\" + literalEscape(found) + \"\\\"\" : \"end of input\";\n    }\n\n    return \"Expected \" + describeExpected(expected) + \" but \" + describeFound(found) + \" found.\";\n  };\n\n  function peg$parse(input, options) {\n    options = options !== void 0 ? options : {};\n\n    // KEEP THIS WHEN REGENERATING THE PARSER !!\n    var nOpenParentheses = input.split('(').length - 1;\n    var nCloseParentheses = input.split(')').length - 1;\n\n    if (nOpenParentheses !== nCloseParentheses) {\n      throw peg$buildSimpleError('The number of opening parentheses does not match the number of closing parentheses.', 0);\n    }\n    // KEEP THIS WHEN REGENERATING THE PARSER !!\n\n    var peg$FAILED = {},\n\n      peg$startRuleFunctions = {\n        chain: peg$parsechain\n      },\n      peg$startRuleFunction = peg$parsechain,\n\n      peg$c0 = function (s) {\n        var branches = [];\n        var rings = [];\n\n        for (var i = 0; i < s[1].length; i++) {\n          branches.push(s[1][i]);\n        }\n\n\n        for (var i = 0; i < s[2].length; i++) {\n          var bond = (s[2][i][0]) ? s[2][i][0] : '-';\n          rings.push({\n            'bond': bond,\n            'id': s[2][i][1]\n          });\n        }\n\n        for (var i = 0; i < s[3].length; i++) {\n          branches.push(s[3][i]);\n        }\n\n        for (var i = 0; i < s[6].length; i++) {\n          branches.push(s[6][i]);\n        }\n\n        return {\n          'atom': s[0],\n          'isBracket': s[0].element ? true : false,\n          'branches': branches,\n          'branchCount': branches.length,\n          'ringbonds': rings,\n          'ringbondCount': rings.length,\n          'bond': s[4] ? s[4] : '-',\n          'next': s[5],\n          'hasNext': s[5] ? true : false\n        }\n      },\n      peg$c1 = \"(\",\n      peg$c2 = peg$literalExpectation(\"(\", false),\n      peg$c3 = \")\",\n      peg$c4 = peg$literalExpectation(\")\", false),\n      peg$c5 = function (b) {\n        var bond = (b[1]) ? b[1] : '-';\n        b[2].branchBond = bond;\n        return b[2]\n      },\n      peg$c6 = function (a) {\n        return a;\n      },\n      peg$c7 = /^[\\-=#$:\\/\\\\.]/,\n      peg$c8 = peg$classExpectation([\"-\", \"=\", \"#\", \"$\", \":\", \"/\", \"\\\\\", \".\"], false, false),\n      peg$c9 = function (b) {\n        return b;\n      },\n      peg$c10 = \"[\",\n      peg$c11 = peg$literalExpectation(\"[\", false),\n      peg$c12 = \"se\",\n      peg$c13 = peg$literalExpectation(\"se\", false),\n      peg$c14 = \"as\",\n      peg$c15 = peg$literalExpectation(\"as\", false),\n      peg$c16 = \"]\",\n      peg$c17 = peg$literalExpectation(\"]\", false),\n      peg$c18 = function (b) {\n        return {\n          'isotope': b[1],\n          'element': b[2],\n          'chirality': b[3],\n          'hcount': b[4],\n          'charge': b[5],\n          'class': b[6]\n        }\n      },\n      peg$c19 = \"B\",\n      peg$c20 = peg$literalExpectation(\"B\", false),\n      peg$c21 = \"r\",\n      peg$c22 = peg$literalExpectation(\"r\", false),\n      peg$c23 = \"C\",\n      peg$c24 = peg$literalExpectation(\"C\", false),\n      peg$c25 = \"l\",\n      peg$c26 = peg$literalExpectation(\"l\", false),\n      peg$c27 = /^[NOPSFI]/,\n      peg$c28 = peg$classExpectation([\"N\", \"O\", \"P\", \"S\", \"F\", \"I\"], false, false),\n      peg$c29 = function (o) {\n        if (o.length > 1) return o.join('');\n        return o;\n      },\n      peg$c30 = /^[bcnops]/,\n      peg$c31 = peg$classExpectation([\"b\", \"c\", \"n\", \"o\", \"p\", \"s\"], false, false),\n      peg$c32 = \"*\",\n      peg$c33 = peg$literalExpectation(\"*\", false),\n      peg$c34 = function (w) {\n        return w;\n      },\n      peg$c35 = /^[A-Z]/,\n      peg$c36 = peg$classExpectation([\n        [\"A\", \"Z\"]\n      ], false, false),\n      peg$c37 = /^[a-z]/,\n      peg$c38 = peg$classExpectation([\n        [\"a\", \"z\"]\n      ], false, false),\n      peg$c39 = function (e) {\n        return e.join('');\n      },\n      peg$c40 = \"%\",\n      peg$c41 = peg$literalExpectation(\"%\", false),\n      peg$c42 = /^[1-9]/,\n      peg$c43 = peg$classExpectation([\n        [\"1\", \"9\"]\n      ], false, false),\n      peg$c44 = /^[0-9]/,\n      peg$c45 = peg$classExpectation([\n        [\"0\", \"9\"]\n      ], false, false),\n      peg$c46 = function (r) {\n        if (r.length == 1) return Number(r);\n        return Number(r.join('').replace('%', ''));\n      },\n      peg$c47 = \"@\",\n      peg$c48 = peg$literalExpectation(\"@\", false),\n      peg$c49 = \"TH\",\n      peg$c50 = peg$literalExpectation(\"TH\", false),\n      peg$c51 = /^[12]/,\n      peg$c52 = peg$classExpectation([\"1\", \"2\"], false, false),\n      peg$c53 = \"AL\",\n      peg$c54 = peg$literalExpectation(\"AL\", false),\n      peg$c55 = \"SP\",\n      peg$c56 = peg$literalExpectation(\"SP\", false),\n      peg$c57 = /^[1-3]/,\n      peg$c58 = peg$classExpectation([\n        [\"1\", \"3\"]\n      ], false, false),\n      peg$c59 = \"TB\",\n      peg$c60 = peg$literalExpectation(\"TB\", false),\n      peg$c61 = \"OH\",\n      peg$c62 = peg$literalExpectation(\"OH\", false),\n      peg$c63 = function (c) {\n        if (!c[1]) return '@';\n        if (c[1] == '@') return '@@';\n\n        return c[1].join('').replace(',', '');\n      },\n      peg$c64 = function (c) {\n        return c;\n      },\n      peg$c65 = \"+\",\n      peg$c66 = peg$literalExpectation(\"+\", false),\n      peg$c67 = function (c) {\n        if (!c[1]) return 1;\n        if (c[1] != '+') return Number(c[1].join(''));\n        return 2;\n      },\n      peg$c68 = \"-\",\n      peg$c69 = peg$literalExpectation(\"-\", false),\n      peg$c70 = function (c) {\n        if (!c[1]) return -1;\n        if (c[1] != '-') return -Number(c[1].join(''));\n        return -2;\n      },\n      peg$c71 = \"H\",\n      peg$c72 = peg$literalExpectation(\"H\", false),\n      peg$c73 = function (h) {\n        if (h[1]) return Number(h[1]);\n        return 1;\n      },\n      peg$c74 = \":\",\n      peg$c75 = peg$literalExpectation(\":\", false),\n      peg$c76 = /^[0]/,\n      peg$c77 = peg$classExpectation([\"0\"], false, false),\n      peg$c78 = function (c) {\n        return Number(c[1][0] + c[1][1].join(''));\n      },\n      peg$c79 = function (i) {\n        return Number(i.join(''));\n      },\n\n      peg$currPos = 0,\n      peg$savedPos = 0,\n      peg$posDetailsCache = [{\n        line: 1,\n        column: 1\n      }],\n      peg$maxFailPos = 0,\n      peg$maxFailExpected = [],\n      peg$silentFails = 0,\n\n      peg$result;\n\n    if (\"startRule\" in options) {\n      if (!(options.startRule in peg$startRuleFunctions)) {\n        throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");\n      }\n\n      peg$startRuleFunction = peg$startRuleFunctions[options.startRule];\n    }\n\n    function text() {\n      return input.substring(peg$savedPos, peg$currPos);\n    }\n\n    function location() {\n      return peg$computeLocation(peg$savedPos, peg$currPos);\n    }\n\n    function expected(description, location) {\n      location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\n\n      throw peg$buildStructuredError(\n        [peg$otherExpectation(description)],\n        input.substring(peg$savedPos, peg$currPos),\n        location\n      );\n    }\n\n    function error(message, location) {\n      location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\n\n      throw peg$buildSimpleError(message, location);\n    }\n\n    function peg$literalExpectation(text, ignoreCase) {\n      return {\n        type: \"literal\",\n        text: text,\n        ignoreCase: ignoreCase\n      };\n    }\n\n    function peg$classExpectation(parts, inverted, ignoreCase) {\n      return {\n        type: \"class\",\n        parts: parts,\n        inverted: inverted,\n        ignoreCase: ignoreCase\n      };\n    }\n\n    function peg$anyExpectation() {\n      return {\n        type: \"any\"\n      };\n    }\n\n    function peg$endExpectation() {\n      return {\n        type: \"end\"\n      };\n    }\n\n    function peg$otherExpectation(description) {\n      return {\n        type: \"other\",\n        description: description\n      };\n    }\n\n    function peg$computePosDetails(pos) {\n      var details = peg$posDetailsCache[pos],\n        p;\n\n      if (details) {\n        return details;\n      } else {\n        p = pos - 1;\n        while (!peg$posDetailsCache[p]) {\n          p--;\n        }\n\n        details = peg$posDetailsCache[p];\n        details = {\n          line: details.line,\n          column: details.column\n        };\n\n        while (p < pos) {\n          if (input.charCodeAt(p) === 10) {\n            details.line++;\n            details.column = 1;\n          } else {\n            details.column++;\n          }\n\n          p++;\n        }\n\n        peg$posDetailsCache[pos] = details;\n        return details;\n      }\n    }\n\n    function peg$computeLocation(startPos, endPos) {\n      var startPosDetails = peg$computePosDetails(startPos),\n        endPosDetails = peg$computePosDetails(endPos);\n\n      return {\n        start: {\n          offset: startPos,\n          line: startPosDetails.line,\n          column: startPosDetails.column\n        },\n        end: {\n          offset: endPos,\n          line: endPosDetails.line,\n          column: endPosDetails.column\n        }\n      };\n    }\n\n    function peg$fail(expected) {\n      if (peg$currPos < peg$maxFailPos) {\n        return;\n      }\n\n      if (peg$currPos > peg$maxFailPos) {\n        peg$maxFailPos = peg$currPos;\n        peg$maxFailExpected = [];\n      }\n\n      peg$maxFailExpected.push(expected);\n    }\n\n    function peg$buildSimpleError(message, location) {\n      return new peg$SyntaxError(message, null, null, location);\n    }\n\n    function peg$buildStructuredError(expected, found, location) {\n      return new peg$SyntaxError(\n        peg$SyntaxError.buildMessage(expected, found),\n        expected,\n        found,\n        location\n      );\n    }\n\n    function peg$parsechain() {\n      var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      s2 = peg$parseatom();\n      if (s2 !== peg$FAILED) {\n        s3 = [];\n        s4 = peg$parsebranch();\n        while (s4 !== peg$FAILED) {\n          s3.push(s4);\n          s4 = peg$parsebranch();\n        }\n        if (s3 !== peg$FAILED) {\n          s4 = [];\n          s5 = peg$currPos;\n          s6 = peg$parsebond();\n          if (s6 === peg$FAILED) {\n            s6 = null;\n          }\n          if (s6 !== peg$FAILED) {\n            s7 = peg$parsering();\n            if (s7 !== peg$FAILED) {\n              s6 = [s6, s7];\n              s5 = s6;\n            } else {\n              peg$currPos = s5;\n              s5 = peg$FAILED;\n            }\n          } else {\n            peg$currPos = s5;\n            s5 = peg$FAILED;\n          }\n          while (s5 !== peg$FAILED) {\n            s4.push(s5);\n            s5 = peg$currPos;\n            s6 = peg$parsebond();\n            if (s6 === peg$FAILED) {\n              s6 = null;\n            }\n            if (s6 !== peg$FAILED) {\n              s7 = peg$parsering();\n              if (s7 !== peg$FAILED) {\n                s6 = [s6, s7];\n                s5 = s6;\n              } else {\n                peg$currPos = s5;\n                s5 = peg$FAILED;\n              }\n            } else {\n              peg$currPos = s5;\n              s5 = peg$FAILED;\n            }\n          }\n          if (s4 !== peg$FAILED) {\n            s5 = [];\n            s6 = peg$parsebranch();\n            while (s6 !== peg$FAILED) {\n              s5.push(s6);\n              s6 = peg$parsebranch();\n            }\n            if (s5 !== peg$FAILED) {\n              s6 = peg$parsebond();\n              if (s6 === peg$FAILED) {\n                s6 = null;\n              }\n              if (s6 !== peg$FAILED) {\n                s7 = peg$parsechain();\n                if (s7 === peg$FAILED) {\n                  s7 = null;\n                }\n                if (s7 !== peg$FAILED) {\n                  s8 = [];\n                  s9 = peg$parsebranch();\n                  while (s9 !== peg$FAILED) {\n                    s8.push(s9);\n                    s9 = peg$parsebranch();\n                  }\n                  if (s8 !== peg$FAILED) {\n                    s2 = [s2, s3, s4, s5, s6, s7, s8];\n                    s1 = s2;\n                  } else {\n                    peg$currPos = s1;\n                    s1 = peg$FAILED;\n                  }\n                } else {\n                  peg$currPos = s1;\n                  s1 = peg$FAILED;\n                }\n              } else {\n                peg$currPos = s1;\n                s1 = peg$FAILED;\n              }\n            } else {\n              peg$currPos = s1;\n              s1 = peg$FAILED;\n            }\n          } else {\n            peg$currPos = s1;\n            s1 = peg$FAILED;\n          }\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c0(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parsebranch() {\n      var s0, s1, s2, s3, s4, s5;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      if (input.charCodeAt(peg$currPos) === 40) {\n        s2 = peg$c1;\n        peg$currPos++;\n      } else {\n        s2 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c2);\n        }\n      }\n      if (s2 !== peg$FAILED) {\n        s3 = peg$parsebond();\n        if (s3 === peg$FAILED) {\n          s3 = null;\n        }\n        if (s3 !== peg$FAILED) {\n          s4 = peg$parsechain();\n          if (s4 !== peg$FAILED) {\n            if (input.charCodeAt(peg$currPos) === 41) {\n              s5 = peg$c3;\n              peg$currPos++;\n            } else {\n              s5 = peg$FAILED;\n              if (peg$silentFails === 0) {\n                peg$fail(peg$c4);\n              }\n            }\n            if (s5 !== peg$FAILED) {\n              s2 = [s2, s3, s4, s5];\n              s1 = s2;\n            } else {\n              peg$currPos = s1;\n              s1 = peg$FAILED;\n            }\n          } else {\n            peg$currPos = s1;\n            s1 = peg$FAILED;\n          }\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c5(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parseatom() {\n      var s0, s1;\n\n      s0 = peg$currPos;\n      s1 = peg$parseorganicsymbol();\n      if (s1 === peg$FAILED) {\n        s1 = peg$parsearomaticsymbol();\n        if (s1 === peg$FAILED) {\n          s1 = peg$parsebracketatom();\n          if (s1 === peg$FAILED) {\n            s1 = peg$parsewildcard();\n          }\n        }\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c6(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parsebond() {\n      var s0, s1;\n      s0 = peg$currPos;\n      if (peg$c7.test(input.charAt(peg$currPos))) {\n        s1 = input.charAt(peg$currPos);\n\n        // Hack to resolve problem caused by:\n        // O=C(N[C@@H](CC(O)=O)C(N[C@H](C1=CC=C(O)C=C1)C(N[C@@H](CC(O)=O)C(NCC(N[C@@H](C(N[C@@H]([C@H](C)CC(O)=O)C(N/C(C(O[C@H](C)[C@@H]2NC([C@H](CO)NC(C(O3)C3CCC)=O)=O)=O)=C\\\\\\\\C4=CNC5=C4C=CC=C5)=O)=O)[C@H](O)C(N)=O)=O)=O)=O)=O)[C@H](CC(O)=O)NC([C@@H](CC6=CNC7=C6C=CC=C7)NC2=O)=O\n        // KEEP THIS WHEN REGENERATING THE PARSER !!\n        if (s1 === input.charAt(peg$currPos + 1)) {\n          s1 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            throw peg$buildSimpleError('The parser encountered a bond repetition.', peg$currPos + 1);\n          }\n        }\n        // KEEP THIS WHEN REGENERATING THE PARSER !!\n\n        peg$currPos++;\n      } else {\n        s1 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c8);\n        }\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c9(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parsebracketatom() {\n      var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      if (input.charCodeAt(peg$currPos) === 91) {\n        s2 = peg$c10;\n        peg$currPos++;\n      } else {\n        s2 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c11);\n        }\n      }\n      if (s2 !== peg$FAILED) {\n        s3 = peg$parseisotope();\n        if (s3 === peg$FAILED) {\n          s3 = null;\n        }\n        if (s3 !== peg$FAILED) {\n          if (input.substr(peg$currPos, 2) === peg$c12) {\n            s4 = peg$c12;\n            peg$currPos += 2;\n          } else {\n            s4 = peg$FAILED;\n            if (peg$silentFails === 0) {\n              peg$fail(peg$c13);\n            }\n          }\n          if (s4 === peg$FAILED) {\n            if (input.substr(peg$currPos, 2) === peg$c14) {\n              s4 = peg$c14;\n              peg$currPos += 2;\n            } else {\n              s4 = peg$FAILED;\n              if (peg$silentFails === 0) {\n                peg$fail(peg$c15);\n              }\n            }\n            if (s4 === peg$FAILED) {\n              s4 = peg$parsearomaticsymbol();\n              if (s4 === peg$FAILED) {\n                s4 = peg$parseelementsymbol();\n                if (s4 === peg$FAILED) {\n                  s4 = peg$parsewildcard();\n                }\n              }\n            }\n          }\n          if (s4 !== peg$FAILED) {\n            s5 = peg$parsechiral();\n            if (s5 === peg$FAILED) {\n              s5 = null;\n            }\n            if (s5 !== peg$FAILED) {\n              s6 = peg$parsehcount();\n              if (s6 === peg$FAILED) {\n                s6 = null;\n              }\n              if (s6 !== peg$FAILED) {\n                s7 = peg$parsecharge();\n                if (s7 === peg$FAILED) {\n                  s7 = null;\n                }\n                if (s7 !== peg$FAILED) {\n                  s8 = peg$parseclass();\n                  if (s8 === peg$FAILED) {\n                    s8 = null;\n                  }\n                  if (s8 !== peg$FAILED) {\n                    if (input.charCodeAt(peg$currPos) === 93) {\n                      s9 = peg$c16;\n                      peg$currPos++;\n                    } else {\n                      s9 = peg$FAILED;\n                      if (peg$silentFails === 0) {\n                        peg$fail(peg$c17);\n                      }\n                    }\n                    if (s9 !== peg$FAILED) {\n                      s2 = [s2, s3, s4, s5, s6, s7, s8, s9];\n                      s1 = s2;\n                    } else {\n                      peg$currPos = s1;\n                      s1 = peg$FAILED;\n                    }\n                  } else {\n                    peg$currPos = s1;\n                    s1 = peg$FAILED;\n                  }\n                } else {\n                  peg$currPos = s1;\n                  s1 = peg$FAILED;\n                }\n              } else {\n                peg$currPos = s1;\n                s1 = peg$FAILED;\n              }\n            } else {\n              peg$currPos = s1;\n              s1 = peg$FAILED;\n            }\n          } else {\n            peg$currPos = s1;\n            s1 = peg$FAILED;\n          }\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c18(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parseorganicsymbol() {\n      var s0, s1, s2, s3;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      if (input.charCodeAt(peg$currPos) === 66) {\n        s2 = peg$c19;\n        peg$currPos++;\n      } else {\n        s2 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c20);\n        }\n      }\n      if (s2 !== peg$FAILED) {\n        if (input.charCodeAt(peg$currPos) === 114) {\n          s3 = peg$c21;\n          peg$currPos++;\n        } else {\n          s3 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            peg$fail(peg$c22);\n          }\n        }\n        if (s3 === peg$FAILED) {\n          s3 = null;\n        }\n        if (s3 !== peg$FAILED) {\n          s2 = [s2, s3];\n          s1 = s2;\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 === peg$FAILED) {\n        s1 = peg$currPos;\n        if (input.charCodeAt(peg$currPos) === 67) {\n          s2 = peg$c23;\n          peg$currPos++;\n        } else {\n          s2 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            peg$fail(peg$c24);\n          }\n        }\n        if (s2 !== peg$FAILED) {\n          if (input.charCodeAt(peg$currPos) === 108) {\n            s3 = peg$c25;\n            peg$currPos++;\n          } else {\n            s3 = peg$FAILED;\n            if (peg$silentFails === 0) {\n              peg$fail(peg$c26);\n            }\n          }\n          if (s3 === peg$FAILED) {\n            s3 = null;\n          }\n          if (s3 !== peg$FAILED) {\n            s2 = [s2, s3];\n            s1 = s2;\n          } else {\n            peg$currPos = s1;\n            s1 = peg$FAILED;\n          }\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n        if (s1 === peg$FAILED) {\n          if (peg$c27.test(input.charAt(peg$currPos))) {\n            s1 = input.charAt(peg$currPos);\n            peg$currPos++;\n          } else {\n            s1 = peg$FAILED;\n            if (peg$silentFails === 0) {\n              peg$fail(peg$c28);\n            }\n          }\n        }\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c29(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parsearomaticsymbol() {\n      var s0, s1;\n\n      s0 = peg$currPos;\n      if (peg$c30.test(input.charAt(peg$currPos))) {\n        s1 = input.charAt(peg$currPos);\n        peg$currPos++;\n      } else {\n        s1 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c31);\n        }\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c6(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parsewildcard() {\n      var s0, s1;\n\n      s0 = peg$currPos;\n      if (input.charCodeAt(peg$currPos) === 42) {\n        s1 = peg$c32;\n        peg$currPos++;\n      } else {\n        s1 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c33);\n        }\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c34(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parseelementsymbol() {\n      var s0, s1, s2, s3;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      if (peg$c35.test(input.charAt(peg$currPos))) {\n        s2 = input.charAt(peg$currPos);\n        peg$currPos++;\n      } else {\n        s2 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c36);\n        }\n      }\n      if (s2 !== peg$FAILED) {\n        if (peg$c37.test(input.charAt(peg$currPos))) {\n          s3 = input.charAt(peg$currPos);\n          peg$currPos++;\n        } else {\n          s3 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            peg$fail(peg$c38);\n          }\n        }\n        if (s3 === peg$FAILED) {\n          s3 = null;\n        }\n        if (s3 !== peg$FAILED) {\n          s2 = [s2, s3];\n          s1 = s2;\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c39(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parsering() {\n      var s0, s1, s2, s3, s4;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      if (input.charCodeAt(peg$currPos) === 37) {\n        s2 = peg$c40;\n        peg$currPos++;\n      } else {\n        s2 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c41);\n        }\n      }\n      if (s2 !== peg$FAILED) {\n        if (peg$c42.test(input.charAt(peg$currPos))) {\n          s3 = input.charAt(peg$currPos);\n          peg$currPos++;\n        } else {\n          s3 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            peg$fail(peg$c43);\n          }\n        }\n        if (s3 !== peg$FAILED) {\n          if (peg$c44.test(input.charAt(peg$currPos))) {\n            s4 = input.charAt(peg$currPos);\n            peg$currPos++;\n          } else {\n            s4 = peg$FAILED;\n            if (peg$silentFails === 0) {\n              peg$fail(peg$c45);\n            }\n          }\n          if (s4 !== peg$FAILED) {\n            s2 = [s2, s3, s4];\n            s1 = s2;\n          } else {\n            peg$currPos = s1;\n            s1 = peg$FAILED;\n          }\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 === peg$FAILED) {\n        if (peg$c44.test(input.charAt(peg$currPos))) {\n          s1 = input.charAt(peg$currPos);\n          peg$currPos++;\n        } else {\n          s1 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            peg$fail(peg$c45);\n          }\n        }\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c46(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parsechiral() {\n      var s0, s1, s2, s3, s4, s5, s6;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      if (input.charCodeAt(peg$currPos) === 64) {\n        s2 = peg$c47;\n        peg$currPos++;\n      } else {\n        s2 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c48);\n        }\n      }\n      if (s2 !== peg$FAILED) {\n        if (input.charCodeAt(peg$currPos) === 64) {\n          s3 = peg$c47;\n          peg$currPos++;\n        } else {\n          s3 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            peg$fail(peg$c48);\n          }\n        }\n        if (s3 === peg$FAILED) {\n          s3 = peg$currPos;\n          if (input.substr(peg$currPos, 2) === peg$c49) {\n            s4 = peg$c49;\n            peg$currPos += 2;\n          } else {\n            s4 = peg$FAILED;\n            if (peg$silentFails === 0) {\n              peg$fail(peg$c50);\n            }\n          }\n          if (s4 !== peg$FAILED) {\n            if (peg$c51.test(input.charAt(peg$currPos))) {\n              s5 = input.charAt(peg$currPos);\n              peg$currPos++;\n            } else {\n              s5 = peg$FAILED;\n              if (peg$silentFails === 0) {\n                peg$fail(peg$c52);\n              }\n            }\n            if (s5 !== peg$FAILED) {\n              s4 = [s4, s5];\n              s3 = s4;\n            } else {\n              peg$currPos = s3;\n              s3 = peg$FAILED;\n            }\n          } else {\n            peg$currPos = s3;\n            s3 = peg$FAILED;\n          }\n          if (s3 === peg$FAILED) {\n            s3 = peg$currPos;\n            if (input.substr(peg$currPos, 2) === peg$c53) {\n              s4 = peg$c53;\n              peg$currPos += 2;\n            } else {\n              s4 = peg$FAILED;\n              if (peg$silentFails === 0) {\n                peg$fail(peg$c54);\n              }\n            }\n            if (s4 !== peg$FAILED) {\n              if (peg$c51.test(input.charAt(peg$currPos))) {\n                s5 = input.charAt(peg$currPos);\n                peg$currPos++;\n              } else {\n                s5 = peg$FAILED;\n                if (peg$silentFails === 0) {\n                  peg$fail(peg$c52);\n                }\n              }\n              if (s5 !== peg$FAILED) {\n                s4 = [s4, s5];\n                s3 = s4;\n              } else {\n                peg$currPos = s3;\n                s3 = peg$FAILED;\n              }\n            } else {\n              peg$currPos = s3;\n              s3 = peg$FAILED;\n            }\n            if (s3 === peg$FAILED) {\n              s3 = peg$currPos;\n              if (input.substr(peg$currPos, 2) === peg$c55) {\n                s4 = peg$c55;\n                peg$currPos += 2;\n              } else {\n                s4 = peg$FAILED;\n                if (peg$silentFails === 0) {\n                  peg$fail(peg$c56);\n                }\n              }\n              if (s4 !== peg$FAILED) {\n                if (peg$c57.test(input.charAt(peg$currPos))) {\n                  s5 = input.charAt(peg$currPos);\n                  peg$currPos++;\n                } else {\n                  s5 = peg$FAILED;\n                  if (peg$silentFails === 0) {\n                    peg$fail(peg$c58);\n                  }\n                }\n                if (s5 !== peg$FAILED) {\n                  s4 = [s4, s5];\n                  s3 = s4;\n                } else {\n                  peg$currPos = s3;\n                  s3 = peg$FAILED;\n                }\n              } else {\n                peg$currPos = s3;\n                s3 = peg$FAILED;\n              }\n              if (s3 === peg$FAILED) {\n                s3 = peg$currPos;\n                if (input.substr(peg$currPos, 2) === peg$c59) {\n                  s4 = peg$c59;\n                  peg$currPos += 2;\n                } else {\n                  s4 = peg$FAILED;\n                  if (peg$silentFails === 0) {\n                    peg$fail(peg$c60);\n                  }\n                }\n                if (s4 !== peg$FAILED) {\n                  if (peg$c42.test(input.charAt(peg$currPos))) {\n                    s5 = input.charAt(peg$currPos);\n                    peg$currPos++;\n                  } else {\n                    s5 = peg$FAILED;\n                    if (peg$silentFails === 0) {\n                      peg$fail(peg$c43);\n                    }\n                  }\n                  if (s5 !== peg$FAILED) {\n                    if (peg$c44.test(input.charAt(peg$currPos))) {\n                      s6 = input.charAt(peg$currPos);\n                      peg$currPos++;\n                    } else {\n                      s6 = peg$FAILED;\n                      if (peg$silentFails === 0) {\n                        peg$fail(peg$c45);\n                      }\n                    }\n                    if (s6 === peg$FAILED) {\n                      s6 = null;\n                    }\n                    if (s6 !== peg$FAILED) {\n                      s4 = [s4, s5, s6];\n                      s3 = s4;\n                    } else {\n                      peg$currPos = s3;\n                      s3 = peg$FAILED;\n                    }\n                  } else {\n                    peg$currPos = s3;\n                    s3 = peg$FAILED;\n                  }\n                } else {\n                  peg$currPos = s3;\n                  s3 = peg$FAILED;\n                }\n                if (s3 === peg$FAILED) {\n                  s3 = peg$currPos;\n                  if (input.substr(peg$currPos, 2) === peg$c61) {\n                    s4 = peg$c61;\n                    peg$currPos += 2;\n                  } else {\n                    s4 = peg$FAILED;\n                    if (peg$silentFails === 0) {\n                      peg$fail(peg$c62);\n                    }\n                  }\n                  if (s4 !== peg$FAILED) {\n                    if (peg$c42.test(input.charAt(peg$currPos))) {\n                      s5 = input.charAt(peg$currPos);\n                      peg$currPos++;\n                    } else {\n                      s5 = peg$FAILED;\n                      if (peg$silentFails === 0) {\n                        peg$fail(peg$c43);\n                      }\n                    }\n                    if (s5 !== peg$FAILED) {\n                      if (peg$c44.test(input.charAt(peg$currPos))) {\n                        s6 = input.charAt(peg$currPos);\n                        peg$currPos++;\n                      } else {\n                        s6 = peg$FAILED;\n                        if (peg$silentFails === 0) {\n                          peg$fail(peg$c45);\n                        }\n                      }\n                      if (s6 === peg$FAILED) {\n                        s6 = null;\n                      }\n                      if (s6 !== peg$FAILED) {\n                        s4 = [s4, s5, s6];\n                        s3 = s4;\n                      } else {\n                        peg$currPos = s3;\n                        s3 = peg$FAILED;\n                      }\n                    } else {\n                      peg$currPos = s3;\n                      s3 = peg$FAILED;\n                    }\n                  } else {\n                    peg$currPos = s3;\n                    s3 = peg$FAILED;\n                  }\n                }\n              }\n            }\n          }\n        }\n        if (s3 === peg$FAILED) {\n          s3 = null;\n        }\n        if (s3 !== peg$FAILED) {\n          s2 = [s2, s3];\n          s1 = s2;\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c63(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parsecharge() {\n      var s0, s1;\n\n      s0 = peg$currPos;\n      s1 = peg$parseposcharge();\n      if (s1 === peg$FAILED) {\n        s1 = peg$parsenegcharge();\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c64(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parseposcharge() {\n      var s0, s1, s2, s3, s4, s5;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      if (input.charCodeAt(peg$currPos) === 43) {\n        s2 = peg$c65;\n        peg$currPos++;\n      } else {\n        s2 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c66);\n        }\n      }\n      if (s2 !== peg$FAILED) {\n        if (input.charCodeAt(peg$currPos) === 43) {\n          s3 = peg$c65;\n          peg$currPos++;\n        } else {\n          s3 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            peg$fail(peg$c66);\n          }\n        }\n        if (s3 === peg$FAILED) {\n          s3 = peg$currPos;\n          if (peg$c42.test(input.charAt(peg$currPos))) {\n            s4 = input.charAt(peg$currPos);\n            peg$currPos++;\n          } else {\n            s4 = peg$FAILED;\n            if (peg$silentFails === 0) {\n              peg$fail(peg$c43);\n            }\n          }\n          if (s4 !== peg$FAILED) {\n            if (peg$c44.test(input.charAt(peg$currPos))) {\n              s5 = input.charAt(peg$currPos);\n              peg$currPos++;\n            } else {\n              s5 = peg$FAILED;\n              if (peg$silentFails === 0) {\n                peg$fail(peg$c45);\n              }\n            }\n            if (s5 === peg$FAILED) {\n              s5 = null;\n            }\n            if (s5 !== peg$FAILED) {\n              s4 = [s4, s5];\n              s3 = s4;\n            } else {\n              peg$currPos = s3;\n              s3 = peg$FAILED;\n            }\n          } else {\n            peg$currPos = s3;\n            s3 = peg$FAILED;\n          }\n        }\n        if (s3 === peg$FAILED) {\n          s3 = null;\n        }\n        if (s3 !== peg$FAILED) {\n          s2 = [s2, s3];\n          s1 = s2;\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c67(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parsenegcharge() {\n      var s0, s1, s2, s3, s4, s5;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      if (input.charCodeAt(peg$currPos) === 45) {\n        s2 = peg$c68;\n        peg$currPos++;\n      } else {\n        s2 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c69);\n        }\n      }\n      if (s2 !== peg$FAILED) {\n        if (input.charCodeAt(peg$currPos) === 45) {\n          s3 = peg$c68;\n          peg$currPos++;\n        } else {\n          s3 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            peg$fail(peg$c69);\n          }\n        }\n        if (s3 === peg$FAILED) {\n          s3 = peg$currPos;\n          if (peg$c42.test(input.charAt(peg$currPos))) {\n            s4 = input.charAt(peg$currPos);\n            peg$currPos++;\n          } else {\n            s4 = peg$FAILED;\n            if (peg$silentFails === 0) {\n              peg$fail(peg$c43);\n            }\n          }\n          if (s4 !== peg$FAILED) {\n            if (peg$c44.test(input.charAt(peg$currPos))) {\n              s5 = input.charAt(peg$currPos);\n              peg$currPos++;\n            } else {\n              s5 = peg$FAILED;\n              if (peg$silentFails === 0) {\n                peg$fail(peg$c45);\n              }\n            }\n            if (s5 === peg$FAILED) {\n              s5 = null;\n            }\n            if (s5 !== peg$FAILED) {\n              s4 = [s4, s5];\n              s3 = s4;\n            } else {\n              peg$currPos = s3;\n              s3 = peg$FAILED;\n            }\n          } else {\n            peg$currPos = s3;\n            s3 = peg$FAILED;\n          }\n        }\n        if (s3 === peg$FAILED) {\n          s3 = null;\n        }\n        if (s3 !== peg$FAILED) {\n          s2 = [s2, s3];\n          s1 = s2;\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c70(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parsehcount() {\n      var s0, s1, s2, s3;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      if (input.charCodeAt(peg$currPos) === 72) {\n        s2 = peg$c71;\n        peg$currPos++;\n      } else {\n        s2 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c72);\n        }\n      }\n      if (s2 !== peg$FAILED) {\n        if (peg$c44.test(input.charAt(peg$currPos))) {\n          s3 = input.charAt(peg$currPos);\n          peg$currPos++;\n        } else {\n          s3 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            peg$fail(peg$c45);\n          }\n        }\n        if (s3 === peg$FAILED) {\n          s3 = null;\n        }\n        if (s3 !== peg$FAILED) {\n          s2 = [s2, s3];\n          s1 = s2;\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c73(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parseclass() {\n      var s0, s1, s2, s3, s4, s5, s6;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      if (input.charCodeAt(peg$currPos) === 58) {\n        s2 = peg$c74;\n        peg$currPos++;\n      } else {\n        s2 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c75);\n        }\n      }\n      if (s2 !== peg$FAILED) {\n        s3 = peg$currPos;\n        if (peg$c42.test(input.charAt(peg$currPos))) {\n          s4 = input.charAt(peg$currPos);\n          peg$currPos++;\n        } else {\n          s4 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            peg$fail(peg$c43);\n          }\n        }\n        if (s4 !== peg$FAILED) {\n          s5 = [];\n          if (peg$c44.test(input.charAt(peg$currPos))) {\n            s6 = input.charAt(peg$currPos);\n            peg$currPos++;\n          } else {\n            s6 = peg$FAILED;\n            if (peg$silentFails === 0) {\n              peg$fail(peg$c45);\n            }\n          }\n          while (s6 !== peg$FAILED) {\n            s5.push(s6);\n            if (peg$c44.test(input.charAt(peg$currPos))) {\n              s6 = input.charAt(peg$currPos);\n              peg$currPos++;\n            } else {\n              s6 = peg$FAILED;\n              if (peg$silentFails === 0) {\n                peg$fail(peg$c45);\n              }\n            }\n          }\n          if (s5 !== peg$FAILED) {\n            s4 = [s4, s5];\n            s3 = s4;\n          } else {\n            peg$currPos = s3;\n            s3 = peg$FAILED;\n          }\n        } else {\n          peg$currPos = s3;\n          s3 = peg$FAILED;\n        }\n        if (s3 === peg$FAILED) {\n          if (peg$c76.test(input.charAt(peg$currPos))) {\n            s3 = input.charAt(peg$currPos);\n            peg$currPos++;\n          } else {\n            s3 = peg$FAILED;\n            if (peg$silentFails === 0) {\n              peg$fail(peg$c77);\n            }\n          }\n        }\n        if (s3 !== peg$FAILED) {\n          s2 = [s2, s3];\n          s1 = s2;\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c78(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    function peg$parseisotope() {\n      var s0, s1, s2, s3, s4;\n\n      s0 = peg$currPos;\n      s1 = peg$currPos;\n      if (peg$c42.test(input.charAt(peg$currPos))) {\n        s2 = input.charAt(peg$currPos);\n        peg$currPos++;\n      } else {\n        s2 = peg$FAILED;\n        if (peg$silentFails === 0) {\n          peg$fail(peg$c43);\n        }\n      }\n      if (s2 !== peg$FAILED) {\n        if (peg$c44.test(input.charAt(peg$currPos))) {\n          s3 = input.charAt(peg$currPos);\n          peg$currPos++;\n        } else {\n          s3 = peg$FAILED;\n          if (peg$silentFails === 0) {\n            peg$fail(peg$c45);\n          }\n        }\n        if (s3 === peg$FAILED) {\n          s3 = null;\n        }\n        if (s3 !== peg$FAILED) {\n          if (peg$c44.test(input.charAt(peg$currPos))) {\n            s4 = input.charAt(peg$currPos);\n            peg$currPos++;\n          } else {\n            s4 = peg$FAILED;\n            if (peg$silentFails === 0) {\n              peg$fail(peg$c45);\n            }\n          }\n          if (s4 === peg$FAILED) {\n            s4 = null;\n          }\n          if (s4 !== peg$FAILED) {\n            s2 = [s2, s3, s4];\n            s1 = s2;\n          } else {\n            peg$currPos = s1;\n            s1 = peg$FAILED;\n          }\n        } else {\n          peg$currPos = s1;\n          s1 = peg$FAILED;\n        }\n      } else {\n        peg$currPos = s1;\n        s1 = peg$FAILED;\n      }\n      if (s1 !== peg$FAILED) {\n        peg$savedPos = s0;\n        s1 = peg$c79(s1);\n      }\n      s0 = s1;\n\n      return s0;\n    }\n\n    peg$result = peg$startRuleFunction();\n\n    if (peg$result !== peg$FAILED && peg$currPos === input.length) {\n      return peg$result;\n    } else {\n      if (peg$result !== peg$FAILED && peg$currPos < input.length) {\n        peg$fail(peg$endExpectation());\n      }\n\n      throw peg$buildStructuredError(\n        peg$maxFailExpected,\n        peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,\n        peg$maxFailPos < input.length ?\n          peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) :\n          peg$computeLocation(peg$maxFailPos, peg$maxFailPos)\n      );\n    }\n  }\n\n  return {\n    SyntaxError: peg$SyntaxError,\n    parse: peg$parse\n  };\n})();", "import Graph  from './Graph';\nimport Parser from './Parser';\n\n// A TypeScript wrapper class for the autogenerated Parser code.\n// This prevents a confusing error involving peg$SyntaxError when\n// the Parser gets attached to the global SmilesDrawer namespace:\n// > Public static property 'Parser' of exported class has or\n// > is using name 'peg$SyntaxError' from external module\n// > \"/mnt/src/Parser\" but cannot be named.\nexport default class ParserWrapper {\n    static SyntaxError: Error = Parser.SyntaxError as unknown as Error;\n\n    static parse(smiles: string): Graph {\n        return Parser.parse(smiles);\n    }\n}\n", "// @ts-check\n\nexport default {\n    C2H4O2:    'acetic acid',\n    C3H6O:     'acetone',\n    C2H3N:     'acetonitrile',\n    C6H6:      'benzene',\n    CCl4:      'carbon tetrachloride',\n    C6H5Cl:    'chlorobenzene',\n    CHCl3:     'chloroform',\n    C6H12:     'cyclohexane',\n    C2H4Cl2:   '1,2-dichloroethane',\n    C4H10O3:   'diethylene glycol',\n    C6H14O3:   'diglyme',\n    C4H10O2:   'DME',\n    C3H7NO:    'DMF',\n    C2H6OS:    'DMSO',\n    C2H6O:     'ethanol',\n    C2H6O2:    'ethylene glycol',\n    C3H8O3:    'glycerin',\n    C7H16:     'heptane',\n    C6H18N3OP: 'HMPA',\n    C6H18N3P:  'HMPT',\n    C6H14:     'hexane',\n    CH4O:      'methanol',\n    C5H12O:    'MTBE',\n    CH2Cl2:    'methylene chloride',\n    CH5H9NO:   'NMP',\n    CH3NO2:    'nitromethane',\n    C5H12:     'pentane',\n    C5H5N:     'pyridine',\n    C7H8:      'toluene',\n    C6H15N:    'triethyl amine',\n    H2O:       'water',\n};\n", "import formulaToCommonName from './FormulaToCommonName';\nimport Options             from './Options.js';\nimport SvgDrawer           from './SvgDrawer';\nimport SvgWrapper          from './SvgWrapper';\nimport ThemeManager        from './ThemeManager';\n\nexport default class ReactionDrawer {\n    /**\n     * The constructor for the class ReactionDrawer.\n     *\n     * @param {Object} reactionOptions An object containing reaction drawing specific options.\n     * @param {Object} moleculeOptions An object containing molecule drawing specific options.\n     */\n    constructor(reactionOptions, moleculeOptions) {\n        this.drawer  = new SvgDrawer(moleculeOptions);\n        this.molOpts = this.drawer.opts;\n\n        this.defaultOptions = {\n            scale:      this.molOpts.scale > 0.0 ? this.molOpts.scale : 1.0,\n            fontSize:   this.molOpts.fontSizeLarge * 0.8,\n            fontFamily: 'Arial, Helvetica, sans-serif',\n            spacing:    10,\n\n            plus: {\n                size:      9,\n                thickness: 1.0,\n            },\n\n            arrow: {\n                length:    this.molOpts.bondLength * 4.0,\n                headSize:  6.0,\n                thickness: 1.0,\n                margin:    3,\n            },\n\n            weights: {\n                normalize: false,\n            },\n        };\n\n        this.opts = Options.extend(true, this.defaultOptions, reactionOptions);\n    }\n\n    /**\n   * Draws the parsed reaction smiles data to a canvas element.\n   *\n   * @param {Object} reaction The reaction object returned by the reaction smiles parser.\n   * @param {(String|SVGElement)} target The id of the HTML canvas element the structure is drawn to - or the element itself.\n   * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\n   * @param {?Object} weights=null The weights for reactants, agents, and products.\n   * @param {String} textAbove='{reagents}' The text above the arrow.\n   * @param {String} textBelow='' The text below the arrow.\n   * @param {?Object} weights=null The weights for reactants, agents, and products.\n   * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\n   *\n   * @returns {SVGElement} The svg element\n   */\n    draw(reaction, target, themeName = 'light', weights = null, textAbove = '{reagents}', textBelow = '', infoOnly = false) {\n        this.themeManager = new ThemeManager(this.molOpts.themes, themeName);\n\n        // Normalize the weights over the reaction molecules\n        if (this.opts.weights.normalize) {\n            let max = -Number.MAX_SAFE_INTEGER;\n            let min = Number.MAX_SAFE_INTEGER;\n\n            if ('reactants' in weights) {\n                for (let i = 0; i < weights.reactants.length; i++) {\n                    for (let j = 0; j < weights.reactants[i].length; j++) {\n                        if (weights.reactants[i][j] < min) {\n                            min = weights.reactants[i][j];\n                        }\n                        if (weights.reactants[i][j] > max) {\n                            max = weights.reactants[i][j];\n                        }\n                    }\n                }\n            }\n\n            if ('reagents' in weights) {\n                for (let i = 0; i < weights.reagents.length; i++) {\n                    for (let j = 0; j < weights.reagents[i].length; j++) {\n                        if (weights.reagents[i][j] < min) {\n                            min = weights.reagents[i][j];\n                        }\n                        if (weights.reagents[i][j] > max) {\n                            max = weights.reagents[i][j];\n                        }\n                    }\n                }\n            }\n\n            if ('products' in weights) {\n                for (let i = 0; i < weights.products.length; i++) {\n                    for (let j = 0; j < weights.products[i].length; j++) {\n                        if (weights.products[i][j] < min) {\n                            min = weights.products[i][j];\n                        }\n                        if (weights.products[i][j] > max) {\n                            max = weights.products[i][j];\n                        }\n                    }\n                }\n            }\n\n            let abs_max = Math.max(Math.abs(min), Math.abs(max));\n            if (abs_max === 0.0) {\n                abs_max = 1;\n            }\n\n            if ('reactants' in weights) {\n                for (let i = 0; i < weights.reactants.length; i++) {\n                    for (let j = 0; j < weights.reactants[i].length; j++) {\n                        weights.reactants[i][j] /= abs_max;\n                    }\n                }\n            }\n\n            if ('reagents' in weights) {\n                for (let i = 0; i < weights.reagents.length; i++) {\n                    for (let j = 0; j < weights.reagents[i].length; j++) {\n                        weights.reagents[i][j] /= abs_max;\n                    }\n                }\n            }\n\n            if ('products' in weights) {\n                for (let i = 0; i < weights.products.length; i++) {\n                    for (let j = 0; j < weights.products[i].length; j++) {\n                        weights.products[i][j] /= abs_max;\n                    }\n                }\n            }\n        }\n\n        let svg = null;\n\n        if (target === null || target === 'svg') {\n            svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n            svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');\n            svg.setAttributeNS(null, 'width', 500 + '');\n            svg.setAttributeNS(null, 'height', 500 + '');\n        }\n        else if (typeof target === 'string' || target instanceof String) {\n            svg = document.getElementById(target);\n        }\n        else {\n            svg = target;\n        }\n\n        while (svg.firstChild) {\n            svg.removeChild(svg.firstChild);\n        }\n\n        let elements = [];\n\n        let maxHeight = 0.0;\n\n        // Reactants\n        for (let i = 0; i < reaction.reactants.length; i++) {\n            if (i > 0) {\n                elements.push({\n                    width:  this.opts.plus.size * this.opts.scale,\n                    height: this.opts.plus.size * this.opts.scale,\n                    svg:    this.getPlus(),\n                });\n            }\n\n            let reactantWeights = null;\n            if (weights && 'reactants' in weights && weights.reactants.length > i) {\n                reactantWeights = weights.reactants[i];\n            }\n\n            let reactantSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n\n            this.drawer.draw(reaction.reactants[i], reactantSvg, themeName, reactantWeights, infoOnly, [], this.opts.weights.normalize);\n\n            let element = {\n                width:  reactantSvg.viewBox.baseVal.width  * this.opts.scale,\n                height: reactantSvg.viewBox.baseVal.height * this.opts.scale,\n                svg:    reactantSvg,\n            };\n\n            elements.push(element);\n\n            if (element.height > maxHeight) {\n                maxHeight = element.height;\n            }\n        }\n\n        // Arrow\n        elements.push({\n            width:  this.opts.arrow.length   * this.opts.scale,\n            height: this.opts.arrow.headSize * this.opts.scale * 2.0,\n            svg:    this.getArrow(),\n        });\n\n        // Text above the arrow / reagents\n        let reagentsText = '';\n        for (let i = 0; i < reaction.reagents.length; i++) {\n            if (i > 0) {\n                reagentsText += ', ';\n            }\n\n            let text = this.drawer.getMolecularFormula(reaction.reagents[i]);\n            if (text in formulaToCommonName) {\n                text = formulaToCommonName[text];\n            }\n\n            reagentsText += SvgWrapper.replaceNumbersWithSubscript(text);\n        }\n\n        textAbove = textAbove.replace('{reagents}', reagentsText);\n\n        const topText = SvgWrapper.writeText(\n            textAbove,\n            this.themeManager,\n            this.opts.fontSize * this.opts.scale,\n            this.opts.fontFamily,\n            this.opts.arrow.length * this.opts.scale\n        );\n\n        let centerOffsetX = (this.opts.arrow.length * this.opts.scale - topText.width) / 2.0;\n\n        elements.push({\n            svg:      topText.svg,\n            height:   topText.height,\n            width:    topText.width,\n            offsetX:  -(this.opts.arrow.length * this.opts.scale + this.opts.spacing) + centerOffsetX,\n            offsetY:  -(topText.height / 2.0) - this.opts.arrow.margin,\n            position: 'relative',\n        });\n\n        // Text below arrow\n        const bottomText = SvgWrapper.writeText(\n            textBelow,\n            this.themeManager,\n            this.opts.fontSize * this.opts.scale,\n            this.opts.fontFamily,\n            this.opts.arrow.length * this.opts.scale\n        );\n\n        centerOffsetX = (this.opts.arrow.length * this.opts.scale - bottomText.width) / 2.0;\n\n        elements.push({\n            svg:      bottomText.svg,\n            height:   bottomText.height,\n            width:    bottomText.width,\n            offsetX:  -(this.opts.arrow.length * this.opts.scale + this.opts.spacing) + centerOffsetX,\n            offsetY:  bottomText.height / 2.0 + this.opts.arrow.margin,\n            position: 'relative',\n        });\n\n        // Products\n        for (let i = 0; i < reaction.products.length; i++) {\n            if (i > 0) {\n                elements.push({\n                    width:  this.opts.plus.size * this.opts.scale,\n                    height: this.opts.plus.size * this.opts.scale,\n                    svg:    this.getPlus(),\n                });\n            }\n\n            let productWeights = null;\n            if (weights && 'products' in weights && weights.products.length > i) {\n                productWeights = weights.products[i];\n            }\n\n            let productSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n\n            this.drawer.draw(reaction.products[i], productSvg, themeName, productWeights, infoOnly, [], this.opts.weights.normalize);\n\n            let element = {\n                width:  productSvg.viewBox.baseVal.width  * this.opts.scale,\n                height: productSvg.viewBox.baseVal.height * this.opts.scale,\n                svg:    productSvg,\n            };\n\n            elements.push(element);\n\n            if (element.height > maxHeight) {\n                maxHeight = element.height;\n            }\n        }\n\n        let minY = 0;\n        let maxY = 0;\n        let totalWidth = 0.0;\n\n        elements.forEach((element) => {\n            let offsetX = element.offsetX || 0.0;\n            let offsetY = element.offsetY || 0.0;\n\n            const y = ((maxHeight - element.height) / 2.0) + offsetY;\n            maxY = Math.max(maxY, y + element.height);\n            minY = Math.min(minY, y);\n\n            element.svg.setAttributeNS(null, 'x', Math.round(totalWidth + offsetX));\n            element.svg.setAttributeNS(null, 'y', Math.round(y));\n            element.svg.setAttributeNS(null, 'width', Math.round(element.width));\n            element.svg.setAttributeNS(null, 'height', Math.round(element.height));\n            svg.appendChild(element.svg);\n\n            if (element.position !== 'relative') {\n                totalWidth += Math.round(element.width + this.opts.spacing + offsetX);\n            }\n        });\n\n        const height = Math.max(maxHeight, maxY - minY);\n        svg.setAttributeNS(null, 'viewBox', `0 ${minY} ${totalWidth} ${height}`);\n        svg.style.width = totalWidth + 'px';\n        svg.style.height = maxHeight + 'px';\n\n        return svg;\n    }\n\n    getPlus() {\n        let s = this.opts.plus.size;\n        let w = this.opts.plus.thickness;\n        let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n        let rect_h = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n        let rect_v = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\n\n        svg.setAttributeNS(null, 'id', 'plus');\n\n        rect_h.setAttributeNS(null, 'x', 0);\n        rect_h.setAttributeNS(null, 'y', s / 2.0 - w / 2.0);\n        rect_h.setAttributeNS(null, 'width', s);\n        rect_h.setAttributeNS(null, 'height', w);\n        rect_h.setAttributeNS(null, 'fill', this.themeManager.getColor('C'));\n\n        rect_v.setAttributeNS(null, 'x', s / 2.0 - w / 2.0);\n        rect_v.setAttributeNS(null, 'y', 0);\n        rect_v.setAttributeNS(null, 'width', w);\n        rect_v.setAttributeNS(null, 'height', s);\n        rect_v.setAttributeNS(null, 'fill', this.themeManager.getColor('C'));\n\n        svg.appendChild(rect_h);\n        svg.appendChild(rect_v);\n        svg.setAttributeNS(null, 'viewBox', `0 0 ${s} ${s}`);\n\n        return svg;\n    }\n\n    getArrowhead() {\n        let s = this.opts.arrow.headSize;\n        let marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker');\n        let polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon');\n\n        marker.setAttributeNS(null, 'id', 'arrowhead');\n        marker.setAttributeNS(null, 'viewBox', `0 0 ${s} ${s}`);\n        marker.setAttributeNS(null, 'markerUnits', 'userSpaceOnUse');\n        marker.setAttributeNS(null, 'markerWidth', s);\n        marker.setAttributeNS(null, 'markerHeight', s);\n        marker.setAttributeNS(null, 'refX', 0);\n        marker.setAttributeNS(null, 'refY', s / 2);\n        marker.setAttributeNS(null, 'orient', 'auto');\n        marker.setAttributeNS(null, 'fill', this.themeManager.getColor('C'));\n\n        polygon.setAttributeNS(null, 'points', `0 0, ${s} ${s / 2}, 0 ${s}`);\n\n        marker.appendChild(polygon);\n\n        return marker;\n    }\n\n    getCDArrowhead() {\n        let s = this.opts.arrow.headSize;\n        let sw = s * (7 / 4.5);\n        let marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker');\n        let path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n\n        marker.setAttributeNS(null, 'id', 'arrowhead');\n        marker.setAttributeNS(null, 'viewBox', `0 0 ${sw} ${s}`);\n        marker.setAttributeNS(null, 'markerUnits', 'userSpaceOnUse');\n        marker.setAttributeNS(null, 'markerWidth', sw * 2);\n        marker.setAttributeNS(null, 'markerHeight', s * 2);\n        marker.setAttributeNS(null, 'refX', 2.2);\n        marker.setAttributeNS(null, 'refY', 2.2);\n        marker.setAttributeNS(null, 'orient', 'auto');\n        marker.setAttributeNS(null, 'fill', this.themeManager.getColor('C'));\n\n        path.setAttributeNS(null, 'style', 'fill-rule:nonzero;');\n        path.setAttributeNS(null, 'd', 'm 0 0 l 7 2.25 l -7 2.25 c 0 0 0.735 -1.084 0.735 -2.28 c 0 -1.196 -0.735 -2.22 -0.735 -2.22 z');\n\n        marker.appendChild(path);\n\n        return marker;\n    }\n\n    getArrow() {\n        let s = this.opts.arrow.headSize;\n        let l = this.opts.arrow.length;\n\n        let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n        let defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');\n        let line = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n\n        defs.appendChild(this.getCDArrowhead());\n        svg.appendChild(defs);\n\n        svg.setAttributeNS(null, 'id', 'arrow');\n\n        line.setAttributeNS(null, 'x1', 0.0);\n        line.setAttributeNS(null, 'y1', -this.opts.arrow.thickness / 2.0);\n        line.setAttributeNS(null, 'x2', l);\n        line.setAttributeNS(null, 'y2', -this.opts.arrow.thickness / 2.0);\n        line.setAttributeNS(null, 'stroke-width', this.opts.arrow.thickness);\n        line.setAttributeNS(null, 'stroke', this.themeManager.getColor('C'));\n        line.setAttributeNS(null, 'marker-end', 'url(#arrowhead)');\n\n        svg.appendChild(line);\n        svg.setAttributeNS(null, 'viewBox', `0 ${-s / 2.0} ${l + s * (7 / 4.5)} ${s}`);\n\n        return svg;\n    }\n}\n", "// @ts-check\nimport Parser from './Parser';\n\nexport default class Reaction {\n    /**\n     * The constructor for the class Reaction.\n     *\n     * @param {string} reactionSmiles A reaction SMILES.\n     */\n    constructor(reactionSmiles) {\n        this.reactantsSmiles = [];\n        this.reagentsSmiles  = [];\n        this.productsSmiles  = [];\n\n        this.reactantsWeights = [];\n        this.reagentsWeights  = [];\n        this.productsWeights  = [];\n\n        this.reactants = [];\n        this.reagents  = [];\n        this.products  = [];\n\n        let parts = reactionSmiles.split('>');\n\n        if (parts.length !== 3) {\n            throw new Error('Invalid reaction SMILES: Expected exactly two \">\" symbols.');\n        }\n\n        if (parts[0] !== '') {\n            this.reactantsSmiles = parts[0].split('.');\n        }\n\n        if (parts[1] !== '') {\n            this.reagentsSmiles = parts[1].split('.');\n        }\n\n        if (parts[2] !== '') {\n            this.productsSmiles = parts[2].split('.');\n        }\n\n        for (let i = 0; i < this.reactantsSmiles.length; i++) {\n            this.reactants.push(Parser.parse(this.reactantsSmiles[i]));\n        }\n\n        for (let i = 0; i < this.reagentsSmiles.length; i++) {\n            this.reagents.push(Parser.parse(this.reagentsSmiles[i]));\n        }\n\n        for (let i = 0; i < this.productsSmiles.length; i++) {\n            this.products.push(Parser.parse(this.productsSmiles[i]));\n        }\n    }\n}\n", "// @ts-check\nimport Reaction from './Reaction';\n\nexport default class ReactionParser {\n    /**\n     * Returns the hex code of a color associated with a key from the current theme.\n     *\n     * @param {String} reactionSmiles A reaction SMILES.\n     * @returns {Reaction} A reaction object.\n     */\n    static parse(reactionSmiles) {\n        let reaction = new Reaction(reactionSmiles);\n\n        return reaction;\n    }\n}\n", "// @ts-check\nimport Options        from './Options';\nimport Parser         from './Parser';\nimport ReactionDrawer from './ReactionDrawer';\nimport ReactionParser from './ReactionParser';\nimport SvgDrawer      from './SvgDrawer';\nimport SvgWrapper     from './SvgWrapper';\n\nexport default class SmilesDrawer {\n    constructor(moleculeOptions = {}, reactionOptions = {}) {\n        this.drawer = new SvgDrawer(moleculeOptions);\n\n        // moleculeOptions gets edited in reactionOptions, so clone\n        this.reactionDrawer = new ReactionDrawer(reactionOptions, JSON.parse(JSON.stringify(this.drawer.opts)));\n    }\n\n    static apply(moleculeOptions = {}, reactionOptions = {}, attribute = 'data-smiles', theme = 'light', successCallback = null, errorCallback = null) {\n        const drawer = new SmilesDrawer(moleculeOptions, reactionOptions);\n        drawer.apply(attribute, theme, successCallback, errorCallback);\n    }\n\n    apply(attribute = 'data-smiles', theme = 'light', successCallback = null, errorCallback = null) {\n        let elements = document.querySelectorAll(`[${attribute}]`);\n        elements.forEach((element) => {\n            let smiles = element.getAttribute(attribute);\n\n            if (smiles === null) {\n                throw Error('No SMILES provided.');\n            }\n\n            let currentTheme = theme;\n            let weights = null;\n\n            if (element.hasAttribute('data-smiles-theme')) {\n                currentTheme = element.getAttribute('data-smiles-theme');\n            }\n\n            if (element.hasAttribute('data-smiles-weights')) {\n                weights = element.getAttribute('data-smiles-weights').split(',').map(parseFloat);\n            }\n\n            if (element.hasAttribute('data-smiles-reactant-weights')\n                || element.hasAttribute('data-smiles-reagent-weights')\n                || element.hasAttribute('data-smiles-product-weights')\n            ) {\n                weights = {reactants: [], reagents: [], products: []};\n                if (element.hasAttribute('data-smiles-reactant-weights')) {\n                    weights.reactants = element.getAttribute('data-smiles-reactant-weights').split(';').map((v) => {\n                        return v.split(',').map(parseFloat);\n                    });\n                }\n\n                if (element.hasAttribute('data-smiles-reagent-weights')) {\n                    weights.reagents = element.getAttribute('data-smiles-reagent-weights').split(';').map((v) => {\n                        return v.split(',').map(parseFloat);\n                    });\n                }\n\n                if (element.hasAttribute('data-smiles-product-weights')) {\n                    weights.products = element.getAttribute('data-smiles-product-weights').split(';').map((v) => {\n                        return v.split(',').map(parseFloat);\n                    });\n                }\n            }\n\n            if (element.hasAttribute('data-smiles-options') || element.hasAttribute('data-smiles-reaction-options')) {\n                let moleculeOptions = {};\n                if (element.hasAttribute('data-smiles-options')) {\n                    const attr = element.getAttribute('data-smiles-options');\n                    try {\n                        moleculeOptions = JSON.parse(attr);\n                    }\n                    catch {\n                        moleculeOptions = JSON.parse(attr.replace(/'/g, '\"'));\n                    }\n                }\n\n                let reactionOptions = {};\n                if (element.hasAttribute('data-smiles-reaction-options')) {\n                    const attr = element.getAttribute('data-smiles-reaction-options');\n                    try {\n                        reactionOptions = JSON.parse(attr);\n                    }\n                    catch {\n                        reactionOptions = JSON.parse(attr.replace(/'/g, '\"'));\n                    }\n                }\n\n                let smilesDrawer = new SmilesDrawer(moleculeOptions, reactionOptions);\n                smilesDrawer.draw(smiles, element, currentTheme, successCallback, errorCallback, weights);\n            }\n            else {\n                this.draw(smiles, element, currentTheme, successCallback, errorCallback, weights);\n            }\n        });\n    }\n\n    /**\n     * Draw the smiles to the target.\n     * @param {String} smiles The SMILES to be depicted.\n     * @param {*} target The target element.\n     * @param {String} theme The theme.\n     * @param {?CallableFunction} successCallback The function called on success.\n     * @param {?CallableFunction} errorCallback The function called on error.\n     * @param {?Number[]|Object} weights The weights for the gaussians.\n     */\n    draw(smiles, target, theme = 'light', successCallback = null, errorCallback = null, weights = null) {\n        // get the settings\n        let rest = [];\n        [smiles, ...rest] = smiles.split(' ');\n        let info = rest.join(' ');\n\n        let settings = {};\n\n        if (info.includes('__')) {\n            let settingsString = info.substring(\n                info.indexOf('__') + 2,\n                info.lastIndexOf('__')\n            );\n\n            try {\n                settings = JSON.parse(settingsString);\n            }\n            catch {\n                settings = JSON.parse(settingsString.replace(/'/g, '\"'));\n            }\n        }\n\n        let defaultSettings = {\n            textAboveArrow: '{reagents}',\n            textBelowArrow: '',\n        };\n\n        settings = Options.extend(true, defaultSettings, settings);\n\n        if (smiles.includes('>')) {\n            try {\n                this.drawReaction(smiles, target, theme, settings, weights, successCallback);\n            }\n            catch (err) {\n                if (errorCallback) {\n                    errorCallback(err);\n                }\n                else {\n                    console.error(err);\n                }\n            }\n        }\n        else {\n            try {\n                this.drawMolecule(smiles, target, theme, weights, successCallback);\n            }\n            catch (err) {\n                if (errorCallback) {\n                    errorCallback(err);\n                }\n                else {\n                    console.error(err);\n                }\n            }\n        }\n    }\n\n    drawMolecule(smiles, target, theme, weights, callback) {\n        let parseTree = Parser.parse(smiles);\n\n        if (target === null || target === 'svg') {\n            let svg = this.drawer.draw(parseTree, null, theme, weights);\n            let dims = this.getDimensions(svg);\n            svg.setAttributeNS(null, 'width', '' + dims.w);\n            svg.setAttributeNS(null, 'height', '' + dims.h);\n            if (callback) {\n                callback(svg);\n            }\n        }\n        else if (target === 'canvas') {\n            let canvas = this.svgToCanvas(this.drawer.draw(parseTree, null, theme, weights));\n            if (callback) {\n                callback(canvas);\n            }\n        }\n        else if (target === 'img') {\n            let img = this.svgToImg(this.drawer.draw(parseTree, null, theme, weights));\n            if (callback) {\n                callback(img);\n            }\n        }\n        else if (target instanceof HTMLImageElement) {\n            this.svgToImg(this.drawer.draw(parseTree, null, theme, weights), target);\n            if (callback) {\n                callback(target);\n            }\n        }\n        else if (target instanceof SVGElement) {\n            this.drawer.draw(parseTree, target, theme, weights);\n            if (callback) {\n                callback(target);\n            }\n        }\n        else {\n            let elements = document.querySelectorAll(target);\n            elements.forEach((element) => {\n                let tag = element.nodeName.toLowerCase();\n                if (tag === 'svg') {\n                    this.drawer.draw(parseTree, element, theme, weights);\n                    // let dims = this.getDimensions(element);\n                    // element.setAttributeNS(null, 'width', '' + dims.w);\n                    // element.setAttributeNS(null, 'height', '' + dims.h);\n                    if (callback) {\n                        callback(element);\n                    }\n                }\n                else if (tag === 'canvas') {\n                    this.svgToCanvas(this.drawer.draw(parseTree, null, theme, weights), element);\n                    if (callback) {\n                        callback(element);\n                    }\n                }\n                else if (tag === 'img') {\n                    this.svgToImg(this.drawer.draw(parseTree, null, theme, weights), element);\n                    if (callback) {\n                        callback(element);\n                    }\n                }\n            });\n        }\n    }\n\n    drawReaction(smiles, target, theme, settings, weights, callback) {\n        let reaction = ReactionParser.parse(smiles);\n\n        if (target === null || target === 'svg') {\n            let svg = this.reactionDrawer.draw(reaction, null, theme);\n            let dims = this.getDimensions(svg);\n            svg.setAttributeNS(null, 'width', '' + dims.w);\n            svg.setAttributeNS(null, 'height', '' + dims.h);\n            if (callback) {\n                callback(svg);\n            }\n        }\n        else if (target === 'canvas') {\n            let canvas = this.svgToCanvas(this.reactionDrawer.draw(reaction, null, theme, weights, settings.textAboveArrow, settings.textBelowArrow));\n            if (callback) {\n                callback(canvas);\n            }\n        }\n        else if (target === 'img') {\n            let img = this.svgToImg(this.reactionDrawer.draw(reaction, null, theme, weights, settings.textAboveArrow, settings.textBelowArrow));\n            if (callback) {\n                callback(img);\n            }\n        }\n        else if (target instanceof HTMLImageElement) {\n            this.svgToImg(this.reactionDrawer.draw(reaction, null, theme, weights, settings.textAboveArrow, settings.textBelowArrow), target);\n            if (callback) {\n                callback(target);\n            }\n        }\n        else if (target instanceof SVGElement) {\n            this.reactionDrawer.draw(reaction, target, theme, weights, settings.textAboveArrow, settings.textBelowArrow);\n            if (callback) {\n                callback(target);\n            }\n        }\n        else {\n            let elements = document.querySelectorAll(target);\n            elements.forEach((element) => {\n                let tag = element.nodeName.toLowerCase();\n                if (tag === 'svg') {\n                    this.reactionDrawer.draw(reaction, element, theme, weights, settings.textAboveArrow, settings.textBelowArrow);\n                    // The svg has to have a css width and height set for the other\n                    // tags, however, here it would overwrite the chosen width and height\n                    if (this.reactionDrawer.opts.scale <= 0) {\n                        element.style.width = null;\n                        element.style.height = null;\n                    }\n                    // let dims = this.getDimensions(element);\n                    // element.setAttributeNS(null, 'width', '' + dims.w);\n                    // element.setAttributeNS(null, 'height', '' + dims.h);\n                    if (callback) {\n                        callback(element);\n                    }\n                }\n                else if (tag === 'canvas') {\n                    this.svgToCanvas(this.reactionDrawer.draw(reaction, null, theme, weights, settings.textAboveArrow, settings.textBelowArrow), element);\n                    if (callback) {\n                        callback(element);\n                    }\n                }\n                else if (tag === 'img') {\n                    this.svgToImg(this.reactionDrawer.draw(reaction, null, theme, weights, settings.textAboveArrow, settings.textBelowArrow), element);\n                    if (callback) {\n                        callback(element);\n                    }\n                }\n            });\n        }\n    }\n\n    svgToCanvas(svg, canvas = null) {\n        if (canvas === null) {\n            canvas = document.createElement('canvas');\n        }\n\n        let dims = this.getDimensions(canvas, svg);\n\n        SvgWrapper.svgToCanvas(svg, canvas, dims.w, dims.h);\n        return canvas;\n    }\n\n    svgToImg(svg, img = null) {\n        if (img === null) {\n            img = document.createElement('img');\n        }\n\n        let dims = this.getDimensions(img, svg);\n\n        SvgWrapper.svgToImg(svg, img, dims.w, dims.h);\n        return img;\n    }\n\n    /**\n     *\n     * @param {HTMLImageElement|HTMLCanvasElement|SVGElement} element\n     * @param {SVGElement} svg\n     * @returns {{w: Number, h: Number}} The width and height.\n     */\n    getDimensions(element, svg = null) {\n        let w = this.drawer.opts.width;\n        let h = this.drawer.opts.height;\n\n        if (this.drawer.opts.scale <= 0) {\n            if (!(element instanceof SVGElement)) {\n                if (w === null) w = element.width;\n                if (h === null) h = element.height;\n            }\n\n            if (element.style.width !== '') {\n                w = parseInt(element.style.width);\n            }\n\n            if (element.style.height !== '') {\n                h = parseInt(element.style.height);\n            }\n        }\n        else if (svg) {\n            w = parseFloat(svg.style.width);\n            h = parseFloat(svg.style.height);\n        }\n\n        return {w: w, h: h};\n    }\n}\n", "import Drawer         from './src/Drawer';\nimport GaussDrawer    from './src/GaussDrawer';\nimport Graph          from './src/Graph';\nimport Parser         from './src/ParserWrapper';\nimport Reaction       from './src/Reaction';\nimport ReactionDrawer from './src/ReactionDrawer';\nimport ReactionParser from './src/ReactionParser';\nimport SmiDrawer      from './src/SmilesDrawer';\nimport SvgDrawer      from './src/SvgDrawer';\n\n/**\n * The SmilesDrawer namespace.\n * @typicalname SmilesDrawer\n */\nexport default class SmilesDrawerNS {\n    static Version = '2.4.1';\n\n    static Drawer         = Drawer;\n    static GaussDrawer    = GaussDrawer;\n    static Parser         = Parser;\n    static ReactionDrawer = ReactionDrawer;\n    static ReactionParser = ReactionParser;\n    static SmiDrawer      = SmiDrawer;\n    static SvgDrawer      = SvgDrawer;\n\n    /**\n    * Cleans a SMILES string (by removing all non-valid characters)\n    *\n    * @param smiles - A SMILES string.\n    * @returns The clean SMILES string.\n    */\n    static clean(smiles: string): string {\n        return smiles.replace(/[^A-Za-z0-9@.+\\-?!()[\\]{}/\\\\=#$:*]/g, '');\n    }\n\n    /**\n    * Applies the smiles drawer draw function to each canvas element that has a smiles string in the data-smiles attribute.\n    *\n    * @param options   - SmilesDrawer options.\n    * @param selector  - A CSS selector that identifies drawable elements (default \"canvas[data-smiles]\").\n    * @param themeName - The theme to apply (default \"light\").\n    * @param onError   - An optional callback function that takes an error object (default null).\n    */\n    static apply(options: object, selector: string = 'canvas[data-smiles]', themeName: string = 'light', onError?: (e: Error) => void): void {\n        const smilesDrawer = new Drawer(options);\n        const elements = document.querySelectorAll(selector);\n\n        for (let i = 0; i < elements.length; i++) {\n            // TODO: This should also support SVGs, IMGs, etc!\n            const element = elements[i] as HTMLCanvasElement;\n\n            SmilesDrawerNS.parse(element.getAttribute('data-smiles'), function(tree) {\n                smilesDrawer.draw(tree, element, themeName, false);\n            }, function(err) {\n                if (onError) {\n                    onError(err);\n                }\n            });\n        }\n    }\n\n    /**\n    * Parses a SMILES string.\n    *\n    * @param smiles          - A SMILES string.\n    * @param successCallback - A callback that is called on success with the parse tree.\n    * @param errorCallback   - A callback that is called with the error object on error.\n    */\n    static parse(smiles: string, successCallback: (g: Graph) => void, errorCallback?: (e: Error) => void): void {\n        try {\n            if (successCallback) {\n                successCallback(Parser.parse(smiles));\n            }\n        }\n        catch (err) {\n            if (errorCallback) {\n                errorCallback(err);\n            }\n        }\n    }\n\n    /**\n    * Parses a reaction SMILES string.\n    *\n    * @param reactionSmiles  - A reaction SMILES string.\n    * @param successCallback - A callback that is called on success with the parse tree.\n    * @param errorCallback   - A callback that is called with the error object on error.\n    */\n    static parseReaction(reactionSmiles: string, successCallback: (r: Reaction) => void, errorCallback?: (e: Error) => void): void {\n        try {\n            if (successCallback) {\n                successCallback(ReactionParser.parse(reactionSmiles));\n            }\n        }\n        catch (err) {\n            if (errorCallback) {\n                errorCallback(err);\n            }\n        }\n    }\n}\n\n// If we're in a browser window, add the SmilesDrawer globals\n// TypeScript tricks from https://stackoverflow.com/a/12709880\ndeclare global {\n    interface Window {\n        SmilesDrawer: typeof SmilesDrawerNS\n        SmiDrawer:    typeof SmiDrawer\n    }\n}\n\nif (typeof window !== 'undefined' && window.document && window.document.createElement) {\n    window.SmilesDrawer = SmilesDrawerNS;\n    window.SmiDrawer    = SmiDrawer;\n}\n\n// If we've been required via CommonJS, export as the Romans do...\n// if (typeof module !== 'undefined' && module.exports && typeof require === 'function') {\n//     try {\n//         const commonjs   = module;\n//         commonjs.exports = SmilesDrawerNS;\n//     }\n//     catch {\n//         // TypeError: ESM module.exports only has a getter in Node.\n//         // I guess we're not in CommonJS after all...\n//     }\n// }\n"],
  "mappings": "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",
  "names": ["require_chroma", "__commonJSMin", "exports", "module", "global", "factory", "limit$2", "x", "min", "max", "limit$1", "clip_rgb$3", "rgb", "i", "classToType", "i$1", "list$1", "name", "type$p", "obj", "type$o", "unpack$B", "args", "keyOrder", "k", "type$n", "last$4", "l", "PI$2", "utils", "input$h", "last$3", "clip_rgb$2", "type$m", "_input", "Color$D", "len", "me", "mode", "autodetect", "a", "b", "list", "chk", "Color_1", "chroma$k", "chroma_1", "unpack$A", "max$2", "rgb2cmyk$1", "ref", "r", "g", "f", "c", "m", "y", "rgb2cmyk_1", "unpack$z", "cmyk2rgb", "alpha", "cmyk2rgb_1", "chroma$j", "Color$C", "input$g", "unpack$y", "type$l", "rgb2cmyk", "unpack$x", "last$2", "rnd", "hsl2css$1", "hsla", "hsl2css_1", "unpack$w", "rgb2hsl$3", "s", "h", "rgb2hsl_1", "unpack$v", "last$1", "hsl2css", "rgb2hsl$2", "round$6", "rgb2css$1", "rgba", "rgb2css_1", "unpack$u", "round$5", "hsl2rgb$1", "assign", "t3", "t2", "t1", "h_", "hsl2rgb_1", "hsl2rgb", "input$f", "RE_RGB", "RE_RGBA", "RE_RGB_PCT", "RE_RGBA_PCT", "RE_HSL", "RE_HSLA", "round$4", "css2rgb$1", "css", "e", "rgb$1", "rgb$2", "i$2", "rgb$3", "i$3", "hsl", "rgb$4", "hsl$1", "rgb$5", "css2rgb_1", "chroma$i", "Color$B", "input$e", "type$k", "rgb2css", "css2rgb", "rest", "Color$A", "chroma$h", "input$d", "unpack$t", "unpack$s", "rgb2hcg$1", "delta", "_g", "rgb2hcg_1", "unpack$r", "floor$3", "hcg2rgb", "assign$1", "assign$2", "assign$3", "assign$4", "assign$5", "_c", "p", "q", "t", "v", "hcg2rgb_1", "unpack$q", "type$j", "chroma$g", "Color$z", "input$c", "rgb2hcg", "unpack$p", "last", "round$3", "rgb2hex$2", "u", "str", "hxa", "rgb2hex_1", "RE_HEX", "RE_HEXA", "hex2rgb$1", "hex", "u$1", "r$1", "g$1", "b$1", "hex2rgb_1", "chroma$f", "Color$y", "type$i", "input$b", "rgb2hex$1", "unpack$o", "TWOPI$2", "min$2", "sqrt$4", "acos", "rgb2hsi$1", "min_", "rgb2hsi_1", "unpack$n", "limit", "TWOPI$1", "PITHIRD", "cos$4", "hsi2rgb", "hsi2rgb_1", "unpack$m", "type$h", "chroma$e", "Color$x", "input$a", "rgb2hsi", "unpack$l", "type$g", "chroma$d", "Color$w", "input$9", "rgb2hsl$1", "unpack$k", "min$1", "max$1", "rgb2hsl", "max_", "rgb2hsv$1", "unpack$j", "floor$2", "hsv2rgb", "hsv2rgb_1", "unpack$i", "type$f", "chroma$c", "Color$v", "input$8", "rgb2hsv", "labConstants", "LAB_CONSTANTS$3", "unpack$h", "pow$a", "rgb2lab$2", "ref$1", "rgb2xyz", "z", "rgb_xyz", "xyz_lab", "rgb2lab_1", "LAB_CONSTANTS$2", "unpack$g", "pow$9", "lab2rgb$1", "b_", "lab_xyz", "xyz_rgb", "lab2rgb_1", "unpack$f", "type$e", "chroma$b", "Color$u", "input$7", "rgb2lab$1", "unpack$e", "RAD2DEG", "sqrt$3", "atan2$2", "round$2", "lab2lch$2", "lab2lch_1", "unpack$d", "rgb2lab", "lab2lch$1", "rgb2lch$1", "rgb2lch_1", "unpack$c", "DEG2RAD", "sin$3", "cos$3", "lch2lab$2", "lch2lab_1", "unpack$b", "lch2lab$1", "lab2rgb", "lch2rgb$1", "L", "lch2rgb_1", "unpack$a", "lch2rgb", "hcl2rgb", "hcl", "hcl2rgb_1", "unpack$9", "type$d", "chroma$a", "Color$t", "input$6", "rgb2lch", "w3cx11$1", "w3cx11_1", "Color$s", "input$5", "type$c", "w3cx11", "hex2rgb", "rgb2hex", "n", "unpack$8", "rgb2num$1", "rgb2num_1", "type$b", "num2rgb", "num", "num2rgb_1", "chroma$9", "Color$r", "input$4", "type$a", "rgb2num", "chroma$8", "Color$q", "input$3", "unpack$7", "type$9", "round$1", "log$1", "temperature2rgb$1", "kelvin", "temp", "temperature2rgb_1", "temperature2rgb", "unpack$6", "round", "rgb2temperature$1", "minTemp", "maxTemp", "eps", "rgb2temperature_1", "chroma$7", "Color$p", "input$2", "rgb2temperature", "unpack$5", "cbrt", "pow$8", "sign$1", "rgb2oklab$2", "rgb2lrgb", "lr", "lg", "lb", "rgb2oklab_1", "abs", "unpack$4", "pow$7", "sign", "oklab2rgb$1", "lrgb2rgb", "oklab2rgb_1", "unpack$3", "type$8", "chroma$6", "Color$o", "input$1", "rgb2oklab$1", "unpack$2", "rgb2oklab", "lab2lch", "rgb2oklch$1", "rgb2oklch_1", "unpack$1", "lch2lab", "oklab2rgb", "oklch2rgb", "oklch2rgb_1", "unpack", "type$7", "chroma$5", "Color$n", "input", "rgb2oklch", "Color$m", "type$6", "mutate", "Color$l", "Color$k", "LAB_CONSTANTS$1", "amount", "lab", "Color$j", "mc", "channel", "src", "Color$i", "type$5", "pow$6", "EPS", "MAX_ITER", "lum", "cur_lum", "max_iter", "test", "low", "high", "mid", "lm", "rgb2luminance", "luminance_x", "interpolator$1", "Color$h", "type$4", "interpolator", "mix$1", "col1", "col2", "Color$g", "mix", "Color$f", "Color$e", "LAB_CONSTANTS", "lch", "Color$d", "type$3", "value", "out", "Color$c", "xyz0", "xyz1", "Color$b", "sqrt$2", "pow$5", "lrgb", "x1", "y1", "z1", "x2", "y2", "z2", "Color$a", "Color$9", "_hsx", "hue0", "hue1", "sat0", "sat1", "lbv0", "lbv1", "sat", "hue", "lbv", "dh", "interpolate_hsx$5", "Color$8", "c1", "c2", "interpolate_hsx$4", "hcg", "interpolate_hsx$3", "hsi", "interpolate_hsx$2", "interpolate_hsx$1", "hsv", "Color$7", "oklab", "interpolate_hsx", "oklch", "Color$6", "clip_rgb$1", "pow$4", "sqrt$1", "PI$1", "cos$2", "sin$2", "atan2$1", "average", "colors", "weights", "w", "_average_lrgb", "first", "xyz", "cnt", "dx", "dy", "A", "ci", "xyz2", "A$1", "col", "chroma$4", "type$2", "pow$3", "scale$2", "_mode", "_nacol", "_spread", "_domain", "_pos", "_padding", "_classes", "_colors", "_out", "_min", "_max", "_correctLightness", "_colorCache", "_useCache", "_gamma", "setColors", "c$1", "resetCache", "getClass", "tMapLightness", "tMapDomain", "getColor", "val", "bypassMap", "classes", "d", "domain", "tOut", "tBreaks", "_m", "_o", "L0", "L1", "pol", "L_actual", "L_ideal", "L_diff", "t0", "numColors", "result", "dm", "dd", "__range__", "samples", "end", "asc", "left", "right", "inclusive", "range", "ascending", "Color$5", "scale$1", "binom_row", "row", "newrow", "j", "bezier", "I", "lab0", "lab1", "lab2", "lab3", "labs", "sum", "el", "bezier_1", "chroma$3", "blend", "bottom", "top", "blend_f", "c0", "each", "normal", "multiply", "darken", "lighten", "screen", "overlay", "burn", "dodge", "blend_1", "type$1", "clip_rgb", "TWOPI", "pow$2", "sin$1", "cos$1", "chroma$2", "cubehelix", "start", "rotations", "gamma", "lightness", "dl", "fract", "amp", "cos_a", "sin_a", "Color$4", "digits", "floor$1", "random", "random_1", "code", "type", "log", "pow$1", "floor", "abs$1", "analyze", "data", "key", "limits", "values", "min_log", "max_log", "pb", "pr", "cluster", "assignments", "clusterSizes", "repeat", "nb_iters", "centroids", "i$4", "mindist", "best", "j$1", "dist", "newCentroids", "j$2", "i$5", "j$3", "j$4", "kClusters", "j$5", "i$6", "tmpKMeansBreaks", "j$6", "i$7", "analyze_1", "Color$3", "contrast", "l1", "l2", "Color$2", "sqrt", "pow", "atan2", "cos", "sin", "exp", "PI", "deltaE", "Kl", "Kc", "Kh", "rad2deg", "rad", "deg2rad", "deg", "a1", "b1", "L2", "a2", "b2", "avgL", "C1", "C2", "avgC", "G", "a1p", "a2p", "C1p", "C2p", "avgCp", "arctan1", "arctan2", "h1p", "h2p", "avgHp", "T", "deltaHp", "deltaL", "deltaCp", "sl", "sc", "sh", "deltaTheta", "Rc", "Rt", "Color$1", "distance", "sum_sq", "Color", "valid", "chroma$1", "scale", "scales", "colorbrewer", "colorbrewer_1", "chroma", "chroma_js", "ArrayHelper", "_ArrayHelper", "arr", "out", "key", "value", "arrA", "arrB", "tmpA", "tmpB", "i", "s", "callback", "property", "options", "intersection", "j", "contains", "count", "newArr", "removed", "tmp", "index", "item", "containing", "map", "e", "a", "b", "min", "_Atom", "element", "bondType", "previousElement", "hydrogenCount", "charge", "key", "ordered", "ringId", "ArrayHelper", "i", "atomA", "atomB", "j", "arr", "bonds", "valences", "valence", "n", "__publicField", "Atom", "Vector2", "_Vector2", "x", "y", "vec", "scalar", "v", "a", "b", "center", "angle", "tmp", "cosAngle", "sinAngle", "s", "c", "offsetAngle", "distSqA", "polygon", "inside", "i", "j", "vecA", "vecB", "vecC", "d", "dRef", "delta", "dot", "ab", "bc", "abLength", "bcLength", "unit", "vecs", "avg", "Line", "_Line", "from", "Vector2", "to", "elementFrom", "elementTo", "chiralFrom", "chiralTo", "dx", "dy", "x", "y", "left", "theta", "l", "sinTheta", "cosTheta", "by", "f", "MathHelper", "_MathHelper", "value", "decimals", "pow", "arr", "sin", "cos", "n", "s", "r", "rad", "deg", "visited", "evenLengthCycleCount", "traverseCycle", "i", "cycleLength", "Vertex", "_Vertex", "value", "x", "y", "Vector2", "v", "vertexId", "ringbondIndex", "index", "parentVertexId", "clone", "ArrayHelper", "vertex", "referenceVector", "returnAsDegrees", "u", "MathHelper", "vertices", "onlyHorizontal", "neighbours", "angles", "i", "textAngle", "halfPi", "arr", "ringId", "previousVertexId", "RingConnection", "firstRing", "secondRing", "m", "c", "d", "vertexId", "ringId", "otherRingId", "vertices", "v1", "v2", "v2NeighbourSet", "nRings", "ringConnections", "firstRingId", "secondRingId", "ringConnection", "i", "neighbours", "Ring", "_Ring", "members", "Vector2", "clone", "ArrayHelper", "vertices", "polygon", "i", "callback", "startVertexId", "previousVertexId", "current", "max", "prev", "ringConnections", "orderedNeighbours", "RingConnection", "a", "b", "db", "length", "doubleBondCount", "atom", "vertexId", "ThemeManager", "colors", "theme", "key", "getChargeText", "charge", "CanvasWrapper", "target", "themeManager", "options", "element", "width", "height", "theme", "vertices", "maxX", "maxY", "minX", "minY", "i", "p", "padding", "scaleX", "scaleY", "scale", "key", "x", "y", "radius", "color", "fill", "debug", "debugText", "ctx", "offsetX", "offsetY", "MathHelper", "line", "dashed", "alpha", "shortLine", "l", "r", "gradient", "_width", "normals", "Vector2", "isRightChiralCenter", "start", "end", "t", "u", "v", "w", "sStart", "sEnd", "dir", "length", "step", "changed", "to", "startDash", "dashOffset", "text", "elementName", "hydrogens", "direction", "isTerminal", "isotope", "vertexCount", "attachedPseudoElement", "pseudoElementHandled", "chargeText", "chargeWidth", "isotopeText", "isotopeWidth", "dim", "cursorPos", "cursorPosLeft", "hydrogenWidth", "hydrogenCountWidth", "hx", "hy", "openParenthesisWidth", "closeParenthesisWidth", "elementCount", "hydrogenCount", "elementCharge", "elementWidth", "elementCountWidth", "elementChargeText", "elementChargeWidth", "ring", "CIPTree", "_CIPTree", "graph", "vertex", "root", "lhs", "rhs", "cmp", "lqueue", "rqueue", "stereo", "q", "ls", "rs", "len", "i", "d", "parent", "magic", "Vertex", "mydepth", "visited", "index", "links", "neighbour", "depth", "child", "hydrogens", "a", "b", "sum", "CIP", "nNeighbours", "order", "vid", "nid", "Edge", "_Edge", "sourceId", "targetId", "weight", "bondType", "Graph", "_Graph", "parseTree", "isomeric", "node", "_order", "parentVertexId", "isBranch", "element", "atom", "Atom", "vertex", "Vertex", "parentVertex", "edge", "Edge", "offset", "stereoHydrogens", "i", "source", "target", "vertexIdA", "vertexIdB", "edgeId", "vertexId", "edgeIds", "arr", "length", "adjacencyMatrix", "bridges", "vertexIds", "j", "adja", "dist", "k", "adjacencyList", "ring", "startVertexId", "insiderSet", "perimeter", "id", "perimeterSet", "adjacency", "neighbours", "neighbourId", "start", "ordered", "previous", "current", "a", "b", "next", "visited", "disc", "low", "parent", "adj", "outBridges", "callback", "queue", "u", "v", "max", "childId", "d", "maxDepth", "ignoreFirst", "depth", "matDist", "n", "bondLength", "dsq", "rowMean", "grandMean", "s", "B", "eigvec1", "eval1", "eigvec2", "eval2", "scale1", "scale2", "xs", "ys", "maxDistSq", "dx", "dy", "dSq", "maxDist", "mat", "maxIter", "w", "iter", "norm", "r", "center", "threshold", "innerThreshold", "maxIteration", "maxInnerIteration", "maxEnergy", "edgeStrength", "arrPositionX", "arrPositionY", "arrPositioned", "radius", "MathHelper", "angle", "insiders", "anyPositioned", "perimeterCount", "perimeterRadius", "perimeterAngle", "perimeterOffset", "initialPositions", "startVertexIndex", "startVertex", "Vector2", "point", "innerRadius", "direction", "initial", "mds", "idx", "matLength", "matStrength", "matEnergy", "arrEnergySumX", "arrEnergySumY", "ux", "uy", "dEx", "dEy", "vx", "vy", "denom", "energy", "index", "highestEnergy", "highEnergy", "highEnergyId", "highDEX", "highDEY", "delta", "dEX", "dEY", "update", "dxx", "dyy", "dxy", "arrL", "arrK", "l", "m", "stepLen", "scale", "arrE", "prevEx", "prevEy", "invDist", "maxEnergyId", "iteration", "innerIteration", "components", "component", "count", "Options", "_Options", "extended", "deep", "i", "length", "merge", "obj", "prop", "BitSet", "_BitSet", "size", "numWords", "i", "other", "op", "result", "count", "word", "highestSetBit", "MAX_INT", "shortestPaths", "graph", "start", "limit", "ordering", "n", "distTo", "precedes", "routeTo", "nPathsTo", "queue", "qLen", "i", "v", "dist", "k", "w", "newSeq", "routeToPath", "route", "len", "path", "cur", "routeToPaths", "parentPaths", "j", "leftPaths", "rightPaths", "end", "singletonIntersect", "p", "q", "pathToEdgeVector", "edgeIndex", "nEdges", "bs", "BitSet", "u", "key", "indexEdges", "toIndex", "computeOrdering", "maxDeg", "order", "buckets", "d", "rank", "computeInitialCycles", "cycles", "vertices", "addCycle", "edgeVector", "group", "s", "first", "r", "paths", "y", "sizeOfS", "z", "distToZ", "distToY", "pathToY", "pathToZ", "l", "pathToP", "pathToQ", "BitMatrix", "columns", "maxRows", "row", "tmpRow", "tmpIdx", "x", "GreedyBasis", "cycle", "candidate", "matrix", "minimumCycleBasis", "adjList", "initialCycles", "basis", "nSssr", "sortedCycles", "a", "b", "li", "ci", "c", "relevantCycles", "relevant", "pending", "matrixToAdjList", "adj", "SSSR", "_SSSR", "graph", "_experimental", "forLayout", "adjacencyMatrix", "connectedComponents", "Graph", "rings", "i", "connectedComponent", "ccAdjacencyMatrix", "adjList", "matrixToAdjList", "cyclePaths", "relevantCycles", "minimumCycleBasis", "j", "path", "ring", "k", "matrix", "str", "setA", "setB", "element", "DrawerBase", "_DrawerBase", "options", "Options", "opts", "allowed", "mode", "data", "target", "themeName", "infoOnly", "ThemeManager", "CanvasWrapper", "edgeId", "edge", "a", "b", "ring", "result", "i", "maxDist", "vertexA", "j", "vertexB", "dist", "angle", "Vector2", "remainder", "hac", "molecularFormula", "counts", "graph", "Graph", "atom", "hydrogens", "h", "count", "Atom", "e", "highlight_atoms", "overlapScore", "o", "subTreeDepthA", "subTreeDepthB", "neighboursB", "neighbour", "MathHelper", "newTotalOverlapScore", "neighbourA", "neighbourB", "ringId", "bestAngle", "bestOverlap", "stepAngle", "maxSteps", "step", "angleA", "angleB", "bond", "fwd", "rev", "openBonds", "vertex", "ringbondId", "ringbondBond", "sourceVertexId", "targetVertexId", "targetRingbondBond", "Edge", "targetVertex", "targetRingbondIdx", "k", "rings", "SSSR", "ringVertices", "Ring", "ringConnection", "RingConnection", "id", "involvedRings", "recurse", "r", "n", "changed", "rc", "hasFirst", "hasSecond", "ArrayHelper", "fusedCount", "fusedNeighbours", "visited", "cagedRings", "rootId", "component", "queue", "cur", "neighbours", "ringIds", "seedCount", "stats", "ringMemberSets", "atoms", "degreeByAtom", "members", "edgeCount", "boundaryEdgeCount", "ringCount", "nonCageAtomCount", "degree", "_sourceVertexId", "ringMembers", "vertices", "leftovers", "intersection", "insideRing", "onRing", "connections", "commonRings", "maxSize", "largestCommonRing", "size", "position", "radius", "excludeVertexId", "locals", "minDist", "minVertex", "v", "distSq", "item", "ringConnectionId", "vertexIdA", "vertexIdB", "toRemove", "ringConnections", "total", "overlapScores", "weighted", "sortable", "sides", "an", "bn", "anCount", "bnCount", "tn", "sideCount", "totalSideCount", "ringSize", "center", "smallest", "debug", "drawn", "edges", "elementA", "elementB", "normals", "aromaticRing", "inRing", "s", "line", "Line", "lineA", "lineB", "isChiralCenterA", "isChiralCenterB", "midpoint", "charge", "isotope", "element", "dir", "showCarbonsMode", "isTerminal", "isCarbon", "isRingCarbon", "value", "startVertex", "bridgedRings", "bridgedRing", "previousVertex", "orderedNeighbours", "startingAngle", "startVertexId", "apothem", "nextCenter", "posA", "posB", "ringMember", "ringMemberNeighbours", "vA", "vB", "stereoA", "stereoB", "nid", "neighborAbove", "expectedSameSide", "posS1", "posS2", "ax", "ay", "cross1", "cross2", "actualSameSide", "countA", "countB", "flipId", "pivotId", "pivot", "len2", "dx", "dy", "dot", "rdx", "rdy", "rdot", "vertexId", "parentVertexId", "rotationCenter", "vertexOverlapScores", "score", "vec", "rSq", "overlaps", "done", "nonRingNeighbours", "overlap", "subTreeOverlapA", "subTreeOverlapB", "scores", "closest", "closestPosition", "vertexPreviousPosition", "originShortest", "skipPositioning", "doubleBondConfigSet", "joinedVertex", "pos", "dummy", "nextRing", "tmpNeighbours", "previousAngle", "nextVertex", "prevEdge", "nextEdge", "proposedAngleA", "proposedAngleB", "proposedVectorA", "proposedVectorB", "centerOfMass", "distanceA", "distanceB", "bondType", "l", "subTreeDepthC", "cis", "trans", "cisVertex", "transVertex", "prevShortest", "newvertex", "subtreedepth", "totalNeighbors", "angleDelta", "radiusSq", "source", "tolerance", "positions", "minR", "maxR", "v1", "v2", "nrneighbours", "minimumDistance", "distance", "externalConnections", "memberId", "neighbourId", "currentOverlap", "currentMinimumDistance", "minimumAllowedDistance", "bestMinimumDistance", "baseAngle", "direction", "newOverlap", "newMinimumDistance", "order", "CIP", "parity", "rotation", "rs", "wedgeId", "rank", "wedge", "wedgeTargetId", "nNeighbours", "wedgeCipRank", "others", "wedgePos", "cx", "cy", "sa", "neighbourIds", "heteroAtomCount", "ctn", "neighbouringElement", "neighbourCount", "previous", "convertImage", "img", "each", "obj", "fn", "length", "i", "componentToHex", "c", "hex", "getColor", "r", "g", "b", "a", "makePathData", "x", "y", "w", "makePath", "color", "data", "colorsToPaths", "colors", "output", "values", "paths", "curPath", "index", "value", "getColors", "image", "len", "dummyDiv", "import_chroma_js", "GaussDrawer", "points", "weights", "width", "height", "sigma", "interval", "colormap", "opacity", "normalized", "arr_points", "arr_weights", "a", "Vector2", "w", "m", "x", "row", "y", "divisor", "i", "v", "dx", "dy", "v_xy", "val", "abs_max", "max", "min", "scale", "chroma", "r", "g", "b", "callback", "image", "err", "convertImage", "vec", "makeid", "length", "result", "characters", "charactersLength", "SvgWrapper", "_SvgWrapper", "themeManager", "target", "options", "clear", "defs", "masks", "background", "highlights", "paths", "vertices", "pathChildNodes", "mask", "path", "backgroundItem", "highlight", "vertex", "gradient", "svg", "vertex1", "vertex2", "c1", "c2", "cc", "d", "color1", "color2", "gradientUrl", "point", "radius", "stops", "gradientId", "offset", "color", "stop", "point1", "point2", "text", "shift", "elem", "n", "i", "p", "padding", "scale", "x", "y", "width", "height", "diff", "elementName", "r", "ball", "line", "l", "normals", "Vector2", "isRightChiralCenter", "start", "end", "t", "u", "v", "w", "polygon", "dir", "step", "to", "startDash", "dashOffset", "endDash", "Line", "debugText", "textElem", "s", "circleElem", "MathHelper", "dashed", "linecap", "lineElem", "hydrogens", "direction", "isTerminal", "charge", "isotope", "totalVertices", "attachedPseudoElement", "display", "key", "pe", "pe_display", "hcount", "weights", "points", "sigma", "cmap", "pos", "neg", "g", "weight", "circle", "singleVertex", "bbox", "fullBbox", "cx", "cy", "part", "tspanElem", "maskRadius", "canvas", "image", "parsed", "subscriptNumbers", "value", "fontSize", "fontFamily", "ctx", "textMetrics", "h", "char", "callback", "context", "err", "img", "maxWidth", "style", "lines", "words", "maxLineWidth", "dims", "SvgDrawer", "options", "clear", "DrawerBase", "data", "target", "themeName", "weights", "infoOnly", "highlight_atoms", "weightsNormalized", "svg", "optionBackup", "preprocessor", "ThemeManager", "SvgWrapper", "canvas", "ring", "debug", "graph", "rings", "drawn", "vertex", "edges", "i", "edgeId", "opts", "svgWrapper", "edge", "vertexA", "vertexB", "elementA", "elementB", "color", "a", "b", "normals", "sides", "ArrayHelper", "aromaticRing", "inRing", "s", "center", "line", "Vector2", "Line", "lineA", "lineB", "isChiralCenterA", "isChiralCenterB", "midpoint", "_debug", "atom", "j", "highlight", "charge", "isotope", "element", "hydrogens", "dir", "showCarbonsMode", "isTerminal", "isCarbon", "isRingCarbon", "attachedPseudoElements", "angle", "value", "vertex_ids", "min", "max", "weight", "points", "vid", "scale", "minX", "minY", "gd", "GaussDrawer", "background", "spacing", "Drawer", "options", "SvgDrawer", "data", "target", "themeName", "infoOnly", "highlight_atoms", "element", "canvas", "svg", "Parser_default", "peg$subclass", "child", "parent", "ctor", "peg$SyntaxError", "message", "expected", "found", "location", "DESCRIBE_EXPECTATION_FNS", "expectation", "literalEscape", "escapedParts", "i", "classEscape", "hex", "ch", "s", "describeExpectation", "describeExpected", "descriptions", "j", "describeFound", "peg$parse", "input", "options", "nOpenParentheses", "nCloseParentheses", "peg$buildSimpleError", "peg$FAILED", "peg$startRuleFunctions", "peg$parsechain", "peg$startRuleFunction", "peg$c0", "branches", "rings", "bond", "peg$c1", "peg$c2", "peg$literalExpectation", "peg$c3", "peg$c4", "peg$c5", "b", "peg$c6", "a", "peg$c7", "peg$c8", "peg$classExpectation", "peg$c9", "peg$c10", "peg$c11", "peg$c12", "peg$c13", "peg$c14", "peg$c15", "peg$c16", "peg$c17", "peg$c18", "peg$c19", "peg$c20", "peg$c21", "peg$c22", "peg$c23", "peg$c24", "peg$c25", "peg$c26", "peg$c27", "peg$c28", "peg$c29", "o", "peg$c30", "peg$c31", "peg$c32", "peg$c33", "peg$c34", "w", "peg$c35", "peg$c36", "peg$c37", "peg$c38", "peg$c39", "e", "peg$c40", "peg$c41", "peg$c42", "peg$c43", "peg$c44", "peg$c45", "peg$c46", "r", "peg$c47", "peg$c48", "peg$c49", "peg$c50", "peg$c51", "peg$c52", "peg$c53", "peg$c54", "peg$c55", "peg$c56", "peg$c57", "peg$c58", "peg$c59", "peg$c60", "peg$c61", "peg$c62", "peg$c63", "c", "peg$c64", "peg$c65", "peg$c66", "peg$c67", "peg$c68", "peg$c69", "peg$c70", "peg$c71", "peg$c72", "peg$c73", "h", "peg$c74", "peg$c75", "peg$c76", "peg$c77", "peg$c78", "peg$c79", "peg$currPos", "peg$savedPos", "peg$posDetailsCache", "peg$maxFailPos", "peg$maxFailExpected", "peg$silentFails", "peg$result", "text", "peg$computeLocation", "description", "peg$buildStructuredError", "peg$otherExpectation", "error", "ignoreCase", "parts", "inverted", "peg$anyExpectation", "peg$endExpectation", "peg$computePosDetails", "pos", "details", "p", "startPos", "endPos", "startPosDetails", "endPosDetails", "peg$fail", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "peg$parseatom", "peg$parsebranch", "peg$parsebond", "peg$parsering", "peg$parseorganicsymbol", "peg$parsearomaticsymbol", "peg$parsebracketatom", "peg$parsewildcard", "peg$parseisotope", "peg$parseelementsymbol", "peg$parsechiral", "peg$parsehcount", "peg$parsecharge", "peg$parseclass", "peg$parseposcharge", "peg$parsenegcharge", "ParserWrapper", "smiles", "Parser_default", "FormulaToCommonName_default", "ReactionDrawer", "reactionOptions", "moleculeOptions", "SvgDrawer", "Options", "reaction", "target", "themeName", "weights", "textAbove", "textBelow", "infoOnly", "ThemeManager", "max", "min", "i", "j", "abs_max", "svg", "elements", "maxHeight", "reactantWeights", "reactantSvg", "element", "reagentsText", "text", "FormulaToCommonName_default", "SvgWrapper", "topText", "centerOffsetX", "bottomText", "productWeights", "productSvg", "minY", "maxY", "totalWidth", "offsetX", "offsetY", "y", "height", "s", "w", "rect_h", "rect_v", "marker", "polygon", "sw", "path", "l", "defs", "line", "Reaction", "reactionSmiles", "parts", "i", "Parser_default", "ReactionParser", "reactionSmiles", "Reaction", "SmilesDrawer", "_SmilesDrawer", "moleculeOptions", "reactionOptions", "SvgDrawer", "ReactionDrawer", "attribute", "theme", "successCallback", "errorCallback", "element", "smiles", "currentTheme", "weights", "v", "attr", "e", "target", "rest", "info", "settings", "settingsString", "defaultSettings", "Options", "err", "callback", "parseTree", "Parser_default", "svg", "dims", "canvas", "img", "tag", "reaction", "ReactionParser", "SvgWrapper", "w", "h", "_SmilesDrawerNS", "smiles", "options", "selector", "themeName", "onError", "smilesDrawer", "Drawer", "elements", "i", "element", "tree", "err", "successCallback", "errorCallback", "ParserWrapper", "reactionSmiles", "ReactionParser", "GaussDrawer", "ReactionDrawer", "SmilesDrawer", "SvgDrawer", "SmilesDrawerNS"]
}
