clustergrammer
Version:
This is a clustergram implemented in D3.js. I started from the example http://bost.ocks.org/mike/miserables/ and added the following features
1,656 lines (1,382 loc) • 960 kB
JavaScript
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
var make_config = __webpack_require__(1);
var make_params = __webpack_require__(9);
var make_viz = __webpack_require__(89);
var resize_viz = __webpack_require__(152);
var play_demo = __webpack_require__(229);
var ini_demo = __webpack_require__(247);
var filter_viz_using_nodes = __webpack_require__(250);
var filter_viz_using_names = __webpack_require__(251);
var update_cats = __webpack_require__(252);
var reset_cats = __webpack_require__(253);
var two_translate_zoom = __webpack_require__(144);
var update_view = __webpack_require__(202);
var save_matrix = __webpack_require__(255);
var brush_crop_matrix = __webpack_require__(259);
var run_zoom = __webpack_require__(153);
var d3_tip_custom = __webpack_require__(100);
var all_reorder = __webpack_require__(143);
var make_matrix_string = __webpack_require__(257);
// moved d3.slider to src
d3.slider = __webpack_require__(261);
/* eslint-disable */
var awesomplete = __webpack_require__(263);
// getting css from src
__webpack_require__(265);
__webpack_require__(269);
/* clustergrammer v1.19.5
* Nicolas Fernandez, Ma'ayan Lab, Icahn School of Medicine at Mount Sinai
* (c) 2017
*/
function Clustergrammer(args) {
/* Main program
* ----------------------------------------------------------------------- */
// consume and validate user input
// build giant config object
// visualize based on config object
// handle user events
// consume and validate user arguments, produce configuration object
var config = make_config(args);
var cgm = {};
// make visualization parameters using configuration object
cgm.params = make_params(config);
cgm.config = config;
// set up zoom
cgm.params.zoom_behavior = d3.behavior.zoom().scaleExtent([1, cgm.params.viz.square_zoom * cgm.params.viz.zoom_ratio.x]).on('zoom', function () {
run_zoom(cgm);
});
cgm.params.zoom_behavior.translate([cgm.params.viz.clust.margin.left, cgm.params.viz.clust.margin.top]);
if (cgm.params.use_sidebar) {
var make_sidebar = __webpack_require__(271);
make_sidebar(cgm);
}
// make visualization using parameters
make_viz(cgm);
function external_resize() {
d3.select(cgm.params.viz.viz_svg).style('opacity', 0.5);
var wait_time = 500;
if (this.params.viz.run_trans === true) {
wait_time = 2500;
}
setTimeout(resize_fun, wait_time, this);
}
function resize_fun(cgm) {
resize_viz(cgm);
}
function run_update_cats(cat_data) {
update_cats(this, cat_data);
}
function zoom_api(pan_dx, pan_dy, fin_zoom) {
two_translate_zoom(this, pan_dx, pan_dy, fin_zoom);
}
function expose_d3_tip_custom() {
// this allows external modules to have access to d3_tip
return d3_tip_custom;
}
function api_reorder(inst_rc, inst_order) {
if (inst_order === 'sum') {
inst_order = 'rank';
}
if (inst_order === 'var') {
inst_order = 'rankvar';
}
all_reorder(this, inst_order, inst_rc);
}
function export_matrix_string() {
return make_matrix_string(this.params);
}
function external_update_view(filter_type, inst_state) {
update_view(this, filter_type, inst_state);
}
// add more API endpoints
cgm.update_view = update_view;
cgm.resize_viz = external_resize;
cgm.play_demo = play_demo;
cgm.ini_demo = ini_demo;
cgm.filter_viz_using_nodes = filter_viz_using_nodes;
cgm.filter_viz_using_names = filter_viz_using_names;
cgm.update_cats = run_update_cats;
cgm.reset_cats = reset_cats;
cgm.zoom = zoom_api;
cgm.save_matrix = save_matrix;
cgm.brush_crop_matrix = brush_crop_matrix;
cgm.d3_tip_custom = expose_d3_tip_custom;
cgm.reorder = api_reorder;
cgm.export_matrix_string = export_matrix_string;
cgm.update_view = external_update_view;
return cgm;
}
module.exports = Clustergrammer;
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
var utils = __webpack_require__(2);
var transpose_network = __webpack_require__(3);
var get_available_filters = __webpack_require__(4);
var get_filter_default_state = __webpack_require__(5);
var set_defaults = __webpack_require__(6);
var check_sim_mat = __webpack_require__(7);
var check_nodes_for_categories = __webpack_require__(8);
module.exports = function make_config(args) {
var defaults = set_defaults();
// Mixin defaults with user-defined arguments.
var config = utils.extend(defaults, args);
config.network_data = args.network_data;
var super_string = ': ';
// replace undersores with space in row/col names
_.each(['row', 'col'], function (inst_rc) {
var inst_nodes = config.network_data[inst_rc + '_nodes'];
var has_cats = check_nodes_for_categories(inst_nodes);
inst_nodes.forEach(function (d, i) {
// add index to row_nodes and col_nodes
d[inst_rc + '_index'] = i;
if (has_cats) {
config.super_labels = true;
config.super[inst_rc] = d.name.split(super_string)[0];
d.name = d.name.split(super_string)[1];
}
d.name = String(d.name);
d.name = d.name.replace(/_/g, ' ');
});
});
config.network_data.row_nodes_names = utils.pluck(config.network_data.row_nodes, 'name');
config.network_data.col_nodes_names = utils.pluck(config.network_data.col_nodes, 'name');
config.sim_mat = check_sim_mat(config);
var filters = get_available_filters(config.network_data.views);
var default_states = {};
_.each(_.keys(filters.possible_filters), function (inst_filter) {
var tmp_state = get_filter_default_state(filters.filter_data, inst_filter);
default_states[inst_filter] = tmp_state;
});
// process view
if (_.has(config.network_data, 'views')) {
config.network_data.views.forEach(function (inst_view) {
_.each(_.keys(filters.possible_filters), function (inst_filter) {
if (!_.has(inst_view, inst_filter)) {
inst_view[inst_filter] = default_states[inst_filter];
}
});
var inst_nodes = inst_view.nodes;
// proc row/col nodes names in views
_.each(['row', 'col'], function (inst_rc) {
var has_cats = check_nodes_for_categories(inst_nodes[inst_rc + '_nodes']);
inst_nodes[inst_rc + '_nodes'].forEach(function (d, i) {
// add index to row_nodes and col_nodes
d[inst_rc + '_index'] = i;
if (has_cats) {
d.name = d.name.split(super_string)[1];
}
d.name = String(d.name);
d.name = d.name.replace(/_/g, ' ');
});
});
});
}
var col_nodes = config.network_data.col_nodes;
var row_nodes = config.network_data.row_nodes;
// console.log( config.network_data.links[0] )
// console.log( config.network_data.links[1] )
// console.log( config.network_data.links[2] )
// console.log(_.has(config.network_data,'mat'));
///////////////////////////
// convert 'mat' to links
///////////////////////////
if (_.has(config.network_data, 'mat')) {
var links = [];
var mat = config.network_data.mat;
var inst_link = {};
// console.log('found mat')
for (var i = 0; i < mat.length; i++) {
for (var j = 0; j < mat[0].length; j++) {
// console.log(mat[i][j])
inst_link = {};
inst_link.source = i;
inst_link.target = j;
inst_link.value = mat[i][j];
links.push(inst_link);
}
}
// save to network_data
config.network_data.links = links;
}
// add names and instantaneous positions to links
config.network_data.links.forEach(function (d) {
d.name = row_nodes[d.source].name + '_' + col_nodes[d.target].name;
d.row_name = row_nodes[d.source].name;
d.col_name = col_nodes[d.target].name;
});
// transpose network if necessary
if (config.transpose) {
config.network_data = transpose_network(config.network_data);
var tmp_col_label = args.col_label;
var tmp_row_label = args.row_label;
args.row_label = tmp_col_label;
args.col_label = tmp_row_label;
}
// super-row/col labels
if (!utils.is_undefined(args.row_label) && !utils.is_undefined(args.col_label)) {
config.super_labels = true;
config.super = {};
config.super.row = args.row_label;
config.super.col = args.col_label;
}
// initialize cluster ordering - both rows and columns
config.inst_order = {};
if (!utils.is_undefined(args.order) && utils.is_supported_order(args.order)) {
config.inst_order.row = args.order;
config.inst_order.col = args.order;
} else {
config.inst_order.row = 'clust';
config.inst_order.col = 'clust';
}
// set row or column order directly -- note that row/col are swapped
// !! need to swap row/col orderings
if (!utils.is_undefined(args.row_order) && utils.is_supported_order(args.row_order)) {
// !! row and col orderings are swapped, need to fix
config.inst_order.col = args.row_order;
}
if (!utils.is_undefined(args.col_order) && utils.is_supported_order(args.col_order)) {
// !! row and col orderings are swapped, need to fix
config.inst_order.row = args.col_order;
}
var row_has_group = utils.has(config.network_data.row_nodes[0], 'group');
var col_has_group = utils.has(config.network_data.col_nodes[0], 'group');
config.show_dendrogram = row_has_group || col_has_group;
if (utils.has(config.network_data.links[0], 'value_orig')) {
config.keep_orig = true;
} else {
config.keep_orig = false;
}
return config;
};
/***/ }),
/* 2 */
/***/ (function(module, exports) {
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
/* Utility functions
* ----------------------------------------------------------------------- */
module.exports = {
normal_name: function normal_name(d) {
var inst_name = d.name.replace(/_/g, ' ').split('#')[0];
return inst_name;
},
is_supported_order: function is_supported_order(order) {
return order === 'ini' || order === 'clust' || order === 'rank_var' || order === 'rank' || order === 'class' || order == 'alpha';
},
/* Returns whether or not an object has a certain property.
*/
has: function has(obj, key) {
return obj != null && hasOwnProperty.call(obj, key);
},
property: function property(key) {
return function (obj) {
return obj == null ? void 0 : obj[key];
};
},
// Convenience version of a common use case of `map`: fetching a property.
pluck: function pluck(arr, key) {
var self = this;
// Double check that we have lodash or underscore available
if (window._) {
// Underscore provides a _.pluck function. Use that.
if (typeof _.pluck === 'function') {
return _.pluck(arr, key);
} else if (typeof _.map === 'function') {
// Lodash does not have a pluck function.
// Use _.map with the property function defined above.
return _.map(arr, self.property(key));
}
} else if (arr.map && typeof arr.map === 'function') {
// If lodash or underscore not available, check to see if the native arr.map is available.
// If so, use it with the property function defined above.
return arr.map(self.property(key));
}
},
/* Returns true if the object is undefined.
*/
is_undefined: function is_undefined(obj) {
return obj === void 0;
},
/* Mixes two objects in together, overwriting a target with a source.
*/
extend: function extend(target, source) {
target = target || {};
for (var prop in source) {
if (_typeof(source[prop]) === 'object') {
target[prop] = this.extend(target[prop], source[prop]);
} else {
target[prop] = source[prop];
}
}
return target;
}
};
/***/ }),
/* 3 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
var utils = __webpack_require__(2);
/* Transpose network.
*/
module.exports = function (net) {
var tnet = {},
inst_link,
i;
tnet.row_nodes = net.col_nodes;
tnet.col_nodes = net.row_nodes;
tnet.links = [];
for (i = 0; i < net.links.length; i++) {
inst_link = {};
inst_link.source = net.links[i].target;
inst_link.target = net.links[i].source;
inst_link.value = net.links[i].value;
// Optional highlight.
if (utils.has(net.links[i], 'highlight')) {
inst_link.highlight = net.links[i].highlight;
}
if (utils.has(net.links[i], 'value_up')) {
inst_link.value_up = net.links[i].value_up;
}
if (utils.has(net.links[i], 'value_dn')) {
inst_link.value_dn = net.links[i].value_dn;
}
if (utils.has(net.links[i], 'info')) {
inst_link.info = net.links[i].info;
}
tnet.links.push(inst_link);
}
return tnet;
};
/***/ }),
/* 4 */
/***/ (function(module, exports) {
'use strict';
module.exports = function get_available_filters(views) {
var possible_filters = {};
var filter_data = {};
_.each(views, function (inst_view) {
var inst_keys = _.keys(inst_view);
_.each(inst_keys, function (inst_key) {
if (inst_key != 'nodes') {
if (!_.has(filter_data, inst_key)) {
filter_data[inst_key] = [];
}
filter_data[inst_key].push(inst_view[inst_key]);
filter_data[inst_key] = _.uniq(filter_data[inst_key]);
}
});
});
var tmp_filters = _.keys(filter_data);
_.each(tmp_filters, function (inst_filter) {
var options = filter_data[inst_filter];
var num_options = options.length;
var filter_type = 'categorical';
_.each(options, function (inst_option) {
if (typeof inst_option === 'number') {
filter_type = 'numerical';
}
});
if (num_options > 1) {
possible_filters[inst_filter] = filter_type;
}
});
var filters = {};
filters.possible_filters = possible_filters;
filters.filter_data = filter_data;
return filters;
};
/***/ }),
/* 5 */
/***/ (function(module, exports) {
"use strict";
module.exports = function get_filter_default_state(filter_data, filter_type) {
var default_state = filter_data[filter_type].sort(function (a, b) {
return b - a;
})[0];
default_state = String(default_state);
return default_state;
};
/***/ }),
/* 6 */
/***/ (function(module, exports) {
'use strict';
module.exports = function set_defaults() {
var defaults = {
// Label options
row_label_scale: 1,
col_label_scale: 1,
super_labels: false,
super: {},
show_label_tooltips: true,
show_tile_tooltips: true,
// matrix options
transpose: false,
tile_colors: ['#FF0000', '#1C86EE'],
bar_colors: ['#FF0000', '#1C86EE'],
// value-cat colors
// cat_value_colors: ['#2F4F4F', '#8A2BE2'],
cat_value_colors: ['#2F4F4F', '#9370DB'],
outline_colors: ['orange', 'black'],
highlight_color: '#FFFF00',
tile_title: false,
// Default domain is set to 0: the domain will be set automatically
input_domain: 0,
opacity_scale: 'linear',
do_zoom: true,
is_zoom: 0,
is_slider_drag: false,
is_cropping: false,
background_color: '#FFFFFF',
super_border_color: '#F5F5F5',
outer_margins: {
top: 0,
bottom: 0,
left: 0,
right: 0
},
ini_expand: false,
grey_border_width: 2,
tile_click_hlight: false,
super_label_scale: 1,
make_tile_tooltip: function make_tile_tooltip(d) {
return d.info;
},
// initialize view, e.g. initialize with row filtering
ini_view: null,
// record of requested views
requested_view: null,
use_sidebar: true,
title: null,
about: null,
sidebar_width: 160,
sidebar_icons: true,
row_search_placeholder: 'Row',
buffer_width: 10,
show_sim_mat: false,
cat_colors: null,
resize: true,
clamp_opacity: 0.85,
expand_button: true,
max_allow_fs: 20,
dendro_filter: { 'row': false, 'col': false },
cat_filter: { 'row': false, 'col': false },
crop_filter_nodes: { 'row': false, 'col': false },
row_tip_callback: null,
col_tip_callback: null,
tile_tip_callback: null,
matrix_update_callback: null,
cat_update_callback: null,
dendro_callback: null,
dendro_click_callback: null,
new_row_cats: null,
make_modals: true,
show_viz_border: false
};
return defaults;
};
/***/ }),
/* 7 */
/***/ (function(module, exports) {
"use strict";
module.exports = function check_sim_mat(config) {
var sim_mat = false;
var num_rows = config.network_data.row_nodes_names.length;
var num_cols = config.network_data.col_nodes_names.length;
if (num_rows == num_cols) {
// the sort here was causing errors
var rows = config.network_data.row_nodes_names;
var cols = config.network_data.col_nodes_names;
sim_mat = true;
_.each(rows, function (inst_row) {
var inst_index = rows.indexOf(inst_row);
if (inst_row !== cols[inst_index]) {
sim_mat = false;
}
});
}
if (sim_mat) {
config.expand_button = false;
}
return sim_mat;
};
/***/ }),
/* 8 */
/***/ (function(module, exports) {
'use strict';
module.exports = function check_nodes_for_categories(nodes) {
var super_string = ': ';
var has_cat = true;
_.each(nodes, function (inst_node) {
var inst_name = String(inst_node.name);
if (inst_name.indexOf(super_string) < 0) {
has_cat = false;
}
});
return has_cat;
};
/***/ }),
/* 9 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
var make_network_using_view = __webpack_require__(10);
var ini_sidebar_params = __webpack_require__(64);
var make_requested_view = __webpack_require__(65);
var get_available_filters = __webpack_require__(4);
var calc_viz_params = __webpack_require__(66);
var ini_zoom_info = __webpack_require__(88);
/*
Params: calculates the size of all the visualization elements in the
clustergram.
*/
module.exports = function make_params(input_config) {
var config = $.extend(true, {}, input_config);
var params = config;
// keep a copy of inst_view
params.inst_nodes = {};
params.inst_nodes.row_nodes = params.network_data.row_nodes;
params.inst_nodes.col_nodes = params.network_data.col_nodes;
// when pre-loading the visualization using a view
if (params.ini_view !== null) {
var requested_view = params.ini_view;
var filters = get_available_filters(params.network_data.views);
params.viz = {};
params.viz.possible_filters = filters.possible_filters;
params.viz.filter_data = filters.filter_data;
requested_view = make_requested_view(params, requested_view);
params.network_data = make_network_using_view(config, params, requested_view);
// save ini_view as requested_view
params.requested_view = requested_view;
}
params = calc_viz_params(params);
if (params.use_sidebar) {
params.sidebar = ini_sidebar_params(params);
}
params.zoom_info = ini_zoom_info();
return params;
};
/***/ }),
/* 10 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
var filter_network_using_new_nodes = __webpack_require__(11);
var get_subset_views = __webpack_require__(63);
module.exports = function make_network_using_view(config, params, requested_view) {
var orig_views = config.network_data.views;
var is_enr = false;
if (_.has(orig_views[0], 'enr_score_type')) {
is_enr = true;
}
var sub_views = get_subset_views(params, orig_views, requested_view);
//////////////////////////////
// Enrichr specific rules
//////////////////////////////
if (is_enr && sub_views.length == 0) {
requested_view = { 'N_row_sum': 'all', 'N_col_sum': '10' };
sub_views = get_subset_views(params, orig_views, requested_view);
}
var inst_view = sub_views[0];
var new_network_data;
// get new_network_data or default back to old_network_data
if (typeof inst_view !== 'undefined') {
var new_nodes = inst_view.nodes;
new_network_data = filter_network_using_new_nodes(config, new_nodes);
} else {
new_network_data = config.network_data;
}
return new_network_data;
};
/***/ }),
/* 11 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
var utils = __webpack_require__(2);
var core = __webpack_require__(12);
var math = core.create();
math.import(__webpack_require__(25));
math.import(__webpack_require__(62));
module.exports = function filter_network_using_new_nodes(config, new_nodes) {
var links = config.network_data.links;
// // make new mat from links
// var new_mat = config.network_data.mat;
// get new names of rows and cols
var row_names = utils.pluck(new_nodes.row_nodes, 'name');
var col_names = utils.pluck(new_nodes.col_nodes, 'name');
var new_mat = math.matrix(math.zeros([new_nodes.row_nodes.length, new_nodes.col_nodes.length]));
new_mat = new_mat.toArray();
var new_links = _.filter(links, function (inst_link) {
var inst_row = inst_link.name.split('_')[0];
var inst_col = inst_link.name.split('_')[1];
var row_index = _.indexOf(row_names, inst_row);
var col_index = _.indexOf(col_names, inst_col);
// only keep links that have not been filtered out
if (row_index > -1 & col_index > -1) {
// redefine source and target
inst_link.source = row_index;
inst_link.target = col_index;
new_mat[row_index][col_index] = inst_link.value;
return inst_link;
}
});
// set up new_network_data
var new_network_data = {};
// rows
new_network_data.row_nodes = new_nodes.row_nodes;
new_network_data.row_nodes_names = row_names;
// cols
new_network_data.col_nodes = new_nodes.col_nodes;
new_network_data.col_nodes_names = col_names;
// save all links
new_network_data.links = new_links;
new_network_data.all_links = links;
// mat
new_network_data.mat = new_mat;
// add back all views
new_network_data.views = config.network_data.views;
// add cat_colors if necessary
if (_.has(config.network_data, 'cat_colors')) {
new_network_data.cat_colors = config.network_data.cat_colors;
}
return new_network_data;
};
/***/ }),
/* 12 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
module.exports = __webpack_require__(13);
/***/ }),
/* 13 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
var isFactory = __webpack_require__(14).isFactory;
var typedFactory = __webpack_require__(16);
var emitter = __webpack_require__(20);
var importFactory = __webpack_require__(22);
var configFactory = __webpack_require__(24);
/**
* Math.js core. Creates a new, empty math.js instance
* @param {Object} [options] Available options:
* {number} epsilon
* Minimum relative difference between two
* compared values, used by all comparison functions.
* {string} matrix
* A string 'Matrix' (default) or 'Array'.
* {string} number
* A string 'number' (default), 'BigNumber', or 'Fraction'
* {number} precision
* The number of significant digits for BigNumbers.
* Not applicable for Numbers.
* {boolean} predictable
* Predictable output type of functions. When true,
* output type depends only on the input types. When
* false (default), output type can vary depending
* on input values. For example `math.sqrt(-4)`
* returns `complex('2i')` when predictable is false, and
* returns `NaN` when true.
* {string} randomSeed
* Random seed for seeded pseudo random number generator.
* Set to null to randomly seed.
* @returns {Object} Returns a bare-bone math.js instance containing
* functions:
* - `import` to add new functions
* - `config` to change configuration
* - `on`, `off`, `once`, `emit` for events
*/
exports.create = function create(options) {
// simple test for ES5 support
if (typeof Object.create !== 'function') {
throw new Error('ES5 not supported by this JavaScript engine. ' + 'Please load the es5-shim and es5-sham library for compatibility.');
}
// cached factories and instances
var factories = [];
var instances = [];
// create a namespace for the mathjs instance, and attach emitter functions
var math = emitter.mixin({});
math.type = {};
math.expression = {
transform: {},
mathWithTransform: {}
};
// create a new typed instance
math.typed = typedFactory.create(math.type);
// create configuration options. These are private
var _config = {
// minimum relative difference between two compared values,
// used by all comparison functions
epsilon: 1e-12,
// type of default matrix output. Choose 'matrix' (default) or 'array'
matrix: 'Matrix',
// type of default number output. Choose 'number' (default) 'BigNumber', or 'Fraction
number: 'number',
// number of significant digits in BigNumbers
precision: 64,
// predictable output type of functions. When true, output type depends only
// on the input types. When false (default), output type can vary depending
// on input values. For example `math.sqrt(-4)` returns `complex('2i')` when
// predictable is false, and returns `NaN` when true.
predictable: false,
// random seed for seeded pseudo random number generation
// null = randomly seed
randomSeed: null
};
/**
* Load a function or data type from a factory.
* If the function or data type already exists, the existing instance is
* returned.
* @param {{type: string, name: string, factory: Function}} factory
* @returns {*}
*/
function load(factory) {
if (!isFactory(factory)) {
throw new Error('Factory object with properties `type`, `name`, and `factory` expected');
}
var index = factories.indexOf(factory);
var instance;
if (index === -1) {
// doesn't yet exist
if (factory.math === true) {
// pass with math namespace
instance = factory.factory(math.type, _config, load, math.typed, math);
} else {
instance = factory.factory(math.type, _config, load, math.typed);
}
// append to the cache
factories.push(factory);
instances.push(instance);
} else {
// already existing function, return the cached instance
instance = instances[index];
}
return instance;
}
// load the import and config functions
math['import'] = load(importFactory);
math['config'] = load(configFactory);
math.expression.mathWithTransform['config'] = math['config'];
// apply options
if (options) {
math.config(options);
}
return math;
};
/***/ }),
/* 14 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var isBigNumber = __webpack_require__(15);
/**
* Clone an object
*
* clone(x)
*
* Can clone any primitive type, array, and object.
* If x has a function clone, this function will be invoked to clone the object.
*
* @param {*} x
* @return {*} clone
*/
exports.clone = function clone(x) {
var type = typeof x === 'undefined' ? 'undefined' : _typeof(x);
// immutable primitive types
if (type === 'number' || type === 'string' || type === 'boolean' || x === null || x === undefined) {
return x;
}
// use clone function of the object when available
if (typeof x.clone === 'function') {
return x.clone();
}
// array
if (Array.isArray(x)) {
return x.map(function (value) {
return clone(value);
});
}
if (x instanceof Number) return new Number(x.valueOf());
if (x instanceof String) return new String(x.valueOf());
if (x instanceof Boolean) return new Boolean(x.valueOf());
if (x instanceof Date) return new Date(x.valueOf());
if (isBigNumber(x)) return x; // bignumbers are immutable
if (x instanceof RegExp) throw new TypeError('Cannot clone ' + x); // TODO: clone a RegExp
// object
return exports.map(x, clone);
};
/**
* Apply map to all properties of an object
* @param {Object} object
* @param {function} callback
* @return {Object} Returns a copy of the object with mapped properties
*/
exports.map = function (object, callback) {
var clone = {};
for (var key in object) {
if (exports.hasOwnProperty(object, key)) {
clone[key] = callback(object[key]);
}
}
return clone;
};
/**
* Extend object a with the properties of object b
* @param {Object} a
* @param {Object} b
* @return {Object} a
*/
exports.extend = function (a, b) {
for (var prop in b) {
if (exports.hasOwnProperty(b, prop)) {
a[prop] = b[prop];
}
}
return a;
};
/**
* Deep extend an object a with the properties of object b
* @param {Object} a
* @param {Object} b
* @returns {Object}
*/
exports.deepExtend = function deepExtend(a, b) {
// TODO: add support for Arrays to deepExtend
if (Array.isArray(b)) {
throw new TypeError('Arrays are not supported by deepExtend');
}
for (var prop in b) {
if (exports.hasOwnProperty(b, prop)) {
if (b[prop] && b[prop].constructor === Object) {
if (a[prop] === undefined) {
a[prop] = {};
}
if (a[prop].constructor === Object) {
deepExtend(a[prop], b[prop]);
} else {
a[prop] = b[prop];
}
} else if (Array.isArray(b[prop])) {
throw new TypeError('Arrays are not supported by deepExtend');
} else {
a[prop] = b[prop];
}
}
}
return a;
};
/**
* Deep test equality of all fields in two pairs of arrays or objects.
* @param {Array | Object} a
* @param {Array | Object} b
* @returns {boolean}
*/
exports.deepEqual = function deepEqual(a, b) {
var prop, i, len;
if (Array.isArray(a)) {
if (!Array.isArray(b)) {
return false;
}
if (a.length != b.length) {
return false;
}
for (i = 0, len = a.length; i < len; i++) {
if (!exports.deepEqual(a[i], b[i])) {
return false;
}
}
return true;
} else if (a instanceof Object) {
if (Array.isArray(b) || !(b instanceof Object)) {
return false;
}
for (prop in a) {
//noinspection JSUnfilteredForInLoop
if (!exports.deepEqual(a[prop], b[prop])) {
return false;
}
}
for (prop in b) {
//noinspection JSUnfilteredForInLoop
if (!exports.deepEqual(a[prop], b[prop])) {
return false;
}
}
return true;
} else {
return (typeof a === 'undefined' ? 'undefined' : _typeof(a)) === (typeof b === 'undefined' ? 'undefined' : _typeof(b)) && a == b;
}
};
/**
* Test whether the current JavaScript engine supports Object.defineProperty
* @returns {boolean} returns true if supported
*/
exports.canDefineProperty = function () {
// test needed for broken IE8 implementation
try {
if (Object.defineProperty) {
Object.defineProperty({}, 'x', { get: function get() {} });
return true;
}
} catch (e) {}
return false;
};
/**
* Attach a lazy loading property to a constant.
* The given function `fn` is called once when the property is first requested.
* On older browsers (<IE8), the function will fall back to direct evaluation
* of the properties value.
* @param {Object} object Object where to add the property
* @param {string} prop Property name
* @param {Function} fn Function returning the property value. Called
* without arguments.
*/
exports.lazy = function (object, prop, fn) {
if (exports.canDefineProperty()) {
var _uninitialized = true;
var _value;
Object.defineProperty(object, prop, {
get: function get() {
if (_uninitialized) {
_value = fn();
_uninitialized = false;
}
return _value;
},
set: function set(value) {
_value = value;
_uninitialized = false;
},
configurable: true,
enumerable: true
});
} else {
// fall back to immediate evaluation
object[prop] = fn();
}
};
/**
* Traverse a path into an object.
* When a namespace is missing, it will be created
* @param {Object} object
* @param {string} path A dot separated string like 'name.space'
* @return {Object} Returns the object at the end of the path
*/
exports.traverse = function (object, path) {
var obj = object;
if (path) {
var names = path.split('.');
for (var i = 0; i < names.length; i++) {
var name = names[i];
if (!(name in obj)) {
obj[name] = {};
}
obj = obj[name];
}
}
return obj;
};
/**
* A safe hasOwnProperty
* @param {Object} object
* @param {string} property
*/
exports.hasOwnProperty = function (object, property) {
return object && Object.hasOwnProperty.call(object, property);
};
/**
* Test whether an object is a factory. a factory has fields:
*
* - factory: function (type: Object, config: Object, load: function, typed: function [, math: Object]) (required)
* - name: string (optional)
* - path: string A dot separated path (optional)
* - math: boolean If true (false by default), the math namespace is passed
* as fifth argument of the factory function
*
* @param {*} object
* @returns {boolean}
*/
exports.isFactory = function (object) {
return object && typeof object.factory === 'function';
};
/***/ }),
/* 15 */
/***/ (function(module, exports) {
"use strict";
/**
* Test whether a value is a BigNumber
* @param {*} x
* @return {boolean}
*/
module.exports = function isBigNumber(x) {
return x && x.constructor.prototype.isBigNumber || false;
};
/***/ }),
/* 16 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var typedFunction = __webpack_require__(17);
var digits = __webpack_require__(18).digits;
var isBigNumber = __webpack_require__(15);
var isMatrix = __webpack_require__(19);
// returns a new instance of typed-function
var _createTyped = function createTyped() {
// initially, return the original instance of typed-function
// consecutively, return a new instance from typed.create.
_createTyped = typedFunction.create;
return typedFunction;
};
/**
* Factory function for creating a new typed instance
* @param {Object} type Object with data types like Complex and BigNumber
* @returns {Function}
*/
exports.create = function create(type) {
// TODO: typed-function must be able to silently ignore signatures with unknown data types
// type checks for all known types
//
// note that:
//
// - check by duck-typing on a property like `isUnit`, instead of checking instanceof.
// instanceof cannot be used because that would not allow to pass data from
// one instance of math.js to another since each has it's own instance of Unit.
// - check the `isUnit` property via the constructor, so there will be no
// matches for "fake" instances like plain objects with a property `isUnit`.
// That is important for security reasons.
// - It must not be possible to override the type checks used internally,
// for security reasons, so these functions are not exposed in the expression
// parser.
type.isNumber = function (x) {
return typeof x === 'number';
};
type.isComplex = function (x) {
return type.Complex && x instanceof type.Complex || false;
};
type.isBigNumber = isBigNumber;
type.isFraction = function (x) {
return type.Fraction && x instanceof type.Fraction || false;
};
type.isUnit = function (x) {
return x && x.constructor.prototype.isUnit || false;
};
type.isString = function (x) {
return typeof x === 'string';
};
type.isArray = Array.isArray;
type.isMatrix = isMatrix;
type.isDenseMatrix = function (x) {
return x && x.isDenseMatrix && x.constructor.prototype.isMatrix || false;
};
type.isSparseMatrix = function (x) {
return x && x.isSparseMatrix && x.constructor.prototype.isMatrix || false;
};
type.isRange = function (x) {
return x && x.constructor.prototype.isRange || false;
};
type.isIndex = function (x) {
return x && x.constructor.prototype.isIndex || false;
};
type.isBoolean = function (x) {
return typeof x === 'boolean';
};
type.isResultSet = function (x) {
return x && x.constructor.prototype.isResultSet || false;
};
type.isHelp = function (x) {
return x && x.constructor.prototype.isHelp || false;
};
type.isFunction = function (x) {
return typeof x === 'function';
};
type.isDate = function (x) {
return x instanceof Date;
};
type.isRegExp = function (x) {
return x instanceof RegExp;
};
type.isObject = function (x) {
return (typeof x === 'undefined' ? 'undefined' : _typeof(x)) === 'object';
};
type.isNull = function (x) {
return x === null;
};
type.isUndefined = function (x) {
return x === undefined;
};
type.isAccessorNode = function (x) {
return x && x.isAccessorNode && x.constructor.prototype.isNode || false;
};
type.isArrayNode = function (x) {
return x && x.isArrayNode && x.constructor.prototype.isNode || false;
};
type.isAssignmentNode = function (x) {
return x && x.isAssignmentNode && x.constructor.prototype.isNode || false;
};
type.isBlockNode = function (x) {
return x && x.isBlockNode && x.constructor.prototype.isNode || false;
};
type.isConditionalNode = function (x) {
return x && x.isConditionalNode && x.constructor.prototype.isNode || false;
};
type.isConstantNode = function (x) {
return x && x.isConstantNode && x.constructor.prototype.isNode || false;
};
type.isFunctionAssignmentNode = function (x) {
return x && x.isFunctionAssignmentNode && x.constructor.prototype.isNode || false;
};
type.isFunctionNode = function (x) {
return x && x.isFunctionNode && x.constructor.prototype.isNode || false;
};
type.isIndexNode = function (x) {
return x && x.isIndexNode && x.constructor.prototype.isNode || false;
};
type.isNode = function (x) {
return x && x.isNode && x.constructor.prototype.isNode || false;
};
type.isObjectNode = function (x) {
return x && x.isObjectNode && x.constructor.prototype.isNode || false;
};
type.isOperatorNode = function (x) {
return x && x.isOperatorNode && x.constructor.prototype.isNode || false;
};
type.isParenthesisNode = function (x) {
return x && x.isParenthesisNode && x.constructor.prototype.isNode || false;
};
type.isRangeNode = function (x) {
return x && x.isRangeNode && x.constructor.prototype.isNode || false;
};
type.isSymbolNode = function (x) {
return x && x.isSymbolNode && x.constructor.prototype.isNode || false;
};
type.isChain = function (x) {
return x && x.constructor.prototype.isChain || false;
};
// get a new instance of typed-function
var typed = _createTyped();
// define all types. The order of the types determines in which order function
// arguments are type-checked (so for performance it's important to put the
// most used types first).
typed.types = [{ name: 'number', test: type.isNumber }, { name: 'Complex', test: type.isComplex }, { name: 'BigNumber', test: type.isBigNumber }, { name: 'Fraction', test: type.isFraction }, { name: 'Unit', test: type.isUnit }, { name: 'string', test: type.isString }, { name: 'Array', test: type.isArray }, { name: 'Matrix', test: type.isMatrix }, { name: 'DenseMatrix', test: type.isDenseMatrix }, { name: 'SparseMatrix', test: type.isSparseMatrix }, { name: 'Range', test: type.isRange }, { name: 'Index', test: type.isIndex }, { name: 'boolean', test: type.isBoolean }, { name: 'ResultSet', test: type.isResultSet }, { name: 'Help', test: type.isHelp }, { name: 'function', test: type.isFunction }, { name: 'Date', test: type.isDate }, { name: 'RegExp', test: type.isRegExp }, { name: 'Object', test: type.isObject }, { name: 'null', test: type.isNull }, { name: 'undefined', test: type.isUndefined }, { name: 'OperatorNode', test: type.isOperatorNode }, { name: 'ConstantNode', test: type.isConstantNode }, { name: 'SymbolNode', test: type.isSymbolNode }, { name: 'ParenthesisNode', test: type.isParenthesisNode }, { name: 'FunctionNode', test: type.isFunctionNode }, { name: 'FunctionAssignmentNode', test: type.isFunctionAssignmentNode }, { name: 'ArrayNode', test: type.isArrayNode }, { name: 'AssignmentNode', test: type.isAssignmentNode }, { name: 'BlockNode', test: type.isBlockNode }, { name: 'ConditionalNode', test: type.isConditionalNode }, { name: 'IndexNode', test: type.isIndexNode }, { name: 'RangeNode', test: type.isRangeNode }, { name: 'Node', test: type.isNode }];
// TODO: add conversion from BigNumber to number?
typed.conversions = [{
from: 'number',
to: 'BigNumber',
convert: function convert(x) {
// note: conversion from number to BigNumber can fail if x has >15 digits
if (digits(x) > 15) {
throw new TypeError('Cannot implicitly convert a number with >15 significant digits to BigNumber ' + '(value: ' + x + '). ' + 'Use function bignumber(x) to convert to BigNumber.');
}
return new type.BigNumber(x);
}
}, {
from: 'number',
to: 'Complex',
convert: function convert(x) {
return new type.Complex(x, 0);
}
}, {
from: 'number',
to: 'string',
convert: function convert(x) {
return x + '';
}
}, {
from: 'BigNumber',
to: 'Complex',
convert: function convert(x) {
return new type.Complex(x.toNumber(), 0);
}
}, {
from: 'Fraction',
to: 'BigNumber',
convert: function convert(x) {
throw new TypeError('Cannot implicitly convert a Fraction to BigNumber or vice versa. ' + 'Use function bignumber(x) to convert to BigNumber or fraction(x) to convert to Fraction.');
}
}, {
from: 'Fraction',
to: 'Complex',
convert: function convert(x) {
return new type.Complex(x.valueOf(), 0);
}
}, {
from: 'number',
to: 'Fraction',
convert: function convert(x) {
var f = new type.Fraction(x);
if (f.valueOf() !== x) {
throw new TypeError('Cannot implicitly convert a number to a Fraction when there will be a loss of precision ' + '(value: ' + x + '). ' + 'Use function fraction(x) to convert to Fraction.');
}
return new type.Fraction(x);
}
}, {
// FIXME: add conversion from Fraction to number, for example for `sqrt(fraction(1,3))`
// from: 'Fraction',
// to: 'number',
// convert: function (x) {
// return x.valueOf();
// }
//}, {
from: 'string',
to: 'number',
convert: function convert(x) {
var n = Number(x);
if (isNaN(n)) {
throw new Error('Cannot convert "' + x + '" to a number');
}
return n;
}
}, {
from: 'string',
to: 'BigNumber',
convert: function convert(x) {
try {
return new type.BigNumber(x);
} catch (err) {
throw new Error('Cannot convert "' + x + '" to BigNumber');
}
}
}, {
from: 'string',
to: 'Fraction',
convert: function convert(x) {
try {
return new type.Fraction(x);
} catch (err) {
throw new Error('Cannot convert "' + x + '" to Fraction');
}
}
}, {
from: 'string',
to: 'Complex',
convert: function convert(x) {
try {
return new type.Complex(x);
} catch (err) {
throw new Error('Cannot convert "' + x + '" to Complex');
}
}
}, {
from: 'boolean',
to: 'number',
convert: function convert(x) {
return +x;
}
}, {
from: 'boolean',
to: 'BigNumber',
convert: function convert(x) {
return new type.BigNumber(+x);
}
}, {
from: 'boolean',
to: 'Fraction',
convert: function convert(x) {
return new type.Fraction(+x);
}
}, {
from: 'boolean',
to: 'string',
convert: function convert(x) {
return +x;
}
}, {
from: 'null',
to: 'number',
convert: function convert() {
return 0;
}
}, {
from: 'null',
to: 'string',
convert: function convert() {
return 'null';
}
}, {
from: 'null',
to: 'BigNumber',
convert: function convert() {
return new type.BigNumber(0);
}
}, {
from: 'null',
to: 'Fraction',
convert: function convert() {
return new type.Fraction(0);
}
}, {
from: 'Array',
to: 'Matrix',
convert: function convert(array) {
// TODO: how to decide on the right type of matrix to create?
return new type.DenseMatrix(array);
}
}, {
from: 'Matrix',
to: 'Array',
convert: function convert(matrix) {
return matrix.valueOf();
}
}];
return typed;
};
/***/ }),
/* 17 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/**
* typed-function
*
* Type checking for JavaScript functions
*
* https://github.com/josdejong/typed-function
*/
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
(function (root, factory) {
if (true) {
// AMD. Register as an anonymous module.
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object') {
// OldNode. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like OldNode.
module.exports = factory();
} else {
// Browser globals (root is window)
root.typed = factory();
}
})(undefined, function () {
// factory function to create a new instance of typed-function
// TODO: allow passing configuration, type