phyloio 2.1.1 → 2.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,350 @@
1
+ /*
2
+ * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
3
+ * This devtool is neither made for production nor for readable output files.
4
+ * It uses "eval()" calls to create a separate source file in the browser devtools.
5
+ * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
6
+ * or disable the default devtool with "devtool: false".
7
+ * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
8
+ */
9
+ /******/ (() => { // webpackBootstrap
10
+ /******/ var __webpack_modules__ = ({
11
+
12
+ /***/ "./src/model.js":
13
+ /*!**********************!*\
14
+ !*** ./src/model.js ***!
15
+ \**********************/
16
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
17
+
18
+ "use strict";
19
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Model)\n/* harmony export */ });\n/* harmony import */ var d3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! d3 */ \"./node_modules/d3/index.js\");\n/* harmony import */ var minhashjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! minhashjs */ \"./node_modules/minhashjs/index.js\");\n/* harmony import */ var biojs_io_newick__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! biojs-io-newick */ \"./node_modules/biojs-io-newick/src/index.js\");\n\n\n\n\nvar uid_model = 0\nvar uid_untitle_counter = 0\n;\nconst { parse_nhx } = __webpack_require__(/*! ./utils.js */ \"./src/utils.js\");\nconst { phyloXml } = __webpack_require__(/*! ./phyloxml.js */ \"./src/phyloxml.js\");\n\nclass Model {\n\n constructor(data, settings, from_raw_data = true) {\n\n this.zoom;\n this.settings = {\n 'uid': null,\n 'domain_extended_data' : {},\n 'edge_related_data' : ['Length'],\n 'default_internal_label_is_for_branch': false,\n 'extended_data_type' : {'Topology': 'num'},\n 'labels' : {'leaf' : new Set(), 'node':new Set()},\n 'colorlabels' :{'leaf' : new Set(), 'node':new Set([\"Topology\"])},\n 'display_leaves' : true,\n 'display_nodes_labels' : true,\n 'mirror': false,\n 'name': null,\n 'first_time_render': true,\n 'data_type' : 'newick',\n 'use_branch_lenght' : true,\n 'show_tooltips' : false,\n 'subsample_label' : true,\n 'use_internal_node_name_for_triangles' : true,\n 'display_internal_label' : false,\n 'display_internal_label_left_top' : false,\n 'display_internal_label_left_bottom' : false,\n 'display_leaf_label' : false,\n 'display_leaf_label_left_top' : false,\n 'display_leaf_label_left_bottom' : false,\n 'display_duplication' : false,\n 'has_branch_lenght' : true,\n 'has_duplications' : false,\n 'multiple_search':false,\n 'show_histogram' : false,\n 'align_tip' : false,\n 'use_meta_for_leaf' : true,\n 'use_meta_for_node' : false,\n 'has_histogram_data' : false,\n 'similarity': [],\n 'style': {\n 'font_size_internal' : 14,\n 'color_accessor' : {'leaf' : null, 'node': \"Topology\", 'circle': null},\n 'color_extent_min': {'leaf' : {}, 'node': {\"Topology\":0}, 'circle': {} },\n 'color_extent_max':{'leaf' : {}, 'node': {\"Topology\":1}, 'circle': {}},\n 'number_domain':{ 'Topology': 5, 'Length': 5},\n 'color_domain': {\n 'Topology' : [\"#a50026\", \"#f46d43\", \"#ffffbf\", \"#74add1\", \"#313695\"],\n 'Length': ['#253494', '#2C7FB8', '#41B6C4', '#C7E9B4', '#FFFFCC']\n },\n 'color_domain_default': {\n \"Topology\": [\"#a50026\", \"#f46d43\", \"#ffffbf\", \"#74add1\", \"#313695\"],\n \"Length\": ['#253494', '#2C7FB8', '#41B6C4', '#C7E9B4', '#FFFFCC'],\n \"DEFAULT\": ['#C60101', '#FB6A4A', '#F7F7F7', '#6BAED6', '#253494']\n }\n\n },\n 'tree': {\n 'node_vertical_size' : 30,\n 'node_horizontal_size' : 40,\n 'node_radius' : 6, // move to style\n 'line_width' : 3,// move to style\n 'font_size':14, // move to style\n 'max_depth' : 0,\n },\n 'collapse_level': 0,\n 'stack' : {\n 'type': 'genes',//'events',\n 'showHistogramValues' : false,\n 'showHistogramSummaryValue' : true,\n 'legendTxtSize' : 12,\n 'margin' : 8,\n 'xInitialRightMargin' : 45,\n 'stackHeight' : 120,\n 'stackWidth' : 30,\n 'maxStackHeight': 'max', // ratio -> stack height fixed | max -> largest data = stack height\n 'has_support' : false,\n 'only_support' : false,\n\n },\n 'sync_coloring': false,\n 'selected_triangle_coloring': 'None',\n 'selected_collapse_uncolored': 'Leaves',\n 'selected_collapse_monocolored': 'Leaves',\n 'colorScale': {'leaf' : null, 'node':null, 'circle': {}},\n 'intercolor': {'leaf' : null, 'node': null, 'circle': {}}\n }\n\n if (settings) {\n\n for(var key in settings) {\n\n if (key == 'labels_array_leaf'){\n var value = settings[key];\n this.settings['labels']['leaf'] = new Set(value);\n }\n if (key == 'labels_array_node'){\n var value = settings[key];\n this.settings['labels']['node'] = new Set(value);\n }\n if (key == 'colorlabels_array_leaf'){\n var value = settings[key];\n this.settings['colorlabels']['leaf'] = new Set(value);\n }\n\n if (key == 'colorlabels_array_node'){\n var value = settings[key];\n this.settings['colorlabels']['node'] = new Set(value);\n }\n\n else{\n var value = settings[key];\n this.settings[key] = value;\n }\n\n\n }\n\n }\n\n this.settings.name = this.settings.name ? this.settings.name : \"Untitled \" + uid_untitle_counter++\n\n this.uid = null\n this.input_data = data;\n this.leaves = []\n\n\n\n if (from_raw_data){\n this.uid = uid_model++;\n this.settings.uid = this.uid;\n this.data = this.factory(this.parse());\n }\n else{\n this.uid = settings.uid;\n this.settings.uid = this.uid;\n this.data = data\n data.leaves = this.get_leaves(data)\n this.traverse(data, function(n,c){\n n.leaves = this.get_leaves(n)\n })\n this.set_color_scale('node');\n this.set_color_scale('leaf');\n }\n\n this.data.root = true;\n this.data.elementS = {}\n this.data.elementBCN = {}\n this.rooted = this.data.children.length !== 3\n this.big_tree = (this.leaves.length > 500)\n\n // check that histogram data is present and compute\n if(this.settings.show_histogram && this.data.evolutionaryEvents) {\n this.settings.has_histogram_data = true;\n this.largestGenome = 0;\n this.largestEvents = 0; // todo\n\n this.traverse(this.data , function(n,c){\n\n let g = n.nr_hogs ? n.nr_hogs : n.nr_proteins\n if (g > this.largestGenome ) {this.largestGenome = g;}\n\n if (n.evolutionaryEvents){\n\n var ga = n.evolutionaryEvents.gained ? n.evolutionaryEvents.gained : 0\n var l = n.evolutionaryEvents.lost ? n.evolutionaryEvents.lost : 0\n var d = n.evolutionaryEvents.duplications ? n.evolutionaryEvents.duplications : 0\n\n let e = ga + l + d\n\n\n if (e > this.largestEvents ) {this.largestEvents = e;}\n\n }\n\n if (this.settings.stack.has_support){\n\n let g_support = n.nr_hogs_support ? n.nr_hogs_support : n.nr_proteins_support\n if (g_support > this.largestGenome_support ) {this.largestGenome_support = g_support;}\n\n if (n.evolutionaryEvents_support){\n\n\n var ga_support = n.evolutionaryEvents_support.gained ? n.evolutionaryEvents_support.gained : 0\n var l_support = n.evolutionaryEvents_support.lost ? n.evolutionaryEvents_support.lost : 0\n var d_support = n.evolutionaryEvents_support.duplications ? n.evolutionaryEvents_support.duplications : 0\n\n let e_support = ga_support + l_support + d_support\n\n if (e_support > this.largestEvents_support ) {this.largestEvents_support = e_support;}\n\n }\n }\n\n\n\n })\n\n\n }\n\n }\n\n set_all_color_scale(){\n this.set_color_scale('node');\n this.set_color_scale('leaf');\n this.set_color_scale('circle');\n }\n\n remove_all_color_scale(){\n this.settings.colorScale ={'leaf' : null, 'node':null, 'circle': {}}\n this.settings.intercolor ={'leaf' : null, 'node':null, 'circle': {}}\n }\n\n\n\n get_name(){\n return this.settings.name\n }\n\n set_name(name){\n this.settings.name = name\n }\n\n traverse(o,func_pre, func_post) {\n\n if (func_pre){\n func_pre.apply(this,[o,o[\"children\"]])\n }\n\n if(o[\"children\"]){\n\n for (var c in o[\"children\"] ) {\n\n var child = o[\"children\"][c]\n\n child = this.traverse(child, func_pre, func_post)\n\n if (func_post) {\n func_post.apply(this,[child,o])\n }\n\n\n }\n\n\n }\n\n return o\n\n }\n\n set_color_scale(type, api){\n\n\n var type = (typeof type !== 'undefined') ? type : 'node';\n var api = (typeof type !== 'undefined') ? api : null;\n\n\n var colorScaleDomain = false;\n var colorScaleRange;\n var number;\n\n\n if (typeof this != \"undefined\" && this) {\n\n\n // If categorical do special\n var acc = this.settings.style.color_accessor[type]\n var type_acc = this.settings.extended_data_type[acc]\n\n\n if (acc === null){\n this.settings.colorScale[type] = null\n return\n }\n\n\n if (type_acc == 'cat'){\n\n this.settings.colorScale[type] = api.get_color_scale(acc)\n\n\n //var dom = this.settings.domain_extended_data[acc]\n //this.settings.colorScale[type] = d3.scaleOrdinal().domain(dom).range(d3.schemePaired);\n return\n }\n\n else if (type_acc == 'color'){\n\n this.settings.colorScale[type] = null\n return\n }\n\n\n\n number = this.settings.style.number_domain[acc]\n\n\n if (this.settings.style.color_accessor[type] != null && this.settings.style.color_accessor[type] != 'Topology' ) {\n\n var ms = this.settings.style;\n\n var ca = ms.color_accessor[type];\n\n if (ms.color_extent_max[type][ca] == ms.color_extent_min[type][ca]){\n this.settings.intercolor[type] = d3__WEBPACK_IMPORTED_MODULE_0__.interpolate( ms.color_extent_max[type][ca], ms.color_extent_max[type][ca]-1)\n }else{\n this.settings.intercolor[type] = d3__WEBPACK_IMPORTED_MODULE_0__.interpolate( ms.color_extent_max[type][ca], ms.color_extent_min[type][ca])\n }\n\n\n colorScaleRange = this.settings.style.color_domain[acc];\n\n }\n\n else {\n this.settings.intercolor[type] = d3__WEBPACK_IMPORTED_MODULE_0__.interpolate(1,0)\n colorScaleRange = this.settings.style.color_domain[acc];\n }\n\n\n\n }\n else {\n\n number = 5;\n colorScaleRange = ['#253494', '#2C7FB8', '#41B6C4', '#C7E9B4', '#FFFFCC']\n this.settings.intercolor[type] = d3__WEBPACK_IMPORTED_MODULE_0__.interpolate(1, 0);\n }\n\n\n switch (number) {\n case 2:\n colorScaleDomain = [this.settings.intercolor[type](0),this.settings.intercolor[type](1)]\n break;\n case 3:\n colorScaleDomain = [this.settings.intercolor[type](0),this.settings.intercolor[type](0.5) , this.settings.intercolor[type](1)]\n break;\n case 4:\n colorScaleDomain = [this.settings.intercolor[type](0),this.settings.intercolor[type](0.33),this.settings.intercolor[type](0.66) , this.settings.intercolor[type](1)]\n break;\n case 5:\n colorScaleDomain = [this.settings.intercolor[type](0),this.settings.intercolor[type](0.25) ,this.settings.intercolor[type](0.5) ,this.settings.intercolor[type](0.75) , this.settings.intercolor[type](1)]\n\n }\n\n\n this.settings.colorScale[type] = d3__WEBPACK_IMPORTED_MODULE_0__.scaleLinear()\n .domain(colorScaleDomain)\n .range(colorScaleRange);\n\n\n\n }\n\n traverse_hierarchy(o,func_pre, func_post) {\n\n var children = o[\"children\"] ? o[\"children\"] : o[\"_children\"]\n\n if (func_pre){\n func_pre.apply(this,[o,children])\n }\n\n if(children ){\n\n for (var c in children) {\n\n var child = children[c]\n\n child = this.traverse_hierarchy(child, func_pre, func_post)\n\n if (func_post) {\n func_post.apply(this,[child,o])\n }\n\n\n }\n\n\n }\n\n return o\n\n }\n\n set_parent(node,parent){\n node.parent = parent\n }\n\n set_cumulated_length(node, children){\n if (node.parent) {\n node.depth = node.parent.depth + 1\n node.distance_to_root = node.parent.distance_to_root + node.branch_length\n }\n else{\n node.distance_to_root = 0\n node.depth = 0}\n\n }\n\n factory(json){ // todo do one traversal with all in one function\n\n var p;\n\n //has_branch_lenght\n this.settings.has_branch_lenght = false;\n\n json.children.forEach((child) => {\n if (typeof child.branch_length != 'undefined') { this.settings.has_branch_lenght = true; }\n })\n\n if (this.settings.has_branch_lenght) {\n this.settings.labels['node'].add('Length')\n this.settings.labels['leaf'].add('Length')\n this.settings.colorlabels['node'].add('Length')\n this.settings.colorlabels['leaf'].add('Length')\n this.settings.extended_data_type['Length'] = 'num'\n\n this.settings.style.color_extent_max['node']['Length'] = 0;\n this.settings.style.color_extent_min['node']['Length'] = 1000000000;\n\n this.settings.style.color_extent_max['leaf']['Length'] = 0;\n this.settings.style.color_extent_min['leaf']['Length'] = 1000000000;\n }\n\n\n // if branch size is not used put 1\n if (!this.settings.has_branch_lenght) {\n p = this.traverse(json, function(n,c){n.branch_length=1})\n p.branch_length = 0 // root\n }\n else{ // sanity check\n p = this.traverse(json, function(n,c){if (typeof n.branch_length == 'undefined') {n.branch_length=1} })\n if (typeof p.branch_length == 'undefined') {p.branch_length=1}\n }\n\n // set parent attribute\n p = this.traverse(json, null , this.set_parent)\n\n // compute cumulated lenght\n p = this.traverse(p, this.set_cumulated_length , null)\n\n this.traverse(p, function(n,c){\n\n n.extended_informations = {}\n n.elementS = {}\n n.elementBCN = {}\n n.force_label_show = null;\n\n if(n.branch_length){\n n.extended_informations['Length'] = n.branch_length;\n if (this.settings.style.color_extent_max['node']['Length'] < n.branch_length){\n this.settings.style.color_extent_max['node']['Length'] = n.branch_length\n this.settings.style.color_extent_max['leaf']['Length'] = n.branch_length\n }\n\n if (this.settings.style.color_extent_min['node']['Length'] > n.branch_length){\n this.settings.style.color_extent_min['node']['Length'] = n.branch_length\n this.settings.style.color_extent_min['leaf']['Length'] = n.branch_length\n }\n }\n\n if (typeof c !== 'undefined' && typeof n.name !== 'undefined' && n.name !== \"\" ) {\n n.extended_informations['Data'] = n.name;\n this.settings.labels['node'].add('Data')\n this.settings.labels['leaf'].add('Data')\n this.settings.extended_data_type['Data'] = 'num'\n\n if (!isNaN(n.name)){\n\n if (!this.settings.colorlabels['node'].has('Data')){\n this.settings.colorlabels['node'].add('Data');\n this.settings.style.color_extent_max['node']['Data'] = 0;\n this.settings.style.color_extent_min['node']['Data'] = 1000000000;\n }\n\n if (this.settings.style.color_extent_max['node']['Data'] <n.name){\n this.settings.style.color_extent_max['node']['Data'] = n.name\n }\n\n if (this.settings.style.color_extent_min['node']['Data'] > n.name){\n this.settings.style.color_extent_min['node']['Data'] = n.name\n }\n\n }\n\n else {this.settings.extended_data_type['Data'] = 'cat'}\n }\n\n if(n.data_nhx && Object.keys(n.data_nhx).length > 0){\n\n Object.entries(n.data_nhx).forEach(([key, value]) => {\n\n this.settings.labels['node'].add(key)\n this.settings.labels['leaf'].add(key)\n\n this.settings.colorlabels['node'].add(key)\n this.settings.colorlabels['leaf'].add(key)\n\n\n switch(key){\n case 'Ev':\n if (value == 'duplication') {\n n.duplication = true\n this.settings.has_duplications = true;\n }\n n.extended_informations.events = value\n n.extended_informations[key] = value\n this.settings.extended_data_type['Ev'] = 'cat'\n break;\n case 'DD':\n case 'D':\n if (value == 'Y') {\n n.duplication = true\n this.settings.has_duplications = true;\n\n }\n else if (value == 'N'){\n n.duplication = false\n this.settings.has_duplications = true;\n }\n n.extended_informations.events = value\n n.extended_informations[key] = value\n this.settings.extended_data_type['D'] = 'cat'\n break;\n case 'XB':\n case 'B':\n this.settings.edge_related_data.push(key)\n n.extended_informations[key] = value\n this.settings.extended_data_type[key] = 'num'\n default:\n n.extended_informations[key] = value\n this.settings.extended_data_type[key] = 'cat'\n break;\n }\n });\n\n\n }\n // phyloxml specific attributes\n for (let attr of [\"taxonomies\", \"sequences\"]) {\n if (n.hasOwnProperty(attr)) {\n Object.entries(n[attr][0]).forEach(([key, value]) => {\n n.extended_informations[attr + \"_\" + key] = value;\n this.settings.extended_data_type[attr + \"_\" + key] = \"cat\";\n });\n if (n.name === undefined || n.name === \"\") {\n if (attr === \"taxonomies\" && n.taxonomies[0].hasOwnProperty(\"scientific_name\")) {\n n.name = n.taxonomies[0].scientific_name;\n } else if (attr === \"sequences\" && n.sequence.hasOwnProperty(\"name\")) {\n n.name = n.sequences[0].name;\n }\n }\n }\n }\n if (n.hasOwnProperty(\"date\")){\n n.extended_informations['date'] = n.date;\n this.settings.extended_data_type['date'] = \"cat\";\n }\n\n if (n.depth > this.settings.tree.max_depth){\n this.settings.tree.max_depth = n.depth\n }\n if (!(n.hasOwnProperty('children'))){\n this.leaves.push(n)\n n.correspondingLeaf = {}\n\n }\n\n n.leaves = this.get_leaves(n)\n\n })\n\n // check the type of all extended data\n this.traverse(p, function(n,c){\n\n for (var key in n.extended_informations){\n if (n.extended_informations.hasOwnProperty(key)) {\n\n if (this.settings.extended_data_type[key] === 'num'){\n continue\n }\n\n if (!isNaN(n.extended_informations[key])){\n this.settings.extended_data_type[key] = 'num'\n }\n\n }\n }\n\n })\n\n\n this.settings.colorlabels['node'].forEach( (value) => {\n if (this.settings.extended_data_type[value] === 'num' && value !== 'Topology' ) {\n this.settings.style.color_extent_max['node'][value] = 0\n this.settings.style.color_extent_min['node'][value] = 1000000000\n }\n });\n\n this.settings.colorlabels['leaf'].forEach( (value) => {\n if (this.settings.extended_data_type[value] === 'num' ) {\n this.settings.style.color_extent_max['leaf'][value] = 0\n this.settings.style.color_extent_min['leaf'][value] = 1000000000\n }\n });\n\n\n this.traverse(p, function(n,c) {\n for (var key in n.extended_informations) {\n\n if (n.extended_informations.hasOwnProperty(key)) {\n\n\n\n if (this.settings.extended_data_type[key] === 'num') {\n\n // check if min and max are set for node and leaf\n\n var val = n.extended_informations[key].toString().indexOf('.') != -1 ? parseFloat(n.extended_informations[key]) : parseInt(n.extended_informations[key])\n\n if (this.settings.style.color_extent_max['node'][key] < val) {\n this.settings.style.color_extent_max['node'][key] = val\n\n }\n\n if (this.settings.style.color_extent_min['node'][key] > val) {\n this.settings.style.color_extent_min['node'][key] = val\n }\n\n if (this.settings.style.color_extent_max['leaf'][key] < val) {\n this.settings.style.color_extent_max['leaf'][key] = val\n }\n\n if (this.settings.style.color_extent_min['leaf'][key] > val) {\n this.settings.style.color_extent_min['leaf'][key] = val\n }\n\n }\n\n }\n }\n\n })\n\n\n\n this.settings.suggestions = [] // autocomplete name\n this.traverse(json, function(n,c){\n\n if (n.name !== ''){this.settings.suggestions.push(n.name)}}) //todo add id also and ncBI and more + check empty cfucntion\n\n return p\n }\n\n build_hierarchy_mockup(){\n return d3__WEBPACK_IMPORTED_MODULE_0__.hierarchy(this.data, d => d.children );\n }\n\n parse(){\n\n if (this.settings.data_type === \"newick\") {\n return biojs_io_newick__WEBPACK_IMPORTED_MODULE_2__.parse_newick(this.input_data);\n }\n\n else if (this.settings.data_type === \"nhx\") {\n return parse_nhx(this.input_data);\n }\n\n else if (this.settings.data_type === \"json\") {\n return this.input_data\n }\n else if (this.settings.data_type === \"phyloxml\") {\n let phylogenies = phyloXml.parse(this.input_data);\n if (phylogenies === undefined || phylogenies.length === 0){\n console.error(\"No phylogenies found\");\n return {};\n } else if (phylogenies.length > 1) {\n console.log(\"dataset contains more than one phylogenies: \"+phylogenies.length + \" Will only use the first one\");\n }\n return phylogenies[0].children[0]; // return toplevel clade which is returned as children[0].\n }\n }\n\n collapse(data, action){\n if (!data.children){return}\n if (action) {data.collapse = true}\n else if (action == false){data.collapse = false}\n else{data.collapse ? data.collapse = false : data.collapse = true;}\n\n }\n\n toggle_show_label(data){\n data.force_label_show || data.force_label_show == null ? data.force_label_show = false : data.force_label_show = true;\n }\n\n collapseAll(data, action){\n if (action) {\n this.traverse(data, (n,c) => {\n this.collapse(n, true)\n //n.collapse = true\n } , null)}\n else if (action == false){\n this.traverse(data, (n,c) => {\n this.collapse(n, false)\n //n.collapse = false\n } , null)}\n\n\n }\n\n get_all_collapse(data){\n\n var collapsed = []\n\n this.traverse(data, (n,c) => {if (n.collapse){\n collapsed.push(n)\n }}, null)\n\n return collapsed\n\n }\n\n apply_collapse_to_list(collapsed){\n this.traverse(this.data, (n,c) => {\n if (collapsed.includes(n)){\n this.collapse(n, true)\n }\n else{\n this.collapse(n, false)\n }\n } , null)\n }\n\n swap_subtrees(data){\n var e = data.children.pop()\n data.children.unshift(e)\n data.leaves = this.get_leaves(data)\n }\n\n unswap_subtrees(data){\n var e = data.children.shift()\n data.children.push(e)\n data.leaves = this.get_leaves(data)\n\n }\n\n reroot(data){\n\n // extract meta data (zoom)\n var meta = this.zoom;\n\n // create new root r\n\n var root = {\"children\": [], \"name\": \"\", \"branch_length\": 0, \"extended_informations\": {}}\n\n\n for (var key in data.extended_informations) {\n\n\n if (this.settings.edge_related_data.includes(key)) {\n root.extended_informations[key] = data.extended_informations[key]\n }\n\n else{\n root.extended_informations[key] = null\n }\n\n }\n\n // source and target node of the clicked edges\n var parent = data.parent\n var child = data\n\n // insert new root node between target and source and connect\n root.children.push(child)\n parent.children.push(root)\n this.set_parent(child, root )\n this.set_parent(root, parent )\n const index = parent.children.indexOf(child);\n if (index > -1) {\n parent.children.splice(index, 1);\n }\n\n // ajust distance now that distance target/source is splitted in two\n var old_distance = child.branch_length\n\n child.branch_length = old_distance/2\n child.extended_informations['Length'] = old_distance/2\n\n parent.branch_length_before_reverse = parent.branch_length\n parent.branch_length = old_distance /2\n parent.extended_informations['Length'] = old_distance/2\n\n // Until we reach the old root reverse child/parent order\n var child = root\n var stack = []\n\n while (parent.root != true) {\n\n stack.push([parent,child])\n\n child = parent\n parent = parent.parent\n\n parent.values_before_reverse = {}\n parent.branch_length_before_reverse = parent.branch_length\n\n for (var value of this.settings.edge_related_data) {\n\n parent.values_before_reverse[value] = parent.extended_informations[value]\n\n if (value=== 'Length'){\n parent.branch_length = child.branch_length_before_reverse || child.branch_length;\n parent.extended_informations['Length'] = parent.branch_length;\n\n }\n else{\n if ( child.values_before_reverse && value in child.values_before_reverse){\n parent.extended_informations[value] = child.values_before_reverse[value]\n }\n else{\n parent.extended_informations[value] = child.extended_informations[value]\n child.extended_informations[value] = null\n }\n\n }\n\n\n\n }\n\n\n }\n stack.push([parent,child])\n for (var e in stack){\n var p = stack[e][0]\n var c = stack[e][1]\n\n this.reverse_order(p,c)\n\n }\n\n // Remove old root\n\n var old_root = parent\n var leading_branch = parent.parent\n\n\n\n if (old_root.children.length == 1){\n\n const ce = leading_branch.children.indexOf(old_root);\n if (ce > -1) {\n leading_branch.children.splice(ce, 1);\n }\n\n var i = 0,len = old_root.children.length;\n while (i < len) {\n let c = old_root.children[i]\n c.parent = leading_branch\n leading_branch.children.push(c)\n i++\n }\n\n old_root = null\n\n\n\n }\n\n // For multifurcation we need to keep the root\n else {\n old_root.root = false\n old_root.branch_length = leading_branch.branch_length\n parent.extended_informations['Length'] = leading_branch.branch_length\n }\n\n\n for (var key of this.settings.edge_related_data) {\n\n for (var childy of root.children) {\n\n childy.extended_informations[key] = root.extended_informations[key]\n\n }\n\n root.extended_informations[key] = null\n }\n\n\n // configure new root\n root.zoom = meta\n this.data = root;\n this.data.root = true;\n\n root.leaves = this.get_leaves(root)\n\n\n this.traverse(root, function(n,c){\n n.leaves = this.get_leaves(n)\n n.values_before_reverse = {}\n n.branch_length_before_reverse = undefined\n })\n\n\n\n }\n\n trim(branch){\n\n // source and target node of the clicked edges\n var parent = branch.parent\n var child = branch\n\n var untrim_data = {\n \"parent\" : null,\n \"floating\" : null,\n \"untrim_data\" : null,\n \"index\": null,\n \"root_mode\": false,\n }\n\n\n if (parent.children.length > 2) {\n untrim_data.index = this.detach_child(parent,child)\n\n untrim_data.parent = parent;\n untrim_data.floating = false;\n untrim_data.child = child;\n\n return untrim_data;\n }\n\n else{\n\n if (typeof parent.parent == 'undefined'){ // parent is root\n untrim_data.root_mode = true;\n\n var sibling = parent.children[0] == child ? parent.children[1] : parent.children[0]\n untrim_data.index = this.detach_child(parent, sibling)\n\n this.data = sibling;\n\n untrim_data.parent = null;\n untrim_data.floating = parent;\n untrim_data.child = sibling;\n\n return untrim_data;\n\n }\n\n else{\n\n this.detach_child(parent.parent, parent)\n var sibling = parent.children[0] == child ? parent.children[1] : parent.children[0]\n untrim_data.index = this.detach_child(parent, sibling)\n this.attach_child(parent.parent, sibling)\n\n untrim_data.parent = parent.parent;\n untrim_data.floating = parent;\n untrim_data.child = sibling;\n\n return untrim_data;\n\n }\n\n\n }\n\n }\n\n untrim(parent, floating, child, index, root_mode){\n\n if (floating != false){\n if (root_mode){\n this.data = floating\n this.attach_child(floating,child, index)\n\n }else{\n this.detach_child(parent,child)\n this.attach_child(parent,floating)\n this.attach_child(floating,child, index)\n }\n\n }\n else {\n this.attach_child(parent,child, index)\n }\n }\n\n detach_child(parent, child){\n var index = parent.children.indexOf(child);\n if (index > -1) {\n parent.children.splice(index, 1);\n }\n return index\n }\n\n attach_child(parent,child_to_adopt, index){\n\n if (typeof index !== 'undefined') {\n parent.children.splice( index, 0, child_to_adopt );\n child_to_adopt.parent = parent;\n\n } else {\n parent.children.push(child_to_adopt);\n child_to_adopt.parent = parent;\n }\n\n\n }\n\n interleave_node(parent, to_insert,child){\n this.detach_child(parent, child)\n this.attach_child(parent,to_insert)\n this.attach_child(to_insert, child)\n }\n\n store_zoomTransform(zoom){\n\n this.zoom = {\n \"k\":zoom.k,\n \"x\":zoom.x,\n \"y\":zoom.y,\n };\n }\n\n /**\n Description:\n Creates list of leaves of each node in subtree rooted at v\n\n Note:\n Difference between deep leaf list and leaves in:\n (A:0.1,B:0.2,(C:0.3,D:0.4):0.5);\n - Root has leaves: A, B, C and D (terminal leaves)\n - Root has deep leaves: A, B, C, D and CD (terminal leaves + intermediate leaves)\n */\n createDeepLeafList(filter) {\n\n function is_leaf(str) {\n return !str.includes(\"|__|\");\n }\n\n var build_deepLeafList = function(child, node){\n\n if ( child.hasOwnProperty('children') ){\n var dp = child.deepLeafList.filter(is_leaf).sort()\n if (!dp.every((e) => e === '')){\n child.deepLeafList.push(dp.join('|__|'));\n }\n\n }\n\n node.deepLeafList = node.deepLeafList.concat(child.deepLeafList)\n }\n\n var build_deepLeafLeaves = function(node,children){\n\n if (!(node.hasOwnProperty('children') )){\n\n if (typeof filter != 'undefined') {\n if (filter.includes(node.name)){\n node.deepLeafList = [node.name]\n }\n else{\n node.deepLeafList = []\n }\n\n }\n else{\n node.deepLeafList = [node.name]\n }\n\n }\n else {\n node.deepLeafList = []\n }\n\n\n }\n\n this.traverse(this.data, build_deepLeafLeaves, build_deepLeafList)\n\n }\n\n createMinHash(){\n\n var assign_hash = function(node,children){\n\n node.min_hash = new minhashjs__WEBPACK_IMPORTED_MODULE_1__.MinHash.MinHash()\n node.deepLeafList.map(function(w) { node.min_hash.update(w) });\n }\n\n this.traverse(this.data, assign_hash, null)\n }\n\n removeMinHash(){\n\n var remove_hash = function(node,children){\n\n node.min_hash = null\n }\n\n this.traverse(this.data, remove_hash, null)\n\n }\n\n reverse_order(parent,child) {\n\n child.children.push(parent)\n parent.parent =child\n\n const b = parent.children.indexOf(child);\n if (b > -1) {\n parent.children.splice(b, 1);\n }\n\n }\n\n get_leaves(node){\n\n\n var l = []\n\n this.traverse(node, function(n,c){\n if (!(n.hasOwnProperty('children'))){\n l.push(n)\n }\n\n\n })\n return l\n }\n\n remove_circularity(){ // safe my model\n var data = Object.assign({}, this.data);\n\n this.traverse(data, function(n,c){\n n.parent=null;\n n.leaves=null;\n n.correspondingLeaf = {}\n n.elementBCN = null})\n\n return data\n }\n\n remove_circularity_only_parent_and_leaves(){ // safe my model\n var data = Object.assign({}, this.data);\n\n this.traverse(data, function(n,c){\n n.parent=null;\n n.leaves=null;\n })\n\n return data\n }\n\n add_circularity_back(){\n\n this.data.leaves = this.get_leaves(this.data)\n\n this.traverse(this.data, function(n,c){n.leaves = this.get_leaves(n)}, this.set_parent)\n\n\n }\n\n add_meta_leaves(meta, headers, api, reference){\n\n // headers: column_name -> type\n\n Object.keys(headers).forEach(item => {\n\n\n if (item != reference || item != 'Length' ) {\n\n this.settings.extended_data_type[item] = headers[item]\n this.settings.domain_extended_data[item] = []\n this.settings.labels['leaf'].add(item)\n this.settings.colorlabels['leaf'].add(item)\n\n if (headers[item] == 'num'){\n this.settings.style.color_extent_max['leaf'][item] = 0\n this.settings.style.color_extent_min['leaf'][item] = 100000\n }\n }\n\n })\n\n this.get_leaves(this.data).forEach(d => {\n if (d.name in meta){\n\n Object.entries(meta[d.name]).forEach(item => {\n if (item[0] != reference){\n\n d.extended_informations[item[0]]= item[1]\n\n if (this.settings.extended_data_type[item[0]] == 'num' && !isNaN(item[1])) {\n\n item[1] = item[1].toString().indexOf('.') != -1 ? parseFloat(item[1]) : parseInt(item[1])\n\n if (this.settings.style.color_extent_max['leaf'][item[0]] < item[1]) {\n this.settings.style.color_extent_max['leaf'][item[0]] = item[1]\n }\n\n if (this.settings.style.color_extent_min['leaf'][item[0]] > item[1]) {\n this.settings.style.color_extent_min['leaf'][item[0]] = item[1]\n }\n\n }\n\n if (this.settings.extended_data_type[item[0]] == 'cat'){\n\n var cs = api.get_color_scale(item[0])\n cs.add_value_to_map(item[1])\n\n this.settings.domain_extended_data[item[0]].push(item[1])\n }\n\n }\n\n })\n\n }\n\n })\n\n\n Object.keys(headers).forEach(item => {\n if (item != reference || item != 'Length' ) {\n\n\n if (headers[item] == 'cat'){\n api.get_color_scale(item).update()\n\n }\n }\n\n })\n\n\n\n }\n\n add_meta_nodes(meta, headers, api, reference){\n\n\n Object.keys(headers).forEach(item => {\n if (item != reference|| item != 'Length' ) {\n this.settings.extended_data_type[item] = headers[item]\n this.settings.domain_extended_data[item] = []\n this.settings.labels['node'].add(item)\n this.settings.colorlabels['node'].add(item)\n\n if (headers[item] == 'num'){\n this.settings.style.color_extent_max['node'][item] = 0\n this.settings.style.color_extent_min['node'][item] = 100000\n }\n }\n\n })\n\n this.traverse(this.data, function(n,c){\n\n var name_value = n.name in meta ? n.name : n.extended_informations['Data'] in meta ? n.extended_informations['Data'] : false\n\n if (name_value){\n\n Object.entries(meta[name_value]).forEach(item => {\n\n if (item[0] != reference){\n n.extended_informations[item[0]]= item[1]\n\n if (this.settings.extended_data_type[item[0]] == 'cat'){\n\n var cs = api.get_color_scale(item[0])\n cs.add_value_to_map(item[1])\n\n }\n\n else if (this.settings.extended_data_type[item[0]] == 'num' && !isNaN(item[1]) ) {\n\n item[1] = item[1].toString().indexOf('.') != -1 ? parseFloat(item[1]) : parseInt(item[1])\n\n if (this.settings.style.color_extent_max['node'][item[0]] < item[1]) {\n this.settings.style.color_extent_max['node'][item[0]] = item[1]\n }\n\n if (this.settings.style.color_extent_min['node'][item[0]] > item[1]) {\n this.settings.style.color_extent_min['node'][item[0]] = item[1]\n }\n\n }\n }\n })\n\n }\n })\n\n Object.keys(headers).forEach(item => {\n\n if (item != reference || item != 'Length' ) {\n\n\n if (headers[item] == 'cat'){\n api.get_color_scale(item).update()\n\n }\n }\n\n })\n }\n\n get_node_by_leafset(lset){\n\n function setsAreEqual(a, b) {\n if (a.size !== b.size) {\n return false;\n }\n\n return Array.from(a).every(element => {\n return b.has(element);\n });\n }\n\n lset = new Set(lset.map(leaf => leaf.toString()))\n\n var target = false\n\n\n var check = function(node,children){\n\n var nl = new Set(node.leaves.map(leaf => leaf.name.replaceAll(\"'\", '').toString()))\n\n if ( setsAreEqual(nl,lset)){\n target = node\n }\n\n }\n\n this.traverse(this.data, check, null)\n\n return target\n }\n\n};\n\n//# sourceURL=webpack://PhyloIO/./src/model.js?");
20
+
21
+ /***/ }),
22
+
23
+ /***/ "./src/phyloxml.js":
24
+ /*!*************************!*\
25
+ !*** ./src/phyloxml.js ***!
26
+ \*************************/
27
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
28
+
29
+ eval("/**\n * Copyright (C) 2019 Christian M. Zmasek\n * Copyright (C) 2019 J. Craig Venter Institute\n * All rights reserved\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\n *\n * Created by czmasek on 7/7/2016.\n */\n\n// v 1.0.0\n// 2019-05-16\n//\n// phyloxml.js is a JavaScript program for reading (SAX style parser)\n// and writing phylogenetic trees in phyloXML format.\n//\n// phyloXML website: http://www.phyloxml.org/\n//\n// Availability:\n// https://github.com/cmzmasek/phyloxml-js\n// https://www.npmjs.com/package/phyloxml\n//\n// Dependencies:\n// sax.js (1.2.4): https://www.npmjs.com/package/sax/v/1.2.4\n//\n//\n// Example:\n// This basic example shows how to parse a phyloXML formatted String into to a\n// object representing a phylogenetic tree. Followed by printing some elements\n// and then converting the object back to a phyloXML formatted String.\n//\n// Change './phyloxml' to 'phyloxml' if you use this code outside of this package\n//\n// var phyloXml = require('./phyloxml').phyloXml;\n//\n// phlyoXmlFormattedString = '<phyloxml xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ' +\n// 'xmlns=\"http://www.phyloxml.org\" ' +\n// 'xsi:schemaLocation=\"http://www.phyloxml.org http://www.phyloxml.org/1.10/phyloxml.xsd\">' +\n// '<phylogeny rooted=\"true\" rerootable=\"false\">' +\n// '<clade><branch_length>0.2</branch_length>' +\n// '<clade><branch_length>0.4</branch_length><name>A</name></clade>' +\n// '<clade><branch_length>0.6</branch_length><name>B</name></clade>' +\n// '</clade>' +\n// '</phylogeny>' +\n// '</phyloxml>';\n//\n// var phylogeneticTree = phyloXml.parse(phlyoXmlFormattedString, {trim: true, normalize: true})[0];\n//\n// console.log('Root branch length : ' + phylogeneticTree.children[0].branch_length);\n// console.log('Node A name : ' + phylogeneticTree.children[0].children[0].name);\n// console.log('Node A branch length: ' + phylogeneticTree.children[0].children[0].branch_length);\n// console.log('Node B name : ' + phylogeneticTree.children[0].children[1].name);\n// console.log('Node B branch length: ' + phylogeneticTree.children[0].children[1].branch_length);\n//\n// console.log('Entire tree in phyloXML format:');\n// console.log(phyloXml.toPhyloXML(phylogeneticTree, 4));\n//\n//\n// Synchronous parsing of phyloXML-formatted String:\n//\n// var px = require('./phyloxml').phyloXml;\n// var phys = px.parse(phyloxmlText, {trim: true, normalize: true});\n// console.log(px.toPhyloXML(phys[0], 6));\n//\n//\n// Asynchronous parsing of phyloXML-formatted Stream:\n//\n// var fs = require('fs');\n// var px = require('./phyloxml').phyloXml;\n// var stream = fs.createReadStream(xmlFile, {encoding: 'utf8'});\n// px.parseAsync(stream, {trim: true, normalize: true});\n\n\n(function phyloXml() {\n\n \"use strict\";\n\n var sax = null;\n if ( true && module.exports && !__webpack_require__.g.xmldocAssumeBrowser) {\n // Being used in a Node-like environment\n sax = __webpack_require__(/*! sax */ \"./node_modules/sax/lib/sax.js\");\n }\n else if (typeof window !== \"undefined\") {\n // Attached to the Window object in a browser\n sax = window.sax;\n if (!sax) {\n throw new Error(\"Expected sax to be defined. Make sure you are including sax.js before this file.\");\n }\n }\n else {\n sax = this.sax;\n if (!sax) {\n throw new Error(\"Expected sax to be defined. Make sure you are including sax.js before this file.\");\n }\n }\n\n // --------------------------------------------------------------\n // phyloXML constants\n // --------------------------------------------------------------\n\n // Accession\n var ACCESSION = 'accession';\n var ACCESSION_SOURCE_ATTR = 'source';\n var ACCESSION_COMMENT_ATTR = 'comment';\n\n // Annotation\n var ANNOTATION = 'annotation';\n var ANNOTATION_REF_ATTR = 'ref';\n var ANNOTATION_SOURCE_ATTR = 'source';\n var ANNOTATION_EVIDENCE_ATTR = 'evidence';\n var ANNOTATION_TYPE_ATTR = 'type';\n var ANNOTATION_DESC = 'desc';\n\n // Clade\n var CLADE = 'clade';\n var CLADE_BRANCH_LENGTH = 'branch_length';\n var CLADE_ID_SOURCE_ATTR = 'id_source';\n var CLADE_COLLAPSE_ATTR = 'collapse';\n var CLADE_NAME = 'name';\n var CLADE_WIDTH = 'width';\n\n // Clade Relation\n var CLADE_RELATION = 'clade_relation';\n var CLADE_RELATION_DISTANCE_ATTR = 'distance';\n var CLADE_RELATION_ID_REF_0_ATTR = 'id_ref_0';\n var CLADE_RELATION_ID_REF_1_ATTR = 'id_ref_1';\n var CLADE_RELATION_TYPE_ATTR = 'type';\n\n // Sequence Relation\n var SEQUENCE_RELATION = 'sequence_relation';\n var SEQUENCE_RELATION_DISTANCE_ATTR = 'distance';\n var SEQUENCE_RELATION_ID_REF_0_ATTR = 'id_ref_0';\n var SEQUENCE_RELATION_ID_REF_1_ATTR = 'id_ref_1';\n var SEQUENCE_RELATION_TYPE_ATTR = 'type';\n\n // Color\n var COLOR = 'color';\n var COLOR_RED = 'red';\n var COLOR_GREEN = 'green';\n var COLOR_BLUE = 'blue';\n var COLOR_ALPHA = 'alpha';\n\n // Confidence\n var CONFIDENCE = 'confidence';\n var CONFIDENCE_TYPE_ATTR = 'type';\n var CONFIDENCE_STDDEV_ATTR = 'stddev';\n var CONFIDENCES = 'confidences';\n\n // Cross References\n var CROSS_REFERENCES = 'cross_references';\n\n // Date\n var DATE = 'date';\n var DATE_UNIT_ATTR = 'unit';\n var DATE_DESC = 'desc';\n var DATE_VALUE = 'value';\n var DATE_MINIMUM = 'minimum';\n var DATE_MAXIMUM = 'maximum';\n\n // Distribution\n var DISTRIBUTION = 'distribution';\n var DISTRIBUTION_DESC = 'desc';\n\n // Domain Architecture\n var DOMAIN_ARCHITECTURE = 'domain_architecture';\n var DOMAIN_ARCHITECTURE_LENGTH_ATTR = 'length';\n\n // Events\n var EVENTS = 'events';\n var EVENTS_TYPE = 'type';\n var EVENTS_DUPLICATIONS = 'duplications';\n var EVENTS_SPECIATIONS = 'speciations';\n var EVENTS_LOSSES = 'losses';\n\n // Id\n var ID = 'id';\n var ID_PROVIDER_ATTR = 'provider';\n\n // Mol Seq\n var MOLSEQ = 'mol_seq';\n var MOLSEQ_IS_ALIGNED_ATTR = 'is_aligned';\n\n // Phylogeny\n var PHYLOGENY = 'phylogeny';\n\n // Phyloxml\n var PHYLOXML = 'phyloxml';\n\n // Point\n var POINT = 'point';\n var POINT_ALT_UNIT_ATTR = 'alt_unit';\n var POINT_GEODETIC_DATUM_ATTR = 'geodetic_datum';\n var POINT_LAT = 'lat';\n var POINT_LONG = 'long';\n var POINT_ALT = 'alt';\n\n // Property\n var PROPERTY = 'property';\n var PROPERTY_REF_ATTR = 'ref';\n var PROPERTY_ID_REF_ATTR = 'id_ref';\n var PROPERTY_UNIT_ATTR = 'unit';\n var PROPERTY_DATATYPE_ATTR = 'datatype';\n var PROPERTY_APPLIES_TO_ATTR = 'applies_to';\n var PROPERTIES = 'properties';\n\n // Protein Domain\n var PROTEINDOMAIN = 'domain';\n var PROTEINDOMAIN_FROM_ATTR = 'from';\n var PROTEINDOMAIN_TO_ATTR = 'to';\n var PROTEINDOMAIN_CONFIDENCE_ATTR = 'confidence';\n var PROTEINDOMAIN_ID_ATTR = 'id';\n\n // Reference\n var REFERENCE = 'reference';\n var REFERENCE_DOI_ATTR = 'doi';\n var REFERENCE_DESC = 'desc';\n\n // Sequence\n var SEQUENCE = 'sequence';\n var SEQUENCE_ID_SOURCE_ATTR = 'id_source';\n var SEQUENCE_ID_REF_ATTR = 'id_ref';\n var SEQUENCE_TYPE_ATTR = 'type';\n var SEQUENCE_SYMBOL = 'symbol';\n var SEQUENCE_NAME = 'name';\n var SEQUENCE_GENE_NAME = 'gene_name';\n var SEQUENCE_LOCATION = 'location';\n var SEQUENCES = 'sequences';\n\n // Taxonomy\n var TAXONOMY = 'taxonomy';\n var TAXONOMY_ID_SOURCE_ATTR = 'id_source';\n var TAXONOMY_CODE = 'code';\n var TAXONOMY_SCIENTIFIC_NAME = 'scientific_name';\n var TAXONOMY_AUTHORITY = 'authority';\n var TAXONOMY_COMMON_NAME = 'common_name';\n var TAXONOMY_SYNONYM = 'synonym';\n var TAXONOMY_RANK = 'rank';\n var TAXONOMIES = 'taxonomies';\n var TAXONOMY_SYNONYMS = 'synonyms';\n\n // Uri\n var URI = 'uri';\n var URI_TYPE_ATTR = 'type';\n var URI_DESC_ATTR = 'desc';\n\n // Phylogeny\n var PHYLOGENY_ROOTED_ATTR = 'rooted';\n var PHYLOGENY_REROOTABLE_ATTR = 'rerootable';\n var PHYLOGENY_BRANCH_LENGTH_UNIT_ATTR = 'branch_length_unit';\n var PHYLOGENY_TYPE_ATTR = 'type';\n var PHYLOGENY_NAME = 'name';\n var PHYLOGENY_DESCRIPTION = 'description';\n var PHYLOGENY_DATE = 'date';\n\n // Simple_Characteristics (to be deprecated!)\n var X_SIMPLE_CHARACTERISTICS = 'Simple_Characteristics';\n var X_SIMPLE_CHARACTERISTIC_COUNTRY = 'Country';\n var X_SIMPLE_CHARACTERISTIC_YEAR = 'Year';\n var X_SIMPLE_CHARACTERISTIC_HOST = 'Host';\n var X_SIMPLE_CHARACTERISTIC_HA = 'HA';\n var X_SIMPLE_CHARACTERISTIC_NA = 'NA';\n\n // appType (special for Virus BRC)\n var APPTYPE = 'flu_type';\n\n // Unknown source, id, confidence type:\n var UNKNOWN = 'unknown';\n\n // --------------------------------------------------------------\n // Instance variables\n // --------------------------------------------------------------\n var _phylogenies = null;\n var _phylogeny = null;\n var _cladeStack = null;\n var _tagStack = null;\n var _objectStack = null;\n\n // --------------------------------------------------------------\n // Others\n // --------------------------------------------------------------\n var PROPERTY_REF_RE = /[a-zA-Z0-9_]+:\\S+/;\n var PROPERTY_UNIT_RE = /[a-zA-Z0-9_]+:\\S+/;\n var PROPERTY_DATATYPE_RE = /xsd:\\S+/;\n\n // --------------------------------------------------------------\n // Functions for object creation\n // --------------------------------------------------------------\n function newAccession(tag) {\n var parent = _tagStack.get(1);\n if (!(parent === SEQUENCE || parent === CROSS_REFERENCES)) {\n throw new PhyloXmlError(\"found accession outside of sequence or cross-references\");\n }\n var acc = {};\n acc.value = null;\n acc.source = getAttribute(ACCESSION_SOURCE_ATTR, tag.attributes);\n acc.comment = getAttribute(ACCESSION_COMMENT_ATTR, tag.attributes);\n if (!acc.source) {\n acc.source = UNKNOWN;\n }\n if (parent === SEQUENCE) {\n getCurrentObject().accession = acc;\n }\n else {\n addToArrayInCurrentObjectUnnamed(acc);\n }\n _objectStack.push(acc);\n }\n\n function newAnnotation(tag) {\n var parent = _tagStack.get(1);\n if (parent != SEQUENCE) {\n throw new PhyloXmlError(\"found annotation outside of sequence\");\n }\n var ann = {};\n ann.evidence = getAttribute(ANNOTATION_EVIDENCE_ATTR, tag.attributes);\n ann.ref = getAttribute(ANNOTATION_REF_ATTR, tag.attributes);\n ann.source = getAttribute(ANNOTATION_SOURCE_ATTR, tag.attributes);\n ann.type = getAttribute(ANNOTATION_TYPE_ATTR, tag.attributes);\n addToArrayInCurrentObject('annotations', ann);\n _objectStack.push(ann);\n }\n\n function newBranchColor() {\n var parent = _tagStack.get(1);\n if (parent != CLADE) {\n throw new PhyloXmlError(\"found branch color outside of clade\");\n }\n var col = {};\n col.red = 0;\n col.green = 0;\n col.blue = 0;\n getCurrentObject().color = col;\n _objectStack.push(col);\n }\n\n function newClade(tag) {\n var newClade = {};\n newClade.branch_length = getAttributeAsFloat(CLADE_BRANCH_LENGTH, tag.attributes);\n newClade.collapse = getAttributeAsBoolean(CLADE_COLLAPSE_ATTR, tag.attributes);\n if (CLADE_ID_SOURCE_ATTR in tag.attributes) {\n newClade.id_source = tag.attributes[CLADE_ID_SOURCE_ATTR];\n }\n if (_phylogeny === null) {\n var phylogeny_data = _objectStack.pop();\n if (!_objectStack.isEmpty()) {\n throw new PhyloXmlError('severe phyloXML format error');\n }\n _phylogeny = phylogeny_data;\n _phylogeny.children = [newClade];\n }\n else {\n var currClade = getCurrentClade();\n if (currClade.children === undefined) {\n currClade.children = [newClade];\n }\n else {\n currClade.children.push(newClade);\n }\n }\n _cladeStack.push(newClade);\n _objectStack.push(newClade);\n }\n\n function newCladeRelation(tag) {\n var cr = {};\n cr.distance = getAttributeAsFloat(CLADE_RELATION_DISTANCE_ATTR, tag.attributes);\n cr.id_ref_0 = getAttribute(CLADE_RELATION_ID_REF_0_ATTR, tag.attributes);\n cr.id_ref_1 = getAttribute(CLADE_RELATION_ID_REF_1_ATTR, tag.attributes);\n cr.type = getAttribute(CLADE_RELATION_TYPE_ATTR, tag.attributes);\n addToArrayInCurrentObject('clade_relations', cr);\n _objectStack.push(cr);\n }\n\n function newSequenceRelation(tag) {\n var sr = {};\n sr.distance = getAttributeAsFloat(SEQUENCE_RELATION_DISTANCE_ATTR, tag.attributes);\n sr.id_ref_0 = getAttribute(SEQUENCE_RELATION_ID_REF_0_ATTR, tag.attributes);\n sr.id_ref_1 = getAttribute(SEQUENCE_RELATION_ID_REF_1_ATTR, tag.attributes);\n sr.type = getAttribute(SEQUENCE_RELATION_TYPE_ATTR, tag.attributes);\n addToArrayInCurrentObject('sequence_relations', sr);\n _objectStack.push(sr);\n }\n\n function newConfidence(tag) {\n var conf = {};\n conf.value = null;\n conf.type = getAttribute(CONFIDENCE_TYPE_ATTR, tag.attributes);\n conf.stddev = getAttributeAsFloat(CONFIDENCE_STDDEV_ATTR, tag.attributes);\n var parent = _tagStack.get(1);\n if (parent === CLADE || parent === PHYLOGENY) {\n addToArrayInCurrentObject(CONFIDENCES, conf);\n }\n else if (parent === ANNOTATION || parent === EVENTS || parent === CLADE_RELATION || parent === SEQUENCE_RELATION) {\n getCurrentObject().confidence = conf;\n }\n _objectStack.push(conf);\n }\n\n function newCrossReferences() {\n var parent = _tagStack.get(1);\n if (parent != SEQUENCE) {\n throw new PhyloXmlError(\"found cross-reference outside of sequence\");\n }\n var xrefs = [];\n getCurrentObject().cross_references = xrefs;\n _objectStack.push(xrefs);\n }\n\n function newDate(tag) {\n var date = {};\n date.unit = getAttribute(DATE_UNIT_ATTR, tag.attributes);\n getCurrentObject().date = date;\n _objectStack.push(date);\n }\n\n function newDistribution(tag) {\n var dist = {};\n dist.desc = null;\n dist.unit = getAttribute(DATE_UNIT_ATTR, tag.attributes);\n addToArrayInCurrentObject('distributions', dist);\n _objectStack.push(dist);\n }\n\n function newDomainArchitecture(tag) {\n var da = {};\n da.domains = null;\n da.length = getAttributeAsInt(DOMAIN_ARCHITECTURE_LENGTH_ATTR, tag.attributes);\n getCurrentObject().domain_architecture = da;\n _objectStack.push(da);\n }\n\n function newEvents() {\n var events = {};\n getCurrentObject().events = events;\n _objectStack.push(events);\n }\n\n function newId(tag) {\n var i = {};\n i.value = null;\n i.provider = getAttribute(ID_PROVIDER_ATTR, tag.attributes);\n getCurrentObject().id = i;\n _objectStack.push(i);\n }\n\n function newMolecularSequence(tag) {\n var mol_seq = {};\n mol_seq.is_aligned = getAttributeAsBoolean(MOLSEQ_IS_ALIGNED_ATTR, tag.attributes);\n getCurrentObject().mol_seq = mol_seq;\n _objectStack.push(mol_seq);\n }\n\n function newPoint(tag) {\n var p = {};\n p.alt_unit = getAttribute(POINT_ALT_UNIT_ATTR, tag.attributes);\n p.geodetic_datum = getAttribute(POINT_GEODETIC_DATUM_ATTR, tag.attributes);\n var parent = _tagStack.get(1);\n if (parent === DISTRIBUTION) {\n addToArrayInCurrentObject('points', p);\n }\n _objectStack.push(p);\n }\n\n function newProperty(tag) {\n var prop = {};\n prop.ref = getAttribute(PROPERTY_REF_ATTR, tag.attributes);\n prop.unit = getAttribute(PROPERTY_UNIT_ATTR, tag.attributes);\n prop.datatype = getAttribute(PROPERTY_DATATYPE_ATTR, tag.attributes);\n prop.applies_to = getAttribute(PROPERTY_APPLIES_TO_ATTR, tag.attributes);\n prop.id_ref = getAttribute(PROPERTY_ID_REF_ATTR, tag.attributes);\n\n if (!prop.ref) {\n throw new PhyloXmlError('property ref is missing');\n }\n if (!prop.datatype) {\n throw new PhyloXmlError('property data-type is missing');\n }\n if (!prop.applies_to) {\n throw new PhyloXmlError('property applies-to is missing');\n }\n if (!PROPERTY_REF_RE.test(prop.ref)) {\n throw new PhyloXmlError('property ref is ill-formatted: ' + prop.ref);\n }\n if (!PROPERTY_DATATYPE_RE.test(prop.datatype)) {\n throw new PhyloXmlError('property data-type is ill-formatted: ' + prop.datatype);\n }\n if (prop.unit && !PROPERTY_UNIT_RE.test(prop.unit)) {\n throw new PhyloXmlError('property unit is ill-formatted: ' + prop.unit);\n }\n\n addToArrayInCurrentObject(PROPERTIES, prop);\n _objectStack.push(prop);\n }\n\n function newProteinDomain(tag) {\n var pd = {};\n pd.name = null;\n pd.from = getAttributeAsInt(PROTEINDOMAIN_FROM_ATTR, tag.attributes);\n pd.to = getAttributeAsInt(PROTEINDOMAIN_TO_ATTR, tag.attributes);\n pd.confidence = getAttributeAsFloat(PROTEINDOMAIN_CONFIDENCE_ATTR, tag.attributes);\n pd.id = getAttribute(PROTEINDOMAIN_ID_ATTR, tag.attributes);\n addToArrayInCurrentObject('domains', pd);\n _objectStack.push(pd);\n }\n\n function newReference(tag) {\n var reference = {};\n reference.doi = getAttribute(REFERENCE_DOI_ATTR, tag.attributes);\n addToArrayInCurrentObject('references', reference);\n _objectStack.push(reference);\n }\n\n function newSequence(tag) {\n var seq = {};\n seq.type = getAttribute(SEQUENCE_TYPE_ATTR, tag.attributes);\n seq.id_source = getAttribute(SEQUENCE_ID_SOURCE_ATTR, tag.attributes);\n seq.id_ref = getAttribute(SEQUENCE_ID_REF_ATTR, tag.attributes);\n addToArrayInCurrentObject(SEQUENCES, seq);\n _objectStack.push(seq);\n }\n\n function newTaxonomy(tag) {\n var tax = {};\n tax.id_source = getAttribute(TAXONOMY_ID_SOURCE_ATTR, tag.attributes);\n addToArrayInCurrentObject(TAXONOMIES, tax);\n _objectStack.push(tax);\n }\n\n function newUri(tag) {\n var uri = {};\n uri.value = null;\n uri.desc = getAttribute(URI_DESC_ATTR, tag.attributes);\n uri.type = getAttribute(URI_TYPE_ATTR, tag.attributes);\n addToArrayInCurrentObject('uris', uri);\n _objectStack.push(uri);\n }\n\n function newPhylogeny(tag) {\n var phy = {};\n phy.rooted = getAttributeAsBoolean(PHYLOGENY_ROOTED_ATTR, tag.attributes);\n if (phy.rooted === undefined) {\n phy.rooted = true;\n }\n phy.rerootable = getAttributeAsBoolean(PHYLOGENY_REROOTABLE_ATTR, tag.attributes);\n if (phy.rerootable === undefined) {\n phy.rerootable = true;\n }\n phy.branch_length_unit = getAttribute(PHYLOGENY_BRANCH_LENGTH_UNIT_ATTR, tag.attributes);\n phy.type = getAttribute(PHYLOGENY_TYPE_ATTR, tag.attributes);\n _objectStack.push(phy);\n }\n\n function newSimpleCharacteristics() {\n //To be deprecated.\n var sc = {};\n getCurrentObject().simple_characteristics = sc;\n _objectStack.push(sc);\n }\n\n\n // --------------------------------------------------------------\n // Functions for processing text\n // --------------------------------------------------------------\n\n function inAccession(text) {\n getCurrentObject().value = text;\n }\n\n function inAnnotation(text) {\n if (getCurrentTag() === ANNOTATION_DESC) {\n getCurrentObject().desc = text;\n }\n }\n\n function inAppType(text) {\n if (getCurrentTag() === APPTYPE) {\n getCurrentObject().desc = text;\n }\n }\n\n function inBranchColor(text) {\n if (getCurrentTag() === COLOR_RED) {\n getCurrentObject().red = parseIntNumber(text);\n }\n else if (getCurrentTag() === COLOR_GREEN) {\n getCurrentObject().green = parseIntNumber(text);\n }\n else if (getCurrentTag() === COLOR_BLUE) {\n getCurrentObject().blue = parseIntNumber(text);\n }\n if (getCurrentTag() === COLOR_ALPHA) {\n getCurrentObject().alpha = parseIntNumber(text);\n }\n }\n\n function inClade(text) {\n if (getCurrentTag() === CLADE_NAME) {\n getCurrentClade().name = text;\n }\n else if (getCurrentTag() === CLADE_BRANCH_LENGTH) {\n getCurrentClade().branch_length = parseFloatNumber(text);\n }\n else if (getCurrentTag() === CLADE_WIDTH) {\n getCurrentClade().width = parseFloatNumber(text);\n }\n }\n\n function inConfidence(text) {\n getCurrentObject().value = parseFloatNumber(text);\n }\n\n function inDate(text) {\n if (getCurrentTag() === DATE_DESC) {\n getCurrentObject().desc = text;\n }\n else if (getCurrentTag() === DATE_VALUE) {\n getCurrentObject().value = parseFloatNumber(text);\n }\n else if (getCurrentTag() === DATE_MINIMUM) {\n getCurrentObject().minimum = parseFloatNumber(text);\n }\n else if (getCurrentTag() === DATE_MAXIMUM) {\n getCurrentObject().maximum = parseFloatNumber(text);\n }\n }\n\n function inDistribution(text) {\n if (getCurrentTag() === DISTRIBUTION_DESC) {\n getCurrentObject().desc = text;\n }\n }\n\n function inEvents(text) {\n if (getCurrentTag() === EVENTS_TYPE) {\n getCurrentObject().type = text;\n }\n else if (getCurrentTag() === EVENTS_DUPLICATIONS) {\n getCurrentObject().duplications = parseIntNumber(text);\n }\n else if (getCurrentTag() === EVENTS_SPECIATIONS) {\n getCurrentObject().speciations = parseIntNumber(text);\n }\n else if (getCurrentTag() === EVENTS_LOSSES) {\n getCurrentObject().losses = parseIntNumber(text);\n }\n }\n\n function inId(text) {\n getCurrentObject().value = text;\n }\n\n function inMolecularSequence(text) {\n getCurrentObject().value = text;\n }\n\n function inPoint(text) {\n if (getCurrentTag() === POINT_LAT) {\n getCurrentObject().lat = text;\n }\n else if (getCurrentTag() === POINT_LONG) {\n getCurrentObject().long = text;\n }\n else if (getCurrentTag() === POINT_ALT) {\n getCurrentObject().alt = text;\n }\n }\n\n function inProperty(text) {\n getCurrentObject().value = text;\n }\n\n function inProteinDomain(text) {\n getCurrentObject().name = text;\n }\n\n function inPhylogeny(text) {\n if (getCurrentTag() === PHYLOGENY_NAME) {\n getCurrentObject().name = text;\n }\n else if (getCurrentTag() === PHYLOGENY_DESCRIPTION) {\n getCurrentObject().description = text;\n }\n else if (getCurrentTag() === PHYLOGENY_DATE) {\n getCurrentObject().date = text;\n }\n }\n\n function inReference(text) {\n if (getCurrentTag() === REFERENCE_DESC) {\n getCurrentObject().desc = text;\n }\n }\n\n function inSequence(text) {\n if (getCurrentTag() === SEQUENCE_SYMBOL) {\n getCurrentObject().symbol = text;\n }\n else if (getCurrentTag() === SEQUENCE_NAME) {\n getCurrentObject().name = text;\n }\n else if (getCurrentTag() === SEQUENCE_GENE_NAME) {\n getCurrentObject().gene_name = text;\n }\n else if (getCurrentTag() === SEQUENCE_LOCATION) {\n getCurrentObject().location = text;\n }\n }\n\n function inTaxonomy(text) {\n if (getCurrentTag() === TAXONOMY_CODE) {\n getCurrentObject().code = text;\n }\n else if (getCurrentTag() === TAXONOMY_SCIENTIFIC_NAME) {\n getCurrentObject().scientific_name = text;\n }\n else if (getCurrentTag() === TAXONOMY_AUTHORITY) {\n getCurrentObject().authority = text;\n }\n else if (getCurrentTag() === TAXONOMY_COMMON_NAME) {\n getCurrentObject().common_name = text;\n }\n else if (getCurrentTag() === TAXONOMY_SYNONYM) {\n addToArrayInCurrentObject(TAXONOMY_SYNONYMS, text);\n }\n else if (getCurrentTag() === TAXONOMY_RANK) {\n getCurrentObject().rank = text;\n }\n }\n\n function inUri(text) {\n getCurrentObject().value = text;\n }\n\n function inSimpleCharacteristics(text) {\n //To be deprecated.\n if (getCurrentTag() === X_SIMPLE_CHARACTERISTIC_COUNTRY) {\n getCurrentObject().country = text;\n }\n else if (getCurrentTag() === X_SIMPLE_CHARACTERISTIC_HOST) {\n getCurrentObject().host = text;\n }\n else if (getCurrentTag() === X_SIMPLE_CHARACTERISTIC_YEAR) {\n getCurrentObject().year = text;\n }\n else if (getCurrentTag() === X_SIMPLE_CHARACTERISTIC_HA) {\n getCurrentObject().ha = text;\n }\n else if (getCurrentTag() === X_SIMPLE_CHARACTERISTIC_NA) {\n getCurrentObject().na = text;\n }\n }\n\n // --------------------------------------------------------------\n // Functions for SAX parser\n // --------------------------------------------------------------\n function phyloxmlOnopentag(tag) {\n _tagStack.push(tag.name);\n switch (tag.name) {\n case CLADE:\n newClade(tag);\n break;\n case ACCESSION:\n newAccession(tag);\n break;\n case ANNOTATION:\n newAnnotation(tag);\n break;\n case CLADE_RELATION:\n if (_tagStack.get(1) === PHYLOGENY) {\n newCladeRelation(tag);\n }\n break;\n case COLOR:\n newBranchColor();\n break;\n case CONFIDENCE:\n newConfidence(tag);\n break;\n case CROSS_REFERENCES:\n newCrossReferences();\n break;\n case DATE:\n if (_tagStack.get(1) === CLADE) {\n newDate(tag);\n }\n break;\n case DISTRIBUTION:\n newDistribution(tag);\n break;\n case DOMAIN_ARCHITECTURE:\n newDomainArchitecture(tag);\n break;\n case EVENTS:\n newEvents();\n break;\n case ID:\n newId(tag);\n break;\n case MOLSEQ:\n newMolecularSequence(tag);\n break;\n case POINT:\n newPoint(tag);\n break;\n case PROTEINDOMAIN:\n newProteinDomain(tag);\n break;\n case PHYLOGENY:\n newPhylogeny(tag);\n break;\n case PROPERTY:\n newProperty(tag);\n break;\n case REFERENCE:\n newReference(tag);\n break;\n case SEQUENCE:\n newSequence(tag);\n break;\n case SEQUENCE_RELATION:\n if (_tagStack.get(1) === PHYLOGENY) {\n newSequenceRelation(tag);\n }\n break;\n case TAXONOMY:\n newTaxonomy(tag);\n break;\n case URI:\n newUri(tag);\n break;\n case X_SIMPLE_CHARACTERISTICS:\n //To be deprecated.\n newSimpleCharacteristics();\n break;\n default:\n }\n }\n\n function phyloxmlOnclosetag(tag) {\n if (tag === CLADE) {\n _tagStack.pop();\n _objectStack.pop();\n _cladeStack.pop();\n }\n else if (\n tag === ACCESSION\n || tag === ANNOTATION\n || ( tag === CLADE_RELATION && (_tagStack.get(1) === PHYLOGENY) )\n || tag === COLOR\n || tag === CONFIDENCE\n || tag === CROSS_REFERENCES\n || ( tag === DATE && (_tagStack.get(1) === CLADE) )\n || tag === DISTRIBUTION\n || tag === TAXONOMY\n || tag === ID\n || tag === EVENTS\n || tag === MOLSEQ\n || tag === REFERENCE\n || tag === DOMAIN_ARCHITECTURE\n || tag === PROTEINDOMAIN\n || tag === SEQUENCE\n || ( tag === SEQUENCE_RELATION && (_tagStack.get(1) === PHYLOGENY) )\n || tag === PROPERTY\n || tag === POINT\n || tag === URI\n || tag === X_SIMPLE_CHARACTERISTICS) {\n _tagStack.pop();\n _objectStack.pop();\n }\n else if (!(tag === PHYLOGENY || tag === PHYLOXML)) {\n _tagStack.pop();\n }\n else if (tag === PHYLOGENY) {\n phyloxmlOnClosetagSanityCheck();\n _phylogenies.push(_phylogeny);\n startNewPhylogeny();\n }\n }\n\n function phyloxmlOntext(text) {\n var parentTag = _tagStack.get(1);\n var currentTag = _tagStack.peek();\n if (parentTag === CLADE) {\n inClade(text);\n }\n else if (parentTag === ANNOTATION) {\n inAnnotation(text);\n }\n else if (parentTag === COLOR) {\n inBranchColor(text);\n }\n else if (parentTag === DATE) {\n inDate(text);\n }\n else if (parentTag === DISTRIBUTION) {\n inDistribution(text);\n }\n else if (parentTag === EVENTS) {\n inEvents(text);\n }\n else if (parentTag === REFERENCE) {\n inReference(text);\n }\n else if (parentTag === PHYLOGENY) {\n inPhylogeny(text);\n }\n else if (parentTag === POINT) {\n inPoint(text);\n }\n else if (parentTag === SEQUENCE) {\n inSequence(text);\n }\n else if (parentTag === TAXONOMY) {\n inTaxonomy(text);\n }\n if (currentTag === ACCESSION) {\n inAccession(text);\n }\n else if (currentTag === APPTYPE) {\n inAppType(text);\n }\n else if (currentTag === CONFIDENCE) {\n inConfidence(text);\n }\n else if (currentTag === ID) {\n inId(text);\n }\n else if (currentTag === MOLSEQ) {\n inMolecularSequence(text);\n }\n else if (currentTag === PROTEINDOMAIN) {\n inProteinDomain(text);\n }\n else if (currentTag === PROPERTY) {\n inProperty(text);\n }\n else if (currentTag === URI) {\n inUri(text);\n }\n else if (parentTag === X_SIMPLE_CHARACTERISTICS) {\n inSimpleCharacteristics(text);\n }\n }\n\n function phyloxmlOnerror(error) {\n throw error;\n }\n\n function addPhyloxmlParserEvents(sax_parser) {\n sax_parser.onopentag = phyloxmlOnopentag;\n sax_parser.onclosetag = phyloxmlOnclosetag;\n sax_parser.ontext = phyloxmlOntext;\n sax_parser.onerror = phyloxmlOnerror;\n // Ignoring: oncdata, oncomment, ondoctype\n }\n\n // --------------------------------------------------------------\n // Helper functions\n // --------------------------------------------------------------\n function getCurrentClade() {\n return _cladeStack.peek();\n }\n\n function getCurrentTag() {\n return _tagStack.peek();\n }\n\n function getCurrentObject() {\n return _objectStack.peek();\n }\n\n function getAttribute(attribute_name, attributes) {\n if (attribute_name in attributes) {\n return attributes[attribute_name];\n }\n return undefined;\n }\n\n function getAttributeAsInt(attribute_name, attributes) {\n if (attribute_name in attributes) {\n return parseIntNumber(attributes[attribute_name]);\n }\n return undefined;\n }\n\n function getAttributeAsFloat(attribute_name, attributes) {\n if (attribute_name in attributes) {\n return parseFloatNumber(attributes[attribute_name]);\n }\n return undefined;\n }\n\n function getAttributeAsBoolean(attribute_name, attributes) {\n if (attribute_name in attributes) {\n return parseBoolean(attributes[attribute_name]);\n }\n return undefined;\n }\n\n function addToArrayInCurrentObject(name, value) {\n var parent = null;\n if (getCurrentObject()) {\n parent = getCurrentObject();\n }\n else {\n parent = _phylogeny;\n }\n var ary = parent[name];\n if (ary) {\n ary.push(value);\n }\n else {\n parent[name] = [value];\n }\n }\n\n function addToArrayInCurrentObjectUnnamed(value) {\n var obj = getCurrentObject();\n obj.push(value);\n }\n\n function parseFloatNumber(text) {\n var f = parseFloat(text);\n if (isNaN(f)) {\n throw new PhyloXmlError(\"could not parse floating point number from '\" + text + \"'\");\n }\n return f;\n }\n\n function parseIntNumber(text) {\n var i = parseInt(text);\n if (isNaN(i)) {\n throw new PhyloXmlError(\"could not parse integer number from '\" + text + \"'\");\n }\n return i;\n }\n\n function parseBoolean(text) {\n if (text === 'true') {\n return true;\n }\n else if (text === 'false') {\n return false;\n }\n else {\n throw new PhyloXmlError(\"could not parse boolean from '\" + text + \"'\");\n }\n }\n\n function startNewPhylogeny() {\n _phylogeny = null;\n _cladeStack = new Stack();\n _tagStack = new Stack();\n _objectStack = new Stack();\n }\n\n function phyloxmlOnClosetagSanityCheck() {\n if (!(_cladeStack.isEmpty() && _objectStack.isEmpty() )) {\n throw new PhyloXmlError('severe phyloXML format error')\n }\n }\n\n function finalSanityCheck() {\n if (!_tagStack.isEmpty()) {\n throw new PhyloXmlError('severe phyloXML format error');\n }\n }\n\n // --------------------------------------------------------------\n // Stack\n // --------------------------------------------------------------\n function Stack() {\n this._stack = [];\n this.pop = function () {\n var p = this._stack.pop();\n if (p === undefined) {\n throw new Error('severe phyloXML format error')\n }\n return p;\n };\n this.push = function (item) {\n this._stack.push(item);\n };\n this.peek = function () {\n return this._stack[this._stack.length - 1];\n };\n this.get = function (i) {\n return this._stack[this._stack.length - (1 + i)];\n };\n this.length = function () {\n return this._stack.length;\n };\n this.isEmpty = function () {\n return this._stack.length < 1;\n };\n }\n\n // --------------------------------------------------------------\n // phyloXML error\n // --------------------------------------------------------------\n function PhyloXmlError(message) {\n this.name = 'phyloXmlError';\n this.message = message || 'phyloXML format error';\n }\n\n PhyloXmlError.prototype = Object.create(Error.prototype);\n\n // --------------------------------------------------------------\n // To phyloXML\n // --------------------------------------------------------------\n phyloXml.toPhyloXML_ = function (phy, dec) {\n var x = '';\n var ind = '';\n openPhyloXml();\n openPhylogeny(phy, [PHYLOGENY_ROOTED_ATTR, PHYLOGENY_REROOTABLE_ATTR,\n PHYLOGENY_BRANCH_LENGTH_UNIT_ATTR, PHYLOGENY_TYPE_ATTR]);\n addSingleElement(PHYLOGENY_NAME, phy.name);\n addSingleElement(PHYLOGENY_DESCRIPTION, phy.description);\n addSingleElement(PHYLOGENY_DATE, phy.date);\n if (phy.children && phy.children.length === 1) {\n toPhyloXMLhelper(phy.children[0]);\n }\n closePhylogeny();\n closePhyloXml();\n return x;\n\n function toPhyloXMLhelper(node) {\n var l;\n var i;\n\n openClade(node, [CLADE_ID_SOURCE_ATTR, CLADE_COLLAPSE_ATTR]);\n\n addSingleElement(CLADE_NAME, node.name);\n\n if (node[CLADE_BRANCH_LENGTH]) {\n addSingleElement(CLADE_BRANCH_LENGTH, (dec && dec > 0) ? roundNumber(node[CLADE_BRANCH_LENGTH], dec) : node[CLADE_BRANCH_LENGTH]);\n }\n\n if (node[CONFIDENCES] && node[CONFIDENCES].length > 0) {\n l = node[CONFIDENCES].length;\n for (i = 0; i < l; ++i) {\n var conf = node[CONFIDENCES][i];\n if (!conf[CONFIDENCE_TYPE_ATTR]) {\n conf[CONFIDENCE_TYPE_ATTR] = UNKNOWN;\n }\n addSingleElement(CONFIDENCE, conf.value, conf,\n [CONFIDENCE_TYPE_ATTR, CONFIDENCE_STDDEV_ATTR]);\n }\n }\n\n addSingleElement(CLADE_WIDTH, node[CLADE_WIDTH]);\n\n if (node[COLOR]) {\n var col = node[COLOR];\n open(COLOR);\n addSingleElement(COLOR_RED, col[COLOR_RED]);\n addSingleElement(COLOR_GREEN, col[COLOR_GREEN]);\n addSingleElement(COLOR_BLUE, col[COLOR_BLUE]);\n addSingleElement(COLOR_ALPHA, col[COLOR_ALPHA]);\n close(COLOR);\n }\n\n if (node[TAXONOMIES] && node[TAXONOMIES].length > 0) {\n l = node[TAXONOMIES].length;\n for (i = 0; i < l; ++i) {\n var tax = node[TAXONOMIES][i];\n open(TAXONOMY, tax, [TAXONOMY_ID_SOURCE_ATTR]);\n if (tax[ID]) {\n if (!tax[ID][ID_PROVIDER_ATTR]) {\n tax[ID][ID_PROVIDER_ATTR] = UNKNOWN;\n }\n addSingleElement(ID, tax[ID].value, tax[ID],\n [ID_PROVIDER_ATTR]);\n }\n addSingleElement(TAXONOMY_CODE, tax[TAXONOMY_CODE]);\n addSingleElement(TAXONOMY_SCIENTIFIC_NAME, tax[TAXONOMY_SCIENTIFIC_NAME]);\n addSingleElement(TAXONOMY_AUTHORITY, tax[TAXONOMY_AUTHORITY]);\n addSingleElement(TAXONOMY_COMMON_NAME, tax[TAXONOMY_COMMON_NAME]);\n if (tax[TAXONOMY_SYNONYMS] && tax[TAXONOMY_SYNONYMS].length > 0) {\n var ll = tax[TAXONOMY_SYNONYMS].length;\n for (var ii = 0; ii < ll; ++ii) {\n addSingleElement(TAXONOMY_SYNONYM, tax[TAXONOMY_SYNONYMS][ii]);\n }\n }\n addSingleElement(TAXONOMY_RANK, tax[TAXONOMY_RANK]);\n close(TAXONOMY);\n }\n }\n\n if (node[SEQUENCES] && node[SEQUENCES].length > 0) {\n l = node[SEQUENCES].length;\n for (i = 0; i < l; ++i) {\n var seq = node[SEQUENCES][i];\n open(SEQUENCE, seq, [SEQUENCE_TYPE_ATTR, SEQUENCE_ID_SOURCE_ATTR, SEQUENCE_ID_REF_ATTR]);\n addSingleElement(SEQUENCE_SYMBOL, seq[SEQUENCE_SYMBOL]);\n if (seq[ACCESSION]) {\n if (!seq[ACCESSION][ACCESSION_SOURCE_ATTR]) {\n seq[ACCESSION][ACCESSION_SOURCE_ATTR] = UNKNOWN;\n }\n addSingleElement(ACCESSION, seq[ACCESSION].value, seq[ACCESSION],\n [ACCESSION_SOURCE_ATTR, ACCESSION_COMMENT_ATTR]);\n }\n addSingleElement(SEQUENCE_NAME, seq[SEQUENCE_NAME]);\n addSingleElement(SEQUENCE_GENE_NAME, seq[SEQUENCE_GENE_NAME]);\n addSingleElement(SEQUENCE_LOCATION, seq[SEQUENCE_LOCATION]);\n if (seq[MOLSEQ]) {\n addSingleElement(MOLSEQ, seq[MOLSEQ].value, seq[MOLSEQ],\n [MOLSEQ_IS_ALIGNED_ATTR]);\n }\n close(SEQUENCE);\n }\n }\n\n if (node[EVENTS]) {\n var ev = node[EVENTS];\n open(EVENTS);\n addSingleElement(EVENTS_TYPE, ev[EVENTS_TYPE]);\n addSingleElement(EVENTS_DUPLICATIONS, ev[EVENTS_DUPLICATIONS]);\n addSingleElement(EVENTS_SPECIATIONS, ev[EVENTS_SPECIATIONS]);\n addSingleElement(EVENTS_LOSSES, ev[EVENTS_LOSSES]);\n if (ev[CONFIDENCE]) {\n var evconf = ev[CONFIDENCE];\n addSingleElement(CONFIDENCE, evconf.value, evconf,\n [CONFIDENCE_TYPE_ATTR, CONFIDENCE_STDDEV_ATTR]);\n }\n close(EVENTS);\n }\n\n if (node[PROPERTIES] && node[PROPERTIES].length > 0) {\n l = node[PROPERTIES].length;\n for (i = 0; i < l; ++i) {\n var prop = node[PROPERTIES][i];\n if (!prop[PROPERTY_APPLIES_TO_ATTR]) {\n throw new PhyloXmlError(\"property applies-to is missing\");\n }\n if (!prop[PROPERTY_DATATYPE_ATTR]) {\n throw new PhyloXmlError(\"property data-type is missing\");\n }\n if (!prop[PROPERTY_REF_ATTR]) {\n throw new PhyloXmlError(\"property ref is missing\");\n }\n addSingleElement(PROPERTY, prop.value, prop, [PROPERTY_REF_ATTR,\n PROPERTY_UNIT_ATTR, PROPERTY_DATATYPE_ATTR, PROPERTY_APPLIES_TO_ATTR,\n PROPERTY_ID_REF_ATTR]);\n }\n }\n\n if (node.children) {\n l = node.children.length;\n for (i = 0; i < l; ++i) {\n toPhyloXMLhelper(node.children[i]);\n }\n }\n else if (node._children) {\n l = node._children.length;\n for (i = 0; i < l; ++i) {\n toPhyloXMLhelper(node._children[i]);\n }\n }\n\n closeClade();\n\n } // toPhyloXMLhelper\n\n function addSingleElement(elemName, elemValue, object, attributeNames) {\n if ((elemValue !== null) && (elemValue !== undefined)) {\n if (typeof elemValue === 'string' || elemValue instanceof String) {\n elemValue = elemValue.trim();\n if (elemValue.length > 0) {\n if ((elemValue.indexOf('&') > -1) || ( elemValue.indexOf('<') > -1) || ( elemValue.indexOf('>') > -1)\n || (elemValue.indexOf('\"') > -1) || ( elemValue.indexOf(\"'\") > -1)) {\n elemValue = replaceUnsafeChars(elemValue);\n }\n }\n else {\n return;\n }\n }\n x += ( ind + '<' + elemName);\n if (object && attributeNames && attributeNames.length > 0) {\n addAttributes(object, attributeNames);\n }\n x += ( '>' + elemValue + '</' + elemName + '>\\n');\n }\n }\n\n function open(elemName, object, attributeNames) {\n if (object && attributeNames && attributeNames.length > 0) {\n x += ( ind + '<' + elemName);\n addAttributes(object, attributeNames);\n x += '>\\n';\n }\n else {\n x += (ind + '<' + elemName + '>\\n' );\n }\n ind = ind + ' ';\n }\n\n function close(elemName) {\n reduceInd();\n x += ( ind + '</' + elemName + '>\\n' );\n }\n\n function openClade(object, attributeNames) {\n if (object && attributeNames && attributeNames.length > 0) {\n x += ind + '<clade';\n addAttributes(object, attributeNames);\n x += '>\\n';\n }\n else {\n x += ind + '<clade>\\n';\n }\n ind = ind + ' ';\n }\n\n function closeClade() {\n reduceInd();\n x += ind + '</clade>\\n';\n }\n\n function openPhylogeny(object, attributeNames) {\n if (object[PHYLOGENY_ROOTED_ATTR] === undefined ||\n object[PHYLOGENY_ROOTED_ATTR] === null) {\n object[PHYLOGENY_ROOTED_ATTR] = true;\n }\n if (object[PHYLOGENY_REROOTABLE_ATTR] === undefined ||\n object[PHYLOGENY_REROOTABLE_ATTR] === null) {\n object[PHYLOGENY_REROOTABLE_ATTR] = true;\n }\n if (object && attributeNames && attributeNames.length > 0) {\n x += ' <phylogeny';\n addAttributes(object, attributeNames);\n x += '>\\n';\n }\n else {\n x += ' <phylogeny>\\n';\n }\n ind = ' ';\n }\n\n function closePhylogeny() {\n ind = ' ';\n x += ' </phylogeny>\\n';\n }\n\n function openPhyloXml() {\n ind = '';\n x += '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n';\n x += '<phyloxml xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.phyloxml.org http://www.phyloxml.org/1.20/phyloxml.xsd\" xmlns=\"http://www.phyloxml.org\">\\n';\n }\n\n function closePhyloXml() {\n x += '</phyloxml>\\n';\n }\n\n function addAttributes(object, attributeNames) {\n var l = attributeNames.length;\n for (var i = 0; i < l; ++i) {\n var attributeName = attributeNames[i];\n if (attributeName && ( object[attributeName] !== undefined && object[attributeName] !== null )) {\n x += (' ' + attributeName + '=\"' + object[attributeName] + '\"' );\n }\n }\n }\n\n function roundNumber(num, dec) {\n return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);\n }\n\n function replaceUnsafeChars(str) {\n return str\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n }\n\n function reduceInd() {\n var l = ind.length;\n ind = '';\n for (var i = 0; i <= l - 2; ++i) {\n ind += ' ';\n }\n }\n\n }; // toPhyloXML_\n\n\n // --------------------------------------------------------------\n // Main functions\n // --------------------------------------------------------------\n\n /**\n * To parse phyloXML formatted trees from a stream asynchronously.\n *\n * @param stream - The stream to be parsed.\n * @param parseOptions - Options dict for the SAX parser.\n * (example: {trim: true, normalize: true}).\n */\n phyloXml.parseAsync = function (stream, parseOptions) {\n _phylogenies = [];\n startNewPhylogeny();\n var sax_parser = sax.createStream(true, parseOptions);\n addPhyloxmlParserEvents(sax_parser);\n stream.pipe(sax_parser);\n\n sax_parser.on('end', function () {\n finalSanityCheck();\n var len = _phylogenies.length;\n console.log(\"parsed \" + len + \" trees\");\n // for (var i = 0; i < len; ++i) {\n // do something, for example:\n // var str = JSON.stringify(_phylogenies[i], null, 2);\n //}\n });\n\n process.stdout.on('drain', function () {\n stream.resume();\n });\n };\n\n /**\n * To parse a phyloXML formatted source.\n *\n * @param source - The source.\n * @param parseOptions - Options dict for the SAX parser\n * (example: {trim: true, normalize: true}).\n * @returns {*} - Array of phylogentic tree objects.\n */\n phyloXml.parse = function (source, parseOptions) {\n source && ( source = source.toString().trim());\n\n if (!source) {\n throw new Error('phyloXML source is empty');\n }\n\n _phylogenies = [];\n startNewPhylogeny();\n var sax_parser = sax.parser(true, parseOptions);\n addPhyloxmlParserEvents(sax_parser);\n\n sax_parser.onend = function () {\n finalSanityCheck();\n };\n\n sax_parser.write(source).close();\n return _phylogenies;\n };\n\n\n /**\n * To convert a phylogentic tree object to a phyloXML formatted string.\n *\n * @param phy - A phylogentic tree object.\n * @param decPointsMax - Maximal number of decimal points for branch lengths (optional).\n * @returns A phyloXML formatted string.\n */\n phyloXml.toPhyloXML = function (phy, decPointsMax) {\n return phyloXml.toPhyloXML_(phy, decPointsMax);\n };\n\n // --------------------------------------------------------------\n // For exporting\n // --------------------------------------------------------------\n if ( true && module.exports && !__webpack_require__.g.xmldocAssumeBrowser)\n module.exports.phyloXml = phyloXml;\n else if (typeof window !== \"undefined\")\n window.phyloXml = phyloXml;\n else\n this.phyloXml = phyloXml;\n})();\n\n\n//# sourceURL=webpack://PhyloIO/./src/phyloxml.js?");
30
+
31
+ /***/ }),
32
+
33
+ /***/ "./src/worker_bcn.js":
34
+ /*!***************************!*\
35
+ !*** ./src/worker_bcn.js ***!
36
+ \***************************/
37
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
38
+
39
+ "use strict";
40
+ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var minhashjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! minhashjs */ \"./node_modules/minhashjs/index.js\");\n/* harmony import */ var _model__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./model */ \"./src/model.js\");\n\n\n\n\nself.onmessage = (event) => {\n\n var containers = event.data;\n\n var processed_tree = compute_similarity_container_pair(containers.tree1,containers.tree2)\n\n postMessage(processed_tree);\n\n self.close();\n};\n\n\n\nfunction compute_similarity_container_pair(t1,t2){\n\n var t1 = new _model__WEBPACK_IMPORTED_MODULE_1__[\"default\"](t1.data, t1.settings, false)\n var t2 = new _model__WEBPACK_IMPORTED_MODULE_1__[\"default\"](t2.data, t2.settings, false)\n\n\n console.time(\"similarity\");\n\n // X = Intersection of T1 & T2 leaves.\n if (t1.leaves.length <= 0){\n t1.leaves = t1.get_leaves(t1.data)\n }\n if (t2.leaves.length <= 0){\n t2.leaves = t2.get_leaves(t2.data)\n }\n var common_leaves = t1.leaves.map(leaf => leaf.name).filter(value => t2.leaves.map(leaf => leaf.name).includes(value));\n console.log(\"Intersection\");\n console.timeLog(\"similarity\");\n\n // DeepLeaf with filter(X = True)\n t1.createDeepLeafList(common_leaves)\n t2.createDeepLeafList(common_leaves)\n console.log(\"DeepLeaf\");\n console.timeLog(\"similarity\");\n\n // MinHash\n t1.createMinHash()\n t2.createMinHash()\n console.log(\"MinHash\");\n console.timeLog(\"similarity\");\n\n // For all T1 & T2 Nodes compute the BCN with MinHash\n var nodes_t1 = []\n var nodes_t2 = []\n\n var forest1 = new minhashjs__WEBPACK_IMPORTED_MODULE_0__.MinHashLSHForest.MinHashLSHForest()\n var forest2 = new minhashjs__WEBPACK_IMPORTED_MODULE_0__.MinHashLSHForest.MinHashLSHForest()\n\n var cpt =0\n t1.traverse(t1.data, function(h,children){nodes_t1.push(h);forest1.add(h, h.min_hash);cpt++}, null)\n t2.traverse(t2.data, function(z,children){nodes_t2.push(z);forest2.add(z, z.min_hash);cpt++}, null)\n\n forest1.index()\n forest2.index()\n\n find_BCN(nodes_t1, forest2, t2.uid)\n find_BCN(nodes_t2, forest1, t1.uid)\n\n console.log(\"BCN done\");\n\n console.timeLog(\"similarity\");\n\n // Clean non essential datume\n t1.removeMinHash()\n t2.removeMinHash()\n\n console.timeEnd(\"similarity\");\n\n t1.settings.similarity.push(t2.uid)\n t2.settings.similarity.push(t1.uid)\n\n t1.data = t1.remove_circularity_only_parent_and_leaves()\n t2.data = t2.remove_circularity_only_parent_and_leaves()\n\n t1.remove_all_color_scale()\n t2.remove_all_color_scale()\n\n return [t1,t2]\n\n}\n\nfunction find_BCN(nodes_list, target_forest, target_uid){\n nodes_list.forEach((node) => {\n\n function is_leaf(str) {\n return !str.includes(\"|__|\");\n }\n\n var matches = target_forest.query(node.min_hash,10)\n\n var l = new Set(node.deepLeafList.filter(is_leaf))\n if (l.size > 0){\n\n var max_jacc = 0\n var BCN = null\n\n matches.forEach(e => {\n var r = new Set(e.deepLeafList.filter(is_leaf))\n\n if (r.size > 0){\n\n\n var inter = Array.from(r).filter(x => l.has(x)).length\n var union = [...new Set([...l, ...r])].length;\n\n var jj = inter/union\n\n\n\n if (jj > max_jacc){\n max_jacc = jj\n BCN = e\n }\n\n }\n\n\n\n\n\n })\n\n if (max_jacc > 0) {\n node.elementS[target_uid] = max_jacc\n if (!node.elementBCN){\n node.elementBCN = {}\n }\n node.elementBCN[target_uid] = BCN\n }\n\n\n }\n\n\n\n\n })\n}\n\n//# sourceURL=webpack://PhyloIO/./src/worker_bcn.js?");
41
+
42
+ /***/ }),
43
+
44
+ /***/ "?d546":
45
+ /*!************************!*\
46
+ !*** buffer (ignored) ***!
47
+ \************************/
48
+ /***/ (() => {
49
+
50
+ eval("/* (ignored) */\n\n//# sourceURL=webpack://PhyloIO/buffer_(ignored)?");
51
+
52
+ /***/ }),
53
+
54
+ /***/ "?8131":
55
+ /*!************************!*\
56
+ !*** buffer (ignored) ***!
57
+ \************************/
58
+ /***/ (() => {
59
+
60
+ eval("/* (ignored) */\n\n//# sourceURL=webpack://PhyloIO/buffer_(ignored)?");
61
+
62
+ /***/ }),
63
+
64
+ /***/ "?3fc0":
65
+ /*!************************!*\
66
+ !*** crypto (ignored) ***!
67
+ \************************/
68
+ /***/ (() => {
69
+
70
+ eval("/* (ignored) */\n\n//# sourceURL=webpack://PhyloIO/crypto_(ignored)?");
71
+
72
+ /***/ }),
73
+
74
+ /***/ "?4068":
75
+ /*!************************!*\
76
+ !*** buffer (ignored) ***!
77
+ \************************/
78
+ /***/ (() => {
79
+
80
+ eval("/* (ignored) */\n\n//# sourceURL=webpack://PhyloIO/buffer_(ignored)?");
81
+
82
+ /***/ }),
83
+
84
+ /***/ "?e7e4":
85
+ /*!************************!*\
86
+ !*** buffer (ignored) ***!
87
+ \************************/
88
+ /***/ (() => {
89
+
90
+ eval("/* (ignored) */\n\n//# sourceURL=webpack://PhyloIO/buffer_(ignored)?");
91
+
92
+ /***/ }),
93
+
94
+ /***/ "?7bec":
95
+ /*!************************!*\
96
+ !*** buffer (ignored) ***!
97
+ \************************/
98
+ /***/ (() => {
99
+
100
+ eval("/* (ignored) */\n\n//# sourceURL=webpack://PhyloIO/buffer_(ignored)?");
101
+
102
+ /***/ }),
103
+
104
+ /***/ "?0aec":
105
+ /*!************************!*\
106
+ !*** buffer (ignored) ***!
107
+ \************************/
108
+ /***/ (() => {
109
+
110
+ eval("/* (ignored) */\n\n//# sourceURL=webpack://PhyloIO/buffer_(ignored)?");
111
+
112
+ /***/ }),
113
+
114
+ /***/ "?fbf1":
115
+ /*!************************!*\
116
+ !*** buffer (ignored) ***!
117
+ \************************/
118
+ /***/ (() => {
119
+
120
+ eval("/* (ignored) */\n\n//# sourceURL=webpack://PhyloIO/buffer_(ignored)?");
121
+
122
+ /***/ }),
123
+
124
+ /***/ "?ed1b":
125
+ /*!**********************!*\
126
+ !*** util (ignored) ***!
127
+ \**********************/
128
+ /***/ (() => {
129
+
130
+ eval("/* (ignored) */\n\n//# sourceURL=webpack://PhyloIO/util_(ignored)?");
131
+
132
+ /***/ }),
133
+
134
+ /***/ "?d17e":
135
+ /*!**********************!*\
136
+ !*** util (ignored) ***!
137
+ \**********************/
138
+ /***/ (() => {
139
+
140
+ eval("/* (ignored) */\n\n//# sourceURL=webpack://PhyloIO/util_(ignored)?");
141
+
142
+ /***/ })
143
+
144
+ /******/ });
145
+ /************************************************************************/
146
+ /******/ // The module cache
147
+ /******/ var __webpack_module_cache__ = {};
148
+ /******/
149
+ /******/ // The require function
150
+ /******/ function __webpack_require__(moduleId) {
151
+ /******/ // Check if module is in cache
152
+ /******/ var cachedModule = __webpack_module_cache__[moduleId];
153
+ /******/ if (cachedModule !== undefined) {
154
+ /******/ return cachedModule.exports;
155
+ /******/ }
156
+ /******/ // Create a new module (and put it into the cache)
157
+ /******/ var module = __webpack_module_cache__[moduleId] = {
158
+ /******/ id: moduleId,
159
+ /******/ loaded: false,
160
+ /******/ exports: {}
161
+ /******/ };
162
+ /******/
163
+ /******/ // Execute the module function
164
+ /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
165
+ /******/
166
+ /******/ // Flag the module as loaded
167
+ /******/ module.loaded = true;
168
+ /******/
169
+ /******/ // Return the exports of the module
170
+ /******/ return module.exports;
171
+ /******/ }
172
+ /******/
173
+ /******/ // expose the modules object (__webpack_modules__)
174
+ /******/ __webpack_require__.m = __webpack_modules__;
175
+ /******/
176
+ /******/ // the startup function
177
+ /******/ __webpack_require__.x = () => {
178
+ /******/ // Load entry module and return exports
179
+ /******/ // This entry module depends on other loaded chunks and execution need to be delayed
180
+ /******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["vendors-node_modules_d3_index_js-node_modules_file-saver_dist_FileSaver_min_js","vendors-node_modules_biojs-io-newick_src_index_js-node_modules_minhashjs_index_js-node_module-7b40e5","src_utils_js"], () => (__webpack_require__("./src/worker_bcn.js")))
181
+ /******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__);
182
+ /******/ return __webpack_exports__;
183
+ /******/ };
184
+ /******/
185
+ /************************************************************************/
186
+ /******/ /* webpack/runtime/chunk loaded */
187
+ /******/ (() => {
188
+ /******/ var deferred = [];
189
+ /******/ __webpack_require__.O = (result, chunkIds, fn, priority) => {
190
+ /******/ if(chunkIds) {
191
+ /******/ priority = priority || 0;
192
+ /******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
193
+ /******/ deferred[i] = [chunkIds, fn, priority];
194
+ /******/ return;
195
+ /******/ }
196
+ /******/ var notFulfilled = Infinity;
197
+ /******/ for (var i = 0; i < deferred.length; i++) {
198
+ /******/ var [chunkIds, fn, priority] = deferred[i];
199
+ /******/ var fulfilled = true;
200
+ /******/ for (var j = 0; j < chunkIds.length; j++) {
201
+ /******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
202
+ /******/ chunkIds.splice(j--, 1);
203
+ /******/ } else {
204
+ /******/ fulfilled = false;
205
+ /******/ if(priority < notFulfilled) notFulfilled = priority;
206
+ /******/ }
207
+ /******/ }
208
+ /******/ if(fulfilled) {
209
+ /******/ deferred.splice(i--, 1)
210
+ /******/ var r = fn();
211
+ /******/ if (r !== undefined) result = r;
212
+ /******/ }
213
+ /******/ }
214
+ /******/ return result;
215
+ /******/ };
216
+ /******/ })();
217
+ /******/
218
+ /******/ /* webpack/runtime/define property getters */
219
+ /******/ (() => {
220
+ /******/ // define getter functions for harmony exports
221
+ /******/ __webpack_require__.d = (exports, definition) => {
222
+ /******/ for(var key in definition) {
223
+ /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
224
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
225
+ /******/ }
226
+ /******/ }
227
+ /******/ };
228
+ /******/ })();
229
+ /******/
230
+ /******/ /* webpack/runtime/ensure chunk */
231
+ /******/ (() => {
232
+ /******/ __webpack_require__.f = {};
233
+ /******/ // This file contains only the entry chunk.
234
+ /******/ // The chunk loading function for additional chunks
235
+ /******/ __webpack_require__.e = (chunkId) => {
236
+ /******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
237
+ /******/ __webpack_require__.f[key](chunkId, promises);
238
+ /******/ return promises;
239
+ /******/ }, []));
240
+ /******/ };
241
+ /******/ })();
242
+ /******/
243
+ /******/ /* webpack/runtime/get javascript chunk filename */
244
+ /******/ (() => {
245
+ /******/ // This function allow to reference async chunks and sibling chunks for the entrypoint
246
+ /******/ __webpack_require__.u = (chunkId) => {
247
+ /******/ // return url for filenames based on template
248
+ /******/ return "" + chunkId + ".phylo.js";
249
+ /******/ };
250
+ /******/ })();
251
+ /******/
252
+ /******/ /* webpack/runtime/global */
253
+ /******/ (() => {
254
+ /******/ __webpack_require__.g = (function() {
255
+ /******/ if (typeof globalThis === 'object') return globalThis;
256
+ /******/ try {
257
+ /******/ return this || new Function('return this')();
258
+ /******/ } catch (e) {
259
+ /******/ if (typeof window === 'object') return window;
260
+ /******/ }
261
+ /******/ })();
262
+ /******/ })();
263
+ /******/
264
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
265
+ /******/ (() => {
266
+ /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
267
+ /******/ })();
268
+ /******/
269
+ /******/ /* webpack/runtime/make namespace object */
270
+ /******/ (() => {
271
+ /******/ // define __esModule on exports
272
+ /******/ __webpack_require__.r = (exports) => {
273
+ /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
274
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
275
+ /******/ }
276
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
277
+ /******/ };
278
+ /******/ })();
279
+ /******/
280
+ /******/ /* webpack/runtime/node module decorator */
281
+ /******/ (() => {
282
+ /******/ __webpack_require__.nmd = (module) => {
283
+ /******/ module.paths = [];
284
+ /******/ if (!module.children) module.children = [];
285
+ /******/ return module;
286
+ /******/ };
287
+ /******/ })();
288
+ /******/
289
+ /******/ /* webpack/runtime/publicPath */
290
+ /******/ (() => {
291
+ /******/ __webpack_require__.p = "";
292
+ /******/ })();
293
+ /******/
294
+ /******/ /* webpack/runtime/importScripts chunk loading */
295
+ /******/ (() => {
296
+ /******/ // no baseURI
297
+ /******/
298
+ /******/ // object to store loaded chunks
299
+ /******/ // "1" means "already loaded"
300
+ /******/ var installedChunks = {
301
+ /******/ "src_worker_bcn_js": 1
302
+ /******/ };
303
+ /******/
304
+ /******/ // importScripts chunk loading
305
+ /******/ var installChunk = (data) => {
306
+ /******/ var [chunkIds, moreModules, runtime] = data;
307
+ /******/ for(var moduleId in moreModules) {
308
+ /******/ if(__webpack_require__.o(moreModules, moduleId)) {
309
+ /******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
310
+ /******/ }
311
+ /******/ }
312
+ /******/ if(runtime) runtime(__webpack_require__);
313
+ /******/ while(chunkIds.length)
314
+ /******/ installedChunks[chunkIds.pop()] = 1;
315
+ /******/ parentChunkLoadingFunction(data);
316
+ /******/ };
317
+ /******/ __webpack_require__.f.i = (chunkId, promises) => {
318
+ /******/ // "1" is the signal for "already loaded"
319
+ /******/ if(!installedChunks[chunkId]) {
320
+ /******/ if(true) { // all chunks have JS
321
+ /******/ importScripts(__webpack_require__.p + __webpack_require__.u(chunkId));
322
+ /******/ }
323
+ /******/ }
324
+ /******/ };
325
+ /******/
326
+ /******/ var chunkLoadingGlobal = self["webpackChunkPhyloIO"] = self["webpackChunkPhyloIO"] || [];
327
+ /******/ var parentChunkLoadingFunction = chunkLoadingGlobal.push.bind(chunkLoadingGlobal);
328
+ /******/ chunkLoadingGlobal.push = installChunk;
329
+ /******/
330
+ /******/ // no HMR
331
+ /******/
332
+ /******/ // no HMR manifest
333
+ /******/ })();
334
+ /******/
335
+ /******/ /* webpack/runtime/startup chunk dependencies */
336
+ /******/ (() => {
337
+ /******/ var next = __webpack_require__.x;
338
+ /******/ __webpack_require__.x = () => {
339
+ /******/ return Promise.all(["vendors-node_modules_d3_index_js-node_modules_file-saver_dist_FileSaver_min_js","vendors-node_modules_biojs-io-newick_src_index_js-node_modules_minhashjs_index_js-node_module-7b40e5","src_utils_js"].map(__webpack_require__.e, __webpack_require__)).then(next);
340
+ /******/ };
341
+ /******/ })();
342
+ /******/
343
+ /************************************************************************/
344
+ /******/
345
+ /******/ // run startup
346
+ /******/ var __webpack_exports__ = __webpack_require__.x();
347
+ /******/ module.exports.PhyloIO = __webpack_exports__;
348
+ /******/
349
+ /******/ })()
350
+ ;