Mercurial > repos > azomics > clustergrammer_flow
diff js/clustergrammerIPG.js @ 0:fee56ee2f7ac draft
"planemo upload for repository https://github.com/ImmPortDB/immport-galaxy-tools/tree/master/flowtools/clustergrammer_flow commit b11dfcf10d287c1da91ffb1d5d0148c7f8f61356"
author | azomics |
---|---|
date | Fri, 31 Jul 2020 19:06:45 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/clustergrammerIPG.js Fri Jul 31 19:06:45 2020 -0400 @@ -0,0 +1,20775 @@ +var Clustergrammer = +/******/ (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__) { + + var make_config = __webpack_require__(1); + var make_params = __webpack_require__(9); + var make_viz = __webpack_require__(37); + var resize_viz = __webpack_require__(124); + var play_demo = __webpack_require__(165); + var ini_demo = __webpack_require__(205); + var filter_viz_using_nodes = __webpack_require__(208); + var filter_viz_using_names = __webpack_require__(209); + var update_cats = __webpack_require__(210); + var reset_cats = __webpack_require__(211); + var two_translate_zoom = __webpack_require__(116); + var external_update_view = __webpack_require__(213); + var save_matrix = __webpack_require__(216); + var brush_crop_matrix = __webpack_require__(220); + var run_zoom = __webpack_require__(125); + var d3_tip_custom = __webpack_require__(48); + var all_reorder = __webpack_require__(115); + var make_matrix_string = __webpack_require__(218); + + // moved d3.slider to src + d3.slider = __webpack_require__(222); + + /* eslint-disable */ + + var awesomplete = __webpack_require__(224); + // getting css from src + __webpack_require__(225); + __webpack_require__(229); + + /* clustergrammer v1.19.2 + * 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__(231); + 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); + } + + // add more API endpoints + cgm.update_view = external_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; + + return cgm; + } + + module.exports = Clustergrammer; + +/***/ }, +/* 1 */ +/***/ function(module, exports, __webpack_require__) { + + 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) { + + + /* Utility functions + * ----------------------------------------------------------------------- */ + module.exports = { + normal_name: function (d) { + var inst_name = d.name.replace(/_/g, ' ').split('#')[0]; + return inst_name; + }, + is_supported_order: function (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 (obj, key) { + return obj != null && hasOwnProperty.call(obj, key); + }, + + property: function (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 (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 (obj) { + return obj === void 0; + }, + + /* Mixes two objects in together, overwriting a target with a source. + */ + extend: function (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__) { + + 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) { + + 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) { + + 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) { + + 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 (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) { + + 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) { + + 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__) { + + var make_network_using_view = __webpack_require__(10); + var ini_sidebar_params = __webpack_require__(13); + var make_requested_view = __webpack_require__(14); + var get_available_filters = __webpack_require__(4); + var calc_viz_params = __webpack_require__(15); + var ini_zoom_info = __webpack_require__(36); + + /* + 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__) { + + var filter_network_using_new_nodes = __webpack_require__(11); + var get_subset_views = __webpack_require__(12); + + 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__) { + + var utils = __webpack_require__(2); + + module.exports = function filter_network_using_new_nodes(config, new_nodes) { + + var links = config.network_data.links; + + // 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_links = _.filter(links, function (d) { + var inst_row = d.name.split('_')[0]; + var inst_col = d.name.split('_')[1]; + + var row_index = _.indexOf(row_names, inst_row); + var col_index = _.indexOf(col_names, inst_col); + + if (row_index > -1 & col_index > -1) { + // redefine source and target + d.source = row_index; + d.target = col_index; + return d; + } + }); + + // 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; + // links + new_network_data.links = new_links; + // save all links + new_network_data.all_links = links; + // 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__) { + + var utils = __webpack_require__(2); + var get_filter_default_state = __webpack_require__(5); + + module.exports = function get_subset_views(params, views, requested_view) { + + var inst_value; + var found_filter; + + var request_filters = _.keys(requested_view); + + // find a view that matches all of the requested view/filter-attributes + _.each(request_filters, function (inst_filter) { + + inst_value = requested_view[inst_filter]; + + // if the value is a number, then convert it to an integer + if (/[^a-z_]/i.test(inst_value)) { + inst_value = parseInt(inst_value, 10); + } + + // only run filtering if any of the views has the filter + found_filter = false; + _.each(views, function (tmp_view) { + if (utils.has(tmp_view, inst_filter)) { + found_filter = true; + } + }); + + if (found_filter) { + views = _.filter(views, function (d) { + return d[inst_filter] == inst_value; + }); + } + }); + + // remove duplicate complete default states + var export_views = []; + var found_default = false; + var check_default; + var inst_default_state; + + // check if each view is a default state: all filters are at default + // there can only be one of these + _.each(views, function (inst_view) { + + check_default = true; + + // check each filter in a view to see if it is in the default state + _.each(_.keys(params.viz.possible_filters), function (inst_filter) { + + inst_default_state = get_filter_default_state(params.viz.filter_data, inst_filter); + + if (inst_view[inst_filter] != inst_default_state) { + check_default = false; + } + }); + + // found defaule view, only append if you have not already found a default + if (check_default) { + if (found_default === false) { + found_default = true; + export_views.push(inst_view); + } + } else { + export_views.push(inst_view); + } + }); + + // if (export_views.length > 1){ + // console.log('found more than one view in get_subset_views') + // console.log(requested_view) + // console.log(export_views) + // } else { + // console.log('found single view in get_subset_views') + // console.log(requested_view) + // console.log(export_views[0]) + // console.log('\n') + // } + + return export_views; + }; + +/***/ }, +/* 13 */ +/***/ function(module, exports) { + + module.exports = function ini_sidebar_params(params) { + var sidebar = {}; + + sidebar.wrapper = {}; + // sidebar.wrapper.width = 170; + + sidebar.row_search = {}; + sidebar.row_search.box = {}; + sidebar.row_search.box.height = 34; + sidebar.row_search.box.width = 95; + sidebar.row_search.placeholder = params.row_search_placeholder; + sidebar.row_search.margin_left = 7; + + sidebar.slider = {}; + sidebar.slider.width = params.sidebar_width - 30; + sidebar.slider.margin_left = 15; + + sidebar.key_cat = {}; + sidebar.key_cat.width = params.sidebar_width - 15; + sidebar.key_cat.margin_left = 5; + sidebar.key_cat.max_height = 100; + + sidebar.title = params.title; + sidebar.title_margin_left = 7; + sidebar.about = params.about; + sidebar.width = params.sidebar_width; + + sidebar.buttons = {}; + sidebar.buttons.width = params.sidebar_width - 15; + + sidebar.text = {}; + + sidebar.icons = params.sidebar_icons; + sidebar.icon_margin_left = -5; + + return sidebar; + }; + +/***/ }, +/* 14 */ +/***/ function(module, exports) { + + module.exports = function make_view_request(params, requested_view) { + + // this will add all necessary information to a view request + // it will grab necessary view information from the sliders + + // only one component will be changed at a time + var changed_component = _.keys(requested_view)[0]; + + // add additional filter information from othe possible filters + _.each(_.keys(params.viz.possible_filters), function (inst_filter) { + + if (inst_filter != changed_component) { + + if (!d3.select(params.root + ' .slider_' + inst_filter).empty()) { + + var inst_state = d3.select(params.root + ' .slider_' + inst_filter).attr('current_state'); + + requested_view[inst_filter] = inst_state; + } + } + }); + + return requested_view; + }; + +/***/ }, +/* 15 */ +/***/ function(module, exports, __webpack_require__) { + + var ini_label_params = __webpack_require__(16); + var set_viz_wrapper_size = __webpack_require__(17); + var get_svg_dim = __webpack_require__(19); + var calc_label_params = __webpack_require__(20); + var calc_clust_width = __webpack_require__(21); + var calc_clust_height = __webpack_require__(22); + var calc_val_max = __webpack_require__(23); + var calc_matrix_params = __webpack_require__(24); + var set_zoom_params = __webpack_require__(29); + var calc_default_fs = __webpack_require__(31); + var utils = __webpack_require__(2); + var get_available_filters = __webpack_require__(4); + var make_cat_params = __webpack_require__(32); + + module.exports = function calc_viz_params(params, predefined_cat_colors = true) { + + params.labels = ini_label_params(params); + params.viz = ini_viz_params(params, predefined_cat_colors); + + set_viz_wrapper_size(params); + + params = get_svg_dim(params); + params.viz = calc_label_params(params.viz); + params.viz = calc_clust_width(params.viz); + params.viz = calc_clust_height(params.viz); + + if (params.sim_mat) { + if (params.viz.clust.dim.width <= params.viz.clust.dim.height) { + params.viz.clust.dim.height = params.viz.clust.dim.width; + } else { + params.viz.clust.dim.width = params.viz.clust.dim.height; + } + } + + params = calc_val_max(params); + params = calc_matrix_params(params); + params = set_zoom_params(params); + params = calc_default_fs(params); + + function ini_viz_params(params, predefined_cat_colors = true) { + + var viz = {}; + + viz.root = params.root; + + viz.root_tips = params.root.replace('#', '.') + '_' + 'd3-tip'; + + viz.viz_wrapper = params.root + ' .viz_wrapper'; + viz.do_zoom = params.do_zoom; + viz.background_color = params.background_color; + viz.super_border_color = params.super_border_color; + viz.outer_margins = params.outer_margins; + viz.is_expand = params.ini_expand; + viz.grey_border_width = params.grey_border_width; + viz.show_dendrogram = params.show_dendrogram; + viz.tile_click_hlight = params.tile_click_hlight; + viz.inst_order = params.inst_order; + viz.expand_button = params.expand_button; + viz.sim_mat = params.sim_mat; + viz.dendro_filter = params.dendro_filter; + viz.cat_filter = params.cat_filter; + viz.cat_value_colors = params.cat_value_colors; + + viz.viz_svg = viz.viz_wrapper + ' .viz_svg'; + + viz.zoom_element = viz.viz_wrapper + ' .viz_svg'; + + viz.uni_duration = 1000; + // extra space below the clustergram (was 5) + // will increase this to accomidate dendro slider + viz.bottom_space = 10; + viz.run_trans = false; + viz.duration = 1000; + + viz.resize = params.resize; + if (utils.has(params, 'size')) { + viz.fixed_size = params.size; + } else { + viz.fixed_size = false; + } + + // width is 1 over this value + viz.border_fraction = 65; + viz.uni_margin = 5; + + viz.super_labels = {}; + viz.super_labels.margin = {}; + viz.super_labels.dim = {}; + viz.super_labels.margin.left = viz.grey_border_width; + viz.super_labels.margin.top = viz.grey_border_width; + viz.super_labels.dim.width = 0; + if (params.labels.super_labels) { + viz.super_labels.dim.width = 15 * params.labels.super_label_scale; + } + + viz.triangle_opacity = 0.6; + + viz.norm_labels = {}; + viz.norm_labels.width = {}; + + viz.dendro_room = {}; + if (viz.show_dendrogram) { + viz.dendro_room.symbol_width = 10; + } else { + viz.dendro_room.symbol_width = 0; + } + + viz.cat_colors = params.cat_colors; + + // console.log('ini_viz_params -> make_cat_params') + // console.log('predefined_cat_colors outside function ' + String(predefined_cat_colors)) + + viz = make_cat_params(params, viz, predefined_cat_colors); + + if (_.has(params, 'group_level') == false) { + if (viz.show_dendrogram) { + params.group_level = {}; + } + params.group_level.row = 5; + params.group_level.col = 5; + } + + viz.dendro_opacity = 0.35; + + viz.spillover_col_slant = viz.norm_labels.width.col; + + var filters = get_available_filters(params.network_data.views); + + viz.possible_filters = filters.possible_filters; + viz.filter_data = filters.filter_data; + + viz.viz_nodes = {}; + + // nodes that should be visible based on visible area + viz.viz_nodes.row = params.network_data.row_nodes_names; + viz.viz_nodes.col = params.network_data.col_nodes_names; + + // nodes that are currently visible + viz.viz_nodes.curr_row = params.network_data.row_nodes_names; + viz.viz_nodes.curr_col = params.network_data.col_nodes_names; + + // correct panning in x direction + viz.x_offset = 0; + + return viz; + } + + return params; + }; + +/***/ }, +/* 16 */ +/***/ function(module, exports) { + + module.exports = function ini_label_params(params) { + + var labels = {}; + labels.super_label_scale = params.super_label_scale; + labels.super_labels = params.super_labels; + labels.super_label_fs = 20; + + if (labels.super_labels) { + labels.super = {}; + labels.super.row = params.super.row; + labels.super.col = params.super.col; + } + + labels.show_label_tooltips = params.show_label_tooltips; + + labels.row_max_char = _.max(params.network_data.row_nodes, function (inst) { + return inst.name.length; + }).name.length; + + labels.col_max_char = _.max(params.network_data.col_nodes, function (inst) { + return inst.name.length; + }).name.length; + + labels.max_allow_fs = params.max_allow_fs; + + return labels; + }; + +/***/ }, +/* 17 */ +/***/ function(module, exports, __webpack_require__) { + + var calc_viz_dimensions = __webpack_require__(18); + + module.exports = function set_viz_wrapper_size(params) { + + // Create wrapper around SVG visualization + if (d3.select(params.root + ' .viz_wrapper').empty()) { + + d3.select(params.root).append('div').classed('sidebar_wrapper', true); + + d3.select(params.root).append('div').classed('viz_wrapper', true); + } + + var cont_dim = calc_viz_dimensions(params); + + d3.select(params.root + ' .sidebar_wrapper').style('float', 'left').style('width', params.sidebar_width + 'px').style('height', cont_dim.height + 'px').style('overflow', 'hidden'); + + d3.select(params.viz.viz_wrapper).style('float', 'left').style('width', cont_dim.width + 'px').style('height', cont_dim.height + 'px'); + }; + +/***/ }, +/* 18 */ +/***/ function(module, exports) { + + module.exports = function calc_viz_dimensions(params) { + + var cont_dim = {}; + var extra_space = params.buffer_width; + + // var screen_width = window.innerWidth; + // var screen_height = window.innerHeight; + + // // resize container, then resize visualization within container + // d3.select(params.root) + // .style('width', screen_width+'px') + // .style('height', screen_height+'px'); + + var container_width = d3.select(params.root).style('width').replace('px', ''); + var container_height = d3.select(params.root).style('height').replace('px', ''); + + // get outer_margins + var outer_margins; + if (params.viz.is_expand === false) { + outer_margins = params.viz.outer_margins; + cont_dim.width = container_width - params.sidebar_width - extra_space; + } else { + outer_margins = params.viz.outer_margins; + cont_dim.width = container_width - extra_space; + } + + cont_dim.top = outer_margins.top; + cont_dim.left = outer_margins.left; + + if (params.viz.resize) { + + cont_dim.height = container_height; + } else { + + if (params.viz.is_expand) { + cont_dim.width = params.viz.fixed_size.width; + } else { + cont_dim.width = params.viz.fixed_size.width - params.sidebar_width; + } + + cont_dim.height = params.viz.fixed_size.height; + } + + return cont_dim; + }; + +/***/ }, +/* 19 */ +/***/ function(module, exports) { + + module.exports = function get_svg_dim(params) { + + params.viz.svg_dim = {}; + params.viz.svg_dim.width = Number(d3.select(params.viz.viz_wrapper).style('width').replace('px', '')); + + params.viz.svg_dim.height = Number(d3.select(params.viz.viz_wrapper).style('height').replace('px', '')); + + return params; + }; + +/***/ }, +/* 20 */ +/***/ function(module, exports) { + + module.exports = function calc_label_params(viz) { + + viz.norm_labels.margin = {}; + + viz.norm_labels.margin.left = viz.super_labels.margin.left + viz.super_labels.dim.width; + + viz.norm_labels.margin.top = viz.super_labels.margin.top + viz.super_labels.dim.width; + + viz.label_background = {}; + + viz.label_background.row = viz.norm_labels.width.row + viz.cat_room.row + viz.uni_margin; + + viz.label_background.col = viz.norm_labels.width.col + viz.cat_room.col + viz.uni_margin; + + return viz; + }; + +/***/ }, +/* 21 */ +/***/ function(module, exports) { + + module.exports = function calc_clust_width(viz) { + + viz.clust = {}; + viz.clust.margin = {}; + + // margin on left/top of the clustergram/matrix + // 1) norm_label margin and width + // 2) cat_room and uni_margin + viz.clust.margin.left = viz.norm_labels.margin.left + viz.norm_labels.width.row + viz.cat_room.row + viz.uni_margin; + + viz.clust.margin.top = viz.norm_labels.margin.top + viz.norm_labels.width.col + viz.cat_room.col + viz.uni_margin; + + // the clustergram/matrix width is the svg width minus: + // the margin of the clustergram on the left + // the room for the spillover on the right + // ** the dendro will fit in the spillover room on the right + var ini_clust_width = viz.svg_dim.width - viz.clust.margin.left - viz.spillover_col_slant; + + // make tmp scale to calc height of triangle col labels + var tmp_x_scale = d3.scale.ordinal().rangeBands([0, ini_clust_width]).domain(_.range(viz.num_col_nodes)); + + var triangle_height = tmp_x_scale.rangeBand() / 2; + + // prevent the visualization from being unnecessarily wide + if (triangle_height > viz.norm_labels.width.col) { + var reduce_width = viz.norm_labels.width.col / triangle_height; + ini_clust_width = ini_clust_width * reduce_width; + } + + viz.clust.dim = {}; + viz.clust.dim.width = ini_clust_width; + + return viz; + }; + +/***/ }, +/* 22 */ +/***/ function(module, exports) { + + module.exports = function calc_clust_height(viz) { + + // the clustergram/matrix height is the svg width minus: + // the margin of the clustergram on the top + // the dendrogram + // the bottom_space + var ini_clust_height = viz.svg_dim.height - viz.clust.margin.top - viz.dendro_room.col - viz.bottom_space; + + viz.clust.dim.height = ini_clust_height; + + return viz; + }; + +/***/ }, +/* 23 */ +/***/ function(module, exports) { + + module.exports = function calc_val_max(params) { + + var val_max = Math.abs(_.max(params.network_data.col_nodes, function (d) { + return Math.abs(d.value); + }).value); + + params.labels.bar_scale_col = d3.scale.linear().domain([0, val_max]).range([0, 0.75 * params.viz.norm_labels.width.col]); + + val_max = Math.abs(_.max(params.network_data.row_nodes, function (d) { + return Math.abs(d.value); + }).value); + + params.labels.bar_scale_row = d3.scale.linear().domain([0, val_max]).range([0, params.viz.norm_labels.width.row]); + + return params; + }; + +/***/ }, +/* 24 */ +/***/ function(module, exports, __webpack_require__) { + + var ini_matrix_params = __webpack_require__(25); + var calc_downsampled_levels = __webpack_require__(27); + + module.exports = function calc_matrix_params(params) { + + params.matrix = ini_matrix_params(params); + + // X and Y scales: set domains and ranges + ////////////////////////////////////////////// + params.viz.x_scale = d3.scale.ordinal().rangeBands([0, params.viz.clust.dim.width]); + + params.viz.y_scale = d3.scale.ordinal().rangeBands([0, params.viz.clust.dim.height]); + + var inst_order; + + _.each(['row', 'col'], function (inst_rc) { + + inst_order = params.viz.inst_order[inst_rc]; + + if (inst_order === 'custom') { + inst_order = 'clust'; + } + + if (inst_rc === 'row') { + params.viz.x_scale.domain(params.matrix.orders[inst_order + '_' + inst_rc]); + } else { + params.viz.y_scale.domain(params.matrix.orders[inst_order + '_' + inst_rc]); + } + }); + + // border width + params.viz.border_width = {}; + params.viz.border_width.x = params.viz.x_scale.rangeBand() / params.viz.border_fraction; + params.viz.border_width.y = params.viz.y_scale.rangeBand() / params.viz.border_fraction; + + // rect width needs matrix and zoom parameters + params.viz.rect_width = params.viz.x_scale.rangeBand() - params.viz.border_width.x; + + // moved calculateion to calc_matrix_params + params.viz.rect_height = params.viz.y_scale.rangeBand() - params.viz.border_width.y; + + calc_downsampled_levels(params); + + return params; + }; + +/***/ }, +/* 25 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + var initialize_matrix = __webpack_require__(26); + + module.exports = function ini_matrix_params(params) { + + var matrix = {}; + + var network_data = params.network_data; + + matrix.tile_colors = params.tile_colors; + matrix.bar_colors = params.bar_colors; + matrix.outline_colors = params.outline_colors; + matrix.hlight_color = params.highlight_color; + matrix.tile_title = params.tile_title; + matrix.show_tile_tooltips = params.show_tile_tooltips; + matrix.make_tile_tooltip = params.make_tile_tooltip; + + // initialized clicked tile and rows + matrix.click_hlight_x = -666; + matrix.click_hlight_y = -666; + matrix.click_hlight_row = -666; + matrix.click_hlight_col = -666; + + // definition of a large matrix (num links) determines if transition is run + matrix.def_large_matrix = 10000; + matrix.opacity_function = params.opacity_scale; + + matrix.orders = {}; + + _.each(['row', 'col'], function (inst_rc) { + + // row ordering is based on col info and vice versa + var other_rc; + if (inst_rc === 'row') { + other_rc = 'col'; + } else { + other_rc = 'row'; + } + + // the nodes are defined using other_rc + var inst_nodes = network_data[other_rc + '_nodes']; + var num_nodes = inst_nodes.length; + + var nodes_names = utils.pluck(inst_nodes, 'name'); + var tmp = nodes_names.sort(); + + var alpha_index = _.map(tmp, function (d) { + return network_data[other_rc + '_nodes_names'].indexOf(d); + }); + + matrix.orders['alpha_' + inst_rc] = alpha_index; + + var possible_orders = ['clust', 'rank']; + + if (_.has(inst_nodes[0], 'rankvar')) { + possible_orders.push('rankvar'); + } + + if (params.viz.all_cats[other_rc].length > 0) { + _.each(params.viz.all_cats[other_rc], function (inst_cat) { + // the index of the category has replaced - with _ + inst_cat = inst_cat.replace('-', '_'); + possible_orders.push(inst_cat + '_index'); + }); + } + + _.each(possible_orders, function (inst_order) { + + var tmp_order_index = d3.range(num_nodes).sort(function (a, b) { + return inst_nodes[b][inst_order] - inst_nodes[a][inst_order]; + }); + + matrix.orders[inst_order + '_' + inst_rc] = tmp_order_index; + }); + }); + + if (utils.has(network_data, 'all_links')) { + matrix.max_link = _.max(network_data.all_links, function (d) { + return Math.abs(d.value); + }).value; + matrix.true_max=_.max(network_data.all_links, function (d) { + return d.value; + }).value; + matrix.true_min=_.min(network_data.all_links, function (d) { + return d.value; + }).value; + } else { + matrix.max_link = _.max(network_data.links, function (d) { + return Math.abs(d.value); + }).value; + matrix.true_max=_.max(network_data.links, function (d) { + return d.value; + }).value; + matrix.true_min=_.min(network_data.links, function (d) { + return d.value; + }).value; + } + matrix.mid_val = (matrix.true_max + matrix.true_min) / 2; + matrix.abs_max_val = Math.abs(matrix.max_link) * params.clamp_opacity; + + if (params.input_domain === 0) { + if (matrix.opacity_function === 'linear') { + matrix.opacity_scale = d3.scale.linear().domain([matrix.mid_val, matrix.true_max]).clamp(true).range([0.0, 1.0]); + } else if (matrix.opacity_function === 'log') { + matrix.opacity_scale = d3.scale.log().domain([0.001, matrix.abs_max_val]).clamp(true).range([0.0, 1.0]); + } + } else { + if (matrix.opacity_function === 'linear') { + matrix.opacity_scale = d3.scale.linear().domain([0, params.input_domain]).clamp(true).range([0.0, 1.0]); + } else if (matrix.opacity_function === 'log') { + matrix.opacity_scale = d3.scale.log().domain([0.001, params.input_domain]).clamp(true).range([0.0, 1.0]); + } + } + + var has_val_up = utils.has(network_data.links[0], 'value_up'); + var has_val_dn = utils.has(network_data.links[0], 'value_dn'); + + if (has_val_up || has_val_dn) { + matrix.tile_type = 'updn'; + } else { + matrix.tile_type = 'simple'; + } + + if (utils.has(network_data.links[0], 'highlight')) { + matrix.highlight = 1; + } else { + matrix.highlight = 0; + } + + matrix.matrix = initialize_matrix(network_data); + + matrix.wait_tooltip = 0; + + return matrix; + }; + +/***/ }, +/* 26 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + + module.exports = function (network_data) { + var matrix = []; + var ini_object; + + var keep_orig; + if (utils.has(network_data.links[0], 'value_orig')) { + keep_orig = true; + } else { + keep_orig = false; + } + + network_data.row_nodes.forEach(function (tmp, row_index) { + + matrix[row_index] = {}; + matrix[row_index].name = network_data.row_nodes[row_index].name; + matrix[row_index].row_index = row_index; + + matrix[row_index].row_data = d3.range(network_data.col_nodes.length).map(function (col_index) { + + if (utils.has(network_data.links[0], 'value_up') || utils.has(network_data.links[0], 'value_dn')) { + + ini_object = { + pos_x: col_index, + pos_y: row_index, + value: 0, + value_up: 0, + value_dn: 0, + highlight: 0 + }; + } else { + + ini_object = { + pos_x: col_index, + pos_y: row_index, + value: 0, + highlight: 0 + }; + } + + if (keep_orig) { + ini_object.value_orig = 0; + } + + return ini_object; + }); + }); + + network_data.links.forEach(function (link) { + + // transfer additional link information is necessary + matrix[link.source].row_data[link.target].value = link.value; + matrix[link.source].row_data[link.target].row_name = link.row_name; + matrix[link.source].row_data[link.target].col_name = link.col_name; + + if (utils.has(link, 'value_up') || utils.has(link, 'value_dn')) { + matrix[link.source].row_data[link.target].value_up = link.value_up; + matrix[link.source].row_data[link.target].value_dn = link.value_dn; + } + + if (keep_orig) { + matrix[link.source].row_data[link.target].value_orig = link.value_orig; + } + + if (link.highlight) { + matrix[link.source].row_data[link.target].highlight = link.highlight; + } + if (link.info) { + matrix[link.source].row_data[link.target].info = link.info; + } + }); + + return matrix; + }; + +/***/ }, +/* 27 */ +/***/ function(module, exports, __webpack_require__) { + + var calc_downsampled_matrix = __webpack_require__(28); + + module.exports = function calc_downsampled_levels(params) { + + // console.log('---- before ---------') + // console.log(params.matrix.matrix[0].row_data[0].value) + + // height of downsampled rectangles + var ds_height = 3; + + var min_rect_height = 2; + + var total_zoom = ds_height / params.viz.rect_height; + + // amount of zooming that is tolerated for the downsampled rows + var inst_zt = 2; + params.viz.ds_zt = inst_zt; + + var num_levels = Math.floor(Math.log(total_zoom) / Math.log(inst_zt)); + + if (params.viz.rect_height < min_rect_height && num_levels > 0) { + + // increase ds opacity, as more rows are compressed into a single downsampled + // row, increase the opacity of the downsampled row. Max increase will be 2x + // when 100 or more rows are compressed + var max_opacity_scale = 2; + params.viz.ds_opacity_scale = d3.scale.linear().domain([1, 100]).range([1, max_opacity_scale]).clamp(true); + + var ds; + + params.viz.ds_num_levels = num_levels; + + // array of downsampled parameters + params.viz.ds = []; + + // array of downsampled matrices at varying levels + params.matrix.ds_matrix = []; + + var inst_order = params.viz.inst_order.row; + + // cloning + var mat = $.extend(true, {}, params.matrix.matrix); + + // calculate parameters for different levels + for (var i = 0; i < num_levels; i++) { + + // instantaneous ds_level (-1 means no downsampling) + params.viz.ds_level = 0; + + ds = {}; + + ds.height = ds_height; + ds.num_levels = num_levels; + + var inst_zoom_tolerance = Math.pow(inst_zt, i); + + ds.zt = inst_zoom_tolerance; + + // the number of downsampled rows is given by the height of the clustergram + // divided by the adjusted height of the downsampled rect. + // the adjusted height is the height divided by the zooming tolerance of + // the downsampled layer + + // number of downsampled rows + ds.num_rows = Math.round(params.viz.clust.dim.height / (ds.height / inst_zoom_tolerance)); + + // x_scale + ///////////////////////// + ds.x_scale = d3.scale.ordinal().rangeBands([0, params.viz.clust.dim.width]); + + ds.x_scale.domain(params.matrix.orders[inst_order + '_row']); + + // y_scale + ///////////////////////// + ds.y_scale = d3.scale.ordinal().rangeBands([0, params.viz.clust.dim.height]); + ds.y_scale.domain(d3.range(ds.num_rows + 1)); + + ds.rect_height = ds.y_scale.rangeBand() - params.viz.border_width.y; + + params.viz.ds.push(ds); + + var matrix = calc_downsampled_matrix(params, mat, i); + params.matrix.ds_matrix.push(matrix); + } + + // reset row viz_nodes since downsampling + params.viz.viz_nodes.row = d3.range(params.matrix.ds_matrix[0].length).map(String); + } else { + // set ds to null if no downsampling is done + params.viz.ds = null; + // instantaneous ds_level (-1 means no downsampling) + params.viz.ds_level = -1; + params.viz.ds_num_levels = 0; + } + + // console.log('---- after ---------') + // console.log(params.matrix.matrix[0].row_data[0].value) + }; + +/***/ }, +/* 28 */ +/***/ function(module, exports) { + + module.exports = function calc_downsampled_matrix(params, mat, ds_level) { + + var inst_num_rows = params.viz.ds[ds_level].num_rows; + + var num_compressed_rows = params.network_data.row_nodes.length / inst_num_rows; + + // increase ds opacity, as more rows are compressed into a single downsampled + // row, increase the opacity of the downsampled row. + var opacity_factor = params.viz.ds_opacity_scale(num_compressed_rows); + + var mod_val = params.viz.clust.dim.height / inst_num_rows; + + var ds_mat = []; + var inst_obj; + + var len_ds_array = inst_num_rows + 1; + + var i; + var x; + + // initialize array of objects + for (i = 0; i < len_ds_array; i++) { + + inst_obj = {}; + inst_obj.row_index = i; + inst_obj.name = String(i); + inst_obj.all_names = []; + + ds_mat.push(inst_obj); + } + + _.each(mat, function (inst_row) { + + // row ordering information is contained in y_scale + var inst_y = params.viz.y_scale(inst_row.row_index); + + var ds_index = Math.round(inst_y / mod_val); + + var inst_row_data = inst_row.row_data; + + // gather names + ds_mat[ds_index].all_names.push(inst_row.name); + + // gather row_data + if (_.has(ds_mat[ds_index], 'row_data')) { + + for (x = 0; x < inst_row_data.length; x++) { + ds_mat[ds_index].row_data[x].value = ds_mat[ds_index].row_data[x].value + inst_row_data[x].value; + } + } else { + + var new_data = []; + for (x = 0; x < inst_row_data.length; x++) { + new_data[x] = inst_row_data[x]; + } + + ds_mat[ds_index].row_data = new_data; + } + }); + + // average the values + _.each(ds_mat, function (tmp_ds) { + + var tmp_row_data = tmp_ds.row_data; + + var num_names = tmp_ds.all_names.length; + + _.each(tmp_row_data, function (tmp_obj) { + tmp_obj.value = tmp_obj.value / num_names * opacity_factor; + }); + }); + + // all names were found + var all_names = []; + + _.each(ds_mat, function (inst_row) { + all_names = all_names.concat(inst_row.all_names); + }); + + return ds_mat; + }; + +/***/ }, +/* 29 */ +/***/ function(module, exports, __webpack_require__) { + + var calc_zoom_switching = __webpack_require__(30); + + module.exports = function set_zoom_params(params) { + + params.viz.zoom_scale_font = {}; + params.viz.zoom_scale_font.row = 1; + params.viz.zoom_scale_font.col = 1; + + var max_zoom_limit = 0.75; + var half_col_height = params.viz.x_scale.rangeBand() / 2; + params.viz.square_zoom = params.viz.norm_labels.width.col / half_col_height * max_zoom_limit; + + params.viz = calc_zoom_switching(params.viz); + + return params; + }; + +/***/ }, +/* 30 */ +/***/ function(module, exports) { + + module.exports = function calc_zoom_switching(viz) { + + var width_by_col = viz.clust.dim.width / viz.num_col_nodes; + var height_by_row = viz.clust.dim.height / viz.num_row_nodes; + + viz.zoom_ratio = {}; + viz.zoom_ratio.x = width_by_col / height_by_row; + viz.zoom_ratio.y = 1; + + if (viz.zoom_ratio.x < 1) { + viz.zoom_ratio.y = 1 / viz.zoom_ratio.x; + viz.zoom_ratio.x = 1; + } + + return viz; + }; + +/***/ }, +/* 31 */ +/***/ function(module, exports) { + + module.exports = function calc_default_fs(params) { + + params.labels.default_fs_row = params.viz.y_scale.rangeBand() * 1.01; + params.labels.default_fs_col = params.viz.x_scale.rangeBand() * 0.87; + + if (params.labels.default_fs_row > params.labels.max_allow_fs) { + params.labels.default_fs_row = params.labels.max_allow_fs; + } + + if (params.labels.default_fs_col > params.labels.max_allow_fs) { + params.labels.default_fs_col = params.labels.max_allow_fs; + } + + return params; + }; + +/***/ }, +/* 32 */ +/***/ function(module, exports, __webpack_require__) { + + var calc_cat_params = __webpack_require__(33); + var utils = __webpack_require__(2); + var colors = __webpack_require__(34); + var check_if_value_cats = __webpack_require__(35); + + module.exports = function make_cat_params(params, viz, predefined_cat_colors = true) { + + var super_string = ': '; + var tmp_super; + var inst_info; + var inst_color; + + viz.show_categories = {}; + viz.all_cats = {}; + viz.cat_names = {}; + viz.cat_info = {}; + + // this will hold the information for calculating the opacity of the value + // function + var ini_val_opacity = {}; + ini_val_opacity.row = null; + ini_val_opacity.col = null; + + viz.cat_colors = {}; + viz.cat_colors.value_opacity = ini_val_opacity; + + var num_colors = 0; + _.each(['row', 'col'], function (inst_rc) { + + viz.show_categories[inst_rc] = false; + + viz.all_cats[inst_rc] = []; + var tmp_keys = _.keys(params.network_data[inst_rc + '_nodes'][0]); + + tmp_keys = tmp_keys.sort(); + + _.each(tmp_keys, function (d) { + if (d.indexOf('cat-') >= 0) { + viz.show_categories[inst_rc] = true; + viz.all_cats[inst_rc].push(d); + } + }); + + viz.cat_info[inst_rc] = null; + + if (viz.show_categories[inst_rc]) { + + viz.cat_colors[inst_rc] = {}; + viz.cat_info[inst_rc] = {}; + viz.cat_names[inst_rc] = {}; + + _.each(viz.all_cats[inst_rc], function (cat_title) { + + var inst_node = params.network_data[inst_rc + '_nodes'][0]; + + // look for title of category in category name + if (typeof inst_node[cat_title] === 'string') { + + if (inst_node[cat_title].indexOf(super_string) > 0) { + tmp_super = inst_node[cat_title].split(super_string)[0]; + viz.cat_names[inst_rc][cat_title] = tmp_super; + } else { + viz.cat_names[inst_rc][cat_title] = cat_title; + } + } else { + viz.cat_names[inst_rc][cat_title] = cat_title; + } + + var cat_instances_titles = utils.pluck(params.network_data[inst_rc + '_nodes'], cat_title); + var cat_instances = []; + + _.each(cat_instances_titles, function (inst_cat) { + + var new_cat; + if (inst_cat.indexOf(': ') > 0) { + new_cat = inst_cat.split(': ')[1]; + } else { + new_cat = inst_cat; + } + + cat_instances.push(new_cat); + }); + + var cat_states = _.uniq(cat_instances_titles).sort(); + + // check whether all the categories are of value type + inst_info = check_if_value_cats(cat_states); + + // add histogram to inst_info + if (inst_info.type === 'cat_strings') { + // remove titles from categories in hist + var cat_hist = _.countBy(cat_instances); + inst_info.cat_hist = cat_hist; + } else { + inst_info.cat_hist = null; + } + + // pass info_info object + viz.cat_info[inst_rc][cat_title] = inst_info; + + viz.cat_colors[inst_rc][cat_title] = {}; + + _.each(cat_states, function (cat_tmp, inst_index) { + + inst_color = colors.get_random_color(inst_index + num_colors); + + viz.cat_colors[inst_rc][cat_title][cat_tmp] = inst_color; + + // hack to get 'Not' categories to not be dark colored + // also doing this for false + if (typeof cat_tmp === 'string') { + if (cat_tmp.indexOf('Not ') >= 0 || cat_tmp.indexOf(': false') > 0) { + viz.cat_colors[inst_rc][cat_title][cat_tmp] = '#eee'; + } + } + + num_colors = num_colors + 1; + }); + }); + } + + if (_.has(params.network_data, 'cat_colors') && predefined_cat_colors === true) { + viz.cat_colors[inst_rc] = params.network_data.cat_colors[inst_rc]; + } + + if (params.sim_mat) { + // sending row color info to columns since row color info can be updated + viz.cat_colors.col = viz.cat_colors.row; + } + }); + + viz.cat_colors = viz.cat_colors; + + viz.cat_colors.opacity = 0.6; + viz.cat_colors.active_opacity = 0.9; + + viz = calc_cat_params(params, viz); + + return viz; + }; + +/***/ }, +/* 33 */ +/***/ function(module, exports) { + + module.exports = function calc_cat_params(params, viz) { + + var separtion_room; + + // increase the width of the label container based on the label length + var label_scale = d3.scale.linear().domain([5, 15]).range([85, 120]).clamp('true'); + + viz.cat_room = {}; + viz.cat_room.symbol_width = 12; + viz.cat_room.separation = 3; + + _.each(['row', 'col'], function (inst_rc) { + + viz.norm_labels.width[inst_rc] = label_scale(params.labels[inst_rc + '_max_char']) * params[inst_rc + '_label_scale']; + + viz['num_' + inst_rc + '_nodes'] = params.network_data[inst_rc + '_nodes'].length; + + // if (_.has(config, 'group_level')){ + // config.group_level[inst_rc] = 5; + // } + + if (inst_rc === 'row') { + viz.dendro_room[inst_rc] = viz.dendro_room.symbol_width; + } else { + viz.dendro_room[inst_rc] = viz.dendro_room.symbol_width + 3 * viz.uni_margin; + } + + var num_cats = viz.all_cats[inst_rc].length; + + if (viz.show_categories[inst_rc]) { + + separtion_room = (num_cats - 1) * viz.cat_room.separation; + + var adjusted_cats; + if (inst_rc === 'row') { + adjusted_cats = num_cats + 1; + } else { + adjusted_cats = num_cats; + } + + viz.cat_room[inst_rc] = adjusted_cats * viz.cat_room.symbol_width + separtion_room; + } else { + // no categories + if (inst_rc == 'row') { + viz.cat_room[inst_rc] = viz.cat_room.symbol_width; + } else { + viz.cat_room[inst_rc] = 0; + } + } + }); + + return viz; + }; + +/***/ }, +/* 34 */ +/***/ function(module, exports) { + + // colors from http://graphicdesign.stackexchange.com/revisions/3815/8 + var all_colors; + + all_colors = ["#393b79", "#aec7e8", "#ff7f0e", "#ffbb78", "#98df8a", "#bcbd22", "#404040", "#ff9896", "#c5b0d5", "#8c564b", "#1f77b4", "#5254a3", "#FFDB58", "#c49c94", "#e377c2", "#7f7f7f", "#2ca02c", "#9467bd", "#dbdb8d", "#17becf", "#637939", "#6b6ecf", "#9c9ede", "#d62728", "#8ca252", "#8c6d31", "#bd9e39", "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#7b4173", "#a55194", "#ce6dbd", "#de9ed6"]; + + // too light colors + // "#e7969c", + // "#c7c7c7", + // "#f7b6d2", + // "#cedb9c", + // "#9edae5", + + function get_default_color() { + return '#EEE'; + } + + function get_random_color(i) { + return all_colors[i % get_num_colors()]; + } + + function get_num_colors() { + return all_colors.length; + } + + module.exports = { + get_default_color: get_default_color, + get_random_color: get_random_color, + get_num_colors: get_num_colors + }; + +/***/ }, +/* 35 */ +/***/ function(module, exports) { + + module.exports = function check_if_value_cats(cat_states) { + + var tmp_cat = cat_states[0]; + + var has_title = false; + var might_have_values = false; + var cat_types = 'cat_strings'; + var max_abs_val = NaN; + var all_values = []; + var cat_scale = null; + + var super_string = ': '; + + if (typeof tmp_cat === 'string') { + if (tmp_cat.indexOf(super_string) > -1) { + has_title = true; + tmp_cat = tmp_cat.split(super_string)[1]; + } + } + + if (isNaN(tmp_cat) == false) { + might_have_values = true; + } + + // check each value for number + if (might_have_values) { + + // the default state is that all are now values, check each one + cat_types = 'cat_values'; + + _.each(cat_states, function (inst_cat) { + + if (has_title) { + inst_cat = inst_cat.split(super_string)[1]; + } + + // checking whether inst_cat is 'not a number' + if (isNaN(inst_cat) === true) { + cat_types = 'cat_strings'; + } else { + inst_cat = parseFloat(inst_cat); + all_values.push(inst_cat); + } + }); + } + + if (cat_types === 'cat_values') { + + // get absolute value + var max_value = _.max(all_values, function (d) { + return Math.abs(d); + }); + + max_abs_val = Math.abs(max_value); + + cat_scale = d3.scale.linear().domain([0, max_abs_val]).range([0, 1]); + } + + var inst_info = {}; + inst_info.type = cat_types; + inst_info.max_abs_val = max_abs_val; + inst_info.cat_scale = cat_scale; + + return inst_info; + }; + +/***/ }, +/* 36 */ +/***/ function(module, exports) { + + module.exports = function ini_zoom_info() { + + var zoom_info = {}; + zoom_info.zoom_x = 1; + zoom_info.zoom_y = 1; + zoom_info.trans_x = 0; + zoom_info.trans_y = 0; + + return zoom_info; + }; + +/***/ }, +/* 37 */ +/***/ function(module, exports, __webpack_require__) { + + var generate_matrix = __webpack_require__(38); + var make_row_label_container = __webpack_require__(49); + var make_col_label_container = __webpack_require__(103); + var generate_super_labels = __webpack_require__(111); + var spillover = __webpack_require__(112); + var initialize_resizing = __webpack_require__(123); + var ini_doubleclick = __webpack_require__(133); + var make_col_cat = __webpack_require__(152); + var make_row_cat = __webpack_require__(158); + var trim_text = __webpack_require__(118); + var make_row_dendro = __webpack_require__(159); + var make_col_dendro = __webpack_require__(160); + var make_svg_dendro_sliders = __webpack_require__(161); + var make_row_dendro_spillover = __webpack_require__(164); + + module.exports = function make_viz(cgm) { + + var params = cgm.params; + + d3.select(params.viz.viz_wrapper + ' svg').remove(); + + var svg_group = d3.select(params.viz.viz_wrapper).append('svg').attr('class', 'viz_svg').attr('id', 'svg_' + params.root.replace('#', '')).attr('width', params.viz.svg_dim.width).attr('height', params.viz.svg_dim.height).attr('is_zoom', 0).attr('stopped_zoom', 1); + + svg_group.append('rect').attr('class', 'super_background').style('width', params.viz.svg_dim.width).style('height', params.viz.svg_dim.height).style('fill', 'white'); + + generate_matrix(params, svg_group); + + make_row_label_container(cgm); + + if (params.viz.show_dendrogram) { + make_row_dendro(cgm); + make_col_dendro(cgm); + } + + make_row_dendro_spillover(cgm); + + make_col_label_container(cgm); + + // initial trim text + if (params.viz.ds_level === -1) { + _.each(['row', 'col'], function (inst_rc) { + + var inst_fs = Number(d3.select('.' + inst_rc + '_label_group').select('text').style('font-size').replace('px', '')); + + var min_trim_fs = 8; + if (inst_fs > min_trim_fs) { + d3.selectAll(params.root + ' .' + inst_rc + '_label_group').each(function () { + trim_text(params, this, inst_rc); + }); + } + }); + } + + // make category colorbars + make_row_cat(cgm); + if (params.viz.show_categories.col) { + make_col_cat(cgm); + } + + spillover(cgm); + + if (params.labels.super_labels) { + generate_super_labels(params); + } + + // sliders should go above super labels + make_svg_dendro_sliders(cgm); + + function border_colors() { + var inst_color = params.viz.super_border_color; + if (params.viz.is_expand || params.show_viz_border == false) { + inst_color = 'white'; + } + return inst_color; + } + + // left border + d3.select(params.viz.viz_svg).append('rect').classed('left_border', true).classed('borders', true).attr('fill', border_colors).attr('width', params.viz.grey_border_width).attr('height', params.viz.svg_dim.height).attr('transform', 'translate(0,0)'); + + // right border + d3.select(params.viz.viz_svg).append('rect').classed('right_border', true).classed('borders', true).attr('fill', border_colors).attr('width', params.viz.grey_border_width).attr('height', params.viz.svg_dim.height).attr('transform', function () { + var inst_offset = params.viz.svg_dim.width - params.viz.grey_border_width; + return 'translate(' + inst_offset + ',0)'; + }); + + // top border + d3.select(params.viz.viz_svg).append('rect').classed('top_border', true).classed('borders', true).attr('fill', border_colors).attr('width', params.viz.svg_dim.width).attr('height', params.viz.grey_border_width).attr('transform', function () { + var inst_offset = 0; + return 'translate(' + inst_offset + ',0)'; + }); + + // bottom border + d3.select(params.viz.viz_svg).append('rect').classed('bottom_border', true).classed('borders', true).attr('fill', border_colors).attr('width', params.viz.svg_dim.width).attr('height', params.viz.grey_border_width).attr('transform', function () { + var inst_offset = params.viz.svg_dim.height - params.viz.grey_border_width; + return 'translate(0,' + inst_offset + ')'; + }); + + initialize_resizing(cgm); + + ini_doubleclick(cgm); + + if (params.viz.do_zoom) { + d3.select(params.viz.zoom_element).call(params.zoom_behavior); + } + + d3.select(params.viz.zoom_element).on('dblclick.zoom', null); + }; + +/***/ }, +/* 38 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + var draw_gridlines = __webpack_require__(39); + var add_click_hlight = __webpack_require__(40); + var make_matrix_rows = __webpack_require__(41); + + module.exports = function (params, svg_elem) { + var network_data = params.network_data; + + var matrix = []; + var clust_group; + + // append a group that will hold clust_group and position it once + clust_group = svg_elem.append('g').attr('class', 'clust_container').attr('transform', 'translate(' + params.viz.clust.margin.left + ',' + params.viz.clust.margin.top + ')').append('g').attr('class', 'clust_group').classed('clust_group', true); + + // clustergram background rect + clust_group.append('rect').classed('background', true).classed('grey_background', true).style('fill', '#eee').style('opacity', 0.25).attr('width', params.viz.clust.dim.width).attr('height', params.viz.clust.dim.height); + + // pass in params and the rows (row_nodes) that need to be made + // in this case all row nodes + // make_matrix_rows(params, params.matrix.matrix, params.network_data.row_nodes_names); + + // initialize at ds_level 0 + if (params.viz.ds === null) { + // do not use downsampled matrix + make_matrix_rows(params, params.matrix.matrix, 'all', params.viz.ds_level); + } else { + // use downsampled matrix + make_matrix_rows(params, params.matrix.ds_matrix[0], 'all', params.viz.ds_level); + } + + // add callback function to tile group - if one is supplied by the user + if (typeof params.click_tile === 'function') { + d3.selectAll(params.root + ' .tile').on('click', function (d) { + + // export row/col name and value from tile + var tile_info = {}; + tile_info.row = params.network_data.row_nodes[d.pos_y].name; + tile_info.col = params.network_data.col_nodes[d.pos_x].name; + tile_info.value = d.value; + + if (utils.has(d, 'value_up')) { + tile_info.value_up = d.value_up; + } + if (utils.has(d, 'value_dn')) { + tile_info.value_dn = d.value_dn; + } + if (utils.has(d, 'info')) { + tile_info.info = d.info; + } + // run the user supplied callback function + params.click_tile(tile_info); + add_click_hlight(params, this); + }); + } else { + + // highlight clicked tile + if (params.tile_click_hlight) { + d3.selectAll(params.root + ' .tile').on('click', function () { + add_click_hlight(params, this); + }); + } + } + + // draw grid lines after drawing tiles + var delays = {}; + var duration = 0; + delays.enter = 0; + draw_gridlines(params, delays, duration); + + // Matrix API + return { + get_clust_group: function () { + return clust_group; + }, + get_matrix: function () { + return matrix; + }, + get_nodes: function (type) { + if (type === 'row') { + return network_data.row_nodes; + } + return network_data.col_nodes; + } + }; + }; + +/***/ }, +/* 39 */ +/***/ function(module, exports) { + + // var grid_lines_viz = require('./grid_lines_viz'); + // var toggle_grid_lines = require('./toggle_grid_lines'); + + module.exports = function draw_gridlines(params, delays, duration) { + + // var row_nodes = params.network_data.row_nodes; + // var col_nodes = params.network_data.col_nodes; + + // // Fade in new gridlines + // /////////////////////////// + + // // append horizontal line groups + // var horz_lines = d3.select(params.root+' .clust_group') + // .selectAll('.horz_lines') + // .data(row_nodes, function(d){return d.name;}) + // .enter() + // .append('g') + // .attr('class','horz_lines'); + + // // append vertical line groups + // var vert_lines = d3.select(params.root+' .clust_group') + // .selectAll('.vert_lines') + // .data(col_nodes) + // .enter() + // .append('g') + // .attr('class', 'vert_lines'); + + // grid_lines_viz(params, duration); + + // horz_lines + // .select('line') + // .attr('opacity',0) + // .attr('stroke','white') + // .attr('opacity', 1); + + // vert_lines + // .select('line') + // .style('stroke', 'white') + // .attr('opacity',0) + // .transition().delay(delays.enter).duration(2*duration) + // .attr('opacity', 1); + + // toggle_grid_lines(params); + + }; + +/***/ }, +/* 40 */ +/***/ function(module, exports) { + + module.exports = function (params, clicked_rect) { + + // get x position of rectangle + d3.select(clicked_rect).each(function (d) { + var pos_x = d.pos_x; + var pos_y = d.pos_y; + + d3.selectAll(params.root + ' .click_hlight').remove(); + + if (pos_x != params.matrix.click_hlight_x || pos_y != params.matrix.click_hlight_y) { + + // save pos_x to params.viz.click_hlight_x + params.matrix.click_hlight_x = pos_x; + params.matrix.click_hlight_y = pos_y; + + // draw the highlighting rectangle as four rectangles + // so that the width and height can be controlled + // separately + + var rel_width_hlight = 6; + var opacity_hlight = 0.85; + + var hlight_width = rel_width_hlight * params.viz.border_width.x; + var hlight_height = rel_width_hlight * params.viz.border_width.y; + + // top highlight + d3.select(clicked_rect.parentNode).append('rect').classed('click_hlight', true).classed('top_hlight', true).attr('width', params.viz.x_scale.rangeBand()).attr('height', hlight_height).attr('fill', params.matrix.hlight_color).attr('transform', function () { + return 'translate(' + params.viz.x_scale(pos_x) + ',0)'; + }).attr('opacity', opacity_hlight); + + // left highlight + d3.select(clicked_rect.parentNode) + .append('rect') + .classed('click_hlight', true) + .classed('left_hlight', true) + .attr('width', hlight_width) + .attr('height', params.viz.y_scale.rangeBand() - hlight_height * 0.99) + .attr('fill', params.matrix.hlight_color).attr('transform', function () { + return "translate(" + params.viz.x_scale(pos_x) + "," + hlight_height * 0.99 + ")"; + }) + .attr('opacity', opacity_hlight); + + // right highlight + d3.select(clicked_rect.parentNode).append('rect').classed('click_hlight', true).classed('right_hlight', true).attr('width', hlight_width).attr('height', params.viz.y_scale.rangeBand() - hlight_height * 0.99).attr('fill', params.matrix.hlight_color).attr('transform', function () { + var tmp_translate = params.viz.x_scale(pos_x) + params.viz.x_scale.rangeBand() - hlight_width; + return 'translate(' + tmp_translate + ',' + hlight_height * 0.99 + ')'; + }).attr('opacity', opacity_hlight); + + // bottom highlight + d3.select(clicked_rect.parentNode).append('rect').classed('click_hlight', true).classed('bottom_hlight', true).attr('width', function () { + return params.viz.x_scale.rangeBand() - 1.98 * hlight_width; + }).attr('height', hlight_height).attr('fill', params.matrix.hlight_color).attr('transform', function () { + var tmp_translate_x = params.viz.x_scale(pos_x) + hlight_width * 0.99; + var tmp_translate_y = params.viz.y_scale.rangeBand() - hlight_height; + return 'translate(' + tmp_translate_x + ',' + tmp_translate_y + ')'; + }).attr('opacity', opacity_hlight); + } else { + params.matrix.click_hlight_x = -666; + params.matrix.click_hlight_y = -666; + } + }); + }; + +/***/ }, +/* 41 */ +/***/ function(module, exports, __webpack_require__) { + + var make_simple_rows = __webpack_require__(42); + var d3_tip_custom = __webpack_require__(48); + + // current matrix can change with downsampling + module.exports = function make_matrix_rows(params, current_matrix, row_names = 'all', ds_level = -1) { + + // defaults + var y_scale = params.viz.y_scale; + var make_tip = true; + var row_class = 'row'; + + if (ds_level >= 0) { + y_scale = params.viz.ds[ds_level].y_scale; + + // do not show tip when rows are downsampled + make_tip = false; + row_class = 'ds' + String(ds_level) + '_row'; + } + + if (make_tip) { + + // do not remove tile_tip here + ///////////////////////////////// + + // make rows in the matrix - add key names to rows in matrix + ///////////////////////////////////////////////////////////// + // d3-tooltip - for tiles + var tip = d3_tip_custom().attr('class', function () { + var root_tip_selector = params.viz.root_tips.replace('.', ''); + var class_string = root_tip_selector + ' d3-tip ' + root_tip_selector + '_tile_tip'; + return class_string; + }).style('display', 'none').direction('nw').offset([0, 0]).html(function (d) { + var inst_value = String(d.value.toFixed(3)); + var tooltip_string; + + if (params.keep_orig) { + var orig_value = String(d.value_orig.toFixed(3)); + tooltip_string = '<p>' + d.row_name + ' and ' + d.col_name + '</p>' + '<p> normalized value: ' + inst_value + '</p>' + '<div> original value: ' + orig_value + '</div>'; + } else { + tooltip_string = '<p>' + d.row_name + ' and ' + d.col_name + '</p>' + '<div> value: ' + inst_value + '</div>'; + } + + return tooltip_string; + }); + } else { + tip = null; + } + + // gather a subset of row data from the matrix or use all rows + var matrix_subset = []; + if (row_names === 'all') { + matrix_subset = current_matrix; + } else { + _.each(current_matrix, function (inst_row) { + if (_.contains(row_names, inst_row.name)) { + matrix_subset.push(inst_row); + } + }); + } + + d3.select(params.root + ' .clust_group').selectAll('.row').data(matrix_subset, function (d) { + return d.name; + }).enter().append('g').classed(row_class, true).attr('transform', function (d) { + return 'translate(0,' + y_scale(d.row_index) + ')'; + }).each(function (d) { + make_simple_rows(params, d, tip, this, ds_level); + }); + + if (params.viz.ds_level === -1 && tip != null) { + d3.selectAll(params.root + ' .row').call(tip); + } + }; + +/***/ }, +/* 42 */ +/***/ function(module, exports, __webpack_require__) { + + /* eslint-disable */ + + var draw_up_tile = __webpack_require__(43); + var draw_dn_tile = __webpack_require__(44); + var mouseover_tile = __webpack_require__(45); + var mouseout_tile = __webpack_require__(46); + var fine_position_tile = __webpack_require__(47); + + module.exports = function make_simple_rows(params, inst_data, tip, row_selection, ds_level = -1) { + + var inp_row_data = inst_data.row_data; + + var make_tip = true; + var rect_height = params.viz.rect_height; + if (ds_level >= 0) { + // make_tip = false; + rect_height = params.viz.ds[ds_level].rect_height; + } + + var keep_orig; + if (_.has(params.network_data.links[0], 'value_orig')) { + keep_orig = true; + } else { + keep_orig = false; + } + + var row_values; + if (keep_orig === false) { + // value: remove zero values to make visualization faster + row_values = _.filter(inp_row_data, function (num) { + return num.value !== 0; + }); + } else { + row_values = inp_row_data; + } + + // generate tiles in the current row + var tile = d3.select(row_selection).selectAll('rect').data(row_values, function (d) { + return d.col_name; + }).enter().append('rect').attr('class', 'tile row_tile').attr('width', params.viz.rect_width).attr('height', rect_height).style('fill', function (d) { + // switch the color based on up/dn value + var inst_fill; + if (d.value_orig === 'NaN') { + inst_fill = '#000000'; + } else { + inst_fill = d.value > params.matrix.mid_val ? params.matrix.tile_colors[0] : params.matrix.tile_colors[1]; + } + return inst_fill; + }).style('fill-opacity', function (d) { + // calculate output opacity using the opacity scale + var inst_opacity; + if (d.value_orig === 'NaN') { + // console.log('found NaN while making tiles'); + inst_opacity = 0.175; + } else { + var op_val = params.matrix.mid_val + Math.abs(d.value - params.matrix.mid_val); + + inst_opacity = params.matrix.opacity_scale(op_val); + } + return inst_opacity; + }).attr('transform', function (d) { + return fine_position_tile(params, d); + }); + + if (make_tip) { + tile.on('mouseover', function () { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + mouseover_tile(params, this, tip, args); + }).on('mouseout', function () { + mouseout_tile(params, this, tip); + }); + } + + // // tile circles + // ///////////////////////////// + // var tile = d3.select(row_selection) + // .selectAll('circle') + // .data(row_values, function(d){ return d.col_name; }) + // .enter() + // .append('circle') + // .attr('cx', params.viz.rect_height/2) + // .attr('cy', params.viz.rect_height/2) + // .attr('r', params.viz.rect_height/3) + // .attr('class', 'tile_circle') + // // .attr('width', params.viz.rect_width/2) + // // .attr('height', params.viz.rect_height/2) + // // // switch the color based on up/dn value + // // .style('fill', function(d) { + // // // return d.value > 0 ? params.matrix.tile_colors[0] : params.matrix.tile_colors[1]; + // // return 'black'; + // // }) + // .on('mouseover', function(...args) { + // mouseover_tile(params, this, tip, args); + // }) + // .on('mouseout', function() { + // mouseout_tile(params, this, tip); + // }) + // .style('fill-opacity', function(d) { + // // calculate output opacity using the opacity scale + // var output_opacity = params.matrix.opacity_scale(Math.abs(d.value)); + // if (output_opacity < 0.3){ + // output_opacity = 0; + // } else if (output_opacity < 0.6){ + // output_opacity = 0.35; + // } else { + // output_opacity = 1; + // } + // return output_opacity; + // // return 0.1; + // }) + // .attr('transform', function(d) { + // return fine_position_tile(params, d); + // }); + + + if (params.matrix.tile_type == 'updn') { + + // value split + var row_split_data = _.filter(inp_row_data, function (num) { + return num.value_up != 0 || num.value_dn != 0; + }); + + // tile_up + d3.select(row_selection).selectAll('.tile_up').data(row_split_data, function (d) { + return d.col_name; + }).enter().append('path').attr('class', 'tile_up').attr('d', function () { + return draw_up_tile(params); + }).attr('transform', function (d) { + fine_position_tile(params, d); + }).style('fill', function () { + return params.matrix.tile_colors[0]; + }).style('fill-opacity', function (d) { + var inst_opacity = 0; + if (Math.abs(d.value_dn) > 0) { + inst_opacity = params.matrix.opacity_scale(Math.abs(d.value_up)); + } + return inst_opacity; + }).on('mouseover', function (...args) { + mouseover_tile(params, this, tip, args); + }).on('mouseout', function () { + mouseout_tile(params, this, tip); + }); + + // tile_dn + d3.select(row_selection).selectAll('.tile_dn').data(row_split_data, function (d) { + return d.col_name; + }).enter().append('path').attr('class', 'tile_dn').attr('d', function () { + return draw_dn_tile(params); + }).attr('transform', function (d) { + fine_position_tile(params, d); + }).style('fill', function () { + return params.matrix.tile_colors[1]; + }).style('fill-opacity', function (d) { + var inst_opacity = 0; + if (Math.abs(d.value_up) > 0) { + inst_opacity = params.matrix.opacity_scale(Math.abs(d.value_dn)); + } + return inst_opacity; + }).on('mouseover', function (...args) { + mouseover_tile(params, this, tip, args); + }).on('mouseout', function () { + mouseout_tile(params, this, tip); + }); + + // remove rect when tile is split + tile.each(function (d) { + if (Math.abs(d.value_up) > 0 && Math.abs(d.value_dn) > 0) { + d3.select(this).remove(); + } + }); + } + + // append title to group + if (params.matrix.tile_title) { + tile.append('title').text(function (d) { + var inst_string = 'value: ' + d.value; + return inst_string; + }); + } + }; + +/***/ }, +/* 43 */ +/***/ function(module, exports) { + + module.exports = function draw_up_tile(params) { + + var start_x = 0; + var final_x = params.viz.x_scale.rangeBand() - params.viz.border_width.x; + var start_y = 0; + var final_y = params.viz.y_scale.rangeBand() - params.viz.border_width.y; + + var output_string = 'M' + start_x + ',' + start_y + ', L' + start_x + ', ' + final_y + ', L' + final_x + ',0 Z'; + + return output_string; + }; + +/***/ }, +/* 44 */ +/***/ function(module, exports) { + + module.exports = function draw_dn_tile(params) { + + var start_x = 0; + var final_x = params.viz.x_scale.rangeBand() - params.viz.border_width.x; + var start_y = params.viz.y_scale.rangeBand() - params.viz.border_width.y; + var final_y = params.viz.y_scale.rangeBand() - params.viz.border_width.y; + + var output_string = 'M' + start_x + ', ' + start_y + ' , L' + final_x + ', ' + final_y + ', L' + final_x + ',0 Z'; + + return output_string; + }; + +/***/ }, +/* 45 */ +/***/ function(module, exports) { + + module.exports = function mouseover_tile(params, inst_selection, tip, inst_arguments) { + + var inst_data = inst_arguments[0]; + var args = [].slice.call(inst_arguments); + var timeout; + var delay = 1000; + + d3.select(inst_selection).classed('hovering', true); + + _.each(['row', 'col'], function (inst_rc) { + + d3.selectAll(params.root + ' .' + inst_rc + '_label_group text').style('font-weight', function (d) { + var font_weight; + var inst_found = inst_data[inst_rc + '_name'].replace(/_/g, ' ') === d.name; + + if (inst_found) { + font_weight = 'bold'; + } else { + font_weight = 'normal'; + } + return font_weight; + }); + }); + + args.push(inst_selection); + clearTimeout(timeout); + timeout = setTimeout(check_if_hovering, delay, inst_selection); + + function check_if_hovering() { + + if (d3.select(inst_selection).classed('hovering')) { + + var inst_zoom = Number(d3.select(params.root + ' .viz_svg').attr('is_zoom')); + + if (inst_zoom === 0) { + + if (params.matrix.show_tile_tooltips && tip !== null) { + + d3.selectAll(params.viz.root_tips + '_tile_tip').style('display', 'block'); + + tip.show.apply(inst_selection, args); + + if (params.tile_tip_callback != null) { + var tile_info = args[0]; + params.tile_tip_callback(tile_info); + } + } + } + } + } + }; + +/***/ }, +/* 46 */ +/***/ function(module, exports) { + + module.exports = function mouseout_tile(params, inst_selection, tip) { + + d3.select(inst_selection).classed('hovering', false); + + d3.selectAll(params.viz.root_tips + '_tile_tip').style('display', 'none'); + + _.each(['row', 'col'], function (inst_rc) { + + d3.selectAll(params.root + ' .' + inst_rc + '_label_group text').style('font-weight', 'normal'); + }); + + if (tip != null) { + tip.hide(); + } + }; + +/***/ }, +/* 47 */ +/***/ function(module, exports) { + + module.exports = function fine_position_tile(params, d) { + + var offset_x; + + // prevent rows not in x_scale domain from causing errors + if (d.pos_x in params.viz.x_scale.domain()) { + offset_x = params.viz.x_scale(d.pos_x); + } else { + offset_x = 0; + } + + var x_pos = offset_x + 0.5 * params.viz.border_width.x; + var y_pos = 0.5 * params.viz.border_width.y; + return 'translate(' + x_pos + ',' + y_pos + ')'; + }; + +/***/ }, +/* 48 */ +/***/ function(module, exports) { + + module.exports = function d3_tip_custom() { + /* eslint-disable */ + // Copyright (c) 2013 Justin Palmer + // + // Tooltips for d3.js SVG visualizations + + // Public - contructs a new tooltip + // + // Returns a tip + // ****************** + // Nick Fernandez modified version 4-19-2016 + // improved multiple svg, scrolling+zooming support + // made syntax fixes + ////////////////////////////////////////////// + var direction = d3_tip_direction, + offset = d3_tip_offset, + html = d3_tip_html, + node = initNode(), + svg = null, + point = null, + target = null; + + function tip(vis) { + svg = getSVGNode(vis); + point = svg.createSVGPoint(); + document.body.appendChild(node); + } + + // Public - show the tooltip on the screen + // + // Returns a tip + tip.show = function () { + + var args = Array.prototype.slice.call(arguments); + if (args[args.length - 1] instanceof SVGElement) { + target = args.pop(); + } + + var content = html.apply(this, args); + var poffset = offset.apply(this, args); + var dir = direction.apply(this, args); + var nodel = d3.select(node); + var i = 0; + var coords; + + // add z-index to make sure tooltips appear on top + nodel.html(content).style({ opacity: 1, 'pointer-events': 'all' }).style('z-index', 99); + + while (i--) { + nodel.classed(directions[i], false); + } + coords = direction_callbacks.get(dir).apply(this); + nodel.classed(dir, true).style({ + top: coords.top + poffset[0] + 'px', + left: coords.left + poffset[1] + 'px' + }); + + // quick fix for fading tile tooltips + if (isFunction(this) === false) { + + var inst_class = d3.select(this).attr('class'); + + if (inst_class.indexOf('tile') >= 0) { + setTimeout(fade_tips, 5000, this); + } + } + + return tip; + }; + + // Public - hide the tooltip + // + // Returns a tip + tip.hide = function () { + + // // hide all d3-tip tooltips + // d3.selectAll('.d3-tip') + // .style('display', 'none'); + + var nodel = d3.select(node); + nodel.style({ opacity: 0, 'pointer-events': 'none' }); + return tip; + }; + + // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value. + // + // n - name of the attribute + // v - value of the attribute + // + // Returns tip or attribute value + tip.attr = function (n) { + if (arguments.length < 2 && typeof n === 'string') { + return d3.select(node).attr(n); + } else { + var args = Array.prototype.slice.call(arguments); + d3.selection.prototype.attr.apply(d3.select(node), args); + } + + return tip; + }; + + // Public: Proxy style calls to the d3 tip container. Sets or gets a style value. + // + // n - name of the property + // v - value of the property + // + // Returns tip or style property value + tip.style = function (n) { + if (arguments.length < 2 && typeof n === 'string') { + return d3.select(node).style(n); + } else { + var args = Array.prototype.slice.call(arguments); + d3.selection.prototype.style.apply(d3.select(node), args); + } + + return tip; + }; + + // Public: Set or get the direction of the tooltip + // + // v - One of n(north), s(south), e(east), or w(west), nw(northwest), + // sw(southwest), ne(northeast) or se(southeast) + // + // Returns tip or direction + tip.direction = function (v) { + if (!arguments.length) { + return direction; + } + direction = v == null ? v : d3.functor(v); + + return tip; + }; + + // Public: Sets or gets the offset of the tip + // + // v - Array of [x, y] offset + // + // Returns offset or + tip.offset = function (v) { + if (!arguments.length) { + return offset; + } + offset = v == null ? v : d3.functor(v); + + return tip; + }; + + // Public: sets or gets the html value of the tooltip + // + // v - String value of the tip + // + // Returns html value or tip + tip.html = function (v) { + if (!arguments.length) { + return html; + } + html = v == null ? v : d3.functor(v); + + return tip; + }; + + function d3_tip_direction() { + return 'n'; + } + function d3_tip_offset() { + return [0, 0]; + } + function d3_tip_html() { + return ' '; + } + + var direction_callbacks = d3.map({ + n: direction_n, + s: direction_s, + e: direction_e, + w: direction_w, + nw: direction_nw, + ne: direction_ne, + sw: direction_sw, + se: direction_se, + south_custom: direction_south_custom + }), + directions = direction_callbacks.keys(); + + function direction_south_custom() { + var bbox = getScreenBBox(); + + return { + top: bbox.s.y, + left: bbox.s.x + }; + } + + function direction_n() { + var bbox = getScreenBBox(); + return { + top: bbox.n.y - node.offsetHeight, + left: bbox.n.x - node.offsetWidth / 2 + }; + } + + function direction_s() { + var bbox = getScreenBBox(); + return { + top: bbox.s.y, + left: bbox.s.x - node.offsetWidth / 2 + }; + } + + function direction_e() { + var bbox = getScreenBBox(); + return { + top: bbox.e.y - node.offsetHeight / 2, + left: bbox.e.x + }; + } + + function direction_w() { + var bbox = getScreenBBox(); + return { + top: bbox.w.y - node.offsetHeight / 2, + left: bbox.w.x - node.offsetWidth + }; + } + + function direction_nw() { + var bbox = getScreenBBox(); + return { + top: bbox.nw.y - node.offsetHeight, + left: bbox.nw.x - node.offsetWidth + }; + } + + function direction_ne() { + var bbox = getScreenBBox(); + return { + top: bbox.ne.y - node.offsetHeight, + left: bbox.ne.x + }; + } + + function direction_sw() { + var bbox = getScreenBBox(); + return { + top: bbox.sw.y, + left: bbox.sw.x - node.offsetWidth + }; + } + + function direction_se() { + var bbox = getScreenBBox(); + return { + top: bbox.se.y, + left: bbox.e.x + }; + } + + function initNode() { + var node = d3.select(document.createElement('div')); + node.style({ + position: 'absolute', + opacity: 0, + pointerEvents: 'none', + boxSizing: 'border-box' + }); + + return node.node(); + } + + function getSVGNode(el) { + el = el.node(); + if (el.tagName.toLowerCase() == 'svg') { + return el; + } + + return el.ownerSVGElement; + } + + // Private - gets the screen coordinates of a shape + // + // Given a shape on the screen, will return an SVGPoint for the directions + // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest), + // sw(southwest). + // + // +-+-+ + // | | + // + + + // | | + // +-+-+ + // + // Returns an Object {n, s, e, w, nw, sw, ne, se} + function getScreenBBox() { + var targetel = target || d3.event.target; + var bbox = {}; + var matrix = targetel.getScreenCTM(); + var tbbox = targetel.getBBox(); + var width = tbbox.width; + var height = tbbox.height; + var x = tbbox.x; + var y = tbbox.y; + var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; + var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; + + // Nick - prevents bugs with scrolling and zooming on the same object + matrix.a = 1; + matrix.d = 1; + // changing order of adding scrolling, + // original ordering was causing problems with pre-translated or rotated + // elements. + matrix.e = matrix.e + scrollLeft; + matrix.f = matrix.f + scrollTop; + point.x = x; //+ scrollLeft + point.y = y; //+ scrollTop + + bbox.nw = point.matrixTransform(matrix); + point.x = point.x + width; + bbox.ne = point.matrixTransform(matrix); + point.y = point.y + height; + bbox.se = point.matrixTransform(matrix); + point.x = point.x - width; + bbox.sw = point.matrixTransform(matrix); + point.y = point.y - height / 2; + bbox.w = point.matrixTransform(matrix); + point.x = point.x + width; + bbox.e = point.matrixTransform(matrix); + point.x = point.x - width / 2; + point.y = point.y - height / 2; + bbox.n = point.matrixTransform(matrix); + point.y = point.y + height; + bbox.s = point.matrixTransform(matrix); + + return bbox; + } + + // only fade tips if you are still hovering on the current tip + function fade_tips(inst_selection) { + + var is_hovering = d3.select(inst_selection).classed('hovering'); + + if (is_hovering) { + d3.selectAll('.d3-tip').transition().duration(250).style('opacity', 0).style('display', 'none'); + } + } + + function isFunction(functionToCheck) { + var getType = {}; + return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; + } + + return tip; + }; + +/***/ }, +/* 49 */ +/***/ function(module, exports, __webpack_require__) { + + var make_row_labels = __webpack_require__(50); + + module.exports = function make_row_label_container(cgm, text_delay) { + + var params = cgm.params; + + var row_container; + + // row container holds all row text and row visualizations (triangles rects) + //////////////////////////////////////////////////////////////////////////// + if (d3.select(params.viz.viz_svg + ' .row_container').empty()) { + row_container = d3.select(params.viz.viz_svg).append('g').classed('row_container', true).attr('transform', 'translate(' + params.viz.norm_labels.margin.left + ',' + params.viz.clust.margin.top + ')'); + } else { + row_container = d3.select(params.viz.viz_svg).select('.row_container').attr('transform', 'translate(' + params.viz.norm_labels.margin.left + ',' + params.viz.clust.margin.top + ')'); + } + + if (d3.select(params.root + ' .row_white_background').empty()) { + row_container.append('rect').classed('row_white_background', true).classed('white_bars', true).attr('fill', params.viz.background_color).attr('width', params.viz.label_background.row).attr('height', 30 * params.viz.clust.dim.height + 'px'); + } + + // add container to hold text row labels if not already there + if (d3.select(params.root + ' .row_label_container').empty()) { + row_container.append('g').classed('row_label_container', true).attr('transform', 'translate(' + params.viz.norm_labels.width.row + ',0)').append('g').classed('row_label_zoom_container', true); + } else { + row_container.select(params.root + ' .row_label_container').attr('transform', 'translate(' + params.viz.norm_labels.width.row + ',0)'); + } + + // make row labels in the container + /////////////////////////////////////// + if (params.viz.ds_level === -1) { + make_row_labels(cgm, 'all', text_delay); + } + }; + +/***/ }, +/* 50 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + var add_row_click_hlight = __webpack_require__(51); + var row_reorder = __webpack_require__(52); + var make_row_tooltips = __webpack_require__(102); + + module.exports = function make_row_labels(cgm, row_names = 'all', text_delay = 0) { + + // console.log('make_row_labels') + // console.log(row_names) + + var params = cgm.params; + var row_nodes = []; + + if (row_names === 'all') { + row_nodes = params.network_data.row_nodes; + } else { + _.each(params.network_data.row_nodes, function (inst_row) { + if (_.contains(row_names, inst_row.name)) { + row_nodes.push(inst_row); + } + }); + } + + // make row labels in row_label_zoom_container, bind row_nodes data + var row_labels = d3.select(params.root + ' .row_label_zoom_container').selectAll('g').data(row_nodes, function (d) { + return d.name; + }).enter().append('g').classed('row_label_group', true); + + var row_nodes_names = params.network_data.row_nodes_names; + row_labels.attr('transform', function (d) { + // var inst_index = d.row_index; + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0,' + params.viz.y_scale(inst_index) + ')'; + }); + + row_labels.on('dblclick', function (d) { + + var data_attr = '__data__'; + var row_name = this[data_attr].name; + + // if (params.sim_mat){ + // row_reorder(cgm, this, row_name); + + // d3.selectAll(params.root+' .col_label_text') + // .filter(function(d){ + // return d.name == row_name;} + // )[0][0]; + + // // this is causing buggyness may reenable + // // col_reorder -> two_translate_zoom -> show_visible_area -> make_row_labels -> col_reorder + // // col_reorder(cgm, col_selection, row_name); + + // } else { + // row_reorder(cgm, this, row_name); + // } + + row_reorder(cgm, this, row_name); + + if (params.tile_click_hlight) { + add_row_click_hlight(this, d.ini); + } + }); + + make_row_tooltips(params); + + // append rectangle behind text + row_labels.insert('rect').style('opacity', 0); + + // append row label text + row_labels.append('text').attr('y', params.viz.rect_height * 0.5 + params.labels.default_fs_row * 0.35).attr('text-anchor', 'end').style('font-size', params.labels.default_fs_row + 'px').text(function (d) { + return utils.normal_name(d); + }).attr('pointer-events', 'none').style('opacity', 0).style('cursor', 'default').transition().delay(text_delay).duration(text_delay).style('opacity', 1); + + // change the size of the highlighting rects + row_labels.each(function () { + var bbox = d3.select(this).select('text')[0][0].getBBox(); + d3.select(this).select('rect').attr('x', bbox.x).attr('y', 0).attr('width', bbox.width).attr('height', params.viz.y_scale.rangeBand()).style('fill', function () { + var inst_hl = 'yellow'; + return inst_hl; + }).style('opacity', function (d) { + var inst_opacity = 0; + // highlight target genes + if (d.target === 1) { + inst_opacity = 1; + } + return inst_opacity; + }); + }); + + // almost-deprecated row value bars + /////////////////////////////// + if (utils.has(params.network_data.row_nodes[0], 'value')) { + + row_labels.append('rect').classed('row_bars', true).attr('width', function (d) { + var inst_value = 0; + inst_value = params.labels.bar_scale_row(Math.abs(d.value)); + return inst_value; + }).attr('x', function (d) { + var inst_value = 0; + inst_value = -params.labels.bar_scale_row(Math.abs(d.value)); + return inst_value; + }).attr('height', params.viz.y_scale.rangeBand()).attr('fill', function (d) { + return d.value > 0 ? params.matrix.bar_colors[0] : params.matrix.bar_colors[1]; + }).attr('opacity', 0.4); + } + }; + +/***/ }, +/* 51 */ +/***/ function(module, exports) { + + module.exports = function (params, clicked_row, id_clicked_row) { + if (id_clicked_row != params.click_hlight_row) { + + var rel_width_hlight = 6; + var opacity_hlight = 0.85; + var hlight_height = rel_width_hlight * params.viz.border_width.x; + + d3.selectAll(params.root + ' .click_hlight').remove(); + + // // highlight selected row + // d3.selectAll(params.root+' .row_label_group') + // .select('rect') + // d3.select(this) + // .select('rect') + // .style('opacity', 1); + + d3.select(clicked_row).append('rect').classed('click_hlight', true).classed('row_top_hlight', true).attr('width', params.viz.svg_dim.width).attr('height', hlight_height).attr('fill', params.matrix.hlight_color).attr('opacity', opacity_hlight); + + d3.select(clicked_row).append('rect').classed('click_hlight', true).classed('row_bottom_hlight', true).attr('width', params.viz.svg_dim.width).attr('height', hlight_height).attr('fill', params.matrix.hlight_color).attr('opacity', opacity_hlight).attr('transform', function () { + var tmp_translate_y = params.viz.y_scale.rangeBand() - hlight_height; + return 'translate(0,' + tmp_translate_y + ')'; + }); + } else { + d3.selectAll(params.root + ' .click_hlight').remove(); + params.click_hlight_row = -666; + } + }; + +/***/ }, +/* 52 */ +/***/ function(module, exports, __webpack_require__) { + + var reposition_tile_highlight = __webpack_require__(53); + var toggle_dendro_view = __webpack_require__(54); + var ini_zoom_info = __webpack_require__(36); + var get_previous_zoom = __webpack_require__(101); + var calc_downsampled_levels = __webpack_require__(27); + + module.exports = function row_reorder(cgm, row_selection, inst_row) { + + var params = cgm.params; + var prev_zoom = get_previous_zoom(params); + + if (prev_zoom.zoom_y === 1 && prev_zoom.zoom_x === 1) { + + params.viz.inst_order.row = 'custom'; + toggle_dendro_view(cgm, 'col'); + + d3.selectAll(params.root + ' .toggle_col_order .btn').classed('active', false); + + params.viz.run_trans = true; + + var mat = $.extend(true, {}, params.matrix.matrix); + var row_nodes = params.network_data.row_nodes; + var col_nodes = params.network_data.col_nodes; + + // find the index of the row + var tmp_arr = []; + row_nodes.forEach(function (node) { + tmp_arr.push(node.name); + }); + + // find index + inst_row = _.indexOf(tmp_arr, inst_row); + + // gather the values of the input genes + tmp_arr = []; + col_nodes.forEach(function (node, index) { + tmp_arr.push(mat[inst_row].row_data[index].value); + }); + + // sort the rows + var tmp_sort = d3.range(tmp_arr.length).sort(function (a, b) { + return tmp_arr[b] - tmp_arr[a]; + }); + + // resort cols (cols are reorderd by double clicking a row) + params.viz.x_scale.domain(tmp_sort); + + // save to custom col order + params.matrix.orders.custom_row = tmp_sort; + + // reorder matrix + //////////////////// + var t; + if (params.network_data.links.length > params.matrix.def_large_matrix) { + t = d3.select(params.root + ' .viz_svg'); + } else { + t = d3.select(params.root + ' .viz_svg').transition().duration(2500); + } + + var col_nodes_names = params.network_data.col_nodes_names; + + // Move Col Labels + t.select('.col_zoom_container').selectAll('.col_label_text').attr('transform', function (d) { + var inst_index = _.indexOf(col_nodes_names, d.name); + return 'translate(' + params.viz.x_scale(inst_index) + ')rotate(-90)'; + }); + + // reorder col_class groups + t.selectAll('.col_cat_group').attr('transform', function (d) { + var inst_index = _.indexOf(col_nodes_names, d.name); + return 'translate(' + params.viz.x_scale(inst_index) + ',0)'; + }); + + // reorder tiles in matrix (do not change row order) + if (params.viz.ds_level === -1) { + t.selectAll('.tile').attr('transform', function (d) { + return 'translate(' + params.viz.x_scale(d.pos_x) + ',0)'; + }); + + t.selectAll('.tile_up').attr('transform', function (d) { + return 'translate(' + params.viz.x_scale(d.pos_x) + ',0)'; + }); + + t.selectAll('.tile_dn').attr('transform', function (d) { + return 'translate(' + params.viz.x_scale(d.pos_x) + ',0)'; + }); + } + + // highlight selected row + /////////////////////////////// + // unhilight and unbold all columns (already unbolded earlier) + d3.selectAll(params.root + ' .row_label_group').select('rect').style('opacity', 0); + // highlight column name + d3.select(row_selection).select('rect').style('opacity', 1); + + reposition_tile_highlight(params); + + // redefine x and y positions + params.network_data.links.forEach(function (d) { + d.x = params.viz.x_scale(d.target); + d.y = params.viz.y_scale(d.source); + }); + + params.zoom_info = ini_zoom_info(); + + setTimeout(function () { + params.viz.run_trans = false; + }, 2500); + + // calculate downsmapling if necessary + if (params.viz.ds_num_levels > 0 && params.viz.ds_level >= 0) { + + calc_downsampled_levels(params); + + // var zooming_stopped = true; + // var zooming_out = true; + // var make_all_rows = true; + // // show_visible_area is also run with two_translate_zoom, but at that point + // // the parameters were not updated and two_translate_zoom if only run + // // if needed to reset zoom + // show_visible_area(cgm, zooming_stopped, zooming_out, make_all_rows); + } + } + }; + +/***/ }, +/* 53 */ +/***/ function(module, exports) { + + module.exports = function (params) { + + // resize click hlight + var rel_width_hlight = 6; + // var opacity_hlight = 0.85; + + var hlight_width = rel_width_hlight * params.viz.border_width.x; + var hlight_height = rel_width_hlight * params.viz.border_width.y; + + // reposition tile highlight + //////////////////////////////// + // top highlight + d3.select(params.root + ' .top_hlight').attr('width', params.viz.x_scale.rangeBand()).attr('height', hlight_height).transition().duration(2500).attr('transform', function () { + return 'translate(' + params.viz.x_scale(params.matrix.click_hlight_x) + ',0)'; + }); + + // left highlight + d3.select(params.root + ' .left_hlight').attr('width', hlight_width).attr('height', params.viz.y_scale.rangeBand() - hlight_height * 0.99).transition().duration(2500).attr('transform', function () { + return 'translate(' + params.viz.x_scale(params.matrix.click_hlight_x) + ',' + hlight_height * 0.99 + ')'; + }); + + // right highlight + d3.select(params.root + ' .right_hlight').attr('width', hlight_width).attr('height', params.viz.y_scale.rangeBand() - hlight_height * 0.99).transition().duration(2500).attr('transform', function () { + var tmp_translate = params.viz.x_scale(params.matrix.click_hlight_x) + params.viz.x_scale.rangeBand() - hlight_width; + return 'translate(' + tmp_translate + ',' + hlight_height * 0.99 + ')'; + }); + + // bottom highlight + d3.select(params.root + ' .bottom_hlight').attr('width', function () { + return params.viz.x_scale.rangeBand() - 1.98 * hlight_width; + }).attr('height', hlight_height).transition().duration(2500).attr('transform', function () { + var tmp_translate_x = params.viz.x_scale(params.matrix.click_hlight_x) + hlight_width * 0.99; + var tmp_translate_y = params.viz.y_scale.rangeBand() - hlight_height; + return 'translate(' + tmp_translate_x + ',' + tmp_translate_y + ')'; + }); + }; + +/***/ }, +/* 54 */ +/***/ function(module, exports, __webpack_require__) { + + var make_dendro_triangles = __webpack_require__(55); + + module.exports = function toggle_dendro_view(cgm, inst_rc, wait_time = 1500) { + + var params = cgm.params; + + // row and col are reversed + if (inst_rc === 'row') { + if (params.viz.inst_order.col === 'clust') { + // the last true tells the viz that I'm chaning group size and not to + // delay the change in dendro + setTimeout(make_dendro_triangles, wait_time, cgm, 'row', true); + } + } + + if (inst_rc === 'col') { + if (params.viz.inst_order.row === 'clust') { + setTimeout(make_dendro_triangles, wait_time, cgm, 'col', true); + } + } + + if (params.viz.inst_order.row != 'clust' && params.viz.dendro_filter.col === false) { + d3.selectAll(params.root + ' .col_dendro_group').style('opacity', 0).on('mouseover', null).on('mouseout', null); + + d3.select(params.root + ' .col_slider_group').style('opacity', 0); + + // toggle crop buttons + d3.selectAll(params.root + ' .col_dendro_crop_buttons').style('opacity', 0).on('mouseover', null).on('mouseout', null); + } + + if (params.viz.inst_order.col != 'clust' && params.viz.dendro_filter.row === false) { + + d3.selectAll(params.root + ' .row_dendro_group').style('opacity', 0).on('mouseover', null).on('mouseout', null).on('click', null); + + d3.select(params.root + ' .row_slider_group').style('opacity', 0); + + // toggle crop buttons + d3.selectAll(params.root + ' .row_dendro_crop_buttons').style('opacity', 0).on('mouseover', null).on('mouseout', null); + } + }; + +/***/ }, +/* 55 */ +/***/ function(module, exports, __webpack_require__) { + + var calc_row_dendro_triangles = __webpack_require__(56); + var calc_col_dendro_triangles = __webpack_require__(57); + var dendro_group_highlight = __webpack_require__(58); + var d3_tip_custom = __webpack_require__(48); + var make_dendro_crop_buttons = __webpack_require__(60); + var make_cat_breakdown_graph = __webpack_require__(63); + + module.exports = function make_dendro_triangles(cgm, inst_rc, is_change_group = false) { + + var params = cgm.params; + + // in case sim_mat + if (inst_rc === 'both') { + inst_rc = 'row'; + } + + var other_rc; + if (inst_rc === 'row') { + other_rc = 'col'; + } else { + other_rc = 'row'; + } + + // orders are switched! + if (params.viz.inst_order[other_rc] === 'clust') { + d3.select(params.root + ' .' + inst_rc + '_slider_group').style('opacity', 1); + } + + var dendro_info; + + if (inst_rc === 'row') { + dendro_info = calc_row_dendro_triangles(params); + } else { + dendro_info = calc_col_dendro_triangles(params); + } + + if (d3.select(cgm.params.root + ' .' + inst_rc + '_dendro_crop_buttons').empty() === false) { + make_dendro_crop_buttons(cgm, inst_rc); + } + + // constant dendrogram opacity + var inst_dendro_opacity = params.viz.dendro_opacity; + + function still_hovering(inst_selection, inst_data, i) { + + if (d3.select(inst_selection).classed('hovering')) { + + // define where graph should be built + var inst_selector = params.viz.root_tips + '_' + inst_rc + '_dendro_tip'; + + // prevent mouseover from making multiple graphs + if (d3.select(inst_selector + ' .cat_graph').empty()) { + + if (params.viz.cat_info[inst_rc] !== null) { + make_cat_breakdown_graph(params, inst_rc, inst_data, dendro_info[i], inst_selector, true); + } + } + + d3.selectAll(params.viz.root_tips + '_' + inst_rc + '_dendro_tip').style('opacity', 1); + } + } + + var wait_before_tooltip = 500; + + // remove any old dendro tooltips from this visualization + d3.selectAll(cgm.params.viz.root_tips + '_' + inst_rc + '_dendro_tip').remove(); + + // run transition rules + var run_transition; + if (d3.selectAll(params.root + ' .' + inst_rc + '_dendro_group').empty()) { + run_transition = false; + } else { + run_transition = true; + d3.selectAll(params.root + ' .' + inst_rc + '_dendro_group').remove(); + // d3.selectAll(params.root+' .dendro_tip').remove(); + } + + // d3-tooltip + var tmp_y_offset = 0; + var tmp_x_offset = -5; + var dendro_tip = d3_tip_custom().attr('class', function () { + // add root element to class + var root_tip_selector = params.viz.root_tips.replace('.', ''); + var class_string = root_tip_selector + ' d3-tip ' + root_tip_selector + '_' + inst_rc + '_dendro_tip'; + + return class_string; + }).direction('nw').offset([tmp_y_offset, tmp_x_offset]).style('display', 'none').style('opacity', 0); + + dendro_tip.html(function () { + var full_string = '<div class="cluster_info_container"></div>Click for cluster information <br>' + 'and additional options.'; + return full_string; + }); + + if (is_change_group) { + run_transition = false; + } + + var dendro_traps = d3.select(params.root + ' .' + inst_rc + '_dendro_container').selectAll('path').data(dendro_info, function (d) { + return d.name; + }).enter().append('path').style('opacity', 0).attr('class', inst_rc + '_dendro_group').style('fill', 'black'); + + // draw triangles (shown as trapezoids) + ////////////////////////////////////////// + var start_x; + var start_y; + var mid_x; + var mid_y; + var final_x; + var final_y; + + // row triangles + dendro_traps.attr('d', function (d) { + + if (inst_rc === 'row') { + // row triangles + start_x = 0; + start_y = d.pos_top; + mid_x = 30; + mid_y = d.pos_mid; + final_x = 0; + final_y = d.pos_bot; + } else { + // column triangles + start_x = d.pos_top; + start_y = 0; + mid_x = d.pos_mid; + mid_y = 30; + final_x = d.pos_bot; + final_y = 0; + } + + var output_string = 'M' + start_x + ',' + start_y + ', L' + mid_x + ', ' + mid_y + ', L' + final_x + ',' + final_y + ' Z'; + return output_string; + }); + + dendro_traps.on('mouseover', function (d, i) { + + // if (params.sim_mat){ + // inst_rc = 'both'; + // } + + // run instantly on mouseover + d3.select(this).classed('hovering', true); + + if (cgm.params.dendro_callback != null) { + cgm.params.dendro_callback(this); + } + + // display tip + // this is needed for it to show in the right place and the opacity + // will be toggled to delay the tooltip for the user + d3.select(params.viz.root_tips + '_' + inst_rc + '_dendro_tip').style('display', 'block'); + + dendro_group_highlight(params, this, d, inst_rc); + + // show the tip (make sure it is displaying before it is shown) + dendro_tip.show(d); + + // set opacity to zero + d3.select(params.viz.root_tips + '_' + inst_rc + '_dendro_tip').style('opacity', 0); + + // check if still hovering + setTimeout(still_hovering, wait_before_tooltip, this, d, i); + }).on('mouseout', function () { + if (params.viz.inst_order[other_rc] === 'clust') { + d3.select(this).style('opacity', inst_dendro_opacity); + } + + d3.selectAll(params.root + ' .dendro_shadow').remove(); + + d3.select(this).classed('hovering', false); + dendro_tip.hide(this); + }).on('click', function (d, i) { + + $(params.root + ' .dendro_info').modal('toggle'); + + var group_string = d.all_names.join(', '); + d3.select(params.root + ' .dendro_info input').attr('value', group_string); + + var inst_selector = params.root + ' .dendro_info'; + + // remove old graphs (modals are not within params.root) + d3.selectAll('.dendro_info .cluster_info_container .cat_graph').remove(); + + if (params.viz.cat_info[inst_rc] !== null) { + make_cat_breakdown_graph(params, inst_rc, d, dendro_info[i], inst_selector); + } + + if (cgm.params.dendro_click_callback != null) { + cgm.params.dendro_click_callback(this); + } + }).call(dendro_tip); + + var triangle_opacity; + if (params.viz.inst_order[other_rc] === 'clust') { + triangle_opacity = inst_dendro_opacity; + } else { + triangle_opacity = 0; + } + + if (run_transition) { + + d3.select(params.root + ' .' + inst_rc + '_dendro_container').selectAll('path').transition().delay(1000).duration(1000).style('opacity', triangle_opacity); + } else { + + d3.select(params.root + ' .' + inst_rc + '_dendro_container').selectAll('path').style('opacity', triangle_opacity); + } + }; + +/***/ }, +/* 56 */ +/***/ function(module, exports) { + + module.exports = function calc_row_dendro_triangles(params) { + + var triangle_info = {}; + var inst_level = params.group_level.row; + var row_nodes = params.network_data.row_nodes; + var row_nodes_names = params.network_data.row_nodes_names; + + _.each(row_nodes, function (d) { + + // console.log('row_node '+d.name) + + var tmp_group = d.group[inst_level]; + var inst_index = _.indexOf(row_nodes_names, d.name); + var inst_top = params.viz.y_scale(inst_index); + var inst_bot = inst_top + params.viz.y_scale.rangeBand(); + + if (_.has(triangle_info, tmp_group) === false) { + triangle_info[tmp_group] = {}; + triangle_info[tmp_group].name_top = d.name; + triangle_info[tmp_group].name_bot = d.name; + triangle_info[tmp_group].pos_top = inst_top; + triangle_info[tmp_group].pos_bot = inst_bot; + triangle_info[tmp_group].pos_mid = (inst_top + inst_bot) / 2; + triangle_info[tmp_group].name = tmp_group; + triangle_info[tmp_group].all_names = []; + triangle_info[tmp_group].inst_rc = 'row'; + } + + triangle_info[tmp_group].all_names.push(d.name); + + if (inst_top < triangle_info[tmp_group].pos_top) { + triangle_info[tmp_group].name_top = d.name; + triangle_info[tmp_group].pos_top = inst_top; + triangle_info[tmp_group].pos_mid = (inst_top + triangle_info[tmp_group].pos_bot) / 2; + } + + if (inst_bot > triangle_info[tmp_group].pos_bot) { + triangle_info[tmp_group].name_bot = d.name; + triangle_info[tmp_group].pos_bot = inst_bot; + triangle_info[tmp_group].pos_mid = (triangle_info[tmp_group].pos_top + inst_bot) / 2; + } + }); + + var group_info = []; + + _.each(triangle_info, function (d) { + group_info.push(d); + }); + + return group_info; + }; + +/***/ }, +/* 57 */ +/***/ function(module, exports) { + + module.exports = function calc_col_dendro_triangles(params) { + + var triangle_info = {}; + var inst_level = params.group_level.col; + var col_nodes = params.network_data.col_nodes; + var col_nodes_names = params.network_data.col_nodes_names; + + _.each(col_nodes, function (d) { + + var tmp_group = d.group[inst_level]; + var inst_index = _.indexOf(col_nodes_names, d.name); + var inst_top = params.viz.x_scale(inst_index); + var inst_bot = inst_top + params.viz.x_scale.rangeBand(); + + if (_.has(triangle_info, tmp_group) === false) { + triangle_info[tmp_group] = {}; + triangle_info[tmp_group].name_top = d.name; + triangle_info[tmp_group].name_bot = d.name; + triangle_info[tmp_group].pos_top = inst_top; + triangle_info[tmp_group].pos_bot = inst_bot; + triangle_info[tmp_group].pos_mid = (inst_top + inst_bot) / 2; + triangle_info[tmp_group].name = tmp_group; + triangle_info[tmp_group].all_names = []; + triangle_info[tmp_group].inst_rc = 'col'; + } + + triangle_info[tmp_group].all_names.push(d.name); + + if (inst_top < triangle_info[tmp_group].pos_top) { + triangle_info[tmp_group].name_top = d.name; + triangle_info[tmp_group].pos_top = inst_top; + triangle_info[tmp_group].pos_mid = (inst_top + triangle_info[tmp_group].pos_bot) / 2; + } + + if (inst_bot > triangle_info[tmp_group].pos_bot) { + triangle_info[tmp_group].name_bot = d.name; + triangle_info[tmp_group].pos_bot = inst_bot; + triangle_info[tmp_group].pos_mid = (triangle_info[tmp_group].pos_top + inst_bot) / 2; + } + }); + + var group_info = []; + + _.each(triangle_info, function (d) { + group_info.push(d); + }); + + return group_info; + }; + +/***/ }, +/* 58 */ +/***/ function(module, exports, __webpack_require__) { + + var dendro_shade_bars = __webpack_require__(59); + + module.exports = function dendro_group_highlight(params, inst_selection, inst_data, inst_rc) { + + // only make shadows if there is more than one crop button + if (d3.selectAll(params.root + ' .' + inst_rc + '_dendro_crop_buttons')[0].length > 1) { + setTimeout(still_hovering, 500); + } else { + d3.selectAll(params.root + ' .dendro_shadow').remove(); + } + + function still_hovering() { + + // check that user is still hovering over dendrogram group + if (d3.select(inst_selection).classed('hovering')) { + + // check that user is not using dendrogram slider + if (params.is_slider_drag === false) { + + d3.select(inst_selection).style('opacity', 0.7); + + if (d3.select(params.viz.viz_svg).classed('running_update') === false) { + make_shadow_bars(); + } + } + } + } + + function make_shadow_bars() { + + if (inst_rc === 'row') { + + // row and col labling are reversed + if (params.viz.inst_order.col === 'clust') { + dendro_shade_bars(params, inst_selection, inst_rc, inst_data); + } + } else if (inst_rc === 'col') { + + // row and col labeling are reversed + if (params.viz.inst_order.row === 'clust') { + dendro_shade_bars(params, inst_selection, inst_rc, inst_data); + } + } else if (inst_rc === 'both') { + + if (params.viz.inst_order.col === 'clust') { + dendro_shade_bars(params, inst_selection, 'row', inst_data); + } + if (params.viz.inst_order.row === 'clust') { + dendro_shade_bars(params, inst_selection, 'col', inst_data); + } + } + } + }; + +/***/ }, +/* 59 */ +/***/ function(module, exports) { + + module.exports = function dendro_shade_bars(params, inst_selection, inst_rc, inst_data) { + + var inst_opacity = 0.2; + var bot_height; + + d3.selectAll(params.root + ' .dendro_shadow').remove(); + + if (inst_rc == 'row') { + + // top shade + d3.select(params.root + ' .clust_group').append('rect').attr('width', params.viz.clust.dim.width + 'px').attr('height', inst_data.pos_top + 'px').attr('fill', 'black').classed('dendro_shadow', true).attr('opacity', inst_opacity); + + bot_height = params.viz.clust.dim.height - inst_data.pos_bot; + // bottom shade + d3.select(params.root + ' .clust_group').append('rect').attr('width', params.viz.clust.dim.width + 'px').attr('height', bot_height + 'px').attr('transform', 'translate(0,' + inst_data.pos_bot + ')').attr('fill', 'black').classed('dendro_shadow', true).attr('opacity', inst_opacity); + } else if (inst_rc === 'col') { + + // top shade + d3.select(params.root + ' .clust_group').append('rect').attr('width', inst_data.pos_top + 'px').attr('height', params.viz.clust.dim.height + 'px').attr('fill', 'black').classed('dendro_shadow', true).attr('opacity', inst_opacity); + + // bottom shade + bot_height = params.viz.clust.dim.width - inst_data.pos_bot; + d3.select(params.root + ' .clust_group').append('rect').attr('width', bot_height + 'px').attr('height', params.viz.clust.dim.height + 'px').attr('transform', 'translate(' + inst_data.pos_bot + ',0)').attr('fill', 'black').classed('dendro_shadow', true).attr('opacity', inst_opacity); + } + }; + +/***/ }, +/* 60 */ +/***/ function(module, exports, __webpack_require__) { + + var calc_row_dendro_triangles = __webpack_require__(56); + var calc_col_dendro_triangles = __webpack_require__(57); + var d3_tip_custom = __webpack_require__(48); + var dendro_group_highlight = __webpack_require__(58); + var run_dendro_filter = __webpack_require__(61); + var zoom_crop_triangles = __webpack_require__(62); + + module.exports = function make_dendro_crop_buttons(cgm, inst_rc) { + + var params = cgm.params; + + var button_opacity = params.viz.dendro_opacity * 0.60; + + // information needed to make dendro + var dendro_info; + var other_rc; + if (inst_rc === 'row') { + dendro_info = calc_row_dendro_triangles(params); + other_rc = 'col'; + } else { + dendro_info = calc_col_dendro_triangles(params); + other_rc = 'row'; + } + + // d3-tooltip + var tmp_y_offset = 5; + var tmp_x_offset = -5; + var dendro_crop_tip = d3_tip_custom().attr('class', function () { + var root_tip_selector = params.viz.root_tips.replace('.', ''); + var class_string = root_tip_selector + ' d3-tip ' + root_tip_selector + '_' + inst_rc + '_dendro_crop_tip'; + + return class_string; + }).direction('nw').style('display', 'none').offset([tmp_y_offset, tmp_x_offset]); + + var wait_before_tooltip = 500; + + d3.selectAll(params.viz.root_tips + '_' + inst_rc + '_dendro_crop_tip').remove(); + d3.selectAll(params.root + ' .' + inst_rc + '_dendro_crop_buttons').remove(); + + var icons; + // position triangles + var start_x; + var start_y; + var mid_x; + var mid_y; + var final_x; + var final_y; + + // need to improve to account for zooming + var min_tri_height = 45; + var scale_down_tri = 0.25; + var tri_height; + var tri_width; + var tri_dim; + + // make crop buttons or undo buttons + var button_class = inst_rc + '_dendro_crop_buttons'; + if (d3.select(cgm.params.root + ' .' + inst_rc + '_dendro_icons_group').classed('ran_filter') === false) { + + // Crop Triangle + ////////////////////////////// + icons = d3.select(params.root + ' .' + inst_rc + '_dendro_icons_group').selectAll('path').data(dendro_info, function (d) { + return d.name; + }).enter().append('path').classed(button_class, true).attr('d', function (d) { + + // redefine + tri_height = 10; + tri_width = 10; + + var tmp_height = d.pos_bot - d.pos_top; + + // Row Dendrogram Crop Triangle + if (inst_rc === 'row') { + + if (tmp_height < min_tri_height) { + tri_height = tmp_height * scale_down_tri; + } + + // pointing left + start_x = tri_width; + start_y = -tri_height; + mid_x = 0; + mid_y = 0; + final_x = tri_width; + final_y = tri_height; + + tri_dim = tri_height; + + // Column Dendrogram Crop Triangle + } else { + + if (tmp_height < min_tri_height) { + tri_width = tmp_height * scale_down_tri; + } + + // pointing upward + start_x = -tri_width; + start_y = tri_height; + mid_x = 0; + mid_y = 0; + final_x = tri_width; + final_y = tri_height; + + tri_dim = tri_width; + } + + // save triangle height + // d3.select(this)[0][0].__data__.tri_dim = tri_dim; + var data_key = '__data__'; + d3.select(this)[0][0][data_key].tri_dim = tri_dim; + + var output_string = 'M' + start_x + ',' + start_y + ', L' + mid_x + ', ' + mid_y + ', L' + final_x + ',' + final_y + ' Z'; + + return output_string; + }); + + dendro_crop_tip.html(function () { + var full_string = 'Click to crop cluster'; + return full_string; + }); + } else { + + // Undo Triangle + ////////////////////////////// + icons = d3.select(params.root + ' .' + inst_rc + '_dendro_icons_group').selectAll('path').data(dendro_info, function (d) { + return d.name; + }).enter().append('path').classed(button_class, true).attr('d', function (d) { + + // redefine + tri_height = 10; + tri_width = 12; + + var tmp_height = d.pos_bot - d.pos_top; + + if (inst_rc === 'row') { + + if (tmp_height < min_tri_height) { + tri_height = tmp_height * scale_down_tri; + } + + // pointing right + start_x = 0; + start_y = -tri_height; + mid_x = tri_width; + mid_y = 0; + final_x = 0; + final_y = tri_height; + } else { + + if (tmp_height < min_tri_height) { + tri_width = tmp_height * scale_down_tri; + } + + // pointing downward + start_x = -tri_width; + start_y = 0; + mid_x = 0; + mid_y = tri_height; + final_x = tri_width; + final_y = 0; + } + + // save triangle height + var data_key = '__data__'; + d3.select(this)[0][0][data_key].tri_dim = 10; + + var output_string = 'M' + start_x + ',' + start_y + ', L' + mid_x + ', ' + mid_y + ', L' + final_x + ',' + final_y + ' Z'; + + return output_string; + }); + + dendro_crop_tip.html(function () { + var full_string = 'Click to undo crop'; + return full_string; + }); + } + + icons.style('cursor', 'pointer').style('opacity', function () { + + var inst_opacity; + + // if (d3.select(this).classed('hide_crop')){ + // inst_opacity = 0; + // } else { + // inst_opacity = button_opacity; + // } + + inst_opacity = button_opacity; + return inst_opacity; + }).attr('transform', function (d) { + var inst_translate; + + var inst_x; + var inst_y; + + if (inst_rc === 'row') { + inst_x = params.viz.uni_margin; + inst_y = d.pos_mid; + } else { + inst_x = d.pos_mid; + inst_y = params.viz.uni_margin; + } + + inst_translate = 'translate(' + inst_x + ',' + inst_y + ')'; + return inst_translate; + }).on('mouseover', function (d) { + + d3.select(this).classed('hovering', true); + + dendro_crop_tip.show(d); + + dendro_group_highlight(params, this, d, inst_rc); + + // display with zero opacity + d3.selectAll(params.viz.root_tips + '_' + inst_rc + '_dendro_crop_tip').style('opacity', 0).style('display', 'block'); + + // check if still hovering + setTimeout(still_hovering, wait_before_tooltip, this); + }).on('mouseout', function () { + + d3.select(this).classed('hovering', false); + + d3.selectAll(params.root + ' .dendro_shadow').remove(); + + d3.select(this).style('opacity', button_opacity); + + dendro_crop_tip.hide(this); + }).on('click', function (d) { + + // give user visual cue + d3.select(this).style('opacity', 0.9).transition().duration(1000).style('opacity', 0); + + // remove dendro shadows when clicked + d3.selectAll(params.root + ' .dendro_shadow').remove(); + + /* filter using dendrogram */ + if (cgm.params.dendro_filter.row === false && cgm.params.dendro_filter.col === false && cgm.params.cat_filter.row === false && cgm.params.cat_filter.col === false) { + + // Run Filtering + /////////////////// + + // use class as 'global' variable + d3.select(cgm.params.root + ' .' + inst_rc + '_dendro_icons_group').attr('transform', 'translate(0,0), scale(1,1)').classed('ran_filter', true); + + d3.select(cgm.params.root + ' .' + other_rc + '_dendro_icons_group').attr('transform', 'translate(0,0), scale(1,1)'); + + // do not display dendrogram slider if filtering has been run + d3.select(cgm.params.root + ' .' + inst_rc + '_slider_group').style('display', 'none'); + + // do not display other crop buttons since they are inactive + d3.select(cgm.params.root + ' .' + other_rc + '_dendro_icons_container').style('display', 'none'); + + // do not display brush-crop button if performing dendro crop + d3.select(cgm.params.root + ' .crop_button').style('opacity', 0.2); + } else { + + // Undo Filtering + /////////////////// + // use class as 'global' variable + d3.select(cgm.params.root + ' .' + inst_rc + '_dendro_icons_group').attr('transform', 'translate(0,0), scale(1,1)').classed('ran_filter', false); + + d3.select(cgm.params.root + ' .' + other_rc + '_dendro_icons_group').attr('transform', 'translate(0,0), scale(1,1)'); + + if (params.viz.inst_order[other_rc] === 'clust') { + // display slider when cropping has not been done + d3.select(cgm.params.root + ' .' + inst_rc + '_slider_group').style('display', 'block'); + } + + // display other crop buttons when cropping has not been done + d3.select(cgm.params.root + ' .' + other_rc + '_dendro_icons_container').style('display', 'block'); + + // display brush-crop button if not performing dendro crop + d3.select(cgm.params.root + ' .crop_button').style('opacity', 1); + } + + run_dendro_filter(cgm, d, inst_rc); + }).call(dendro_crop_tip); + + // ordering has been reversed + if (params.viz.inst_order[other_rc] != 'clust') { + // do not display if not in cluster order + d3.select(params.root + ' .' + inst_rc + '_dendro_icons_group').selectAll('path').style('display', 'none'); + } + + function still_hovering(inst_selection) { + + if (d3.select(inst_selection).classed('hovering')) { + // increase opacity + d3.selectAll(params.viz.root_tips + '_' + inst_rc + '_dendro_crop_tip').style('opacity', 1).style('display', 'block'); + } + } + + zoom_crop_triangles(params, params.zoom_info, inst_rc); + }; + +/***/ }, +/* 61 */ +/***/ function(module, exports) { + + module.exports = function run_dendro_filter(cgm, d, inst_rc) { + + var names = {}; + + if (cgm.params.dendro_filter.row === false && cgm.params.dendro_filter.col === false && cgm.params.cat_filter.row === false && cgm.params.cat_filter.col === false) { + + d3.select(cgm.params.root + ' .' + inst_rc + '_slider_group').style('opacity', 0.35).style('pointer-events', 'none'); + + names[inst_rc] = d.all_names; + + var tmp_names = cgm.params.network_data[inst_rc + '_nodes_names']; + + // keep a backup of the inst_view + var inst_row_nodes = cgm.params.network_data.row_nodes; + var inst_col_nodes = cgm.params.network_data.col_nodes; + + cgm.filter_viz_using_names(names); + + // overwrite with backup of original nodes + cgm.params.inst_nodes.row_nodes = inst_row_nodes; + cgm.params.inst_nodes.col_nodes = inst_col_nodes; + + d3.selectAll(cgm.params.root + ' .dendro_shadow').transition().duration(1000).style('opacity', 0).remove(); + + // keep the names of all the nodes + cgm.params.dendro_filter[inst_rc] = tmp_names; + + /* reset filter */ + } else { + + names[inst_rc] = cgm.params.dendro_filter[inst_rc]; + + cgm.filter_viz_using_names(names); + cgm.params.dendro_filter[inst_rc] = false; + } + }; + +/***/ }, +/* 62 */ +/***/ function(module, exports) { + + module.exports = function zoom_crop_triangles(params, zoom_info, inst_rc) { + + if (inst_rc === 'row') { + + // transform icons (undo zoom on triangles) + d3.select(params.root + ' .row_dendro_icons_group').selectAll('path').attr('transform', function (d) { + var inst_x = params.viz.uni_margin; + var inst_y = d.pos_mid; + var curr_zoom = zoom_info.zoom_y; + var tri_dim = d3.select(this).data()[0].tri_dim; + var inst_zoom = constrain_zoom(curr_zoom, tri_dim); + return 'translate(' + inst_x + ',' + inst_y + ') ' + 'scale(1, ' + 1 / inst_zoom + ')'; + }); + } else { + + // transform icons (undo zoom on triangles) + d3.select(params.root + ' .col_dendro_icons_group').selectAll('path').attr('transform', function (d) { + var inst_x = d.pos_mid; + var inst_y = params.viz.uni_margin; + var curr_zoom = zoom_info.zoom_x; + var tri_dim = d3.select(this).data()[0].tri_dim; + var inst_zoom = constrain_zoom(curr_zoom, tri_dim); + return 'translate(' + inst_x + ',' + inst_y + ') ' + 'scale(' + 1 / inst_zoom + ', 1)'; + }); + } + + function constrain_zoom(curr_zoom, tri_height) { + var inst_zoom; + var default_tri_height = 10; + if (tri_height * curr_zoom < default_tri_height) { + inst_zoom = 1; + } else { + var max_zoom = default_tri_height / tri_height; + inst_zoom = curr_zoom / max_zoom; + } + return inst_zoom; + } + }; + +/***/ }, +/* 63 */ +/***/ function(module, exports, __webpack_require__) { + + var calc_cat_cluster_breakdown = __webpack_require__(64); + + module.exports = function make_cat_breakdown_graph(params, inst_rc, inst_data, dendro_info, selector, tooltip = false) { + + /* + This function is used to make the category breakdown graphs for tooltips on + dendrogram mousover and on dendrogram click modal popup. + */ + + // in case sim_mat + if (inst_rc === 'both') { + inst_rc = 'row'; + } + + var cat_breakdown = calc_cat_cluster_breakdown(params, inst_data, inst_rc); + + if (cat_breakdown.length > 0) { + + // put cluster information in dendro_tip + /////////////////////////////////////////// + var cluster_info_container = d3.select(selector + ' .cluster_info_container'); + + // loop through cat_breakdown data + var super_string = ': '; + var paragraph_string = '<p>'; + var width = 370; + var bar_offset = 23; + var bar_height = 20; + var max_string_length = 25; + var bar_width = 180; + var title_height = 27; + var shift_tooltip_left = 177; + + // these are the indexes where the number-of-nodes and the number of downsampled + // nodes are stored + var num_nodes_index = 4; + var num_nodes_ds_index = 5; + var offset_ds_count = 150; + var binom_pval_index = 6; + + var is_downsampled = false; + if (cat_breakdown[0].bar_data[0][num_nodes_ds_index] != null) { + width = width + 100; + shift_tooltip_left = shift_tooltip_left + offset_ds_count - 47; + is_downsampled = true; + } + + // the index that will be used to generate the bars (will be different if + // downsampled) + var cluster_total = dendro_info.all_names.length; + var bars_index = num_nodes_index; + if (is_downsampled) { + bars_index = num_nodes_ds_index; + + // calculate the total number of nodes in downsampled case + var inst_bar_data = cat_breakdown[0].bar_data; + cluster_total = 0; + _.each(inst_bar_data, function (tmp_data) { + cluster_total = cluster_total + tmp_data[num_nodes_ds_index]; + }); + } + + // limit on the number of category types shown + var max_cats = 3; + // limit the number of bars shown + var max_bars = 25; + + // calculate height needed for svg based on cat_breakdown data + var svg_height = 20; + _.each(cat_breakdown.slice(0, max_cats), function (tmp_break) { + var num_bars = tmp_break.bar_data.length; + if (num_bars > max_bars) { + num_bars = max_bars; + } + svg_height = svg_height + title_height * (num_bars + 1); + }); + + // Cluster Information Title (for tooltip only not modal) + if (tooltip) { + cluster_info_container.append('text').text('Cluster Information'); + } + + var main_dendro_svg = cluster_info_container.append('div').style('margin-top', '5px').classed('cat_graph', true).append('svg').style('height', svg_height + 'px').style('width', width + 'px'); + + // make background + main_dendro_svg.append('rect').classed('cat_background', true).attr('height', svg_height + 'px').attr('width', width + 'px').attr('fill', 'white').attr('opacity', 1); + + // the total amout to shift down the next category + var shift_down = title_height; + + // limit the category-types + cat_breakdown = cat_breakdown.slice(0, max_cats); + + _.each(cat_breakdown, function (cat_data) { + + var max_bar_value = cat_data.bar_data[0][bars_index]; + + // offset the count column based on how large the counts are + var digit_offset_scale = d3.scale.linear().domain([0, 100000]).range([20, 30]); + + // only keep the top max_bars categories + cat_data.bar_data = cat_data.bar_data.slice(0, max_bars); + + cluster_info_container.style('margin-bottom', '5px'); + + var cat_graph_group = main_dendro_svg.append('g').classed('cat_graph_group', true).attr('transform', 'translate(10, ' + shift_down + ')'); + + // shift down based on number of bars + shift_down = shift_down + title_height * (cat_data.bar_data.length + 1); + + var inst_title = cat_data.type_name; + // ensure that title is not too long + if (inst_title.length >= max_string_length) { + inst_title = inst_title.slice(0, max_string_length) + '..'; + } + + // make title + cat_graph_group.append('text').classed('cat_graph_title', true).text(inst_title).style('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif').style('font-weight', 800); + + // shift the position of the numbers based on the size of the number + var count_offset = digit_offset_scale(max_bar_value); + + // Count Title + cat_graph_group.append('text').text('Count').attr('transform', function () { + var inst_x = bar_width + count_offset; + var inst_translate = 'translate(' + inst_x + ', 0)'; + return inst_translate; + }); + + // Percentage Title + cat_graph_group.append('text').text('Pct').attr('transform', function () { + var inst_x = bar_width + count_offset + 60; + var inst_translate = 'translate(' + inst_x + ', 0)'; + return inst_translate; + }); + + // Percentage Title + cat_graph_group.append('text').text('P-val').attr('transform', function () { + var inst_x = bar_width + count_offset + 115; + var inst_translate = 'translate(' + inst_x + ', 0)'; + return inst_translate; + }); + + // Count Downsampled Title + if (is_downsampled) { + cat_graph_group.append('text').text('Clusters').attr('transform', function () { + var inst_x = bar_width + offset_ds_count; + var inst_translate = 'translate(' + inst_x + ', 0)'; + return inst_translate; + }); + } + + var line_y = 4; + cat_graph_group.append('line').attr('x1', 0).attr('x2', bar_width).attr('y1', line_y).attr('y2', line_y).attr('stroke', 'blue').attr('stroke-width', 1).attr('opacity', 1.0); + + var cat_bar_container = cat_graph_group.append('g').classed('cat_bar_container', true).attr('transform', 'translate(0, 10)'); + + // make bar groups (hold bar and text) + var cat_bar_groups = cat_bar_container.selectAll('g').data(cat_data.bar_data).enter().append('g').attr('transform', function (d, i) { + var inst_y = i * bar_offset; + return 'translate(0,' + inst_y + ')'; + }); + + // bar length is max when all nodes in cluster are of + // a single cat + var bar_scale = d3.scale.linear().domain([0, max_bar_value]).range([0, bar_width]); + + // make bars + cat_bar_groups.append('rect').attr('height', bar_height + 'px').attr('width', function (d) { + var inst_width = bar_scale(d[bars_index]); + return inst_width + 'px'; + }).attr('fill', function (d) { + // cat color is stored in the third element + return d[3]; + }).attr('opacity', params.viz.cat_colors.opacity).attr('stroke', 'grey').attr('stroke-width', '0.5px'); + + // make bar labels + cat_bar_groups.append('text').classed('bar_labels', true).text(function (d) { + var inst_text = d[1]; + if (inst_text.indexOf(super_string) > 0) { + inst_text = inst_text.split(super_string)[1]; + } + if (inst_text.indexOf(paragraph_string) > 0) { + // required for Enrichr category names (needs improvements) + inst_text = inst_text.split(paragraph_string)[0]; + } + // ensure that bar name is not too long + if (inst_text.length >= max_string_length) { + inst_text = inst_text.slice(0, max_string_length) + '..'; + } + return inst_text; + }).attr('transform', function () { + return 'translate(5, ' + 0.75 * bar_height + ')'; + }).attr('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif').attr('font-weight', 400).attr('text-anchor', 'right'); + + // Count/Pct Rows + ///////////////////////////// + var shift_count_num = 35; + + cat_bar_groups.append('text').classed('count_labels', true).text(function (d) { + var inst_count = d[bars_index]; + inst_count = inst_count.toLocaleString(); + return String(inst_count); + }).attr('transform', function () { + var inst_x = bar_width + count_offset + shift_count_num; + var inst_y = 0.75 * bar_height; + return 'translate(' + inst_x + ', ' + inst_y + ')'; + }).attr('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif').attr('font-weight', 400).attr('text-anchor', 'end'); + + cat_bar_groups.append('text').classed('count_labels', true).text(function (d) { + // calculate the percentage relative to the current cluster + var inst_count = d[bars_index] / cluster_total * 100; + inst_count = Math.round(inst_count * 10) / 10; + inst_count = inst_count.toLocaleString(); + return String(inst_count); + }).attr('transform', function () { + var inst_x = bar_width + count_offset + shift_count_num + 47; + var inst_y = 0.75 * bar_height; + return 'translate(' + inst_x + ', ' + inst_y + ')'; + }).attr('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif').attr('font-weight', 400).attr('text-anchor', 'end'); + + // Binomial Test Pvals + cat_bar_groups.append('text').classed('count_labels', true).text(function (d) { + // calculate the percentage relative to the current cluster + var inst_count = d[binom_pval_index]; + + if (inst_count < 0.1) { + inst_count = parseFloat(inst_count.toPrecision(3)); + inst_count = inst_count.toExponential(); + } else { + inst_count = parseFloat(inst_count.toPrecision(2)); + } + + // inst_count = inst_count.toLocaleString(); + return inst_count; + }).attr('transform', function () { + var inst_x = bar_width + count_offset + shift_count_num + 112; + var inst_y = 0.75 * bar_height; + return 'translate(' + inst_x + ', ' + inst_y + ')'; + }).attr('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif').attr('font-weight', 400).attr('text-anchor', 'end'); + + if (is_downsampled) { + cat_bar_groups.append('text').classed('count_labels', true).text(function (d) { + return String(d[num_nodes_index].toLocaleString()); + }).attr('transform', function () { + // downsampled cluster numbers are smaller and need less flexible offsetting + var inst_x = bar_width + shift_count_num + offset_ds_count + 20; + var inst_y = 0.75 * bar_height; + return 'translate(' + inst_x + ', ' + inst_y + ')'; + }).attr('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif').attr('font-weight', 400).attr('text-anchor', 'end'); + } + }); + + // reposition tooltip + ///////////////////////////////////////////////// + if (tooltip) { + + var dendro_tip = d3.select(selector); + var old_top = dendro_tip.style('top').split('.px')[0]; + var old_left = dendro_tip.style('left').split('.px')[0]; + var shift_top = 0; + var shift_left = 0; + + // shifting + if (inst_rc === 'row') { + + // rows + ////////////// + shift_top = 0; + shift_left = shift_tooltip_left; + + // // prevent graph from being too high + // if (dendro_info.pos_top < svg_height){ + // // do not shift position of category breakdown graph + // // shift_top = -(svg_height + (dendro_info.pos_mid - dendro_info.pos_top)/2) ; + // } + } else { + + // columns + ////////////// + shift_top = svg_height + 32; + shift_left = 30; + } + + dendro_tip.style('top', function () { + var new_top = String(parseInt(old_top, 10) - shift_top) + 'px'; + return new_top; + }).style('left', function () { + var new_left = String(parseInt(old_left, 10) - shift_left) + 'px'; + return new_left; + }); + } + } + }; + +/***/ }, +/* 64 */ +/***/ function(module, exports, __webpack_require__) { + + var binom_test = __webpack_require__(65); + + module.exports = function calc_cat_cluster_breakdown(params, inst_data, inst_rc) { + // Category-breakdown of dendrogram-clusters + ///////////////////////////////////////////// + /* + 1. get information for nodes in cluster + 2. find category-types that are string-type + 3. count instances of each category name for each category-type + */ + + // in case sim_mat + if (inst_rc === 'both') { + inst_rc = 'row'; + } + + // 1: get information for nodes in cluster + /////////////////////////////////////////// + + // names of nodes in cluster + var clust_names = inst_data.all_names; + // array of nodes in the cluster + var clust_nodes = []; + var all_nodes = params.network_data[inst_rc + '_nodes']; + var num_in_clust_index = null; + var is_downsampled = false; + + var inst_name; + _.each(all_nodes, function (inst_node) { + + inst_name = inst_node.name; + + if (clust_names.indexOf(inst_name) >= 0) { + clust_nodes.push(inst_node); + } + }); + + // 2: find category-types that are string-type + /////////////////////////////////////////////// + + var cat_breakdown = []; + + if (params.viz.cat_info[inst_rc] !== null) { + + var inst_cat_info = params.viz.cat_info[inst_rc]; + + // tmp list of all categories + var tmp_types_index = _.keys(inst_cat_info); + // this will hold the indexes of string-type categories + var cat_types_index = []; + + // get category names (only include string-type categories) + var cat_types_names = []; + var type_name; + var inst_index; + var cat_index; + for (var i = 0; i < tmp_types_index.length; i++) { + + cat_index = 'cat-' + String(i); + + if (params.viz.cat_info[inst_rc][cat_index].type === 'cat_strings') { + type_name = params.viz.cat_names[inst_rc][cat_index]; + cat_types_names.push(type_name); + cat_types_index.push(cat_index); + } else { + + // save number in clust category index if found + if (params.viz.cat_names[inst_rc][cat_index] === 'number in clust') { + num_in_clust_index = cat_index; + is_downsampled = true; + } + } + } + + var tmp_run_count = {}; + var inst_breakdown = {}; + var bar_data; + var radix_param = 10; + + // sort by actual counts (rather than cluster counts) + var sorting_index = 4; + if (is_downsampled) { + sorting_index = 5; + } + + var no_title_given; + if (type_name === cat_index) { + no_title_given = true; + } else { + no_title_given = false; + } + + if (cat_types_names.length > 0) { + + // 3: count instances of each category name for each category-type + var cat_name; + var num_in_clust = clust_names.length; + + // use the cat_hist to get the number of instances of this category in + // all rows/cols + // params + + _.each(cat_types_index, function (cat_index) { + + inst_index = cat_index.split('-')[1]; + type_name = cat_types_names[inst_index]; + + if (no_title_given) { + if (cat_index.indexOf('-') >= 0) { + var tmp_num = parseInt(cat_index.split('-')[1], radix_param) + 1; + type_name = 'Category ' + String(tmp_num); + } else { + // backup behavior + type_name = 'Category'; + } + } + + tmp_run_count[type_name] = {}; + + // loop through the nodes and keep a running count of categories + _.each(clust_nodes, function (tmp_node) { + + cat_name = tmp_node[cat_index]; + + if (cat_name.indexOf(': ') >= 0) { + cat_name = cat_name.split(': ')[1]; + } + + if (cat_name in tmp_run_count[type_name]) { + tmp_run_count[type_name][cat_name].num_nodes = tmp_run_count[type_name][cat_name].num_nodes + 1; + + if (num_in_clust_index != null) { + tmp_run_count[type_name][cat_name].num_nodes_ds = tmp_run_count[type_name][cat_name].num_nodes_ds + parseInt(tmp_node[num_in_clust_index].split(': ')[1], radix_param); + } + } else { + + tmp_run_count[type_name][cat_name] = {}; + tmp_run_count[type_name][cat_name].num_nodes = 1; + if (num_in_clust_index != null) { + tmp_run_count[type_name][cat_name].num_nodes_ds = parseInt(tmp_node[num_in_clust_index].split(': ')[1], radix_param); + } + } + }); + + inst_breakdown = {}; + inst_breakdown.type_name = type_name; + inst_breakdown.num_in_clust = num_in_clust; + + // sort cat info in cat_breakdown + bar_data = []; + var bar_color; + var cat_title_and_name; + var inst_run_count = tmp_run_count[type_name]; + + for (var inst_cat in inst_run_count) { + + var tot_num_cat = params.viz.cat_info[inst_rc][cat_index].cat_hist[inst_cat]; + var total_nodes = params.network_data[inst_rc + '_nodes'].length; + var expect_prob = tot_num_cat / total_nodes; + + // if no cat-title given + if (no_title_given) { + cat_title_and_name = inst_cat; + } else { + cat_title_and_name = type_name + ': ' + inst_cat; + } + + // num_nodes: number of cat-nodes drawn in cluster + var num_nodes = inst_run_count[inst_cat].num_nodes; + + var actual_k = num_nodes; + var pval = binom_test(actual_k, num_in_clust, expect_prob); + + // working on tracking the 'real' number of nodes, which is only different + // if downsampling has been done + if (_.has(inst_run_count[inst_cat], 'num_nodes_ds')) { + var num_nodes_ds = inst_run_count[inst_cat].num_nodes_ds; + } else { + num_nodes_ds = null; + } + + bar_color = params.viz.cat_colors[inst_rc][cat_index][cat_title_and_name]; + + bar_data.push([cat_index, cat_title_and_name, inst_run_count[inst_cat], bar_color, num_nodes, num_nodes_ds, pval]); + } + + bar_data.sort(function (a, b) { + return b[sorting_index] - a[sorting_index]; + }); + + inst_breakdown.bar_data = bar_data; + + cat_breakdown.push(inst_breakdown); + }); + } + } + + return cat_breakdown; + }; + +/***/ }, +/* 65 */ +/***/ function(module, exports, __webpack_require__) { + + + // Load the math.js core + // Create a new, empty math.js instance + // It will only contain methods `import` and `config` + // math.import(require('mathjs/lib/type/fraction')); + var p_dict = __webpack_require__(66); + var core = __webpack_require__(67); + var math = core.create(); + + math.import(__webpack_require__(79)); + + module.exports = function binom_test(actual_k, n, p) { + + var fact = math.factorial; + var pval; + + function binom_dist(k, n, p) { + var bin_coeff = fact(n) / (fact(k) * fact(n - k)); + p = bin_coeff * (Math.pow(p, k) * Math.pow(1 - p, n - k)); + return p; + } + + function my_binom_test_2(actual_k, n, p) { + var cp = 0; + var k; + var dp; + for (var inst_k = actual_k; inst_k < n + 1; inst_k++) { + k = inst_k; + dp = binom_dist(k, n, p); + cp = cp + dp; + } + + return cp; + } + + // look up p-value from z-score using table + function binom_prop_table(actual_k, n, p) { + + // expected average number of successes + var mu = n * p; + + // standard deviation + var sigma = Math.sqrt(n * p * (1 - p)); + + // how many standard deviations is the actual_k away + // from the expected value + var z = (actual_k - mu) / sigma; + + var z_vals = p_dict.z; + var p_vals = p_dict.p; + + var found_index = -1; + var found = false; + + for (var index = 0; index < z_vals.length; index++) { + var inst_z = z_vals[index]; + + // increasing inst_z until z is less than inst_z + if (z < inst_z && found === false) { + found_index = index; + found = true; + } + } + + // give it the smallest p-val if the z-score was larger than + // any in the table + if (found_index === -1) { + found_index = z_vals.length - 1; + } + pval = p_vals[found_index]; + + return pval; + } + + // calculate pval + pval = my_binom_test_2(actual_k, n, p); + if (isNaN(pval)) { + pval = binom_prop_table(actual_k, n, p); + } + + return pval; + }; + +/***/ }, +/* 66 */ +/***/ function(module, exports) { + + module.exports = { + "p": [0.5, 0.48006119416162751, 0.46017216272297101, 0.4403823076297575, 0.42074029056089696, 0.4012936743170763, 0.38208857781104733, 0.3631693488243809, 0.34457825838967582, 0.32635522028791997, 0.30853753872598688, 0.29115968678834636, 0.27425311775007355, 0.25784611080586473, 0.24196365222307303, 0.22662735237686821, 0.21185539858339669, 0.19766254312269238, 0.18406012534675947, 0.17105612630848183, 0.15865525393145707, 0.14685905637589591, 0.13566606094638267, 0.12507193563715024, 0.11506967022170828, 0.10564977366685535, 0.096800484585610358, 0.088507991437401956, 0.080756659233771066, 0.073529259609648304, 0.066807201268858071, 0.060570758002059008, 0.054799291699557974, 0.049471468033648075, 0.044565462758543006, 0.040059156863817086, 0.035930319112925789, 0.032156774795613713, 0.028716559816001783, 0.025588059521638611, 0.022750131948179195, 0.020182215405704383, 0.017864420562816542, 0.015777607391090499, 0.013903447513498595, 0.012224472655044696, 0.010724110021675795, 0.0093867055348385662, 0.0081975359245961138, 0.0071428107352714152, 0.0062096653257761323, 0.0053861459540666843, 0.0046611880237187467, 0.0040245885427583027, 0.0034669738030406647, 0.0029797632350545551, 0.002555130330427929, 0.0021859614549132405, 0.0018658133003840339, 0.0015888696473648667, 0.0013498980316300933, 0.0011442068310226977, 0.00096760321321835631, 0.00081635231282856037, 0.00068713793791584708, 0.00057702504239076592, 0.00048342414238377663, 0.0004040578018640207, 0.00033692926567687988, 0.00028029327681617744, 0.00023262907903552502, 0.00019261557563563279, 0.00015910859015753364, 0.00013112015442048433, 0.00010779973347738823, 8.8417285200803773e-05, 7.2348043925119787e-05, 5.9058912418922374e-05, 4.8096344017602614e-05, 3.9075596597787456e-05, 3.1671241833119863e-05, 2.5608816474041489e-05, 2.0657506912546683e-05, 1.6623763729652213e-05, 1.334574901590631e-05, 1.0688525774934402e-05, 8.5399054709917942e-06, 6.8068765993340312e-06, 5.4125439077038407e-06, 4.293514469971858e-06, 3.3976731247300535e-06, 2.6822957796388472e-06, 2.1124547025028419e-06, 1.6596751443714555e-06, 1.3008074539172771e-06, 1.0170832425687032e-06, 7.9332815197558919e-07, 6.1730737200919249e-07, 4.7918327659031855e-07, 3.7106740796333271e-07, 2.8665157187919333e-07, 2.2090503226954194e-07, 1.6982674071475937e-07, 1.3024322953320117e-07, 9.9644263169334701e-08, 7.6049605164887e-08, 5.7901340399645569e-08, 4.3977115940058689e-08, 3.3320448485428448e-08, 2.518491005446105e-08, 1.8989562465887681e-08, 1.4283479893922661e-08, 1.0717590258310852e-08, 8.0223918506634739e-09, 5.9903714010635304e-09, 4.4621724539016108e-09, 3.3157459783261365e-09, 2.4578650618080152e-09, 1.8175078630994235e-09, 1.3407124440918662e-09, 9.8658764503769458e-10, 7.2422917051376055e-10, 5.303423262948808e-10, 3.8741473466756636e-10, 2.8231580370432682e-10, 2.0522634252189396e-10, 1.4882282217622966e-10, 1.0765746385121517e-10, 7.7688475817097756e-11, 5.592507575942645e-11, 4.0160005838590881e-11, 2.8768541736043109e-11, 2.055788909399508e-11, 1.4654650977302715e-11, 1.0420976987965154e-11, 7.3922577780177942e-12, 5.2309575441445253e-12, 3.6924994272355614e-12, 2.600126965638173e-12, 1.8264310619769611e-12, 1.279812543885835e-12, 8.9458895587698439e-13, 6.23784446333152e-13, 4.3388950271780343e-13, 3.0106279811174218e-13, 2.0838581586720548e-13, 1.4388386381575764e-13, 9.9103427495475088e-14, 6.8092248906200155e-14, 4.6670115887190274e-14, 3.1908916729108844e-14, 2.1762912097085575e-14, 1.4806537490047908e-14, 1.0048965656526223e-14, 6.8033115407739012e-15, 4.5946274357785623e-15, 3.095358771958668e-15, 2.0801863521393674e-15, 1.394517146659261e-15, 9.3255757716812045e-16, 6.2209605742717405e-16, 4.1397018162731219e-16, 2.7479593923982212e-16, 1.8196213635266084e-16, 1.2019351542735647e-16, 7.9197263146424757e-17, 5.2055697448902465e-17, 3.4131483264581459e-17, 2.232393197288031e-17, 1.456514112590909e-17, 9.4795348222032499e-18, 6.1544255908503949e-18, 3.985804962848151e-18, 2.5749715380118873e-18, 1.6594208699647519e-18, 1.0667637375474856e-18, 6.840807685935497e-19, 4.3759647993090167e-19, 2.7923343749396233e-19, 1.7774117841455144e-19, 1.1285884059538324e-19, 7.1484170112696837e-20, 4.516591491435403e-20, 2.8466774084602088e-20, 1.7897488120140146e-20, 1.1224633591327901e-20, 7.0222842404415411e-21, 4.3823862990664603e-21, 2.7281535713460872e-21, 1.6941535024881097e-21, 1.0494515075362604e-21, 6.4848144530772079e-22, 3.9972212057261192e-22, 2.4577864834723153e-22, 1.5074931688101589e-22, 9.2234135249393526e-23, 5.6292823113765143e-23, 3.4271987941135974e-23, 2.0813752194932085e-23, 1.2609160670206559e-23], + "z": [0.0, 0.050000000000000003, 0.10000000000000001, 0.15000000000000002, 0.20000000000000001, 0.25, 0.30000000000000004, 0.35000000000000003, 0.40000000000000002, 0.45000000000000001, 0.5, 0.55000000000000004, 0.60000000000000009, 0.65000000000000002, 0.70000000000000007, 0.75, 0.80000000000000004, 0.85000000000000009, 0.90000000000000002, 0.95000000000000007, 1.0, 1.05, 1.1000000000000001, 1.1500000000000001, 1.2000000000000002, 1.25, 1.3, 1.3500000000000001, 1.4000000000000001, 1.4500000000000002, 1.5, 1.55, 1.6000000000000001, 1.6500000000000001, 1.7000000000000002, 1.75, 1.8, 1.8500000000000001, 1.9000000000000001, 1.9500000000000002, 2.0, 2.0500000000000003, 2.1000000000000001, 2.1499999999999999, 2.2000000000000002, 2.25, 2.3000000000000003, 2.3500000000000001, 2.4000000000000004, 2.4500000000000002, 2.5, 2.5500000000000003, 2.6000000000000001, 2.6500000000000004, 2.7000000000000002, 2.75, 2.8000000000000003, 2.8500000000000001, 2.9000000000000004, 2.9500000000000002, 3.0, 3.0500000000000003, 3.1000000000000001, 3.1500000000000004, 3.2000000000000002, 3.25, 3.3000000000000003, 3.3500000000000001, 3.4000000000000004, 3.4500000000000002, 3.5, 3.5500000000000003, 3.6000000000000001, 3.6500000000000004, 3.7000000000000002, 3.75, 3.8000000000000003, 3.8500000000000001, 3.9000000000000004, 3.9500000000000002, 4.0, 4.0499999999999998, 4.1000000000000005, 4.1500000000000004, 4.2000000000000002, 4.25, 4.2999999999999998, 4.3500000000000005, 4.4000000000000004, 4.4500000000000002, 4.5, 4.5499999999999998, 4.6000000000000005, 4.6500000000000004, 4.7000000000000002, 4.75, 4.8000000000000007, 4.8500000000000005, 4.9000000000000004, 4.9500000000000002, 5.0, 5.0500000000000007, 5.1000000000000005, 5.1500000000000004, 5.2000000000000002, 5.25, 5.3000000000000007, 5.3500000000000005, 5.4000000000000004, 5.4500000000000002, 5.5, 5.5500000000000007, 5.6000000000000005, 5.6500000000000004, 5.7000000000000002, 5.75, 5.8000000000000007, 5.8500000000000005, 5.9000000000000004, 5.9500000000000002, 6.0, 6.0500000000000007, 6.1000000000000005, 6.1500000000000004, 6.2000000000000002, 6.25, 6.3000000000000007, 6.3500000000000005, 6.4000000000000004, 6.4500000000000002, 6.5, 6.5500000000000007, 6.6000000000000005, 6.6500000000000004, 6.7000000000000002, 6.75, 6.8000000000000007, 6.8500000000000005, 6.9000000000000004, 6.9500000000000002, 7.0, 7.0500000000000007, 7.1000000000000005, 7.1500000000000004, 7.2000000000000002, 7.25, 7.3000000000000007, 7.3500000000000005, 7.4000000000000004, 7.4500000000000002, 7.5, 7.5500000000000007, 7.6000000000000005, 7.6500000000000004, 7.7000000000000002, 7.75, 7.8000000000000007, 7.8500000000000005, 7.9000000000000004, 7.9500000000000002, 8.0, 8.0500000000000007, 8.0999999999999996, 8.1500000000000004, 8.2000000000000011, 8.25, 8.3000000000000007, 8.3499999999999996, 8.4000000000000004, 8.4500000000000011, 8.5, 8.5500000000000007, 8.5999999999999996, 8.6500000000000004, 8.7000000000000011, 8.75, 8.8000000000000007, 8.8499999999999996, 8.9000000000000004, 8.9500000000000011, 9.0, 9.0500000000000007, 9.0999999999999996, 9.1500000000000004, 9.2000000000000011, 9.25, 9.3000000000000007, 9.3499999999999996, 9.4000000000000004, 9.4500000000000011, 9.5, 9.5500000000000007, 9.6000000000000014, 9.6500000000000004, 9.7000000000000011, 9.75, 9.8000000000000007, 9.8500000000000014, 9.9000000000000004, 9.9500000000000011] + }; + +/***/ }, +/* 67 */ +/***/ function(module, exports, __webpack_require__) { + + module.exports = __webpack_require__(68); + +/***/ }, +/* 68 */ +/***/ function(module, exports, __webpack_require__) { + + var isFactory = __webpack_require__(69).isFactory; + var deepExtend = __webpack_require__(69).deepExtend; + var typedFactory = __webpack_require__(70); + var emitter = __webpack_require__(74); + + var importFactory = __webpack_require__(76); + var configFactory = __webpack_require__(78); + + /** + * 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(-2)` + * returns `NaN` when predictable is false, and + * returns `complex('2i')` when true. + * @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: Object.create(math) + }; + + // 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(-2)` returns `NaN` when + // predictable is false, and returns `complex('2i')` when true. + predictable: false + }; + + /** + * 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); + + // apply options + if (options) { + math.config(options); + } + + return math; + }; + +/***/ }, +/* 69 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * 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; + + // 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 (x && x.isBigNumber === true) return x; // bignumbers are immutable + if (x instanceof RegExp) throw new TypeError('Cannot clone ' + x); // TODO: clone a RegExp + + // object + var m = {}; + for (var key in x) { + if (x.hasOwnProperty(key)) { + m[key] = clone(x[key]); + } + } + return m; + }; + + /** + * 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 (b.hasOwnProperty(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 (b.hasOwnProperty(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 === 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 () {} }); + 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 () { + if (_uninitialized) { + _value = fn(); + _uninitialized = false; + } + return _value; + }, + + set: function (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; + }; + + /** + * 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'; + }; + +/***/ }, +/* 70 */ +/***/ function(module, exports, __webpack_require__) { + + var typedFunction = __webpack_require__(71); + var digits = __webpack_require__(72).digits; + + // returns a new instance of typed-function + var createTyped = function () { + // 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 + + // 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: function (x) { + return typeof x === 'number'; + } }, { name: 'Complex', test: function (x) { + return x && x.isComplex; + } }, { name: 'BigNumber', test: function (x) { + return x && x.isBigNumber; + } }, { name: 'Fraction', test: function (x) { + return x && x.isFraction; + } }, { name: 'Unit', test: function (x) { + return x && x.isUnit; + } }, { name: 'string', test: function (x) { + return typeof x === 'string'; + } }, { name: 'Array', test: Array.isArray }, { name: 'Matrix', test: function (x) { + return x && x.isMatrix; + } }, { name: 'DenseMatrix', test: function (x) { + return x && x.isDenseMatrix; + } }, { name: 'SparseMatrix', test: function (x) { + return x && x.isSparseMatrix; + } }, { name: 'ImmutableDenseMatrix', test: function (x) { + return x && x.isImmutableDenseMatrix; + } }, { name: 'Range', test: function (x) { + return x && x.isRange; + } }, { name: 'Index', test: function (x) { + return x && x.isIndex; + } }, { name: 'boolean', test: function (x) { + return typeof x === 'boolean'; + } }, { name: 'ResultSet', test: function (x) { + return x && x.isResultSet; + } }, { name: 'Help', test: function (x) { + return x && x.isHelp; + } }, { name: 'function', test: function (x) { + return typeof x === 'function'; + } }, { name: 'Date', test: function (x) { + return x instanceof Date; + } }, { name: 'RegExp', test: function (x) { + return x instanceof RegExp; + } }, { name: 'Object', test: function (x) { + return typeof x === 'object'; + } }, { name: 'null', test: function (x) { + return x === null; + } }, { name: 'undefined', test: function (x) { + return x === undefined; + } }]; + + // TODO: add conversion from BigNumber to number? + typed.conversions = [{ + from: 'number', + to: 'BigNumber', + convert: function (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 (x) { + return new type.Complex(x, 0); + } + }, { + from: 'number', + to: 'string', + convert: function (x) { + return x + ''; + } + }, { + from: 'BigNumber', + to: 'Complex', + convert: function (x) { + return new type.Complex(x.toNumber(), 0); + } + }, { + from: 'Fraction', + to: 'Complex', + convert: function (x) { + return new type.Complex(x.valueOf(), 0); + } + }, { + from: 'number', + to: 'Fraction', + convert: function (x) { + if (digits(x) > 15) { + throw new TypeError('Cannot implicitly convert a number with >15 significant digits to Fraction ' + '(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 (x) { + var n = Number(x); + if (isNaN(n)) { + throw new Error('Cannot convert "' + x + '" to a number'); + } + return n; + } + }, { + from: 'boolean', + to: 'number', + convert: function (x) { + return +x; + } + }, { + from: 'boolean', + to: 'BigNumber', + convert: function (x) { + return new type.BigNumber(+x); + } + }, { + from: 'boolean', + to: 'Fraction', + convert: function (x) { + return new type.Fraction(+x); + } + }, { + from: 'boolean', + to: 'string', + convert: function (x) { + return +x; + } + }, { + from: 'null', + to: 'number', + convert: function () { + return 0; + } + }, { + from: 'null', + to: 'string', + convert: function () { + return 'null'; + } + }, { + from: 'null', + to: 'BigNumber', + convert: function () { + return new type.BigNumber(0); + } + }, { + from: 'null', + to: 'Fraction', + convert: function () { + return new type.Fraction(0); + } + }, { + from: 'Array', + to: 'Matrix', + convert: function (array) { + // TODO: how to decide on the right type of matrix to create? + return new type.DenseMatrix(array); + } + }, { + from: 'Matrix', + to: 'Array', + convert: function (matrix) { + return matrix.valueOf(); + } + }]; + + return typed; + }; + +/***/ }, +/* 71 */ +/***/ 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'; + + (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 === '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(); + } + })(this, function () { + // factory function to create a new instance of typed-function + // TODO: allow passing configuration, types, tests via the factory function + function create() { + /** + * Get a type test function for a specific data type + * @param {string} name Name of a data type like 'number' or 'string' + * @returns {Function(obj: *) : boolean} Returns a type testing function. + * Throws an error for an unknown type. + */ + function getTypeTest(name) { + var test; + for (var i = 0; i < typed.types.length; i++) { + var entry = typed.types[i]; + if (entry.name === name) { + test = entry.test; + break; + } + } + + if (!test) { + var hint; + for (i = 0; i < typed.types.length; i++) { + entry = typed.types[i]; + if (entry.name.toLowerCase() == name.toLowerCase()) { + hint = entry.name; + break; + } + } + + throw new Error('Unknown type "' + name + '"' + (hint ? '. Did you mean "' + hint + '"?' : '')); + } + return test; + } + + /** + * Retrieve the function name from a set of functions, and check + * whether the name of all functions match (if given) + * @param {Array.<function>} fns + */ + function getName(fns) { + var name = ''; + + for (var i = 0; i < fns.length; i++) { + var fn = fns[i]; + + // merge function name when this is a typed function + if (fn.signatures && fn.name != '') { + if (name == '') { + name = fn.name; + } else if (name != fn.name) { + var err = new Error('Function names do not match (expected: ' + name + ', actual: ' + fn.name + ')'); + err.data = { + actual: fn.name, + expected: name + }; + throw err; + } + } + } + + return name; + } + + /** + * Create an ArgumentsError. Creates messages like: + * + * Unexpected type of argument (expected: ..., actual: ..., index: ...) + * Too few arguments (expected: ..., index: ...) + * Too many arguments (expected: ..., actual: ...) + * + * @param {String} fn Function name + * @param {number} argCount Number of arguments + * @param {Number} index Current argument index + * @param {*} actual Current argument + * @param {string} [expected] An optional, comma separated string with + * expected types on given index + * @extends Error + */ + function createError(fn, argCount, index, actual, expected) { + var actualType = getTypeOf(actual); + var _expected = expected ? expected.split(',') : null; + var _fn = fn || 'unnamed'; + var anyType = _expected && contains(_expected, 'any'); + var message; + var data = { + fn: fn, + index: index, + actual: actual, + expected: _expected + }; + + if (_expected) { + if (argCount > index && !anyType) { + // unexpected type + message = 'Unexpected type of argument in function ' + _fn + ' (expected: ' + _expected.join(' or ') + ', actual: ' + actualType + ', index: ' + index + ')'; + } else { + // too few arguments + message = 'Too few arguments in function ' + _fn + ' (expected: ' + _expected.join(' or ') + ', index: ' + index + ')'; + } + } else { + // too many arguments + message = 'Too many arguments in function ' + _fn + ' (expected: ' + index + ', actual: ' + argCount + ')'; + } + + var err = new TypeError(message); + err.data = data; + return err; + } + + /** + * Collection with function references (local shortcuts to functions) + * @constructor + * @param {string} [name='refs'] Optional name for the refs, used to generate + * JavaScript code + */ + function Refs(name) { + this.name = name || 'refs'; + this.categories = {}; + } + + /** + * Add a function reference. + * @param {Function} fn + * @param {string} [category='fn'] A function category, like 'fn' or 'signature' + * @returns {string} Returns the function name, for example 'fn0' or 'signature2' + */ + Refs.prototype.add = function (fn, category) { + var cat = category || 'fn'; + if (!this.categories[cat]) this.categories[cat] = []; + + var index = this.categories[cat].indexOf(fn); + if (index == -1) { + index = this.categories[cat].length; + this.categories[cat].push(fn); + } + + return cat + index; + }; + + /** + * Create code lines for all function references + * @returns {string} Returns the code containing all function references + */ + Refs.prototype.toCode = function () { + var code = []; + var path = this.name + '.categories'; + var categories = this.categories; + + for (var cat in categories) { + if (categories.hasOwnProperty(cat)) { + var category = categories[cat]; + + for (var i = 0; i < category.length; i++) { + code.push('var ' + cat + i + ' = ' + path + '[\'' + cat + '\'][' + i + '];'); + } + } + } + + return code.join('\n'); + }; + + /** + * A function parameter + * @param {string | string[] | Param} types A parameter type like 'string', + * 'number | boolean' + * @param {boolean} [varArgs=false] Variable arguments if true + * @constructor + */ + function Param(types, varArgs) { + // parse the types, can be a string with types separated by pipe characters | + if (typeof types === 'string') { + // parse variable arguments operator (ellipses '...number') + var _types = types.trim(); + var _varArgs = _types.substr(0, 3) === '...'; + if (_varArgs) { + _types = _types.substr(3); + } + if (_types === '') { + this.types = ['any']; + } else { + this.types = _types.split('|'); + for (var i = 0; i < this.types.length; i++) { + this.types[i] = this.types[i].trim(); + } + } + } else if (Array.isArray(types)) { + this.types = types; + } else if (types instanceof Param) { + return types.clone(); + } else { + throw new Error('String or Array expected'); + } + + // can hold a type to which to convert when handling this parameter + this.conversions = []; + // TODO: implement better API for conversions, be able to add conversions via constructor (support a new type Object?) + + // variable arguments + this.varArgs = _varArgs || varArgs || false; + + // check for any type arguments + this.anyType = this.types.indexOf('any') !== -1; + } + + /** + * Order Params + * any type ('any') will be ordered last, and object as second last (as other + * types may be an object as well, like Array). + * + * @param {Param} a + * @param {Param} b + * @returns {number} Returns 1 if a > b, -1 if a < b, and else 0. + */ + Param.compare = function (a, b) { + // TODO: simplify parameter comparison, it's a mess + if (a.anyType) return 1; + if (b.anyType) return -1; + + if (contains(a.types, 'Object')) return 1; + if (contains(b.types, 'Object')) return -1; + + if (a.hasConversions()) { + if (b.hasConversions()) { + var i, ac, bc; + + for (i = 0; i < a.conversions.length; i++) { + if (a.conversions[i] !== undefined) { + ac = a.conversions[i]; + break; + } + } + + for (i = 0; i < b.conversions.length; i++) { + if (b.conversions[i] !== undefined) { + bc = b.conversions[i]; + break; + } + } + + return typed.conversions.indexOf(ac) - typed.conversions.indexOf(bc); + } else { + return 1; + } + } else { + if (b.hasConversions()) { + return -1; + } else { + // both params have no conversions + var ai, bi; + + for (i = 0; i < typed.types.length; i++) { + if (typed.types[i].name === a.types[0]) { + ai = i; + break; + } + } + + for (i = 0; i < typed.types.length; i++) { + if (typed.types[i].name === b.types[0]) { + bi = i; + break; + } + } + + return ai - bi; + } + } + }; + + /** + * Test whether this parameters types overlap an other parameters types. + * @param {Param} other + * @return {boolean} Returns true when there are conflicting types + */ + Param.prototype.overlapping = function (other) { + for (var i = 0; i < this.types.length; i++) { + if (contains(other.types, this.types[i])) { + return true; + } + } + return false; + }; + + /** + * Create a clone of this param + * @returns {Param} Returns a cloned version of this param + */ + Param.prototype.clone = function () { + var param = new Param(this.types.slice(), this.varArgs); + param.conversions = this.conversions.slice(); + return param; + }; + + /** + * Test whether this parameter contains conversions + * @returns {boolean} Returns true if the parameter contains one or + * multiple conversions. + */ + Param.prototype.hasConversions = function () { + return this.conversions.length > 0; + }; + + /** + * Tests whether this parameters contains any of the provided types + * @param {Object} types A Map with types, like {'number': true} + * @returns {boolean} Returns true when the parameter contains any + * of the provided types + */ + Param.prototype.contains = function (types) { + for (var i = 0; i < this.types.length; i++) { + if (types[this.types[i]]) { + return true; + } + } + return false; + }; + + /** + * Return a string representation of this params types, like 'string' or + * 'number | boolean' or '...number' + * @param {boolean} [toConversion] If true, the returned types string + * contains the types where the parameter + * will convert to. If false (default) + * the "from" types are returned + * @returns {string} + */ + Param.prototype.toString = function (toConversion) { + var types = []; + var keys = {}; + + for (var i = 0; i < this.types.length; i++) { + var conversion = this.conversions[i]; + var type = toConversion && conversion ? conversion.to : this.types[i]; + if (!(type in keys)) { + keys[type] = true; + types.push(type); + } + } + + return (this.varArgs ? '...' : '') + types.join('|'); + }; + + /** + * A function signature + * @param {string | string[] | Param[]} params + * Array with the type(s) of each parameter, + * or a comma separated string with types + * @param {Function} fn The actual function + * @constructor + */ + function Signature(params, fn) { + var _params; + if (typeof params === 'string') { + _params = params !== '' ? params.split(',') : []; + } else if (Array.isArray(params)) { + _params = params; + } else { + throw new Error('string or Array expected'); + } + + this.params = new Array(_params.length); + for (var i = 0; i < _params.length; i++) { + var param = new Param(_params[i]); + this.params[i] = param; + if (i === _params.length - 1) { + // the last argument + this.varArgs = param.varArgs; + } else { + // non-last argument + if (param.varArgs) { + throw new SyntaxError('Unexpected variable arguments operator "..."'); + } + } + } + + this.fn = fn; + } + + /** + * Create a clone of this signature + * @returns {Signature} Returns a cloned version of this signature + */ + Signature.prototype.clone = function () { + return new Signature(this.params.slice(), this.fn); + }; + + /** + * Expand a signature: split params with union types in separate signatures + * For example split a Signature "string | number" into two signatures. + * @return {Signature[]} Returns an array with signatures (at least one) + */ + Signature.prototype.expand = function () { + var signatures = []; + + function recurse(signature, path) { + if (path.length < signature.params.length) { + var i, newParam, conversion; + + var param = signature.params[path.length]; + if (param.varArgs) { + // a variable argument. do not split the types in the parameter + newParam = param.clone(); + + // add conversions to the parameter + // recurse for all conversions + for (i = 0; i < typed.conversions.length; i++) { + conversion = typed.conversions[i]; + if (!contains(param.types, conversion.from) && contains(param.types, conversion.to)) { + var j = newParam.types.length; + newParam.types[j] = conversion.from; + newParam.conversions[j] = conversion; + } + } + + recurse(signature, path.concat(newParam)); + } else { + // split each type in the parameter + for (i = 0; i < param.types.length; i++) { + recurse(signature, path.concat(new Param(param.types[i]))); + } + + // recurse for all conversions + for (i = 0; i < typed.conversions.length; i++) { + conversion = typed.conversions[i]; + if (!contains(param.types, conversion.from) && contains(param.types, conversion.to)) { + newParam = new Param(conversion.from); + newParam.conversions[0] = conversion; + recurse(signature, path.concat(newParam)); + } + } + } + } else { + signatures.push(new Signature(path, signature.fn)); + } + } + + recurse(this, []); + + return signatures; + }; + + /** + * Compare two signatures. + * + * When two params are equal and contain conversions, they will be sorted + * by lowest index of the first conversions. + * + * @param {Signature} a + * @param {Signature} b + * @returns {number} Returns 1 if a > b, -1 if a < b, and else 0. + */ + Signature.compare = function (a, b) { + if (a.params.length > b.params.length) return 1; + if (a.params.length < b.params.length) return -1; + + // count the number of conversions + var i; + var len = a.params.length; // a and b have equal amount of params + var ac = 0; + var bc = 0; + for (i = 0; i < len; i++) { + if (a.params[i].hasConversions()) ac++; + if (b.params[i].hasConversions()) bc++; + } + + if (ac > bc) return 1; + if (ac < bc) return -1; + + // compare the order per parameter + for (i = 0; i < a.params.length; i++) { + var cmp = Param.compare(a.params[i], b.params[i]); + if (cmp !== 0) { + return cmp; + } + } + + return 0; + }; + + /** + * Test whether any of the signatures parameters has conversions + * @return {boolean} Returns true when any of the parameters contains + * conversions. + */ + Signature.prototype.hasConversions = function () { + for (var i = 0; i < this.params.length; i++) { + if (this.params[i].hasConversions()) { + return true; + } + } + return false; + }; + + /** + * Test whether this signature should be ignored. + * Checks whether any of the parameters contains a type listed in + * typed.ignore + * @return {boolean} Returns true when the signature should be ignored + */ + Signature.prototype.ignore = function () { + // create a map with ignored types + var types = {}; + for (var i = 0; i < typed.ignore.length; i++) { + types[typed.ignore[i]] = true; + } + + // test whether any of the parameters contains this type + for (i = 0; i < this.params.length; i++) { + if (this.params[i].contains(types)) { + return true; + } + } + + return false; + }; + + /** + * Generate the code to invoke this signature + * @param {Refs} refs + * @param {string} prefix + * @returns {string} Returns code + */ + Signature.prototype.toCode = function (refs, prefix) { + var code = []; + + var args = new Array(this.params.length); + for (var i = 0; i < this.params.length; i++) { + var param = this.params[i]; + var conversion = param.conversions[0]; + if (param.varArgs) { + args[i] = 'varArgs'; + } else if (conversion) { + args[i] = refs.add(conversion.convert, 'convert') + '(arg' + i + ')'; + } else { + args[i] = 'arg' + i; + } + } + + var ref = this.fn ? refs.add(this.fn, 'signature') : undefined; + if (ref) { + return prefix + 'return ' + ref + '(' + args.join(', ') + '); // signature: ' + this.params.join(', '); + } + + return code.join('\n'); + }; + + /** + * Return a string representation of the signature + * @returns {string} + */ + Signature.prototype.toString = function () { + return this.params.join(', '); + }; + + /** + * A group of signatures with the same parameter on given index + * @param {Param[]} path + * @param {Signature} [signature] + * @param {Node[]} childs + * @constructor + */ + function Node(path, signature, childs) { + this.path = path || []; + this.param = path[path.length - 1] || null; + this.signature = signature || null; + this.childs = childs || []; + } + + /** + * Generate code for this group of signatures + * @param {Refs} refs + * @param {string} prefix + * @param {Node | undefined} [anyType] Sibling of this node with any type parameter + * @returns {string} Returns the code as string + */ + Node.prototype.toCode = function (refs, prefix, anyType) { + // TODO: split this function in multiple functions, it's too large + var code = []; + + if (this.param) { + var index = this.path.length - 1; + var conversion = this.param.conversions[0]; + var comment = '// type: ' + (conversion ? conversion.from + ' (convert to ' + conversion.to + ')' : this.param); + + // non-root node (path is non-empty) + if (this.param.varArgs) { + if (this.param.anyType) { + // variable arguments with any type + code.push(prefix + 'if (arguments.length > ' + index + ') {'); + code.push(prefix + ' var varArgs = [];'); + code.push(prefix + ' for (var i = ' + index + '; i < arguments.length; i++) {'); + code.push(prefix + ' varArgs.push(arguments[i]);'); + code.push(prefix + ' }'); + code.push(this.signature.toCode(refs, prefix + ' ')); + code.push(prefix + '}'); + } else { + // variable arguments with a fixed type + var getTests = function (types, arg) { + var tests = []; + for (var i = 0; i < types.length; i++) { + tests[i] = refs.add(getTypeTest(types[i]), 'test') + '(' + arg + ')'; + } + return tests.join(' || '); + }.bind(this); + + var allTypes = this.param.types; + var exactTypes = []; + for (var i = 0; i < allTypes.length; i++) { + if (this.param.conversions[i] === undefined) { + exactTypes.push(allTypes[i]); + } + } + + code.push(prefix + 'if (' + getTests(allTypes, 'arg' + index) + ') { ' + comment); + code.push(prefix + ' var varArgs = [arg' + index + '];'); + code.push(prefix + ' for (var i = ' + (index + 1) + '; i < arguments.length; i++) {'); + code.push(prefix + ' if (' + getTests(exactTypes, 'arguments[i]') + ') {'); + code.push(prefix + ' varArgs.push(arguments[i]);'); + + for (var i = 0; i < allTypes.length; i++) { + var conversion_i = this.param.conversions[i]; + if (conversion_i) { + var test = refs.add(getTypeTest(allTypes[i]), 'test'); + var convert = refs.add(conversion_i.convert, 'convert'); + code.push(prefix + ' }'); + code.push(prefix + ' else if (' + test + '(arguments[i])) {'); + code.push(prefix + ' varArgs.push(' + convert + '(arguments[i]));'); + } + } + code.push(prefix + ' } else {'); + code.push(prefix + ' throw createError(name, arguments.length, i, arguments[i], \'' + exactTypes.join(',') + '\');'); + code.push(prefix + ' }'); + code.push(prefix + ' }'); + code.push(this.signature.toCode(refs, prefix + ' ')); + code.push(prefix + '}'); + } + } else { + if (this.param.anyType) { + // any type + code.push(prefix + '// type: any'); + code.push(this._innerCode(refs, prefix, anyType)); + } else { + // regular type + var type = this.param.types[0]; + var test = type !== 'any' ? refs.add(getTypeTest(type), 'test') : null; + + code.push(prefix + 'if (' + test + '(arg' + index + ')) { ' + comment); + code.push(this._innerCode(refs, prefix + ' ', anyType)); + code.push(prefix + '}'); + } + } + } else { + // root node (path is empty) + code.push(this._innerCode(refs, prefix, anyType)); + } + + return code.join('\n'); + }; + + /** + * Generate inner code for this group of signatures. + * This is a helper function of Node.prototype.toCode + * @param {Refs} refs + * @param {string} prefix + * @param {Node | undefined} [anyType] Sibling of this node with any type parameter + * @returns {string} Returns the inner code as string + * @private + */ + Node.prototype._innerCode = function (refs, prefix, anyType) { + var code = []; + var i; + + if (this.signature) { + code.push(prefix + 'if (arguments.length === ' + this.path.length + ') {'); + code.push(this.signature.toCode(refs, prefix + ' ')); + code.push(prefix + '}'); + } + + var nextAnyType; + for (i = 0; i < this.childs.length; i++) { + if (this.childs[i].param.anyType) { + nextAnyType = this.childs[i]; + break; + } + } + + for (i = 0; i < this.childs.length; i++) { + code.push(this.childs[i].toCode(refs, prefix, nextAnyType)); + } + + if (anyType && !this.param.anyType) { + code.push(anyType.toCode(refs, prefix, nextAnyType)); + } + + var exceptions = this._exceptions(refs, prefix); + if (exceptions) { + code.push(exceptions); + } + + return code.join('\n'); + }; + + /** + * Generate code to throw exceptions + * @param {Refs} refs + * @param {string} prefix + * @returns {string} Returns the inner code as string + * @private + */ + Node.prototype._exceptions = function (refs, prefix) { + var index = this.path.length; + + if (this.childs.length === 0) { + // TODO: can this condition be simplified? (we have a fall-through here) + return [prefix + 'if (arguments.length > ' + index + ') {', prefix + ' throw createError(name, arguments.length, ' + index + ', arguments[' + index + ']);', prefix + '}'].join('\n'); + } else { + var keys = {}; + var types = []; + + for (var i = 0; i < this.childs.length; i++) { + var node = this.childs[i]; + if (node.param) { + for (var j = 0; j < node.param.types.length; j++) { + var type = node.param.types[j]; + if (!(type in keys) && !node.param.conversions[j]) { + keys[type] = true; + types.push(type); + } + } + } + } + + return prefix + 'throw createError(name, arguments.length, ' + index + ', arguments[' + index + '], \'' + types.join(',') + '\');'; + } + }; + + /** + * Split all raw signatures into an array with expanded Signatures + * @param {Object.<string, Function>} rawSignatures + * @return {Signature[]} Returns an array with expanded signatures + */ + function parseSignatures(rawSignatures) { + // FIXME: need to have deterministic ordering of signatures, do not create via object + var signature; + var keys = {}; + var signatures = []; + var i; + + for (var types in rawSignatures) { + if (rawSignatures.hasOwnProperty(types)) { + var fn = rawSignatures[types]; + signature = new Signature(types, fn); + + if (signature.ignore()) { + continue; + } + + var expanded = signature.expand(); + + for (i = 0; i < expanded.length; i++) { + var signature_i = expanded[i]; + var key = signature_i.toString(); + var existing = keys[key]; + if (!existing) { + keys[key] = signature_i; + } else { + var cmp = Signature.compare(signature_i, existing); + if (cmp < 0) { + // override if sorted first + keys[key] = signature_i; + } else if (cmp === 0) { + throw new Error('Signature "' + key + '" is defined twice'); + } + // else: just ignore + } + } + } + } + + // convert from map to array + for (key in keys) { + if (keys.hasOwnProperty(key)) { + signatures.push(keys[key]); + } + } + + // order the signatures + signatures.sort(function (a, b) { + return Signature.compare(a, b); + }); + + // filter redundant conversions from signatures with varArgs + // TODO: simplify this loop or move it to a separate function + for (i = 0; i < signatures.length; i++) { + signature = signatures[i]; + + if (signature.varArgs) { + var index = signature.params.length - 1; + var param = signature.params[index]; + + var t = 0; + while (t < param.types.length) { + if (param.conversions[t]) { + var type = param.types[t]; + + for (var j = 0; j < signatures.length; j++) { + var other = signatures[j]; + var p = other.params[index]; + + if (other !== signature && p && contains(p.types, type) && !p.conversions[index]) { + // this (conversion) type already exists, remove it + param.types.splice(t, 1); + param.conversions.splice(t, 1); + t--; + break; + } + } + } + t++; + } + } + } + + return signatures; + } + + /** + * create a map with normalized signatures as key and the function as value + * @param {Signature[]} signatures An array with split signatures + * @return {Object.<string, Function>} Returns a map with normalized + * signatures as key, and the function + * as value. + */ + function mapSignatures(signatures) { + var normalized = {}; + + for (var i = 0; i < signatures.length; i++) { + var signature = signatures[i]; + if (signature.fn && !signature.hasConversions()) { + var params = signature.params.join(','); + normalized[params] = signature.fn; + } + } + + return normalized; + } + + /** + * Parse signatures recursively in a node tree. + * @param {Signature[]} signatures Array with expanded signatures + * @param {Param[]} path Traversed path of parameter types + * @return {Node} Returns a node tree + */ + function parseTree(signatures, path) { + var i, signature; + var index = path.length; + var nodeSignature; + + var filtered = []; + for (i = 0; i < signatures.length; i++) { + signature = signatures[i]; + + // filter the first signature with the correct number of params + if (signature.params.length === index && !nodeSignature) { + nodeSignature = signature; + } + + if (signature.params[index] != undefined) { + filtered.push(signature); + } + } + + // sort the filtered signatures by param + filtered.sort(function (a, b) { + return Param.compare(a.params[index], b.params[index]); + }); + + // recurse over the signatures + var entries = []; + for (i = 0; i < filtered.length; i++) { + signature = filtered[i]; + // group signatures with the same param at current index + var param = signature.params[index]; + + // TODO: replace the next filter loop + var existing = entries.filter(function (entry) { + return entry.param.overlapping(param); + })[0]; + + //var existing; + //for (var j = 0; j < entries.length; j++) { + // if (entries[j].param.overlapping(param)) { + // existing = entries[j]; + // break; + // } + //} + + if (existing) { + if (existing.param.varArgs) { + throw new Error('Conflicting types "' + existing.param + '" and "' + param + '"'); + } + existing.signatures.push(signature); + } else { + entries.push({ + param: param, + signatures: [signature] + }); + } + } + + // parse the childs + var childs = new Array(entries.length); + for (i = 0; i < entries.length; i++) { + var entry = entries[i]; + childs[i] = parseTree(entry.signatures, path.concat(entry.param)); + } + + return new Node(path, nodeSignature, childs); + } + + /** + * Generate an array like ['arg0', 'arg1', 'arg2'] + * @param {number} count Number of arguments to generate + * @returns {Array} Returns an array with argument names + */ + function getArgs(count) { + // create an array with all argument names + var args = []; + for (var i = 0; i < count; i++) { + args[i] = 'arg' + i; + } + + return args; + } + + /** + * Compose a function from sub-functions each handling a single type signature. + * Signatures: + * typed(signature: string, fn: function) + * typed(name: string, signature: string, fn: function) + * typed(signatures: Object.<string, function>) + * typed(name: string, signatures: Object.<string, function>) + * + * @param {string | null} name + * @param {Object.<string, Function>} signatures + * @return {Function} Returns the typed function + * @private + */ + function _typed(name, signatures) { + var refs = new Refs(); + + // parse signatures, expand them + var _signatures = parseSignatures(signatures); + if (_signatures.length == 0) { + throw new Error('No signatures provided'); + } + + // parse signatures into a node tree + var node = parseTree(_signatures, []); + + //var util = require('util'); + //console.log('ROOT'); + //console.log(util.inspect(node, { depth: null })); + + // generate code for the typed function + var code = []; + var _name = name || ''; + var _args = getArgs(maxParams(_signatures)); + code.push('function ' + _name + '(' + _args.join(', ') + ') {'); + code.push(' "use strict";'); + code.push(' var name = \'' + _name + '\';'); + code.push(node.toCode(refs, ' ')); + code.push('}'); + + // generate body for the factory function + var body = [refs.toCode(), 'return ' + code.join('\n')].join('\n'); + + // evaluate the JavaScript code and attach function references + var factory = new Function(refs.name, 'createError', body); + var fn = factory(refs, createError); + + //console.log('FN\n' + fn.toString()); // TODO: cleanup + + // attach the signatures with sub-functions to the constructed function + fn.signatures = mapSignatures(_signatures); + + return fn; + } + + /** + * Calculate the maximum number of parameters in givens signatures + * @param {Signature[]} signatures + * @returns {number} The maximum number of parameters + */ + function maxParams(signatures) { + var max = 0; + + for (var i = 0; i < signatures.length; i++) { + var len = signatures[i].params.length; + if (len > max) { + max = len; + } + } + + return max; + } + + /** + * Get the type of a value + * @param {*} x + * @returns {string} Returns a string with the type of value + */ + function getTypeOf(x) { + var obj; + + for (var i = 0; i < typed.types.length; i++) { + var entry = typed.types[i]; + + if (entry.name === 'Object') { + // Array and Date are also Object, so test for Object afterwards + obj = entry; + } else { + if (entry.test(x)) return entry.name; + } + } + + // at last, test whether an object + if (obj && obj.test(x)) return obj.name; + + return 'unknown'; + } + + /** + * Test whether an array contains some entry + * @param {Array} array + * @param {*} entry + * @return {boolean} Returns true if array contains entry, false if not. + */ + function contains(array, entry) { + return array.indexOf(entry) !== -1; + } + + // data type tests + var types = [{ name: 'number', test: function (x) { + return typeof x === 'number'; + } }, { name: 'string', test: function (x) { + return typeof x === 'string'; + } }, { name: 'boolean', test: function (x) { + return typeof x === 'boolean'; + } }, { name: 'Function', test: function (x) { + return typeof x === 'function'; + } }, { name: 'Array', test: Array.isArray }, { name: 'Date', test: function (x) { + return x instanceof Date; + } }, { name: 'RegExp', test: function (x) { + return x instanceof RegExp; + } }, { name: 'Object', test: function (x) { + return typeof x === 'object'; + } }, { name: 'null', test: function (x) { + return x === null; + } }, { name: 'undefined', test: function (x) { + return x === undefined; + } }]; + + // configuration + var config = {}; + + // type conversions. Order is important + var conversions = []; + + // types to be ignored + var ignore = []; + + // temporary object for holding types and conversions, for constructing + // the `typed` function itself + // TODO: find a more elegant solution for this + var typed = { + config: config, + types: types, + conversions: conversions, + ignore: ignore + }; + + /** + * Construct the typed function itself with various signatures + * + * Signatures: + * + * typed(signatures: Object.<string, function>) + * typed(name: string, signatures: Object.<string, function>) + */ + typed = _typed('typed', { + 'Object': function (signatures) { + var fns = []; + for (var signature in signatures) { + if (signatures.hasOwnProperty(signature)) { + fns.push(signatures[signature]); + } + } + var name = getName(fns); + + return _typed(name, signatures); + }, + 'string, Object': _typed, + // TODO: add a signature 'Array.<function>' + '...Function': function (fns) { + var err; + var name = getName(fns); + var signatures = {}; + + for (var i = 0; i < fns.length; i++) { + var fn = fns[i]; + + // test whether this is a typed-function + if (!(typeof fn.signatures === 'object')) { + err = new TypeError('Function is no typed-function (index: ' + i + ')'); + err.data = { index: i }; + throw err; + } + + // merge the signatures + for (var signature in fn.signatures) { + if (fn.signatures.hasOwnProperty(signature)) { + if (signatures.hasOwnProperty(signature)) { + if (fn.signatures[signature] !== signatures[signature]) { + err = new Error('Signature "' + signature + '" is defined twice'); + err.data = { signature: signature }; + throw err; + } + // else: both signatures point to the same function, that's fine + } else { + signatures[signature] = fn.signatures[signature]; + } + } + } + } + + return _typed(name, signatures); + } + }); + + /** + * Find a specific signature from a (composed) typed function, for + * example: + * + * typed.find(fn, ['number', 'string']) + * typed.find(fn, 'number, string') + * + * Function find only only works for exact matches. + * + * @param {Function} fn A typed-function + * @param {string | string[]} signature Signature to be found, can be + * an array or a comma separated string. + * @return {Function} Returns the matching signature, or + * throws an errror when no signature + * is found. + */ + function find(fn, signature) { + if (!fn.signatures) { + throw new TypeError('Function is no typed-function'); + } + + // normalize input + var arr; + if (typeof signature === 'string') { + arr = signature.split(','); + for (var i = 0; i < arr.length; i++) { + arr[i] = arr[i].trim(); + } + } else if (Array.isArray(signature)) { + arr = signature; + } else { + throw new TypeError('String array or a comma separated string expected'); + } + + var str = arr.join(','); + + // find an exact match + var match = fn.signatures[str]; + if (match) { + return match; + } + + // TODO: extend find to match non-exact signatures + + throw new TypeError('Signature not found (signature: ' + (fn.name || 'unnamed') + '(' + arr.join(', ') + '))'); + } + + /** + * Convert a given value to another data type. + * @param {*} value + * @param {string} type + */ + function convert(value, type) { + var from = getTypeOf(value); + + // check conversion is needed + if (type === from) { + return value; + } + + for (var i = 0; i < typed.conversions.length; i++) { + var conversion = typed.conversions[i]; + if (conversion.from === from && conversion.to === type) { + return conversion.convert(value); + } + } + + throw new Error('Cannot convert from ' + from + ' to ' + type); + } + + // attach types and conversions to the final `typed` function + typed.config = config; + typed.types = types; + typed.conversions = conversions; + typed.ignore = ignore; + typed.create = create; + typed.find = find; + typed.convert = convert; + + // add a type + typed.addType = function (type) { + if (!type || typeof type.name !== 'string' || typeof type.test !== 'function') { + throw new TypeError('Object with properties {name: string, test: function} expected'); + } + + typed.types.push(type); + }; + + // add a conversion + typed.addConversion = function (conversion) { + if (!conversion || typeof conversion.from !== 'string' || typeof conversion.to !== 'string' || typeof conversion.convert !== 'function') { + throw new TypeError('Object with properties {from: string, to: string, convert: function} expected'); + } + + typed.conversions.push(conversion); + }; + + return typed; + } + + return create(); + }); + +/***/ }, +/* 72 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var NumberFormatter = __webpack_require__(73); + + /** + * Test whether value is a number + * @param {*} value + * @return {boolean} isNumber + */ + exports.isNumber = function (value) { + return typeof value === 'number'; + }; + + /** + * Check if a number is integer + * @param {number | boolean} value + * @return {boolean} isInteger + */ + exports.isInteger = function (value) { + return isFinite(value) ? value == Math.round(value) : false; + // Note: we use ==, not ===, as we can have Booleans as well + }; + + /** + * Calculate the sign of a number + * @param {number} x + * @returns {*} + */ + exports.sign = Math.sign || function (x) { + if (x > 0) { + return 1; + } else if (x < 0) { + return -1; + } else { + return 0; + } + }; + + /** + * Convert a number to a formatted string representation. + * + * Syntax: + * + * format(value) + * format(value, options) + * format(value, precision) + * format(value, fn) + * + * Where: + * + * {number} value The value to be formatted + * {Object} options An object with formatting options. Available options: + * {string} notation + * Number notation. Choose from: + * 'fixed' Always use regular number notation. + * For example '123.40' and '14000000' + * 'exponential' Always use exponential notation. + * For example '1.234e+2' and '1.4e+7' + * 'engineering' Always use engineering notation. + * For example '123.4e+0' and '14.0e+6' + * 'auto' (default) Regular number notation for numbers + * having an absolute value between + * `lower` and `upper` bounds, and uses + * exponential notation elsewhere. + * Lower bound is included, upper bound + * is excluded. + * For example '123.4' and '1.4e7'. + * {number} precision A number between 0 and 16 to round + * the digits of the number. + * In case of notations 'exponential' and + * 'auto', `precision` defines the total + * number of significant digits returned + * and is undefined by default. + * In case of notation 'fixed', + * `precision` defines the number of + * significant digits after the decimal + * point, and is 0 by default. + * {Object} exponential An object containing two parameters, + * {number} lower and {number} upper, + * used by notation 'auto' to determine + * when to return exponential notation. + * Default values are `lower=1e-3` and + * `upper=1e5`. + * Only applicable for notation `auto`. + * {Function} fn A custom formatting function. Can be used to override the + * built-in notations. Function `fn` is called with `value` as + * parameter and must return a string. Is useful for example to + * format all values inside a matrix in a particular way. + * + * Examples: + * + * format(6.4); // '6.4' + * format(1240000); // '1.24e6' + * format(1/3); // '0.3333333333333333' + * format(1/3, 3); // '0.333' + * format(21385, 2); // '21000' + * format(12.071, {notation: 'fixed'}); // '12' + * format(2.3, {notation: 'fixed', precision: 2}); // '2.30' + * format(52.8, {notation: 'exponential'}); // '5.28e+1' + * format(12345678, {notation: 'engineering'}); // '12.345678e+6' + * + * @param {number} value + * @param {Object | Function | number} [options] + * @return {string} str The formatted value + */ + exports.format = function (value, options) { + if (typeof options === 'function') { + // handle format(value, fn) + return options(value); + } + + // handle special cases + if (value === Infinity) { + return 'Infinity'; + } else if (value === -Infinity) { + return '-Infinity'; + } else if (isNaN(value)) { + return 'NaN'; + } + + // default values for options + var notation = 'auto'; + var precision = undefined; + + if (options) { + // determine notation from options + if (options.notation) { + notation = options.notation; + } + + // determine precision from options + if (exports.isNumber(options)) { + precision = options; + } else if (options.precision) { + precision = options.precision; + } + } + + // handle the various notations + switch (notation) { + case 'fixed': + return exports.toFixed(value, precision); + + case 'exponential': + return exports.toExponential(value, precision); + + case 'engineering': + return exports.toEngineering(value, precision); + + case 'auto': + return exports.toPrecision(value, precision, options && options.exponential) + + // remove trailing zeros after the decimal point + .replace(/((\.\d*?)(0+))($|e)/, function () { + var digits = arguments[2]; + var e = arguments[4]; + return digits !== '.' ? digits + e : e; + }); + + default: + throw new Error('Unknown notation "' + notation + '". ' + 'Choose "auto", "exponential", or "fixed".'); + } + }; + + /** + * Format a number in exponential notation. Like '1.23e+5', '2.3e+0', '3.500e-3' + * @param {number} value + * @param {number} [precision] Number of digits in formatted output. + * If not provided, the maximum available digits + * is used. + * @returns {string} str + */ + exports.toExponential = function (value, precision) { + return new NumberFormatter(value).toExponential(precision); + }; + + /** + * Format a number in engineering notation. Like '1.23e+6', '2.3e+0', '3.500e-3' + * @param {number} value + * @param {number} [precision] Number of digits in formatted output. + * If not provided, the maximum available digits + * is used. + * @returns {string} str + */ + exports.toEngineering = function (value, precision) { + return new NumberFormatter(value).toEngineering(precision); + }; + + /** + * Format a number with fixed notation. + * @param {number} value + * @param {number} [precision=0] Optional number of decimals after the + * decimal point. Zero by default. + */ + exports.toFixed = function (value, precision) { + return new NumberFormatter(value).toFixed(precision); + }; + + /** + * Format a number with a certain precision + * @param {number} value + * @param {number} [precision=undefined] Optional number of digits. + * @param {{lower: number, upper: number}} [options] By default: + * lower = 1e-3 (excl) + * upper = 1e+5 (incl) + * @return {string} + */ + exports.toPrecision = function (value, precision, options) { + return new NumberFormatter(value).toPrecision(precision, options); + }; + + /** + * Count the number of significant digits of a number. + * + * For example: + * 2.34 returns 3 + * 0.0034 returns 2 + * 120.5e+30 returns 4 + * + * @param {number} value + * @return {number} digits Number of significant digits + */ + exports.digits = function (value) { + return value.toExponential().replace(/e.*$/, '') // remove exponential notation + .replace(/^0\.?0*|\./, '') // remove decimal point and leading zeros + .length; + }; + + /** + * Minimum number added to one that makes the result different than one + */ + exports.DBL_EPSILON = Number.EPSILON || 2.2204460492503130808472633361816E-16; + + /** + * Compares two floating point numbers. + * @param {number} x First value to compare + * @param {number} y Second value to compare + * @param {number} [epsilon] The maximum relative difference between x and y + * If epsilon is undefined or null, the function will + * test whether x and y are exactly equal. + * @return {boolean} whether the two numbers are nearly equal + */ + exports.nearlyEqual = function (x, y, epsilon) { + // if epsilon is null or undefined, test whether x and y are exactly equal + if (epsilon == null) { + return x == y; + } + + // use "==" operator, handles infinities + if (x == y) { + return true; + } + + // NaN + if (isNaN(x) || isNaN(y)) { + return false; + } + + // at this point x and y should be finite + if (isFinite(x) && isFinite(y)) { + // check numbers are very close, needed when comparing numbers near zero + var diff = Math.abs(x - y); + if (diff < exports.DBL_EPSILON) { + return true; + } else { + // use relative error + return diff <= Math.max(Math.abs(x), Math.abs(y)) * epsilon; + } + } + + // Infinite and Number or negative Infinite and positive Infinite cases + return false; + }; + +/***/ }, +/* 73 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * Format a number using methods toPrecision, toFixed, toExponential. + * @param {number | string} value + * @constructor + */ + + function NumberFormatter(value) { + // parse the input value + var match = String(value).toLowerCase().match(/^0*?(-?)(\d+\.?\d*)(e([+-]?\d+))?$/); + if (!match) { + throw new SyntaxError('Invalid number'); + } + + var sign = match[1]; + var coefficients = match[2]; + var exponent = parseFloat(match[4] || '0'); + + var dot = coefficients.indexOf('.'); + exponent += dot !== -1 ? dot - 1 : coefficients.length - 1; + + this.sign = sign; + this.coefficients = coefficients.replace('.', '') // remove the dot (must be removed before removing leading zeros) + .replace(/^0*/, function (zeros) { + // remove leading zeros, add their count to the exponent + exponent -= zeros.length; + return ''; + }).replace(/0*$/, '') // remove trailing zeros + .split('').map(function (d) { + return parseInt(d); + }); + + if (this.coefficients.length === 0) { + this.coefficients.push(0); + exponent++; + } + + this.exponent = exponent; + } + + /** + * Format a number with engineering notation. + * @param {number} [precision=0] Optional number of decimals after the + * decimal point. Zero by default. + */ + NumberFormatter.prototype.toEngineering = function (precision) { + var rounded = this.roundDigits(precision); + + var e = rounded.exponent; + var c = rounded.coefficients; + + // find nearest lower multiple of 3 for exponent + var newExp = e % 3 === 0 ? e : e < 0 ? e - 3 - e % 3 : e - e % 3; + + // concatenate coefficients with necessary zeros + var significandsDiff = e >= 0 ? e : Math.abs(newExp); + + // add zeros if necessary (for ex: 1e+8) + if (c.length - 1 < significandsDiff) c = c.concat(zeros(significandsDiff - (c.length - 1))); + + // find difference in exponents + var expDiff = Math.abs(e - newExp); + + var decimalIdx = 1; + var str = ''; + + // push decimal index over by expDiff times + while (--expDiff >= 0) decimalIdx++; + + // if all coefficient values are zero after the decimal point, don't add a decimal value. + // otherwise concat with the rest of the coefficients + var decimals = c.slice(decimalIdx).join(''); + var decimalVal = decimals.match(/[1-9]/) ? '.' + decimals : ''; + + str = c.slice(0, decimalIdx).join('') + decimalVal; + + str += 'e' + (e >= 0 ? '+' : '') + newExp.toString(); + return rounded.sign + str; + }; + + /** + * Format a number with fixed notation. + * @param {number} [precision=0] Optional number of decimals after the + * decimal point. Zero by default. + */ + NumberFormatter.prototype.toFixed = function (precision) { + var rounded = this.roundDigits(this.exponent + 1 + (precision || 0)); + var c = rounded.coefficients; + var p = rounded.exponent + 1; // exponent may have changed + + // append zeros if needed + var pp = p + (precision || 0); + if (c.length < pp) { + c = c.concat(zeros(pp - c.length)); + } + + // prepend zeros if needed + if (p < 0) { + c = zeros(-p + 1).concat(c); + p = 1; + } + + // insert a dot if needed + if (precision) { + c.splice(p, 0, p === 0 ? '0.' : '.'); + } + + return this.sign + c.join(''); + }; + + /** + * Format a number in exponential notation. Like '1.23e+5', '2.3e+0', '3.500e-3' + * @param {number} [precision] Number of digits in formatted output. + * If not provided, the maximum available digits + * is used. + */ + NumberFormatter.prototype.toExponential = function (precision) { + // round if needed, else create a clone + var rounded = precision ? this.roundDigits(precision) : this.clone(); + var c = rounded.coefficients; + var e = rounded.exponent; + + // append zeros if needed + if (c.length < precision) { + c = c.concat(zeros(precision - c.length)); + } + + // format as `C.CCCe+EEE` or `C.CCCe-EEE` + var first = c.shift(); + return this.sign + first + (c.length > 0 ? '.' + c.join('') : '') + 'e' + (e >= 0 ? '+' : '') + e; + }; + + /** + * Format a number with a certain precision + * @param {number} [precision=undefined] Optional number of digits. + * @param {{lower: number | undefined, upper: number | undefined}} [options] + * By default: + * lower = 1e-3 (excl) + * upper = 1e+5 (incl) + * @return {string} + */ + NumberFormatter.prototype.toPrecision = function (precision, options) { + // determine lower and upper bound for exponential notation. + var lower = options && options.lower !== undefined ? options.lower : 1e-3; + var upper = options && options.upper !== undefined ? options.upper : 1e+5; + + var abs = Math.abs(Math.pow(10, this.exponent)); + if (abs < lower || abs >= upper) { + // exponential notation + return this.toExponential(precision); + } else { + var rounded = precision ? this.roundDigits(precision) : this.clone(); + var c = rounded.coefficients; + var e = rounded.exponent; + + // append trailing zeros + if (c.length < precision) { + c = c.concat(zeros(precision - c.length)); + } + + // append trailing zeros + // TODO: simplify the next statement + c = c.concat(zeros(e - c.length + 1 + (c.length < precision ? precision - c.length : 0))); + + // prepend zeros + c = zeros(-e).concat(c); + + var dot = e > 0 ? e : 0; + if (dot < c.length - 1) { + c.splice(dot + 1, 0, '.'); + } + + return this.sign + c.join(''); + } + }; + + /** + * Crete a clone of the NumberFormatter + * @return {NumberFormatter} Returns a clone of the NumberFormatter + */ + NumberFormatter.prototype.clone = function () { + var clone = new NumberFormatter('0'); + clone.sign = this.sign; + clone.coefficients = this.coefficients.slice(0); + clone.exponent = this.exponent; + return clone; + }; + + /** + * Round the number of digits of a number * + * @param {number} precision A positive integer + * @return {NumberFormatter} Returns a new NumberFormatter with the rounded + * digits + */ + NumberFormatter.prototype.roundDigits = function (precision) { + var rounded = this.clone(); + var c = rounded.coefficients; + + // prepend zeros if needed + while (precision <= 0) { + c.unshift(0); + rounded.exponent++; + precision++; + } + + if (c.length > precision) { + var removed = c.splice(precision, c.length - precision); + + if (removed[0] >= 5) { + var i = precision - 1; + c[i]++; + while (c[i] === 10) { + c.pop(); + if (i === 0) { + c.unshift(0); + rounded.exponent++; + i++; + } + i--; + c[i]++; + } + } + } + + return rounded; + }; + + /** + * Create an array filled with zeros. + * @param {number} length + * @return {Array} + */ + function zeros(length) { + var arr = []; + for (var i = 0; i < length; i++) { + arr.push(0); + } + return arr; + } + + module.exports = NumberFormatter; + +/***/ }, +/* 74 */ +/***/ function(module, exports, __webpack_require__) { + + var Emitter = __webpack_require__(75); + + /** + * Extend given object with emitter functions `on`, `off`, `once`, `emit` + * @param {Object} obj + * @return {Object} obj + */ + exports.mixin = function (obj) { + // create event emitter + var emitter = new Emitter(); + + // bind methods to obj (we don't want to expose the emitter.e Array...) + obj.on = emitter.on.bind(emitter); + obj.off = emitter.off.bind(emitter); + obj.once = emitter.once.bind(emitter); + obj.emit = emitter.emit.bind(emitter); + + return obj; + }; + +/***/ }, +/* 75 */ +/***/ function(module, exports) { + + function E() { + // Keep this empty so it's easier to inherit from + // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3) + } + + E.prototype = { + on: function (name, callback, ctx) { + var e = this.e || (this.e = {}); + + (e[name] || (e[name] = [])).push({ + fn: callback, + ctx: ctx + }); + + return this; + }, + + once: function (name, callback, ctx) { + var self = this; + function listener() { + self.off(name, listener); + callback.apply(ctx, arguments); + }; + + listener._ = callback; + return this.on(name, listener, ctx); + }, + + emit: function (name) { + var data = [].slice.call(arguments, 1); + var evtArr = ((this.e || (this.e = {}))[name] || []).slice(); + var i = 0; + var len = evtArr.length; + + for (i; i < len; i++) { + evtArr[i].fn.apply(evtArr[i].ctx, data); + } + + return this; + }, + + off: function (name, callback) { + var e = this.e || (this.e = {}); + var evts = e[name]; + var liveEvents = []; + + if (evts && callback) { + for (var i = 0, len = evts.length; i < len; i++) { + if (evts[i].fn !== callback && evts[i].fn._ !== callback) liveEvents.push(evts[i]); + } + } + + // Remove event from queue to prevent memory leak + // Suggested by https://github.com/lazd + // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910 + + liveEvents.length ? e[name] = liveEvents : delete e[name]; + + return this; + } + }; + + module.exports = E; + +/***/ }, +/* 76 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var lazy = __webpack_require__(69).lazy; + var isFactory = __webpack_require__(69).isFactory; + var traverse = __webpack_require__(69).traverse; + var extend = __webpack_require__(69).extend; + var ArgumentsError = __webpack_require__(77); + + function factory(type, config, load, typed, math) { + /** + * Import functions from an object or a module + * + * Syntax: + * + * math.import(object) + * math.import(object, options) + * + * Where: + * + * - `object: Object` + * An object with functions to be imported. + * - `options: Object` An object with import options. Available options: + * - `override: boolean` + * If true, existing functions will be overwritten. False by default. + * - `silent: boolean` + * If true, the function will not throw errors on duplicates or invalid + * types. False by default. + * - `wrap: boolean` + * If true, the functions will be wrapped in a wrapper function + * which converts data types like Matrix to primitive data types like Array. + * The wrapper is needed when extending math.js with libraries which do not + * support these data type. False by default. + * + * Examples: + * + * // define new functions and variables + * math.import({ + * myvalue: 42, + * hello: function (name) { + * return 'hello, ' + name + '!'; + * } + * }); + * + * // use the imported function and variable + * math.myvalue * 2; // 84 + * math.hello('user'); // 'hello, user!' + * + * // import the npm module 'numbers' + * // (must be installed first with `npm install numbers`) + * math.import(require('numbers'), {wrap: true}); + * + * math.fibonacci(7); // returns 13 + * + * @param {Object | Array} object Object with functions to be imported. + * @param {Object} [options] Import options. + */ + function math_import(object, options) { + var num = arguments.length; + if (num != 1 && num != 2) { + throw new ArgumentsError('import', num, 1, 2); + } + + if (!options) { + options = {}; + } + + if (isFactory(object)) { + _importFactory(object, options); + } + // TODO: allow a typed-function with name too + else if (Array.isArray(object)) { + object.forEach(function (entry) { + math_import(entry, options); + }); + } else if (typeof object === 'object') { + // a map with functions + for (var name in object) { + if (object.hasOwnProperty(name)) { + var value = object[name]; + if (isSupportedType(value)) { + _import(name, value, options); + } else if (isFactory(object)) { + _importFactory(object, options); + } else { + math_import(value, options); + } + } + } + } else { + if (!options.silent) { + throw new TypeError('Factory, Object, or Array expected'); + } + } + } + + /** + * Add a property to the math namespace and create a chain proxy for it. + * @param {string} name + * @param {*} value + * @param {Object} options See import for a description of the options + * @private + */ + function _import(name, value, options) { + if (options.wrap && typeof value === 'function') { + // create a wrapper around the function + value = _wrap(value); + } + + if (isTypedFunction(math[name]) && isTypedFunction(value)) { + if (options.override) { + // give the typed function the right name + value = typed(name, value.signatures); + } else { + // merge the existing and typed function + value = typed(math[name], value); + } + + math[name] = value; + _importTransform(name, value); + math.emit('import', name, function resolver() { + return value; + }); + return; + } + + if (math[name] === undefined || options.override) { + math[name] = value; + _importTransform(name, value); + math.emit('import', name, function resolver() { + return value; + }); + return; + } + + if (!options.silent) { + throw new Error('Cannot import "' + name + '": already exists'); + } + } + + function _importTransform(name, value) { + if (value && typeof value.transform === 'function') { + math.expression.transform[name] = value.transform; + } + } + + /** + * Create a wrapper a round an function which converts the arguments + * to their primitive values (like convert a Matrix to Array) + * @param {Function} fn + * @return {Function} Returns the wrapped function + * @private + */ + function _wrap(fn) { + var wrapper = function wrapper() { + var args = []; + for (var i = 0, len = arguments.length; i < len; i++) { + var arg = arguments[i]; + args[i] = arg && arg.valueOf(); + } + return fn.apply(math, args); + }; + + if (fn.transform) { + wrapper.transform = fn.transform; + } + + return wrapper; + } + + /** + * Import an instance of a factory into math.js + * @param {{factory: Function, name: string, path: string, math: boolean}} factory + * @param {Object} options See import for a description of the options + * @private + */ + function _importFactory(factory, options) { + if (typeof factory.name === 'string') { + var name = factory.name; + var namespace = factory.path ? traverse(math, factory.path) : math; + var existing = namespace.hasOwnProperty(name) ? namespace[name] : undefined; + + var resolver = function () { + var instance = load(factory); + + if (isTypedFunction(existing) && isTypedFunction(instance)) { + if (options.override) { + // replace the existing typed function (nothing to do) + } else { + // merge the existing and new typed function + instance = typed(existing, instance); + } + + return instance; + } + + if (existing === undefined || options.override) { + return instance; + } + + if (!options.silent) { + throw new Error('Cannot import "' + name + '": already exists'); + } + }; + + if (factory.lazy !== false) { + lazy(namespace, name, resolver); + } else { + namespace[name] = resolver(); + } + + math.emit('import', name, resolver, factory.path); + } else { + // unnamed factory. + // no lazy loading + load(factory); + } + } + + /** + * Check whether given object is a type which can be imported + * @param {Function | number | string | boolean | null | Unit | Complex} object + * @return {boolean} + * @private + */ + function isSupportedType(object) { + return typeof object == 'function' || typeof object === 'number' || typeof object === 'string' || typeof object === 'boolean' || object === null || object && object.isUnit === true || object && object.isComplex === true || object && object.isBigNumber === true || object && object.isFraction === true || object && object.isMatrix === true || object && Array.isArray(object) === true; + } + + /** + * Test whether a given thing is a typed-function + * @param {*} fn + * @return {boolean} Returns true when `fn` is a typed-function + */ + function isTypedFunction(fn) { + return typeof fn === 'function' && typeof fn.signatures === 'object'; + } + + return math_import; + } + + exports.math = true; // request access to the math namespace as 5th argument of the factory function + exports.name = 'import'; + exports.factory = factory; + exports.lazy = true; + +/***/ }, +/* 77 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * Create a syntax error with the message: + * 'Wrong number of arguments in function <fn> (<count> provided, <min>-<max> expected)' + * @param {string} fn Function name + * @param {number} count Actual argument count + * @param {number} min Minimum required argument count + * @param {number} [max] Maximum required argument count + * @extends Error + */ + + function ArgumentsError(fn, count, min, max) { + if (!(this instanceof ArgumentsError)) { + throw new SyntaxError('Constructor must be called with the new operator'); + } + + this.fn = fn; + this.count = count; + this.min = min; + this.max = max; + + this.message = 'Wrong number of arguments in function ' + fn + ' (' + count + ' provided, ' + min + (max != undefined ? '-' + max : '') + ' expected)'; + + this.stack = new Error().stack; + } + + ArgumentsError.prototype = new Error(); + ArgumentsError.prototype.constructor = Error; + ArgumentsError.prototype.name = 'ArgumentsError'; + ArgumentsError.prototype.isArgumentsError = true; + + module.exports = ArgumentsError; + +/***/ }, +/* 78 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var object = __webpack_require__(69); + + function factory(type, config, load, typed, math) { + var MATRIX = ['Matrix', 'Array']; // valid values for option matrix + var NUMBER = ['number', 'BigNumber', 'Fraction']; // valid values for option number + + /** + * Set configuration options for math.js, and get current options. + * Will emit a 'config' event, with arguments (curr, prev). + * + * Syntax: + * + * math.config(config: Object): Object + * + * Examples: + * + * math.config().number; // outputs 'number' + * math.eval('0.4'); // outputs number 0.4 + * math.config({number: 'Fraction'}); + * math.eval('0.4'); // outputs Fraction 2/5 + * + * @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. + * {string} parenthesis + * How to display parentheses in LaTeX and string + * output. + * @return {Object} Returns the current configuration + */ + function _config(options) { + if (options) { + var prev = object.clone(config); + + // validate some of the options + validateOption(options, 'matrix', MATRIX); + validateOption(options, 'number', NUMBER); + + // merge options + object.deepExtend(config, options); + + var curr = object.clone(config); + + // emit 'config' event + math.emit('config', curr, prev); + + return curr; + } else { + return object.clone(config); + } + } + + // attach the valid options to the function so they can be extended + _config.MATRIX = MATRIX; + _config.NUMBER = NUMBER; + + return _config; + } + + /** + * Test whether an Array contains a specific item. + * @param {Array.<string>} array + * @param {string} item + * @return {boolean} + */ + function contains(array, item) { + return array.indexOf(item) !== -1; + } + + /** + * Find a string in an array. Case insensitive search + * @param {Array.<string>} array + * @param {string} item + * @return {number} Returns the index when found. Returns -1 when not found + */ + function findIndex(array, item) { + return array.map(function (i) { + return i.toLowerCase(); + }).indexOf(item.toLowerCase()); + } + + /** + * Validate an option + * @param {Object} options Object with options + * @param {string} name Name of the option to validate + * @param {Array.<string>} values Array with valid values for this option + */ + function validateOption(options, name, values) { + if (options[name] !== undefined && !contains(values, options[name])) { + var index = findIndex(values, options[name]); + if (index !== -1) { + // right value, wrong casing + // TODO: lower case values are deprecated since v3, remove this warning some day. + console.warn('Warning: Wrong casing for configuration option "' + name + '", should be "' + values[index] + '" instead of "' + options[name] + '".'); + + options[name] = values[index]; // change the option to the right casing + } else { + // unknown value + console.warn('Warning: Unknown value "' + options[name] + '" for configuration option "' + name + '". Available options: ' + values.map(JSON.stringify).join(', ') + '.'); + } + } + } + + exports.name = 'config'; + exports.math = true; // request the math namespace as fifth argument + exports.factory = factory; + +/***/ }, +/* 79 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var deepMap = __webpack_require__(80); + + function factory(type, config, load, typed) { + var gamma = load(__webpack_require__(81)); + var latex = __webpack_require__(89); + + /** + * Compute the factorial of a value + * + * Factorial only supports an integer value as argument. + * For matrices, the function is evaluated element wise. + * + * Syntax: + * + * math.factorial(n) + * + * Examples: + * + * math.factorial(5); // returns 120 + * math.factorial(3); // returns 6 + * + * See also: + * + * combinations, gamma, permutations + * + * @param {number | BigNumber | Array | Matrix} n An integer number + * @return {number | BigNumber | Array | Matrix} The factorial of `n` + */ + var factorial = typed('factorial', { + 'number': function (n) { + if (n < 0) { + throw new Error('Value must be non-negative'); + } + + return gamma(n + 1); + }, + + 'BigNumber': function (n) { + if (n.isNegative()) { + throw new Error('Value must be non-negative'); + } + + return gamma(n.plus(1)); + }, + + 'Array | Matrix': function (n) { + return deepMap(n, factorial); + } + }); + + factorial.toTex = { + 1: '\\left(${args[0]}\\right)' + latex.operators['factorial'] + }; + + return factorial; + } + + exports.name = 'factorial'; + exports.factory = factory; + +/***/ }, +/* 80 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * Execute the callback function element wise for each element in array and any + * nested array + * Returns an array with the results + * @param {Array | Matrix} array + * @param {Function} callback The callback is called with two parameters: + * value1 and value2, which contain the current + * element of both arrays. + * @param {boolean} [skipZeros] Invoke callback function for non-zero values only. + * + * @return {Array | Matrix} res + */ + + module.exports = function deepMap(array, callback, skipZeros) { + if (array && typeof array.map === 'function') { + // TODO: replace array.map with a for loop to improve performance + return array.map(function (x) { + return deepMap(x, callback, skipZeros); + }); + } else { + return callback(array); + } + }; + +/***/ }, +/* 81 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var deepMap = __webpack_require__(80); + var isInteger = __webpack_require__(72).isInteger; + + function factory(type, config, load, typed) { + var multiply = load(__webpack_require__(82)); + var pow = load(__webpack_require__(97)); + + /** + * Compute the gamma function of a value using Lanczos approximation for + * small values, and an extended Stirling approximation for large values. + * + * For matrices, the function is evaluated element wise. + * + * Syntax: + * + * math.gamma(n) + * + * Examples: + * + * math.gamma(5); // returns 24 + * math.gamma(-0.5); // returns -3.5449077018110335 + * math.gamma(math.i); // returns -0.15494982830180973 - 0.49801566811835596i + * + * See also: + * + * combinations, factorial, permutations + * + * @param {number | Array | Matrix} n A real or complex number + * @return {number | Array | Matrix} The gamma of `n` + */ + var gamma = typed('gamma', { + 'number': function (n) { + var t, x; + + if (isInteger(n)) { + if (n <= 0) { + return isFinite(n) ? Infinity : NaN; + } + + if (n > 171) { + return Infinity; // Will overflow + } + + var value = n - 2; + var res = n - 1; + while (value > 1) { + res *= value; + value--; + } + + if (res == 0) { + res = 1; // 0! is per definition 1 + } + + return res; + } + + if (n < 0.5) { + return Math.PI / (Math.sin(Math.PI * n) * gamma(1 - n)); + } + + if (n >= 171.35) { + return Infinity; // will overflow + } + + if (n > 85.0) { + // Extended Stirling Approx + var twoN = n * n; + var threeN = twoN * n; + var fourN = threeN * n; + var fiveN = fourN * n; + return Math.sqrt(2 * Math.PI / n) * Math.pow(n / Math.E, n) * (1 + 1 / (12 * n) + 1 / (288 * twoN) - 139 / (51840 * threeN) - 571 / (2488320 * fourN) + 163879 / (209018880 * fiveN) + 5246819 / (75246796800 * fiveN * n)); + } + + --n; + x = p[0]; + for (var i = 1; i < p.length; ++i) { + x += p[i] / (n + i); + } + + t = n + g + 0.5; + return Math.sqrt(2 * Math.PI) * Math.pow(t, n + 0.5) * Math.exp(-t) * x; + }, + + 'Complex': function (n) { + var t, x; + + if (n.im == 0) { + return gamma(n.re); + } + + n = new type.Complex(n.re - 1, n.im); + x = new type.Complex(p[0], 0); + for (var i = 1; i < p.length; ++i) { + var real = n.re + i; // x += p[i]/(n+i) + var den = real * real + n.im * n.im; + if (den != 0) { + x.re += p[i] * real / den; + x.im += -(p[i] * n.im) / den; + } else { + x.re = p[i] < 0 ? -Infinity : Infinity; + } + } + + t = new type.Complex(n.re + g + 0.5, n.im); + var twoPiSqrt = Math.sqrt(2 * Math.PI); + + n.re += 0.5; + var result = pow(t, n); + if (result.im == 0) { + // sqrt(2*PI)*result + result.re *= twoPiSqrt; + } else if (result.re == 0) { + result.im *= twoPiSqrt; + } else { + result.re *= twoPiSqrt; + result.im *= twoPiSqrt; + } + + var r = Math.exp(-t.re); // exp(-t) + t.re = r * Math.cos(-t.im); + t.im = r * Math.sin(-t.im); + + return multiply(multiply(result, t), x); + }, + + 'BigNumber': function (n) { + if (n.isInteger()) { + return n.isNegative() || n.isZero() ? new type.BigNumber(Infinity) : bigFactorial(n.minus(1)); + } + + if (!n.isFinite()) { + return new type.BigNumber(n.isNegative() ? NaN : Infinity); + } + + throw new Error('Integer BigNumber expected'); + }, + + 'Array | Matrix': function (n) { + return deepMap(n, gamma); + } + }); + + /** + * Calculate factorial for a BigNumber + * @param {BigNumber} n + * @returns {BigNumber} Returns the factorial of n + */ + function bigFactorial(n) { + if (n.isZero()) { + return new type.BigNumber(1); // 0! is per definition 1 + } + + var precision = config.precision + (Math.log(n.toNumber()) | 0); + var Big = type.BigNumber.clone({ precision: precision }); + + var res = new Big(n); + var value = n.toNumber() - 1; // number + while (value > 1) { + res = res.times(value); + value--; + } + + return new type.BigNumber(res.toPrecision(type.BigNumber.precision)); + } + + gamma.toTex = { 1: '\\Gamma\\left(${args[0]}\\right)' }; + + return gamma; + } + + // TODO: comment on the variables g and p + + var g = 4.7421875; + + var p = [0.99999999999999709182, 57.156235665862923517, -59.597960355475491248, 14.136097974741747174, -0.49191381609762019978, 0.33994649984811888699e-4, 0.46523628927048575665e-4, -0.98374475304879564677e-4, 0.15808870322491248884e-3, -0.21026444172410488319e-3, 0.21743961811521264320e-3, -0.16431810653676389022e-3, 0.84418223983852743293e-4, -0.26190838401581408670e-4, 0.36899182659531622704e-5]; + + exports.name = 'gamma'; + exports.factory = factory; + +/***/ }, +/* 82 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var extend = __webpack_require__(69).extend; + var array = __webpack_require__(83); + + function factory(type, config, load, typed) { + var latex = __webpack_require__(89); + + var matrix = load(__webpack_require__(90)); + var addScalar = load(__webpack_require__(91)); + var multiplyScalar = load(__webpack_require__(92)); + var equalScalar = load(__webpack_require__(93)); + + var algorithm11 = load(__webpack_require__(95)); + var algorithm14 = load(__webpack_require__(96)); + + var DenseMatrix = type.DenseMatrix; + var SparseMatrix = type.SparseMatrix; + + /** + * Multiply two values, `x * y`. + * For matrices, the matrix product is calculated. + * + * Syntax: + * + * math.multiply(x, y) + * + * Examples: + * + * math.multiply(4, 5.2); // returns number 20.8 + * + * var a = math.complex(2, 3); + * var b = math.complex(4, 1); + * math.multiply(a, b); // returns Complex 5 + 14i + * + * var c = [[1, 2], [4, 3]]; + * var d = [[1, 2, 3], [3, -4, 7]]; + * math.multiply(c, d); // returns Array [[7, -6, 17], [13, -4, 33]] + * + * var e = math.unit('2.1 km'); + * math.multiply(3, e); // returns Unit 6.3 km + * + * See also: + * + * divide + * + * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} x First value to multiply + * @param {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} y Second value to multiply + * @return {number | BigNumber | Fraction | Complex | Unit | Array | Matrix} Multiplication of `x` and `y` + */ + var multiply = typed('multiply', extend({ + // we extend the signatures of multiplyScalar with signatures dealing with matrices + + 'Array, Array': function (x, y) { + // check dimensions + _validateMatrixDimensions(array.size(x), array.size(y)); + + // use dense matrix implementation + var m = multiply(matrix(x), matrix(y)); + // return array or scalar + return m && m.isMatrix === true ? m.valueOf() : m; + }, + + 'Matrix, Matrix': function (x, y) { + // dimensions + var xsize = x.size(); + var ysize = y.size(); + + // check dimensions + _validateMatrixDimensions(xsize, ysize); + + // process dimensions + if (xsize.length === 1) { + // process y dimensions + if (ysize.length === 1) { + // Vector * Vector + return _multiplyVectorVector(x, y, xsize[0]); + } + // Vector * Matrix + return _multiplyVectorMatrix(x, y); + } + // process y dimensions + if (ysize.length === 1) { + // Matrix * Vector + return _multiplyMatrixVector(x, y); + } + // Matrix * Matrix + return _multiplyMatrixMatrix(x, y); + }, + + 'Matrix, Array': function (x, y) { + // use Matrix * Matrix implementation + return multiply(x, matrix(y)); + }, + + 'Array, Matrix': function (x, y) { + // use Matrix * Matrix implementation + return multiply(matrix(x, y.storage()), y); + }, + + 'Matrix, any': function (x, y) { + // result + var c; + + // process storage format + switch (x.storage()) { + case 'sparse': + c = algorithm11(x, y, multiplyScalar, false); + break; + case 'dense': + c = algorithm14(x, y, multiplyScalar, false); + break; + } + return c; + }, + + 'any, Matrix': function (x, y) { + // result + var c; + // check storage format + switch (y.storage()) { + case 'sparse': + c = algorithm11(y, x, multiplyScalar, true); + break; + case 'dense': + c = algorithm14(y, x, multiplyScalar, true); + break; + } + return c; + }, + + 'Array, any': function (x, y) { + // use matrix implementation + return algorithm14(matrix(x), y, multiplyScalar, false).valueOf(); + }, + + 'any, Array': function (x, y) { + // use matrix implementation + return algorithm14(matrix(y), x, multiplyScalar, true).valueOf(); + } + }, multiplyScalar.signatures)); + + var _validateMatrixDimensions = function (size1, size2) { + // check left operand dimensions + switch (size1.length) { + case 1: + // check size2 + switch (size2.length) { + case 1: + // Vector x Vector + if (size1[0] !== size2[0]) { + // throw error + throw new RangeError('Dimension mismatch in multiplication. Vectors must have the same length'); + } + break; + case 2: + // Vector x Matrix + if (size1[0] !== size2[0]) { + // throw error + throw new RangeError('Dimension mismatch in multiplication. Vector length (' + size1[0] + ') must match Matrix rows (' + size2[0] + ')'); + } + break; + default: + throw new Error('Can only multiply a 1 or 2 dimensional matrix (Matrix B has ' + size2.length + ' dimensions)'); + } + break; + case 2: + // check size2 + switch (size2.length) { + case 1: + // Matrix x Vector + if (size1[1] !== size2[0]) { + // throw error + throw new RangeError('Dimension mismatch in multiplication. Matrix columns (' + size1[1] + ') must match Vector length (' + size2[0] + ')'); + } + break; + case 2: + // Matrix x Matrix + if (size1[1] !== size2[0]) { + // throw error + throw new RangeError('Dimension mismatch in multiplication. Matrix A columns (' + size1[1] + ') must match Matrix B rows (' + size2[0] + ')'); + } + break; + default: + throw new Error('Can only multiply a 1 or 2 dimensional matrix (Matrix B has ' + size2.length + ' dimensions)'); + } + break; + default: + throw new Error('Can only multiply a 1 or 2 dimensional matrix (Matrix A has ' + size1.length + ' dimensions)'); + } + }; + + /** + * C = A * B + * + * @param {Matrix} a Dense Vector (N) + * @param {Matrix} b Dense Vector (N) + * + * @return {number} Scalar value + */ + var _multiplyVectorVector = function (a, b, n) { + // check empty vector + if (n === 0) throw new Error('Cannot multiply two empty vectors'); + + // a dense + var adata = a._data; + var adt = a._datatype; + // b dense + var bdata = b._data; + var bdt = b._datatype; + + // datatype + var dt; + // addScalar signature to use + var af = addScalar; + // multiplyScalar signature to use + var mf = multiplyScalar; + + // process data types + if (adt && bdt && adt === bdt && typeof adt === 'string') { + // datatype + dt = adt; + // find signatures that matches (dt, dt) + af = typed.find(addScalar, [dt, dt]); + mf = typed.find(multiplyScalar, [dt, dt]); + } + + // result (do not initialize it with zero) + var c = mf(adata[0], bdata[0]); + // loop data + for (var i = 1; i < n; i++) { + // multiply and accumulate + c = af(c, mf(adata[i], bdata[i])); + } + return c; + }; + + /** + * C = A * B + * + * @param {Matrix} a Dense Vector (M) + * @param {Matrix} b Matrix (MxN) + * + * @return {Matrix} Dense Vector (N) + */ + var _multiplyVectorMatrix = function (a, b) { + // process storage + switch (b.storage()) { + case 'dense': + return _multiplyVectorDenseMatrix(a, b); + } + throw new Error('Not implemented'); + }; + + /** + * C = A * B + * + * @param {Matrix} a Dense Vector (M) + * @param {Matrix} b Dense Matrix (MxN) + * + * @return {Matrix} Dense Vector (N) + */ + var _multiplyVectorDenseMatrix = function (a, b) { + // a dense + var adata = a._data; + var asize = a._size; + var adt = a._datatype; + // b dense + var bdata = b._data; + var bsize = b._size; + var bdt = b._datatype; + // rows & columns + var alength = asize[0]; + var bcolumns = bsize[1]; + + // datatype + var dt; + // addScalar signature to use + var af = addScalar; + // multiplyScalar signature to use + var mf = multiplyScalar; + + // process data types + if (adt && bdt && adt === bdt && typeof adt === 'string') { + // datatype + dt = adt; + // find signatures that matches (dt, dt) + af = typed.find(addScalar, [dt, dt]); + mf = typed.find(multiplyScalar, [dt, dt]); + } + + // result + var c = []; + + // loop matrix columns + for (var j = 0; j < bcolumns; j++) { + // sum (do not initialize it with zero) + var sum = mf(adata[0], bdata[0][j]); + // loop vector + for (var i = 1; i < alength; i++) { + // multiply & accumulate + sum = af(sum, mf(adata[i], bdata[i][j])); + } + c[j] = sum; + } + + // return matrix + return new DenseMatrix({ + data: c, + size: [bcolumns], + datatype: dt + }); + }; + + /** + * C = A * B + * + * @param {Matrix} a Matrix (MxN) + * @param {Matrix} b Dense Vector (N) + * + * @return {Matrix} Dense Vector (M) + */ + var _multiplyMatrixVector = function (a, b) { + // process storage + switch (a.storage()) { + case 'dense': + return _multiplyDenseMatrixVector(a, b); + case 'sparse': + return _multiplySparseMatrixVector(a, b); + } + }; + + /** + * C = A * B + * + * @param {Matrix} a Matrix (MxN) + * @param {Matrix} b Matrix (NxC) + * + * @return {Matrix} Matrix (MxC) + */ + var _multiplyMatrixMatrix = function (a, b) { + // process storage + switch (a.storage()) { + case 'dense': + // process storage + switch (b.storage()) { + case 'dense': + return _multiplyDenseMatrixDenseMatrix(a, b); + case 'sparse': + return _multiplyDenseMatrixSparseMatrix(a, b); + } + break; + case 'sparse': + // process storage + switch (b.storage()) { + case 'dense': + return _multiplySparseMatrixDenseMatrix(a, b); + case 'sparse': + return _multiplySparseMatrixSparseMatrix(a, b); + } + break; + } + }; + + /** + * C = A * B + * + * @param {Matrix} a DenseMatrix (MxN) + * @param {Matrix} b Dense Vector (N) + * + * @return {Matrix} Dense Vector (M) + */ + var _multiplyDenseMatrixVector = function (a, b) { + // a dense + var adata = a._data; + var asize = a._size; + var adt = a._datatype; + // b dense + var bdata = b._data; + var bdt = b._datatype; + // rows & columns + var arows = asize[0]; + var acolumns = asize[1]; + + // datatype + var dt; + // addScalar signature to use + var af = addScalar; + // multiplyScalar signature to use + var mf = multiplyScalar; + + // process data types + if (adt && bdt && adt === bdt && typeof adt === 'string') { + // datatype + dt = adt; + // find signatures that matches (dt, dt) + af = typed.find(addScalar, [dt, dt]); + mf = typed.find(multiplyScalar, [dt, dt]); + } + + // result + var c = []; + + // loop matrix a rows + for (var i = 0; i < arows; i++) { + // current row + var row = adata[i]; + // sum (do not initialize it with zero) + var sum = mf(row[0], bdata[0]); + // loop matrix a columns + for (var j = 1; j < acolumns; j++) { + // multiply & accumulate + sum = af(sum, mf(row[j], bdata[j])); + } + c[i] = sum; + } + + // return matrix + return new DenseMatrix({ + data: c, + size: [arows], + datatype: dt + }); + }; + + /** + * C = A * B + * + * @param {Matrix} a DenseMatrix (MxN) + * @param {Matrix} b DenseMatrix (NxC) + * + * @return {Matrix} DenseMatrix (MxC) + */ + var _multiplyDenseMatrixDenseMatrix = function (a, b) { + // a dense + var adata = a._data; + var asize = a._size; + var adt = a._datatype; + // b dense + var bdata = b._data; + var bsize = b._size; + var bdt = b._datatype; + // rows & columns + var arows = asize[0]; + var acolumns = asize[1]; + var bcolumns = bsize[1]; + + // datatype + var dt; + // addScalar signature to use + var af = addScalar; + // multiplyScalar signature to use + var mf = multiplyScalar; + + // process data types + if (adt && bdt && adt === bdt && typeof adt === 'string') { + // datatype + dt = adt; + // find signatures that matches (dt, dt) + af = typed.find(addScalar, [dt, dt]); + mf = typed.find(multiplyScalar, [dt, dt]); + } + + // result + var c = []; + + // loop matrix a rows + for (var i = 0; i < arows; i++) { + // current row + var row = adata[i]; + // initialize row array + c[i] = []; + // loop matrix b columns + for (var j = 0; j < bcolumns; j++) { + // sum (avoid initializing sum to zero) + var sum = mf(row[0], bdata[0][j]); + // loop matrix a columns + for (var x = 1; x < acolumns; x++) { + // multiply & accumulate + sum = af(sum, mf(row[x], bdata[x][j])); + } + c[i][j] = sum; + } + } + + // return matrix + return new DenseMatrix({ + data: c, + size: [arows, bcolumns], + datatype: dt + }); + }; + + /** + * C = A * B + * + * @param {Matrix} a DenseMatrix (MxN) + * @param {Matrix} b SparseMatrix (NxC) + * + * @return {Matrix} SparseMatrix (MxC) + */ + var _multiplyDenseMatrixSparseMatrix = function (a, b) { + // a dense + var adata = a._data; + var asize = a._size; + var adt = a._datatype; + // b sparse + var bvalues = b._values; + var bindex = b._index; + var bptr = b._ptr; + var bsize = b._size; + var bdt = b._datatype; + // validate b matrix + if (!bvalues) throw new Error('Cannot multiply Dense Matrix times Pattern only Matrix'); + // rows & columns + var arows = asize[0]; + var bcolumns = bsize[1]; + + // datatype + var dt; + // addScalar signature to use + var af = addScalar; + // multiplyScalar signature to use + var mf = multiplyScalar; + // equalScalar signature to use + var eq = equalScalar; + // zero value + var zero = 0; + + // process data types + if (adt && bdt && adt === bdt && typeof adt === 'string') { + // datatype + dt = adt; + // find signatures that matches (dt, dt) + af = typed.find(addScalar, [dt, dt]); + mf = typed.find(multiplyScalar, [dt, dt]); + eq = typed.find(equalScalar, [dt, dt]); + // convert 0 to the same datatype + zero = typed.convert(0, dt); + } + + // result + var cvalues = []; + var cindex = []; + var cptr = []; + // c matrix + var c = new SparseMatrix({ + values: cvalues, + index: cindex, + ptr: cptr, + size: [arows, bcolumns], + datatype: dt + }); + + // loop b columns + for (var jb = 0; jb < bcolumns; jb++) { + // update ptr + cptr[jb] = cindex.length; + // indeces in column jb + var kb0 = bptr[jb]; + var kb1 = bptr[jb + 1]; + // do not process column jb if no data exists + if (kb1 > kb0) { + // last row mark processed + var last = 0; + // loop a rows + for (var i = 0; i < arows; i++) { + // column mark + var mark = i + 1; + // C[i, jb] + var cij; + // values in b column j + for (var kb = kb0; kb < kb1; kb++) { + // row + var ib = bindex[kb]; + // check value has been initialized + if (last !== mark) { + // first value in column jb + cij = mf(adata[i][ib], bvalues[kb]); + // update mark + last = mark; + } else { + // accumulate value + cij = af(cij, mf(adata[i][ib], bvalues[kb])); + } + } + // check column has been processed and value != 0 + if (last === mark && !eq(cij, zero)) { + // push row & value + cindex.push(i); + cvalues.push(cij); + } + } + } + } + // update ptr + cptr[bcolumns] = cindex.length; + + // return sparse matrix + return c; + }; + + /** + * C = A * B + * + * @param {Matrix} a SparseMatrix (MxN) + * @param {Matrix} b Dense Vector (N) + * + * @return {Matrix} SparseMatrix (M, 1) + */ + var _multiplySparseMatrixVector = function (a, b) { + // a sparse + var avalues = a._values; + var aindex = a._index; + var aptr = a._ptr; + var adt = a._datatype; + // validate a matrix + if (!avalues) throw new Error('Cannot multiply Pattern only Matrix times Dense Matrix'); + // b dense + var bdata = b._data; + var bdt = b._datatype; + // rows & columns + var arows = a._size[0]; + var brows = b._size[0]; + // result + var cvalues = []; + var cindex = []; + var cptr = []; + + // datatype + var dt; + // addScalar signature to use + var af = addScalar; + // multiplyScalar signature to use + var mf = multiplyScalar; + // equalScalar signature to use + var eq = equalScalar; + // zero value + var zero = 0; + + // process data types + if (adt && bdt && adt === bdt && typeof adt === 'string') { + // datatype + dt = adt; + // find signatures that matches (dt, dt) + af = typed.find(addScalar, [dt, dt]); + mf = typed.find(multiplyScalar, [dt, dt]); + eq = typed.find(equalScalar, [dt, dt]); + // convert 0 to the same datatype + zero = typed.convert(0, dt); + } + + // workspace + var x = []; + // vector with marks indicating a value x[i] exists in a given column + var w = []; + + // update ptr + cptr[0] = 0; + // rows in b + for (var ib = 0; ib < brows; ib++) { + // b[ib] + var vbi = bdata[ib]; + // check b[ib] != 0, avoid loops + if (!eq(vbi, zero)) { + // A values & index in ib column + for (var ka0 = aptr[ib], ka1 = aptr[ib + 1], ka = ka0; ka < ka1; ka++) { + // a row + var ia = aindex[ka]; + // check value exists in current j + if (!w[ia]) { + // ia is new entry in j + w[ia] = true; + // add i to pattern of C + cindex.push(ia); + // x(ia) = A + x[ia] = mf(vbi, avalues[ka]); + } else { + // i exists in C already + x[ia] = af(x[ia], mf(vbi, avalues[ka])); + } + } + } + } + // copy values from x to column jb of c + for (var p1 = cindex.length, p = 0; p < p1; p++) { + // row + var ic = cindex[p]; + // copy value + cvalues[p] = x[ic]; + } + // update ptr + cptr[1] = cindex.length; + + // return sparse matrix + return new SparseMatrix({ + values: cvalues, + index: cindex, + ptr: cptr, + size: [arows, 1], + datatype: dt + }); + }; + + /** + * C = A * B + * + * @param {Matrix} a SparseMatrix (MxN) + * @param {Matrix} b DenseMatrix (NxC) + * + * @return {Matrix} SparseMatrix (MxC) + */ + var _multiplySparseMatrixDenseMatrix = function (a, b) { + // a sparse + var avalues = a._values; + var aindex = a._index; + var aptr = a._ptr; + var adt = a._datatype; + // validate a matrix + if (!avalues) throw new Error('Cannot multiply Pattern only Matrix times Dense Matrix'); + // b dense + var bdata = b._data; + var bdt = b._datatype; + // rows & columns + var arows = a._size[0]; + var brows = b._size[0]; + var bcolumns = b._size[1]; + + // datatype + var dt; + // addScalar signature to use + var af = addScalar; + // multiplyScalar signature to use + var mf = multiplyScalar; + // equalScalar signature to use + var eq = equalScalar; + // zero value + var zero = 0; + + // process data types + if (adt && bdt && adt === bdt && typeof adt === 'string') { + // datatype + dt = adt; + // find signatures that matches (dt, dt) + af = typed.find(addScalar, [dt, dt]); + mf = typed.find(multiplyScalar, [dt, dt]); + eq = typed.find(equalScalar, [dt, dt]); + // convert 0 to the same datatype + zero = typed.convert(0, dt); + } + + // result + var cvalues = []; + var cindex = []; + var cptr = []; + // c matrix + var c = new SparseMatrix({ + values: cvalues, + index: cindex, + ptr: cptr, + size: [arows, bcolumns], + datatype: dt + }); + + // workspace + var x = []; + // vector with marks indicating a value x[i] exists in a given column + var w = []; + + // loop b columns + for (var jb = 0; jb < bcolumns; jb++) { + // update ptr + cptr[jb] = cindex.length; + // mark in workspace for current column + var mark = jb + 1; + // rows in jb + for (var ib = 0; ib < brows; ib++) { + // b[ib, jb] + var vbij = bdata[ib][jb]; + // check b[ib, jb] != 0, avoid loops + if (!eq(vbij, zero)) { + // A values & index in ib column + for (var ka0 = aptr[ib], ka1 = aptr[ib + 1], ka = ka0; ka < ka1; ka++) { + // a row + var ia = aindex[ka]; + // check value exists in current j + if (w[ia] !== mark) { + // ia is new entry in j + w[ia] = mark; + // add i to pattern of C + cindex.push(ia); + // x(ia) = A + x[ia] = mf(vbij, avalues[ka]); + } else { + // i exists in C already + x[ia] = af(x[ia], mf(vbij, avalues[ka])); + } + } + } + } + // copy values from x to column jb of c + for (var p0 = cptr[jb], p1 = cindex.length, p = p0; p < p1; p++) { + // row + var ic = cindex[p]; + // copy value + cvalues[p] = x[ic]; + } + } + // update ptr + cptr[bcolumns] = cindex.length; + + // return sparse matrix + return c; + }; + + /** + * C = A * B + * + * @param {Matrix} a SparseMatrix (MxN) + * @param {Matrix} b SparseMatrix (NxC) + * + * @return {Matrix} SparseMatrix (MxC) + */ + var _multiplySparseMatrixSparseMatrix = function (a, b) { + // a sparse + var avalues = a._values; + var aindex = a._index; + var aptr = a._ptr; + var adt = a._datatype; + // b sparse + var bvalues = b._values; + var bindex = b._index; + var bptr = b._ptr; + var bdt = b._datatype; + + // rows & columns + var arows = a._size[0]; + var bcolumns = b._size[1]; + // flag indicating both matrices (a & b) contain data + var values = avalues && bvalues; + + // datatype + var dt; + // addScalar signature to use + var af = addScalar; + // multiplyScalar signature to use + var mf = multiplyScalar; + + // process data types + if (adt && bdt && adt === bdt && typeof adt === 'string') { + // datatype + dt = adt; + // find signatures that matches (dt, dt) + af = typed.find(addScalar, [dt, dt]); + mf = typed.find(multiplyScalar, [dt, dt]); + } + + // result + var cvalues = values ? [] : undefined; + var cindex = []; + var cptr = []; + // c matrix + var c = new SparseMatrix({ + values: cvalues, + index: cindex, + ptr: cptr, + size: [arows, bcolumns], + datatype: dt + }); + + // workspace + var x = values ? [] : undefined; + // vector with marks indicating a value x[i] exists in a given column + var w = []; + // variables + var ka, ka0, ka1, kb, kb0, kb1, ia, ib; + // loop b columns + for (var jb = 0; jb < bcolumns; jb++) { + // update ptr + cptr[jb] = cindex.length; + // mark in workspace for current column + var mark = jb + 1; + // B values & index in j + for (kb0 = bptr[jb], kb1 = bptr[jb + 1], kb = kb0; kb < kb1; kb++) { + // b row + ib = bindex[kb]; + // check we need to process values + if (values) { + // loop values in a[:,ib] + for (ka0 = aptr[ib], ka1 = aptr[ib + 1], ka = ka0; ka < ka1; ka++) { + // row + ia = aindex[ka]; + // check value exists in current j + if (w[ia] !== mark) { + // ia is new entry in j + w[ia] = mark; + // add i to pattern of C + cindex.push(ia); + // x(ia) = A + x[ia] = mf(bvalues[kb], avalues[ka]); + } else { + // i exists in C already + x[ia] = af(x[ia], mf(bvalues[kb], avalues[ka])); + } + } + } else { + // loop values in a[:,ib] + for (ka0 = aptr[ib], ka1 = aptr[ib + 1], ka = ka0; ka < ka1; ka++) { + // row + ia = aindex[ka]; + // check value exists in current j + if (w[ia] !== mark) { + // ia is new entry in j + w[ia] = mark; + // add i to pattern of C + cindex.push(ia); + } + } + } + } + // check we need to process matrix values (pattern matrix) + if (values) { + // copy values from x to column jb of c + for (var p0 = cptr[jb], p1 = cindex.length, p = p0; p < p1; p++) { + // row + var ic = cindex[p]; + // copy value + cvalues[p] = x[ic]; + } + } + } + // update ptr + cptr[bcolumns] = cindex.length; + + // return sparse matrix + return c; + }; + + multiply.toTex = { + 2: '\\left(${args[0]}' + latex.operators['multiply'] + '${args[1]}\\right)' + }; + + return multiply; + } + + exports.name = 'multiply'; + exports.factory = factory; + +/***/ }, +/* 83 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var number = __webpack_require__(72); + var string = __webpack_require__(84); + var object = __webpack_require__(69); + var types = __webpack_require__(86); + + var DimensionError = __webpack_require__(87); + var IndexError = __webpack_require__(88); + + /** + * Calculate the size of a multi dimensional array. + * This function checks the size of the first entry, it does not validate + * whether all dimensions match. (use function `validate` for that) + * @param {Array} x + * @Return {Number[]} size + */ + exports.size = function (x) { + var s = []; + + while (Array.isArray(x)) { + s.push(x.length); + x = x[0]; + } + + return s; + }; + + /** + * Recursively validate whether each element in a multi dimensional array + * has a size corresponding to the provided size array. + * @param {Array} array Array to be validated + * @param {number[]} size Array with the size of each dimension + * @param {number} dim Current dimension + * @throws DimensionError + * @private + */ + function _validate(array, size, dim) { + var i; + var len = array.length; + + if (len != size[dim]) { + throw new DimensionError(len, size[dim]); + } + + if (dim < size.length - 1) { + // recursively validate each child array + var dimNext = dim + 1; + for (i = 0; i < len; i++) { + var child = array[i]; + if (!Array.isArray(child)) { + throw new DimensionError(size.length - 1, size.length, '<'); + } + _validate(array[i], size, dimNext); + } + } else { + // last dimension. none of the childs may be an array + for (i = 0; i < len; i++) { + if (Array.isArray(array[i])) { + throw new DimensionError(size.length + 1, size.length, '>'); + } + } + } + } + + /** + * Validate whether each element in a multi dimensional array has + * a size corresponding to the provided size array. + * @param {Array} array Array to be validated + * @param {number[]} size Array with the size of each dimension + * @throws DimensionError + */ + exports.validate = function (array, size) { + var isScalar = size.length == 0; + if (isScalar) { + // scalar + if (Array.isArray(array)) { + throw new DimensionError(array.length, 0); + } + } else { + // array + _validate(array, size, 0); + } + }; + + /** + * Test whether index is an integer number with index >= 0 and index < length + * when length is provided + * @param {number} index Zero-based index + * @param {number} [length] Length of the array + */ + exports.validateIndex = function (index, length) { + if (!number.isNumber(index) || !number.isInteger(index)) { + throw new TypeError('Index must be an integer (value: ' + index + ')'); + } + if (index < 0 || typeof length === 'number' && index >= length) { + throw new IndexError(index, length); + } + }; + + // a constant used to specify an undefined defaultValue + exports.UNINITIALIZED = {}; + + /** + * Resize a multi dimensional array. The resized array is returned. + * @param {Array} array Array to be resized + * @param {Array.<number>} size Array with the size of each dimension + * @param {*} [defaultValue=0] Value to be filled in in new entries, + * zero by default. To leave new entries undefined, + * specify array.UNINITIALIZED as defaultValue + * @return {Array} array The resized array + */ + exports.resize = function (array, size, defaultValue) { + // TODO: add support for scalars, having size=[] ? + + // check the type of the arguments + if (!Array.isArray(array) || !Array.isArray(size)) { + throw new TypeError('Array expected'); + } + if (size.length === 0) { + throw new Error('Resizing to scalar is not supported'); + } + + // check whether size contains positive integers + size.forEach(function (value) { + if (!number.isNumber(value) || !number.isInteger(value) || value < 0) { + throw new TypeError('Invalid size, must contain positive integers ' + '(size: ' + string.format(size) + ')'); + } + }); + + // recursively resize the array + var _defaultValue = defaultValue !== undefined ? defaultValue : 0; + _resize(array, size, 0, _defaultValue); + + return array; + }; + + /** + * Recursively resize a multi dimensional array + * @param {Array} array Array to be resized + * @param {number[]} size Array with the size of each dimension + * @param {number} dim Current dimension + * @param {*} [defaultValue] Value to be filled in in new entries, + * undefined by default. + * @private + */ + function _resize(array, size, dim, defaultValue) { + var i; + var elem; + var oldLen = array.length; + var newLen = size[dim]; + var minLen = Math.min(oldLen, newLen); + + // apply new length + array.length = newLen; + + if (dim < size.length - 1) { + // non-last dimension + var dimNext = dim + 1; + + // resize existing child arrays + for (i = 0; i < minLen; i++) { + // resize child array + elem = array[i]; + if (!Array.isArray(elem)) { + elem = [elem]; // add a dimension + array[i] = elem; + } + _resize(elem, size, dimNext, defaultValue); + } + + // create new child arrays + for (i = minLen; i < newLen; i++) { + // get child array + elem = []; + array[i] = elem; + + // resize new child array + _resize(elem, size, dimNext, defaultValue); + } + } else { + // last dimension + + // remove dimensions of existing values + for (i = 0; i < minLen; i++) { + while (Array.isArray(array[i])) { + array[i] = array[i][0]; + } + } + + if (defaultValue !== exports.UNINITIALIZED) { + // fill new elements with the default value + for (i = minLen; i < newLen; i++) { + array[i] = defaultValue; + } + } + } + } + + /** + * Squeeze a multi dimensional array + * @param {Array} array + * @param {Array} [size] + * @returns {Array} returns the array itself + */ + exports.squeeze = function (array, size) { + var s = size || exports.size(array); + + // squeeze outer dimensions + while (Array.isArray(array) && array.length === 1) { + array = array[0]; + s.shift(); + } + + // find the first dimension to be squeezed + var dims = s.length; + while (s[dims - 1] === 1) { + dims--; + } + + // squeeze inner dimensions + if (dims < s.length) { + array = _squeeze(array, dims, 0); + s.length = dims; + } + + return array; + }; + + /** + * Recursively squeeze a multi dimensional array + * @param {Array} array + * @param {number} dims Required number of dimensions + * @param {number} dim Current dimension + * @returns {Array | *} Returns the squeezed array + * @private + */ + function _squeeze(array, dims, dim) { + var i, ii; + + if (dim < dims) { + var next = dim + 1; + for (i = 0, ii = array.length; i < ii; i++) { + array[i] = _squeeze(array[i], dims, next); + } + } else { + while (Array.isArray(array)) { + array = array[0]; + } + } + + return array; + } + + /** + * Unsqueeze a multi dimensional array: add dimensions when missing + * + * Paramter `size` will be mutated to match the new, unqueezed matrix size. + * + * @param {Array} array + * @param {number} dims Desired number of dimensions of the array + * @param {number} [outer] Number of outer dimensions to be added + * @param {Array} [size] Current size of array. + * @returns {Array} returns the array itself + * @private + */ + exports.unsqueeze = function (array, dims, outer, size) { + var s = size || exports.size(array); + + // unsqueeze outer dimensions + if (outer) { + for (var i = 0; i < outer; i++) { + array = [array]; + s.unshift(1); + } + } + + // unsqueeze inner dimensions + array = _unsqueeze(array, dims, 0); + while (s.length < dims) { + s.push(1); + } + + return array; + }; + + /** + * Recursively unsqueeze a multi dimensional array + * @param {Array} array + * @param {number} dims Required number of dimensions + * @param {number} dim Current dimension + * @returns {Array | *} Returns the squeezed array + * @private + */ + function _unsqueeze(array, dims, dim) { + var i, ii; + + if (Array.isArray(array)) { + var next = dim + 1; + for (i = 0, ii = array.length; i < ii; i++) { + array[i] = _unsqueeze(array[i], dims, next); + } + } else { + for (var d = dim; d < dims; d++) { + array = [array]; + } + } + + return array; + } + /** + * Flatten a multi dimensional array, put all elements in a one dimensional + * array + * @param {Array} array A multi dimensional array + * @return {Array} The flattened array (1 dimensional) + */ + exports.flatten = function (array) { + if (!Array.isArray(array)) { + //if not an array, return as is + return array; + } + var flat = []; + + array.forEach(function callback(value) { + if (Array.isArray(value)) { + value.forEach(callback); //traverse through sub-arrays recursively + } else { + flat.push(value); + } + }); + + return flat; + }; + + /** + * Test whether an object is an array + * @param {*} value + * @return {boolean} isArray + */ + exports.isArray = Array.isArray; + +/***/ }, +/* 84 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var formatNumber = __webpack_require__(72).format; + var formatBigNumber = __webpack_require__(85).format; + + /** + * Test whether value is a string + * @param {*} value + * @return {boolean} isString + */ + exports.isString = function (value) { + return typeof value === 'string'; + }; + + /** + * Check if a text ends with a certain string. + * @param {string} text + * @param {string} search + */ + exports.endsWith = function (text, search) { + var start = text.length - search.length; + var end = text.length; + return text.substring(start, end) === search; + }; + + /** + * Format a value of any type into a string. + * + * Usage: + * math.format(value) + * math.format(value, precision) + * + * When value is a function: + * + * - When the function has a property `syntax`, it returns this + * syntax description. + * - In other cases, a string `'function'` is returned. + * + * When `value` is an Object: + * + * - When the object contains a property `format` being a function, this + * function is invoked as `value.format(options)` and the result is returned. + * - When the object has its own `toString` method, this method is invoked + * and the result is returned. + * - In other cases the function will loop over all object properties and + * return JSON object notation like '{"a": 2, "b": 3}'. + * + * Example usage: + * math.format(2/7); // '0.2857142857142857' + * math.format(math.pi, 3); // '3.14' + * math.format(new Complex(2, 3)); // '2 + 3i' + * math.format('hello'); // '"hello"' + * + * @param {*} value Value to be stringified + * @param {Object | number | Function} [options] Formatting options. See + * lib/utils/number:format for a + * description of the available + * options. + * @return {string} str + */ + exports.format = function (value, options) { + if (typeof value === 'number') { + return formatNumber(value, options); + } + + if (value && value.isBigNumber === true) { + return formatBigNumber(value, options); + } + + if (value && value.isFraction === true) { + if (!options || options.fraction !== 'decimal') { + // output as ratio, like '1/3' + return value.s * value.n + '/' + value.d; + } else { + // output as decimal, like '0.(3)' + return value.toString(); + } + } + + if (Array.isArray(value)) { + return formatArray(value, options); + } + + if (exports.isString(value)) { + return '"' + value + '"'; + } + + if (typeof value === 'function') { + return value.syntax ? String(value.syntax) : 'function'; + } + + if (value && typeof value === 'object') { + if (typeof value.format === 'function') { + return value.format(options); + } else if (value && value.toString() !== {}.toString()) { + // this object has a non-native toString method, use that one + return value.toString(); + } else { + var entries = []; + + for (var key in value) { + if (value.hasOwnProperty(key)) { + entries.push('"' + key + '": ' + exports.format(value[key], options)); + } + } + + return '{' + entries.join(', ') + '}'; + } + } + + return String(value); + }; + + /** + * Recursively format an n-dimensional matrix + * Example output: "[[1, 2], [3, 4]]" + * @param {Array} array + * @param {Object | number | Function} [options] Formatting options. See + * lib/utils/number:format for a + * description of the available + * options. + * @returns {string} str + */ + function formatArray(array, options) { + if (Array.isArray(array)) { + var str = '['; + var len = array.length; + for (var i = 0; i < len; i++) { + if (i != 0) { + str += ', '; + } + str += formatArray(array[i], options); + } + str += ']'; + return str; + } else { + return exports.format(array, options); + } + } + +/***/ }, +/* 85 */ +/***/ function(module, exports) { + + /** + * Convert a BigNumber to a formatted string representation. + * + * Syntax: + * + * format(value) + * format(value, options) + * format(value, precision) + * format(value, fn) + * + * Where: + * + * {number} value The value to be formatted + * {Object} options An object with formatting options. Available options: + * {string} notation + * Number notation. Choose from: + * 'fixed' Always use regular number notation. + * For example '123.40' and '14000000' + * 'exponential' Always use exponential notation. + * For example '1.234e+2' and '1.4e+7' + * 'auto' (default) Regular number notation for numbers + * having an absolute value between + * `lower` and `upper` bounds, and uses + * exponential notation elsewhere. + * Lower bound is included, upper bound + * is excluded. + * For example '123.4' and '1.4e7'. + * {number} precision A number between 0 and 16 to round + * the digits of the number. + * In case of notations 'exponential' and + * 'auto', `precision` defines the total + * number of significant digits returned + * and is undefined by default. + * In case of notation 'fixed', + * `precision` defines the number of + * significant digits after the decimal + * point, and is 0 by default. + * {Object} exponential An object containing two parameters, + * {number} lower and {number} upper, + * used by notation 'auto' to determine + * when to return exponential notation. + * Default values are `lower=1e-3` and + * `upper=1e5`. + * Only applicable for notation `auto`. + * {Function} fn A custom formatting function. Can be used to override the + * built-in notations. Function `fn` is called with `value` as + * parameter and must return a string. Is useful for example to + * format all values inside a matrix in a particular way. + * + * Examples: + * + * format(6.4); // '6.4' + * format(1240000); // '1.24e6' + * format(1/3); // '0.3333333333333333' + * format(1/3, 3); // '0.333' + * format(21385, 2); // '21000' + * format(12.071, {notation: 'fixed'}); // '12' + * format(2.3, {notation: 'fixed', precision: 2}); // '2.30' + * format(52.8, {notation: 'exponential'}); // '5.28e+1' + * + * @param {BigNumber} value + * @param {Object | Function | number} [options] + * @return {string} str The formatted value + */ + exports.format = function (value, options) { + if (typeof options === 'function') { + // handle format(value, fn) + return options(value); + } + + // handle special cases + if (!value.isFinite()) { + return value.isNaN() ? 'NaN' : value.gt(0) ? 'Infinity' : '-Infinity'; + } + + // default values for options + var notation = 'auto'; + var precision = undefined; + + if (options !== undefined) { + // determine notation from options + if (options.notation) { + notation = options.notation; + } + + // determine precision from options + if (typeof options === 'number') { + precision = options; + } else if (options.precision) { + precision = options.precision; + } + } + + // handle the various notations + switch (notation) { + case 'fixed': + return exports.toFixed(value, precision); + + case 'exponential': + return exports.toExponential(value, precision); + + case 'auto': + // determine lower and upper bound for exponential notation. + // TODO: implement support for upper and lower to be BigNumbers themselves + var lower = 1e-3; + var upper = 1e5; + if (options && options.exponential) { + if (options.exponential.lower !== undefined) { + lower = options.exponential.lower; + } + if (options.exponential.upper !== undefined) { + upper = options.exponential.upper; + } + } + + // adjust the configuration of the BigNumber constructor (yeah, this is quite tricky...) + var oldConfig = { + toExpNeg: value.constructor.toExpNeg, + toExpPos: value.constructor.toExpPos + }; + + value.constructor.config({ + toExpNeg: Math.round(Math.log(lower) / Math.LN10), + toExpPos: Math.round(Math.log(upper) / Math.LN10) + }); + + // handle special case zero + if (value.isZero()) return '0'; + + // determine whether or not to output exponential notation + var str; + var abs = value.abs(); + if (abs.gte(lower) && abs.lt(upper)) { + // normal number notation + str = value.toSignificantDigits(precision).toFixed(); + } else { + // exponential notation + str = exports.toExponential(value, precision); + } + + // remove trailing zeros after the decimal point + return str.replace(/((\.\d*?)(0+))($|e)/, function () { + var digits = arguments[2]; + var e = arguments[4]; + return digits !== '.' ? digits + e : e; + }); + + default: + throw new Error('Unknown notation "' + notation + '". ' + 'Choose "auto", "exponential", or "fixed".'); + } + }; + + /** + * Format a number in exponential notation. Like '1.23e+5', '2.3e+0', '3.500e-3' + * @param {BigNumber} value + * @param {number} [precision] Number of digits in formatted output. + * If not provided, the maximum available digits + * is used. + * @returns {string} str + */ + exports.toExponential = function (value, precision) { + if (precision !== undefined) { + return value.toExponential(precision - 1); // Note the offset of one + } else { + return value.toExponential(); + } + }; + + /** + * Format a number with fixed notation. + * @param {BigNumber} value + * @param {number} [precision=0] Optional number of decimals after the + * decimal point. Zero by default. + */ + exports.toFixed = function (value, precision) { + return value.toFixed(precision || 0); + // Note: the (precision || 0) is needed as the toFixed of BigNumber has an + // undefined default precision instead of 0. + }; + +/***/ }, +/* 86 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * Determine the type of a variable + * + * type(x) + * + * The following types are recognized: + * + * 'undefined' + * 'null' + * 'boolean' + * 'number' + * 'string' + * 'Array' + * 'Function' + * 'Date' + * 'RegExp' + * 'Object' + * + * @param {*} x + * @return {string} Returns the name of the type. Primitive types are lower case, + * non-primitive types are upper-camel-case. + * For example 'number', 'string', 'Array', 'Date'. + */ + + exports.type = function (x) { + var type = typeof x; + + if (type === 'object') { + if (x === null) return 'null'; + if (x instanceof Boolean) return 'boolean'; + if (x instanceof Number) return 'number'; + if (x instanceof String) return 'string'; + if (Array.isArray(x)) return 'Array'; + if (x instanceof Date) return 'Date'; + if (x instanceof RegExp) return 'RegExp'; + + return 'Object'; + } + + if (type === 'function') return 'Function'; + + return type; + }; + + /** + * Test whether a value is a scalar + * @param x + * @return {boolean} Returns true when x is a scalar, returns false when + * x is a Matrix or Array. + */ + exports.isScalar = function (x) { + return !(x && x.isMatrix || Array.isArray(x)); + }; + +/***/ }, +/* 87 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * Create a range error with the message: + * 'Dimension mismatch (<actual size> != <expected size>)' + * @param {number | number[]} actual The actual size + * @param {number | number[]} expected The expected size + * @param {string} [relation='!='] Optional relation between actual + * and expected size: '!=', '<', etc. + * @extends RangeError + */ + + function DimensionError(actual, expected, relation) { + if (!(this instanceof DimensionError)) { + throw new SyntaxError('Constructor must be called with the new operator'); + } + + this.actual = actual; + this.expected = expected; + this.relation = relation; + + this.message = 'Dimension mismatch (' + (Array.isArray(actual) ? '[' + actual.join(', ') + ']' : actual) + ' ' + (this.relation || '!=') + ' ' + (Array.isArray(expected) ? '[' + expected.join(', ') + ']' : expected) + ')'; + + this.stack = new Error().stack; + } + + DimensionError.prototype = new RangeError(); + DimensionError.prototype.constructor = RangeError; + DimensionError.prototype.name = 'DimensionError'; + DimensionError.prototype.isDimensionError = true; + + module.exports = DimensionError; + +/***/ }, +/* 88 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * Create a range error with the message: + * 'Index out of range (index < min)' + * 'Index out of range (index < max)' + * + * @param {number} index The actual index + * @param {number} [min=0] Minimum index (included) + * @param {number} [max] Maximum index (excluded) + * @extends RangeError + */ + + function IndexError(index, min, max) { + if (!(this instanceof IndexError)) { + throw new SyntaxError('Constructor must be called with the new operator'); + } + + this.index = index; + if (arguments.length < 3) { + this.min = 0; + this.max = min; + } else { + this.min = min; + this.max = max; + } + + if (this.min !== undefined && this.index < this.min) { + this.message = 'Index out of range (' + this.index + ' < ' + this.min + ')'; + } else if (this.max !== undefined && this.index >= this.max) { + this.message = 'Index out of range (' + this.index + ' > ' + (this.max - 1) + ')'; + } else { + this.message = 'Index out of range (' + this.index + ')'; + } + + this.stack = new Error().stack; + } + + IndexError.prototype = new RangeError(); + IndexError.prototype.constructor = RangeError; + IndexError.prototype.name = 'IndexError'; + IndexError.prototype.isIndexError = true; + + module.exports = IndexError; + +/***/ }, +/* 89 */ +/***/ function(module, exports) { + + 'use strict'; + + exports.symbols = { + // GREEK LETTERS + Alpha: 'A', alpha: '\\alpha', + Beta: 'B', beta: '\\beta', + Gamma: '\\Gamma', gamma: '\\gamma', + Delta: '\\Delta', delta: '\\delta', + Epsilon: 'E', epsilon: '\\epsilon', varepsilon: '\\varepsilon', + Zeta: 'Z', zeta: '\\zeta', + Eta: 'H', eta: '\\eta', + Theta: '\\Theta', theta: '\\theta', vartheta: '\\vartheta', + Iota: 'I', iota: '\\iota', + Kappa: 'K', kappa: '\\kappa', varkappa: '\\varkappa', + Lambda: '\\Lambda', lambda: '\\lambda', + Mu: 'M', mu: '\\mu', + Nu: 'N', nu: '\\nu', + Xi: '\\Xi', xi: '\\xi', + Omicron: 'O', omicron: 'o', + Pi: '\\Pi', pi: '\\pi', varpi: '\\varpi', + Rho: 'P', rho: '\\rho', varrho: '\\varrho', + Sigma: '\\Sigma', sigma: '\\sigma', varsigma: '\\varsigma', + Tau: 'T', tau: '\\tau', + Upsilon: '\\Upsilon', upsilon: '\\upsilon', + Phi: '\\Phi', phi: '\\phi', varphi: '\\varphi', + Chi: 'X', chi: '\\chi', + Psi: '\\Psi', psi: '\\psi', + Omega: '\\Omega', omega: '\\omega', + //logic + 'true': '\\mathrm{True}', + 'false': '\\mathrm{False}', + //other + i: 'i', //TODO use \i ?? + inf: '\\infty', + Inf: '\\infty', + infinity: '\\infty', + Infinity: '\\infty', + oo: '\\infty', + lim: '\\lim', + 'undefined': '\\mathbf{?}' + }; + + exports.operators = { + 'transpose': '^\\top', + 'factorial': '!', + 'pow': '^', + 'dotPow': '.^\\wedge', //TODO find ideal solution + 'unaryPlus': '+', + 'unaryMinus': '-', + 'bitNot': '~', //TODO find ideal solution + 'not': '\\neg', + 'multiply': '\\cdot', + 'divide': '\\frac', //TODO how to handle that properly? + 'dotMultiply': '.\\cdot', //TODO find ideal solution + 'dotDivide': '.:', //TODO find ideal solution + 'mod': '\\mod', + 'add': '+', + 'subtract': '-', + 'to': '\\rightarrow', + 'leftShift': '<<', + 'rightArithShift': '>>', + 'rightLogShift': '>>>', + 'equal': '=', + 'unequal': '\\neq', + 'smaller': '<', + 'larger': '>', + 'smallerEq': '\\leq', + 'largerEq': '\\geq', + 'bitAnd': '\\&', + 'bitXor': '\\underline{|}', + 'bitOr': '|', + 'and': '\\wedge', + 'xor': '\\veebar', + 'or': '\\vee' + }; + + exports.defaultTemplate = '\\mathrm{${name}}\\left(${args}\\right)'; + + var units = { + deg: '^\\circ' + }; + + //@param {string} name + //@param {boolean} isUnit + exports.toSymbol = function (name, isUnit) { + isUnit = typeof isUnit === 'undefined' ? false : isUnit; + if (isUnit) { + if (units.hasOwnProperty(name)) { + return units[name]; + } + return '\\mathrm{' + name + '}'; + } + + if (exports.symbols.hasOwnProperty(name)) { + return exports.symbols[name]; + } else if (name.indexOf('_') !== -1) { + //symbol with index (eg. alpha_1) + var index = name.indexOf('_'); + return exports.toSymbol(name.substring(0, index)) + '_{' + exports.toSymbol(name.substring(index + 1)) + '}'; + } + return name; + }; + +/***/ }, +/* 90 */ +/***/ function(module, exports) { + + 'use strict'; + + function factory(type, config, load, typed) { + /** + * Create a Matrix. The function creates a new `math.type.Matrix` object from + * an `Array`. A Matrix has utility functions to manipulate the data in the + * matrix, like getting the size and getting or setting values in the matrix. + * Supported storage formats are 'dense' and 'sparse'. + * + * Syntax: + * + * math.matrix() // creates an empty matrix using default storage format (dense). + * math.matrix(data) // creates a matrix with initial data using default storage format (dense). + * math.matrix('dense') // creates an empty matrix using the given storage format. + * math.matrix(data, 'dense') // creates a matrix with initial data using the given storage format. + * math.matrix(data, 'sparse') // creates a sparse matrix with initial data. + * math.matrix(data, 'sparse', 'number') // creates a sparse matrix with initial data, number data type. + * + * Examples: + * + * var m = math.matrix([[1, 2], [3, 4]]); + * m.size(); // Array [2, 2] + * m.resize([3, 2], 5); + * m.valueOf(); // Array [[1, 2], [3, 4], [5, 5]] + * m.get([1, 0]) // number 3 + * + * See also: + * + * bignumber, boolean, complex, index, number, string, unit, sparse + * + * @param {Array | Matrix} [data] A multi dimensional array + * @param {string} [format] The Matrix storage format + * + * @return {Matrix} The created matrix + */ + var matrix = typed('matrix', { + '': function () { + return _create([]); + }, + + 'string': function (format) { + return _create([], format); + }, + + 'string, string': function (format, datatype) { + return _create([], format, datatype); + }, + + 'Array': function (data) { + return _create(data); + }, + + 'Matrix': function (data) { + return _create(data, data.storage()); + }, + + 'Array | Matrix, string': _create, + + 'Array | Matrix, string, string': _create + }); + + matrix.toTex = { + 0: '\\begin{bmatrix}\\end{bmatrix}', + 1: '\\left(${args[0]}\\right)', + 2: '\\left(${args[0]}\\right)' + }; + + return matrix; + + /** + * Create a new Matrix with given storage format + * @param {Array} data + * @param {string} [format] + * @param {string} [datatype] + * @returns {Matrix} Returns a new Matrix + * @private + */ + function _create(data, format, datatype) { + // get storage format constructor + var M = type.Matrix.storage(format || 'default'); + + // create instance + return new M(data, datatype); + } + } + + exports.name = 'matrix'; + exports.factory = factory; + +/***/ }, +/* 91 */ +/***/ function(module, exports) { + + 'use strict'; + + function factory(type, config, load, typed) { + + /** + * Add two scalar values, `x + y`. + * This function is meant for internal use: it is used by the public function + * `add` + * + * This function does not support collections (Array or Matrix), and does + * not validate the number of of inputs. + * + * @param {number | BigNumber | Fraction | Complex | Unit} x First value to add + * @param {number | BigNumber | Fraction | Complex} y Second value to add + * @return {number | BigNumber | Fraction | Complex | Unit} Sum of `x` and `y` + * @private + */ + var add = typed('add', { + + 'number, number': function (x, y) { + return x + y; + }, + + 'Complex, Complex': function (x, y) { + return x.add(y); + }, + + 'BigNumber, BigNumber': function (x, y) { + return x.plus(y); + }, + + 'Fraction, Fraction': function (x, y) { + return x.add(y); + }, + + 'Unit, Unit': function (x, y) { + if (x.value == null) throw new Error('Parameter x contains a unit with undefined value'); + if (y.value == null) throw new Error('Parameter y contains a unit with undefined value'); + if (!x.equalBase(y)) throw new Error('Units do not match'); + + var res = x.clone(); + res.value = add(res.value, y.value); + res.fixPrefix = false; + return res; + } + }); + + return add; + } + + exports.factory = factory; + +/***/ }, +/* 92 */ +/***/ function(module, exports) { + + 'use strict'; + + function factory(type, config, load, typed) { + + /** + * Multiply two scalar values, `x * y`. + * This function is meant for internal use: it is used by the public function + * `multiply` + * + * This function does not support collections (Array or Matrix), and does + * not validate the number of of inputs. + * + * @param {number | BigNumber | Fraction | Complex | Unit} x First value to multiply + * @param {number | BigNumber | Fraction | Complex} y Second value to multiply + * @return {number | BigNumber | Fraction | Complex | Unit} Multiplication of `x` and `y` + * @private + */ + var multiplyScalar = typed('multiplyScalar', { + + 'number, number': function (x, y) { + return x * y; + }, + + 'Complex, Complex': function (x, y) { + return x.mul(y); + }, + + 'BigNumber, BigNumber': function (x, y) { + return x.times(y); + }, + + 'Fraction, Fraction': function (x, y) { + return x.mul(y); + }, + + 'number | Fraction | BigNumber | Complex, Unit': function (x, y) { + var res = y.clone(); + res.value = res.value === null ? res._normalize(x) : multiplyScalar(res.value, x); + return res; + }, + + 'Unit, number | Fraction | BigNumber | Complex': function (x, y) { + var res = x.clone(); + res.value = res.value === null ? res._normalize(y) : multiplyScalar(res.value, y); + return res; + }, + + 'Unit, Unit': function (x, y) { + return x.multiply(y); + } + + }); + + return multiplyScalar; + } + + exports.factory = factory; + +/***/ }, +/* 93 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var nearlyEqual = __webpack_require__(72).nearlyEqual; + var bigNearlyEqual = __webpack_require__(94); + + function factory(type, config, load, typed) { + + /** + * Test whether two values are equal. + * + * @param {number | BigNumber | Fraction | boolean | Complex | Unit} x First value to compare + * @param {number | BigNumber | Fraction | boolean | Complex} y Second value to compare + * @return {boolean} Returns true when the compared values are equal, else returns false + * @private + */ + var equalScalar = typed('equalScalar', { + + 'boolean, boolean': function (x, y) { + return x === y; + }, + + 'number, number': function (x, y) { + return x === y || nearlyEqual(x, y, config.epsilon); + }, + + 'BigNumber, BigNumber': function (x, y) { + return x.eq(y) || bigNearlyEqual(x, y, config.epsilon); + }, + + 'Fraction, Fraction': function (x, y) { + return x.equals(y); + }, + + 'Complex, Complex': function (x, y) { + return x.equals(y); + }, + + 'Unit, Unit': function (x, y) { + if (!x.equalBase(y)) { + throw new Error('Cannot compare units with different base'); + } + return equalScalar(x.value, y.value); + }, + + 'string, string': function (x, y) { + return x === y; + } + }); + + return equalScalar; + } + + exports.factory = factory; + +/***/ }, +/* 94 */ +/***/ function(module, exports) { + + 'use strict'; + + /** + * Compares two BigNumbers. + * @param {BigNumber} x First value to compare + * @param {BigNumber} y Second value to compare + * @param {number} [epsilon] The maximum relative difference between x and y + * If epsilon is undefined or null, the function will + * test whether x and y are exactly equal. + * @return {boolean} whether the two numbers are nearly equal + */ + + module.exports = function nearlyEqual(x, y, epsilon) { + // if epsilon is null or undefined, test whether x and y are exactly equal + if (epsilon == null) { + return x.eq(y); + } + + // use "==" operator, handles infinities + if (x.eq(y)) { + return true; + } + + // NaN + if (x.isNaN() || y.isNaN()) { + return false; + } + + // at this point x and y should be finite + if (x.isFinite() && y.isFinite()) { + // check numbers are very close, needed when comparing numbers near zero + var diff = x.minus(y).abs(); + if (diff.isZero()) { + return true; + } else { + // use relative error + var max = x.constructor.max(x.abs(), y.abs()); + return diff.lte(max.times(epsilon)); + } + } + + // Infinite and Number or negative Infinite and positive Infinite cases + return false; + }; + +/***/ }, +/* 95 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + function factory(type, config, load, typed) { + + var equalScalar = load(__webpack_require__(93)); + + var SparseMatrix = type.SparseMatrix; + + /** + * Iterates over SparseMatrix S nonzero items and invokes the callback function f(Sij, b). + * Callback function invoked NZ times (number of nonzero items in S). + * + * + * ┌ f(Sij, b) ; S(i,j) !== 0 + * C(i,j) = ┤ + * â”” 0 ; otherwise + * + * + * @param {Matrix} s The SparseMatrix instance (S) + * @param {Scalar} b The Scalar value + * @param {Function} callback The f(Aij,b) operation to invoke + * @param {boolean} inverse A true value indicates callback should be invoked f(b,Sij) + * + * @return {Matrix} SparseMatrix (C) + * + * https://github.com/josdejong/mathjs/pull/346#issuecomment-97626813 + */ + var algorithm11 = function (s, b, callback, inverse) { + // sparse matrix arrays + var avalues = s._values; + var aindex = s._index; + var aptr = s._ptr; + var asize = s._size; + var adt = s._datatype; + + // sparse matrix cannot be a Pattern matrix + if (!avalues) throw new Error('Cannot perform operation on Pattern Sparse Matrix and Scalar value'); + + // rows & columns + var rows = asize[0]; + var columns = asize[1]; + + // datatype + var dt; + // equal signature to use + var eq = equalScalar; + // zero value + var zero = 0; + // callback signature to use + var cf = callback; + + // process data types + if (typeof adt === 'string') { + // datatype + dt = adt; + // find signature that matches (dt, dt) + eq = typed.find(equalScalar, [dt, dt]); + // convert 0 to the same datatype + zero = typed.convert(0, dt); + // convert b to the same datatype + b = typed.convert(b, dt); + // callback + cf = typed.find(callback, [dt, dt]); + } + + // result arrays + var cvalues = []; + var cindex = []; + var cptr = []; + // matrix + var c = new SparseMatrix({ + values: cvalues, + index: cindex, + ptr: cptr, + size: [rows, columns], + datatype: dt + }); + + // loop columns + for (var j = 0; j < columns; j++) { + // initialize ptr + cptr[j] = cindex.length; + // values in j + for (var k0 = aptr[j], k1 = aptr[j + 1], k = k0; k < k1; k++) { + // row + var i = aindex[k]; + // invoke callback + var v = inverse ? cf(b, avalues[k]) : cf(avalues[k], b); + // check value is zero + if (!eq(v, zero)) { + // push index & value + cindex.push(i); + cvalues.push(v); + } + } + } + // update ptr + cptr[columns] = cindex.length; + + // return sparse matrix + return c; + }; + + return algorithm11; + } + + exports.name = 'algorithm11'; + exports.factory = factory; + +/***/ }, +/* 96 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var clone = __webpack_require__(69).clone; + + function factory(type, config, load, typed) { + + var DenseMatrix = type.DenseMatrix; + + /** + * Iterates over DenseMatrix items and invokes the callback function f(Aij..z, b). + * Callback function invoked MxN times. + * + * C(i,j,...z) = f(Aij..z, b) + * + * @param {Matrix} a The DenseMatrix instance (A) + * @param {Scalar} b The Scalar value + * @param {Function} callback The f(Aij..z,b) operation to invoke + * @param {boolean} inverse A true value indicates callback should be invoked f(b,Aij..z) + * + * @return {Matrix} DenseMatrix (C) + * + * https://github.com/josdejong/mathjs/pull/346#issuecomment-97659042 + */ + var algorithm14 = function (a, b, callback, inverse) { + // a arrays + var adata = a._data; + var asize = a._size; + var adt = a._datatype; + + // datatype + var dt; + // callback signature to use + var cf = callback; + + // process data types + if (typeof adt === 'string') { + // datatype + dt = adt; + // convert b to the same datatype + b = typed.convert(b, dt); + // callback + cf = typed.find(callback, [dt, dt]); + } + + // populate cdata, iterate through dimensions + var cdata = asize.length > 0 ? _iterate(cf, 0, asize, asize[0], adata, b, inverse) : []; + + // c matrix + return new DenseMatrix({ + data: cdata, + size: clone(asize), + datatype: dt + }); + }; + + // recursive function + var _iterate = function (f, level, s, n, av, bv, inverse) { + // initialize array for this level + var cv = []; + // check we reach the last level + if (level === s.length - 1) { + // loop arrays in last level + for (var i = 0; i < n; i++) { + // invoke callback and store value + cv[i] = inverse ? f(bv, av[i]) : f(av[i], bv); + } + } else { + // iterate current level + for (var j = 0; j < n; j++) { + // iterate next level + cv[j] = _iterate(f, level + 1, s, s[level + 1], av[j], bv, inverse); + } + } + return cv; + }; + + return algorithm14; + } + + exports.name = 'algorithm14'; + exports.factory = factory; + +/***/ }, +/* 97 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var isInteger = __webpack_require__(72).isInteger; + var size = __webpack_require__(83).size; + + function factory(type, config, load, typed) { + var latex = __webpack_require__(89); + var eye = load(__webpack_require__(98)); + var multiply = load(__webpack_require__(82)); + var matrix = load(__webpack_require__(90)); + var fraction = load(__webpack_require__(99)); + var number = load(__webpack_require__(100)); + + /** + * Calculates the power of x to y, `x ^ y`. + * Matrix exponentiation is supported for square matrices `x`, and positive + * integer exponents `y`. + * + * For cubic roots of negative numbers, the function returns the principal + * root by default. In order to let the function return the real root, + * math.js can be configured with `math.config({predictable: true})`. + * To retrieve all cubic roots of a value, use `math.cbrt(x, true)`. + * + * Syntax: + * + * math.pow(x, y) + * + * Examples: + * + * math.pow(2, 3); // returns number 8 + * + * var a = math.complex(2, 3); + * math.pow(a, 2) // returns Complex -5 + 12i + * + * var b = [[1, 2], [4, 3]]; + * math.pow(b, 2); // returns Array [[9, 8], [16, 17]] + * + * See also: + * + * multiply, sqrt, cbrt, nthRoot + * + * @param {number | BigNumber | Complex | Array | Matrix} x The base + * @param {number | BigNumber | Complex} y The exponent + * @return {number | BigNumber | Complex | Array | Matrix} The value of `x` to the power `y` + */ + var pow = typed('pow', { + 'number, number': _pow, + + 'Complex, Complex': function (x, y) { + return x.pow(y); + }, + + 'BigNumber, BigNumber': function (x, y) { + if (y.isInteger() || x >= 0 || config.predictable) { + return x.pow(y); + } else { + return new type.Complex(x.toNumber(), 0).pow(y.toNumber(), 0); + } + }, + + 'Fraction, Fraction': function (x, y) { + if (y.d !== 1) { + if (config.predictable) { + throw new Error('Function pow does not support non-integer exponents for fractions.'); + } else { + return _pow(x.valueOf(), y.valueOf()); + } + } else { + return x.pow(y); + } + }, + + 'Array, number': _powArray, + + 'Array, BigNumber': function (x, y) { + return _powArray(x, y.toNumber()); + }, + + 'Matrix, number': _powMatrix, + + 'Matrix, BigNumber': function (x, y) { + return _powMatrix(x, y.toNumber()); + }, + + 'Unit, number': function (x, y) { + return x.pow(y); + } + + }); + + /** + * Calculates the power of x to y, x^y, for two numbers. + * @param {number} x + * @param {number} y + * @return {number | Complex} res + * @private + */ + function _pow(x, y) { + + // Alternatively could define a 'realmode' config option or something, but + // 'predictable' will work for now + if (config.predictable && !isInteger(y) && x < 0) { + // Check to see if y can be represented as a fraction + try { + var yFrac = fraction(y); + var yNum = number(yFrac); + if (y === yNum || Math.abs((y - yNum) / y) < 1e-14) { + if (yFrac.d % 2 === 1) { + return (yFrac.n % 2 === 0 ? 1 : -1) * Math.pow(-x, y); + } + } + } catch (ex) {} + // fraction() throws an error if y is Infinity, etc. + + + // Unable to express y as a fraction, so continue on + } + + if (isInteger(y) || x >= 0 || config.predictable) { + return Math.pow(x, y); + } else { + return new type.Complex(x, 0).pow(y, 0); + } + } + + /** + * Calculate the power of a 2d array + * @param {Array} x must be a 2 dimensional, square matrix + * @param {number} y a positive, integer value + * @returns {Array} + * @private + */ + function _powArray(x, y) { + if (!isInteger(y) || y < 0) { + throw new TypeError('For A^b, b must be a positive integer (value is ' + y + ')'); + } + // verify that A is a 2 dimensional square matrix + var s = size(x); + if (s.length != 2) { + throw new Error('For A^b, A must be 2 dimensional (A has ' + s.length + ' dimensions)'); + } + if (s[0] != s[1]) { + throw new Error('For A^b, A must be square (size is ' + s[0] + 'x' + s[1] + ')'); + } + + var res = eye(s[0]).valueOf(); + var px = x; + while (y >= 1) { + if ((y & 1) == 1) { + res = multiply(px, res); + } + y >>= 1; + px = multiply(px, px); + } + return res; + } + + /** + * Calculate the power of a 2d matrix + * @param {Matrix} x must be a 2 dimensional, square matrix + * @param {number} y a positive, integer value + * @returns {Matrix} + * @private + */ + function _powMatrix(x, y) { + return matrix(_powArray(x.valueOf(), y)); + } + + pow.toTex = { + 2: '\\left(${args[0]}\\right)' + latex.operators['pow'] + '{${args[1]}}' + }; + + return pow; + } + + exports.name = 'pow'; + exports.factory = factory; + +/***/ }, +/* 98 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var array = __webpack_require__(83); + var isInteger = __webpack_require__(72).isInteger; + + function factory(type, config, load, typed) { + + var matrix = load(__webpack_require__(90)); + + /** + * Create a 2-dimensional identity matrix with size m x n or n x n. + * The matrix has ones on the diagonal and zeros elsewhere. + * + * Syntax: + * + * math.eye(n) + * math.eye(n, format) + * math.eye(m, n) + * math.eye(m, n, format) + * math.eye([m, n]) + * math.eye([m, n], format) + * + * Examples: + * + * math.eye(3); // returns [[1, 0, 0], [0, 1, 0], [0, 0, 1]] + * math.eye(3, 2); // returns [[1, 0], [0, 1], [0, 0]] + * + * var A = [[1, 2, 3], [4, 5, 6]]; + * math.eye(math.size(A)); // returns [[1, 0, 0], [0, 1, 0]] + * + * See also: + * + * diag, ones, zeros, size, range + * + * @param {...number | Matrix | Array} size The size for the matrix + * @param {string} [format] The Matrix storage format + * + * @return {Matrix | Array | number} A matrix with ones on the diagonal. + */ + var eye = typed('eye', { + '': function () { + return config.matrix === 'Matrix' ? matrix([]) : []; + }, + + 'string': function (format) { + return matrix(format); + }, + + 'number | BigNumber': function (rows) { + return _eye(rows, rows, config.matrix === 'Matrix' ? 'default' : undefined); + }, + + 'number | BigNumber, string': function (rows, format) { + return _eye(rows, rows, format); + }, + + 'number | BigNumber, number | BigNumber': function (rows, cols) { + return _eye(rows, cols, config.matrix === 'Matrix' ? 'default' : undefined); + }, + + 'number | BigNumber, number | BigNumber, string': function (rows, cols, format) { + return _eye(rows, cols, format); + }, + + 'Array': function (size) { + return _eyeVector(size); + }, + + 'Array, string': function (size, format) { + return _eyeVector(size, format); + }, + + 'Matrix': function (size) { + return _eyeVector(size.valueOf(), size.storage()); + }, + + 'Matrix, string': function (size, format) { + return _eyeVector(size.valueOf(), format); + } + }); + + eye.toTex = undefined; // use default template + + return eye; + + function _eyeVector(size, format) { + switch (size.length) { + case 0: + return format ? matrix(format) : []; + case 1: + return _eye(size[0], size[0], format); + case 2: + return _eye(size[0], size[1], format); + default: + throw new Error('Vector containing two values expected'); + } + } + + /** + * Create an identity matrix + * @param {number | BigNumber} rows + * @param {number | BigNumber} cols + * @param {string} [format] + * @returns {Matrix} + * @private + */ + function _eye(rows, cols, format) { + // BigNumber constructor with the right precision + var Big = rows && rows.isBigNumber === true ? type.BigNumber : cols && cols.isBigNumber === true ? type.BigNumber : null; + + if (rows && rows.isBigNumber === true) rows = rows.toNumber(); + if (cols && cols.isBigNumber === true) cols = cols.toNumber(); + + if (!isInteger(rows) || rows < 1) { + throw new Error('Parameters in function eye must be positive integers'); + } + if (!isInteger(cols) || cols < 1) { + throw new Error('Parameters in function eye must be positive integers'); + } + + var one = Big ? new type.BigNumber(1) : 1; + var defaultValue = Big ? new Big(0) : 0; + var size = [rows, cols]; + + // check we need to return a matrix + if (format) { + // get matrix storage constructor + var F = type.Matrix.storage(format); + // create diagonal matrix (use optimized implementation for storage format) + return F.diagonal(size, one, 0, defaultValue); + } + + // create and resize array + var res = array.resize([], size, defaultValue); + // fill in ones on the diagonal + var minimum = rows < cols ? rows : cols; + // fill diagonal + for (var d = 0; d < minimum; d++) { + res[d][d] = one; + } + return res; + } + } + + exports.name = 'eye'; + exports.factory = factory; + +/***/ }, +/* 99 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var deepMap = __webpack_require__(80); + + function factory(type, config, load, typed) { + /** + * Create a fraction convert a value to a fraction. + * + * Syntax: + * math.fraction(numerator, denominator) + * math.fraction({n: numerator, d: denominator}) + * math.fraction(matrix: Array | Matrix) Turn all matrix entries + * into fractions + * + * Examples: + * + * math.fraction(1, 3); + * math.fraction('2/3'); + * math.fraction({n: 2, d: 3}); + * math.fraction([0.2, 0.25, 1.25]); + * + * See also: + * + * bignumber, number, string, unit + * + * @param {number | string | Fraction | BigNumber | Array | Matrix} [args] + * Arguments specifying the numerator and denominator of + * the fraction + * @return {Fraction | Array | Matrix} Returns a fraction + */ + var fraction = typed('fraction', { + 'number': function (x) { + if (!isFinite(x) || isNaN(x)) { + throw new Error(x + ' cannot be represented as a fraction'); + } + + return new type.Fraction(x); + }, + + 'string': function (x) { + return new type.Fraction(x); + }, + + 'number, number': function (numerator, denominator) { + return new type.Fraction(numerator, denominator); + }, + + 'BigNumber': function (x) { + return new type.Fraction(x.toString()); + }, + + 'Fraction': function (x) { + return x; // fractions are immutable + }, + + 'Object': function (x) { + return new type.Fraction(x); + }, + + 'Array | Matrix': function (x) { + return deepMap(x, fraction); + } + }); + + return fraction; + } + + exports.name = 'fraction'; + exports.factory = factory; + +/***/ }, +/* 100 */ +/***/ function(module, exports, __webpack_require__) { + + 'use strict'; + + var deepMap = __webpack_require__(80); + + function factory(type, config, load, typed) { + /** + * Create a number or convert a string, boolean, or unit to a number. + * When value is a matrix, all elements will be converted to number. + * + * Syntax: + * + * math.number(value) + * math.number(unit, valuelessUnit) + * + * Examples: + * + * math.number(2); // returns number 2 + * math.number('7.2'); // returns number 7.2 + * math.number(true); // returns number 1 + * math.number([true, false, true, true]); // returns [1, 0, 1, 1] + * math.number(math.unit('52cm'), 'm'); // returns 0.52 + * + * See also: + * + * bignumber, boolean, complex, index, matrix, string, unit + * + * @param {string | number | BigNumber | Fraction | boolean | Array | Matrix | Unit | null} [value] Value to be converted + * @param {Unit | string} [valuelessUnit] A valueless unit, used to convert a unit to a number + * @return {number | Array | Matrix} The created number + */ + var number = typed('number', { + '': function () { + return 0; + }, + + 'number': function (x) { + return x; + }, + + 'string': function (x) { + var num = Number(x); + if (isNaN(num)) { + throw new SyntaxError('String "' + x + '" is no valid number'); + } + return num; + }, + + 'BigNumber': function (x) { + return x.toNumber(); + }, + + 'Fraction': function (x) { + return x.valueOf(); + }, + + 'Unit': function (x) { + throw new Error('Second argument with valueless unit expected'); + }, + + 'Unit, string | Unit': function (unit, valuelessUnit) { + return unit.toNumber(valuelessUnit); + }, + + 'Array | Matrix': function (x) { + return deepMap(x, number); + } + }); + + number.toTex = { + 0: '0', + 1: '\\left(${args[0]}\\right)', + 2: '\\left(\\left(${args[0]}\\right)${args[1]}\\right)' + }; + + return number; + } + + exports.name = 'number'; + exports.factory = factory; + +/***/ }, +/* 101 */ +/***/ function(module, exports) { + + module.exports = function get_previous_zoom(params) { + var prev_zoom = {}; + + var inst_trans = d3.select(params.root + ' .clust_group').attr('transform'); + + if (inst_trans != null) { + + // prevent from crashing if no scaling was done + if (inst_trans.indexOf('scale') > 0) { + prev_zoom.zoom_x = parseFloat(inst_trans.split('scale')[1].replace('(', '').replace(')', '').split(',')[0]); + + prev_zoom.zoom_y = parseFloat(inst_trans.split('scale')[1].replace('(', '').replace(')', '').split(',')[1]); + } else { + prev_zoom.zoom_x = 1; + prev_zoom.zoom_y = 1; + } + } else { + prev_zoom.zoom_x = 1; + prev_zoom.zoom_y = 1; + } + + return prev_zoom; + }; + +/***/ }, +/* 102 */ +/***/ function(module, exports, __webpack_require__) { + + var d3_tip_custom = __webpack_require__(48); + + module.exports = function make_row_tooltips(params) { + + if (params.labels.show_label_tooltips) { + + // remove old tooltips + d3.selectAll(params.viz.root_tips + '_row_tip').remove(); + + var root_tip_selector = params.viz.root_tips.replace('.', ''); + + // d3-tooltip + var row_tip = d3_tip_custom().attr('class', function () { + var class_string = root_tip_selector + ' d3-tip ' + root_tip_selector + '_row_tip'; + return class_string; + }).direction('e').offset([0, 10]).style('display', 'none').html(function (d) { + var inst_name = d.name.replace(/_/g, ' ').split('#')[0]; + return "<span>" + inst_name + "</span>"; + }); + + d3.select(params.viz.viz_wrapper).select(params.root + ' .row_container').call(row_tip); + + d3.select(params.root + ' .row_label_zoom_container').selectAll('g').on('mouseover', function (d) { + + d3.select(params.viz.root_tips + '_row_tip').classed(d.name, true); + + d3.selectAll(params.viz.root_tips + '_row_tip').style('display', 'block'); + + d3.select(this).select('text').classed('active', true); + + row_tip.show(d); + + if (params.row_tip_callback != null) { + params.row_tip_callback(params.viz.root_tips, d); + } + }).on('mouseout', function mouseout(d) { + + d3.selectAll(params.viz.root_tips + '_row_tip').style('display', 'none').classed(d.name, false); + + d3.select(this).select('text').classed('active', false); + + row_tip.hide(d); + }); + } else { + + d3.select(params.root + ' .row_label_zoom_container').selectAll('g').on('mouseover', function () { + d3.select(this).select('text').classed('active', true); + }).on('mouseout', function mouseout() { + d3.select(this).select('text').classed('active', false); + }); + } + }; + +/***/ }, +/* 103 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + var add_col_click_hlight = __webpack_require__(104); + var col_reorder = __webpack_require__(105); + var row_reorder = __webpack_require__(52); + var make_col_tooltips = __webpack_require__(109); + var col_viz_aid_triangle = __webpack_require__(110); + + module.exports = function make_col_label_container(cgm, text_delay = 0) { + + var params = cgm.params; + var col_container; + + var col_nodes = params.network_data.col_nodes; + + // offset click group column label + var x_offset_click = params.viz.x_scale.rangeBand() / 2 + params.viz.border_width.x; + // reduce width of rotated rects + + + // make container to pre-position zoomable elements + if (d3.select(params.root + ' .col_container').empty()) { + + col_container = d3.select(params.viz.viz_svg).append('g').attr('class', 'col_container').attr('transform', 'translate(' + params.viz.clust.margin.left + ',' + params.viz.norm_labels.margin.top + ')'); + + // white background rect for col labels + col_container.append('rect').attr('fill', params.viz.background_color) //!! prog_colors + .attr('width', 30 * params.viz.clust.dim.width + 'px').attr('height', params.viz.label_background.col).attr('class', 'white_bars'); + + // col labels + col_container.append('g').attr('class', 'col_label_outer_container') + // position the outer col label group + .attr('transform', 'translate(0,' + params.viz.norm_labels.width.col + ')').append('g').attr('class', 'col_zoom_container'); + } else { + + col_container = d3.select(params.root + ' .col_container').attr('transform', 'translate(' + params.viz.clust.margin.left + ',' + params.viz.norm_labels.margin.top + ')'); + + // white background rect for col labels + col_container.select('.white_bars').attr('fill', params.viz.background_color) //!! prog_colors + .attr('width', 30 * params.viz.clust.dim.width + 'px').attr('height', params.viz.label_background.col); + + // col labels + col_container.select(params.root + ' .col_label_outer_container'); + } + + // add main column label group + var col_label_obj = d3.select(params.root + ' .col_zoom_container').selectAll('.col_label_text').data(col_nodes, function (d) { + return d.name; + }).enter().append('g').attr('class', 'col_label_text').attr('transform', function (d) { + var inst_index = d.col_index; + return 'translate(' + params.viz.x_scale(inst_index) + ', 0) rotate(-90)'; + }); + + // append group for individual column label + var col_label_group = col_label_obj + // append new group for rect and label (not white lines) + .append('g').attr('class', 'col_label_group') + // rotate column labels + .attr('transform', 'translate(' + params.viz.x_scale.rangeBand() / 2 + ',' + x_offset_click + ') rotate(45)').on('mouseover', function () { + d3.select(this).select('text').classed('active', true); + }).on('mouseout', function () { + d3.select(this).select('text').classed('active', false); + }); + + // append column value bars + if (utils.has(params.network_data.col_nodes[0], 'value')) { + + col_label_group.append('rect').attr('class', 'col_bars').attr('width', function (d) { + var inst_value = 0; + if (d.value > 0) { + inst_value = params.labels.bar_scale_col(d.value); + } + return inst_value; + }) + // rotate labels - reduce width if rotating + .attr('height', params.viz.x_scale.rangeBand() * 0.66).style('fill', function (d) { + return d.value > 0 ? params.matrix.bar_colors[0] : params.matrix.bar_colors[1]; + }).attr('opacity', 0.6); + } + + // add column label + col_label_group.append('text').attr('x', 0) + // manually tuned + .attr('y', params.viz.x_scale.rangeBand() * 0.64).attr('dx', params.viz.border_width.x).attr('text-anchor', 'start').attr('full_name', function (d) { + return d.name; + }) + // original font size + .style('font-size', params.labels.default_fs_col + 'px').style('cursor', 'default').text(function (d) { + return utils.normal_name(d); + }) + // .attr('pointer-events','none') + .style('opacity', 0).transition().delay(text_delay).duration(text_delay).style('opacity', 1); + + make_col_tooltips(params); + + // add triangle under rotated labels + col_label_group.append('path').style('stroke-width', 0).attr('d', function () { + return col_viz_aid_triangle(params); + }).attr('fill', '#eee').style('opacity', 0).transition().delay(text_delay).duration(text_delay).style('opacity', params.viz.triangle_opacity); + + // add col callback function + d3.selectAll(params.root + ' .col_label_text').on('click', function (d) { + + if (typeof params.click_label == 'function') { + params.click_label(d.name, 'col'); + add_col_click_hlight(params, this, d.ini); + } else { + + if (params.tile_click_hlight) { + add_col_click_hlight(params, this, d.ini); + } + } + }).on('dblclick', function (d) { + + var data_attr = '__data__'; + var col_name = this[data_attr].name; + + if (params.sim_mat) { + col_reorder(cgm, this, col_name); + + var row_selection = d3.selectAll(params.root + ' .row_label_group').filter(function (d) { + return d.name == col_name; + })[0][0]; + + row_reorder(cgm, row_selection, col_name); + } else { + col_reorder(cgm, this, col_name); + } + + if (params.tile_click_hlight) { + add_col_click_hlight(params, this, d.ini); + } + }); + }; + +/***/ }, +/* 104 */ +/***/ function(module, exports) { + + module.exports = function (params, clicked_col, id_clicked_col) { + + if (id_clicked_col != params.click_hlight_col) { + + params.click_hlight_col = id_clicked_col; + + var rel_width_hlight = 6; + var opacity_hlight = 0.85; + var hlight_width = rel_width_hlight * params.viz.border_width.x; + + d3.selectAll(params.root + ' .click_hlight').remove(); + + // // highlight selected column + // /////////////////////////////// + // // unhilight and unbold all columns (already unbolded earlier) + // d3.selectAll('.col_label_text') + // .select('rect') + // .style('opacity', 0); + // // highlight column name + // d3.select(clicked_col) + // .select('rect') + // .style('opacity', 1); + + d3.select(clicked_col).append('rect').classed('click_hlight', true).classed('col_top_hlight', true).attr('width', params.viz.clust.dim.height).attr('height', hlight_width).attr('fill', params.matrix.hlight_color).attr('opacity', opacity_hlight).attr('transform', function () { + var tmp_translate_y = 0; + var tmp_translate_x = -(params.viz.clust.dim.height + params.viz.cat_room.col + params.viz.uni_margin); + return 'translate(' + tmp_translate_x + ',' + tmp_translate_y + ')'; + }); + + d3.select(clicked_col).append('rect').classed('click_hlight', true).classed('col_bottom_hlight', true).attr('width', params.viz.clust.dim.height).attr('height', hlight_width).attr('fill', params.matrix.hlight_color).attr('opacity', opacity_hlight).attr('transform', function () { + // reverse x and y since rotated + var tmp_translate_y = params.viz.x_scale.rangeBand() - hlight_width; + var tmp_translate_x = -(params.viz.clust.dim.height + params.viz.cat_room.col + params.viz.uni_margin); + return 'translate(' + tmp_translate_x + ',' + tmp_translate_y + ')'; + }); + } else { + d3.selectAll(params.root + ' .click_hlight').remove(); + params.click_hlight_col = -666; + } + }; + +/***/ }, +/* 105 */ +/***/ function(module, exports, __webpack_require__) { + + // var utils = require('../Utils_clust'); + var reposition_tile_highlight = __webpack_require__(53); + var toggle_dendro_view = __webpack_require__(54); + var show_visible_area = __webpack_require__(106); + var ini_zoom_info = __webpack_require__(36); + var get_previous_zoom = __webpack_require__(101); + var calc_downsampled_levels = __webpack_require__(27); + + module.exports = function col_reorder(cgm, col_selection, inst_term) { + + var params = cgm.params; + var prev_zoom = get_previous_zoom(params); + + if (prev_zoom.zoom_y === 1 && prev_zoom.zoom_x === 1) { + + params.viz.inst_order.col = 'custom'; + + toggle_dendro_view(cgm, 'col'); + + d3.selectAll(params.root + ' .toggle_row_order .btn').classed('active', false); + + params.viz.run_trans = true; + + var mat = $.extend(true, {}, params.matrix.matrix); + var row_nodes = params.network_data.row_nodes; + var col_nodes = params.network_data.col_nodes; + + // find the column number of col_selection term from col_nodes + // gather column node names + var tmp_arr = []; + col_nodes.forEach(function (node) { + tmp_arr.push(node.name); + }); + + // find index + var inst_col = _.indexOf(tmp_arr, inst_term); + + // gather the values of the input genes + tmp_arr = []; + row_nodes.forEach(function (node, index) { + tmp_arr.push(mat[index].row_data[inst_col].value); + }); + + // sort the cols + var tmp_sort = d3.range(tmp_arr.length).sort(function (a, b) { + return tmp_arr[b] - tmp_arr[a]; + }); + + // resort rows (rows are reorderd by double clicking a col) + params.viz.y_scale.domain(tmp_sort); + + // save to custom row order + params.matrix.orders.custom_col = tmp_sort; + + var t; + + var row_nodes_names = params.network_data.row_nodes_names; + + // reorder + if (params.network_data.links.length > params.matrix.def_large_matrix) { + t = d3.select(params.root + ' .viz_svg'); + } else { + t = d3.select(params.root + ' .viz_svg').transition().duration(2500); + } + + // reorder row_label_triangle groups + t.selectAll('.row_cat_group').attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0,' + params.viz.y_scale(inst_index) + ')'; + }); + + // Move Row Labels + t.select('.row_label_zoom_container').selectAll('.row_label_group').attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0,' + params.viz.y_scale(inst_index) + ')'; + }); + + // only update matri if not downsampled + if (params.viz.ds_level === -1) { + // reorder matrix rows + t.selectAll('.row').attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0,' + params.viz.y_scale(inst_index) + ')'; + }); + } + + // highlight selected column + /////////////////////////////// + // unhilight and unbold all columns (already unbolded earlier) + d3.selectAll(params.root + ' .col_label_text').select('.highlight_rect').style('opacity', 0); + // highlight column name + d3.select(col_selection).select('.highlight_rect').style('opacity', 1); + + // redefine x and y positions + params.network_data.links.forEach(function (d) { + d.x = params.viz.x_scale(d.target); + d.y = params.viz.y_scale(d.source); + }); + + reposition_tile_highlight(params); + + params.zoom_info = ini_zoom_info(); + + setTimeout(function () { + params.viz.run_trans = false; + }, 2500); + + // calculate downsmapling if necessary + if (params.viz.ds_num_levels > 0 && params.viz.ds_level >= 0) { + + calc_downsampled_levels(params); + + var zooming_stopped = true; + var zooming_out = true; + var make_all_rows = true; + // show_visible_area is also run with two_translate_zoom, but at that point + // the parameters were not updated and two_translate_zoom if only run + // if needed to reset zoom + show_visible_area(cgm, zooming_stopped, zooming_out, make_all_rows); + } + } + }; + +/***/ }, +/* 106 */ +/***/ function(module, exports, __webpack_require__) { + + var find_viz_rows = __webpack_require__(107); + var make_matrix_rows = __webpack_require__(41); + var make_row_labels = __webpack_require__(50); + var make_row_visual_aid_triangles = __webpack_require__(108); + + module.exports = function show_visible_area(cgm, zooming_stopped = false, zooming_out = false, make_all_rows = false) { + + // console.log('show_visible_area stopped: ' + String(zooming_stopped)); + + var params = cgm.params; + var zoom_info = params.zoom_info; + + // update ds_level if necessary + ////////////////////////////////////////////// + var check_ds_level = params.viz.ds_level; + var old_ds_level = params.viz.ds_level; + + // toggle the downsampling level (if necessary) + if (params.viz.ds === null) { + check_ds_level = -1; + } else { + + check_ds_level = Math.floor(Math.log(zoom_info.zoom_y) / Math.log(params.viz.ds_zt)); + + if (check_ds_level > params.viz.ds_num_levels - 1) { + check_ds_level = -1; + } + } + + // check if override_ds is necessary + ////////////////////////////////////////////// + // force update of view if moving to more coarse view + var override_ds = false; + + if (old_ds_level == -1) { + // transitioning to more coarse downsampling view (from real data) + if (check_ds_level >= 0) { + override_ds = true; + } + } else { + // transitioning to more coarse downsampling view + if (check_ds_level < old_ds_level) { + override_ds = true; + } + } + + // update level if zooming has stopped or if transitioning to more coarse view + var new_ds_level; + + if (zooming_stopped === true || override_ds === true) { + + // update new_ds_level if necessary (if decreasing detail, zooming out) + new_ds_level = check_ds_level; + + // set zooming_stopped to true in case of override_ds + zooming_stopped = true; + + params.viz.ds_level = new_ds_level; + } else { + // keep the old level (zooming is still occuring and not zooming out) + new_ds_level = old_ds_level; + } + + var viz_area = {}; + var buffer_size = 5; + // get translation vector absolute values + viz_area.min_x = Math.abs(zoom_info.trans_x) / zoom_info.zoom_x - (buffer_size + 1) * params.viz.rect_width; + viz_area.min_y = Math.abs(zoom_info.trans_y) / zoom_info.zoom_y - (buffer_size + 1) * params.viz.rect_height; + + viz_area.max_x = Math.abs(zoom_info.trans_x) / zoom_info.zoom_x + params.viz.clust.dim.width / zoom_info.zoom_x + buffer_size * params.viz.rect_width; + + viz_area.max_y = Math.abs(zoom_info.trans_y) / zoom_info.zoom_y + params.viz.clust.dim.height / zoom_info.zoom_y + buffer_size * params.viz.rect_height; + + // generate lists of visible rows/cols + find_viz_rows(params, viz_area); + + var missing_rows; + if (make_all_rows === false) { + missing_rows = _.difference(params.viz.viz_nodes.row, params.viz.viz_nodes.curr_row); + } else { + // make all rows (reordering) + missing_rows = 'all'; + + // remove downsampled rows + d3.selectAll(params.root + ' .ds' + String(new_ds_level) + '_row').remove(); + } + + if (params.viz.ds != null) { + var ds_row_class = '.ds' + String(params.viz.ds_level) + '_row'; + d3.selectAll(ds_row_class).style('display', 'block'); + } + + // if downsampling + if (new_ds_level >= 0) { + // remove old rows + d3.selectAll(params.root + ' .row').remove(); + // remove tile tooltips and row tooltips + d3.selectAll(params.viz.root_tips + '_tile_tip').remove(); + d3.selectAll(params.viz.root_tips + '_row_tip').remove(); + } + + // default state for downsampling + var inst_matrix; + + if (new_ds_level < 0) { + // set matrix to default matrix + inst_matrix = params.matrix.matrix; + + // make row visual-aid triangles + make_row_visual_aid_triangles(params); + } else { + // set matrix to downsampled matrix + inst_matrix = params.matrix.ds_matrix[new_ds_level]; + + d3.selectAll(params.root + ' .row_cat_group path').remove(); + } + + // also remove row visual aid triangles if zooming out + if (zooming_out === true) { + d3.selectAll(params.root + ' .row_cat_group path').remove(); + } + + // remove rows and labels that are not visible and change ds_level + /* run when zooming has stopped */ + if (zooming_stopped === true) { + + // remove not visible matrix rows + if (new_ds_level >= 0) { + + // remove downsampled rows + d3.selectAll(params.root + ' .ds' + String(new_ds_level) + '_row').each(function (d) { + if (_.contains(params.viz.viz_nodes.row, d.name) === false) { + d3.select(this).remove(); + } + }); + } else { + // remove real data rows + d3.selectAll(params.root + ' .row').each(function (d) { + if (_.contains(params.viz.viz_nodes.row, d.name) === false) { + d3.select(this).remove(); + } + }); + } + + // remove not visible row labels + d3.selectAll(params.root + ' .row_label_group').each(function (d) { + if (_.contains(params.viz.viz_nodes.row, d.name) === false) { + d3.select(this).remove(); + } + }); + + // level change + if (new_ds_level != old_ds_level) { + + // console.log('old: ' + String(old_ds_level) + ' new: '+ String(new_ds_level)); + + // all visible rows are missing at new downsampling level + missing_rows = params.viz.viz_nodes.row; + + // remove old level rows + d3.selectAll(params.root + ' .ds' + String(old_ds_level) + '_row').remove(); + } + } + + // console.log('missing_rows: ' + String(missing_rows)) + // console.log(missing_rows) + + // only make new matrix_rows if there are missing rows + if (missing_rows.length >= 1 || missing_rows === 'all') { + make_matrix_rows(params, inst_matrix, missing_rows, new_ds_level); + } + + // only make new row_labels if there are missing row_labels, downsampled, and + // not zooming out or zooming has stopped + if (new_ds_level === -1) { + + if (zooming_out === false || zooming_stopped) { + + // check if labels need to be made + /////////////////////////////////// + // get the names visible row_labels + var visible_row_labels = []; + d3.selectAll(params.root + ' .row_label_group').each(function (d) { + visible_row_labels.push(d.name); + }); + + // find missing labels + var missing_row_labels = _.difference(params.viz.viz_nodes.row, visible_row_labels); + + // make labels + ////////////////////////////////// + // only make row labels if there are any missing + var addback_thresh = 1; + if (missing_row_labels.length > addback_thresh) { + make_row_labels(cgm, missing_row_labels); + } + } + } + }; + +/***/ }, +/* 107 */ +/***/ function(module, exports) { + + module.exports = function find_viz_rows(params, viz_area) { + + var should_be_rows = []; + var curr_rows = []; + + // find rows that should be visible + var y_trans; + + // default y_scale (no downsampling) + var y_scale = params.viz.y_scale; + var ds_level = params.viz.ds_level; + var row_names = params.network_data.row_nodes_names; + var row_class = '.row'; + + // if downsampling redefine variables + if (ds_level >= 0) { + y_scale = params.viz.ds[ds_level].y_scale; + row_names = d3.range(params.matrix.ds_matrix[ds_level].length).map(String); + row_class = '.ds' + String(ds_level) + '_row'; + } + + // find rows that should be visible + for (var i = 0; i < row_names.length; i++) { + y_trans = y_scale(i); + if (y_trans < viz_area.max_y && y_trans > viz_area.min_y) { + should_be_rows.push(row_names[i]); + } + } + + // find currently visible rows + d3.selectAll(params.root + ' ' + row_class).each(function (d) { + curr_rows.push(d.name); + }); + + // nodes that should be visible + params.viz.viz_nodes.row = should_be_rows; + // nodes that are visible + params.viz.viz_nodes.curr_row = curr_rows; + }; + +/***/ }, +/* 108 */ +/***/ function(module, exports) { + + module.exports = function make_row_visual_aid_triangles(params) { + + if (d3.select(params.root + ' .row_cat_group path').empty() === true) { + d3.selectAll(params.root + ' .row_cat_group').append('path').attr('d', function () { + var origin_x = params.viz.cat_room.symbol_width - 1; + var origin_y = 0; + var mid_x = 1; + var mid_y = params.viz.y_scale.rangeBand() / 2; + var final_x = params.viz.cat_room.symbol_width - 1; + var final_y = params.viz.y_scale.rangeBand(); + var output_string = 'M ' + origin_x + ',' + origin_y + ' L ' + mid_x + ',' + mid_y + ', L ' + final_x + ',' + final_y + ' Z'; + return output_string; + }).attr('fill', '#eee').style('opacity', params.viz.triangle_opacity); + } + }; + +/***/ }, +/* 109 */ +/***/ function(module, exports, __webpack_require__) { + + var d3_tip_custom = __webpack_require__(48); + + module.exports = function make_col_tooltips(params) { + + if (params.labels.show_label_tooltips) { + + // remove old col tooltips + d3.selectAll(params.viz.root_tips + '_col_tip').remove(); + + // d3-tooltip + var col_tip = d3_tip_custom().attr('class', function () { + var root_tip_selector = params.viz.root_tips.replace('.', ''); + var class_string = root_tip_selector + ' d3-tip ' + root_tip_selector + '_col_tip'; + return class_string; + }).direction('w').offset([20, 0]).style('display', 'none').html(function (d) { + var inst_name = d.name.replace(/_/g, ' ').split('#')[0]; + return "<span>" + inst_name + "</span>"; + }); + + d3.select(params.viz.viz_wrapper).select('svg').select(params.root + ' .col_zoom_container').selectAll('.col_label_group').select('text').call(col_tip); + + d3.select(params.root + ' .col_zoom_container').selectAll('.col_label_group').on('mouseover', function (d) { + + d3.selectAll(params.viz.root_tips + '_col_tip').style('display', 'block'); + + col_tip.show(d); + if (params.col_tip_callback != null) { + params.col_tip_callback(d); + } + }).on('mouseout', function () { + col_tip.hide(this); + + d3.selectAll(params.viz.root_tips + '_col_tip').style('display', 'none'); + }); + } + }; + +/***/ }, +/* 110 */ +/***/ function(module, exports) { + + module.exports = function col_viz_aid_triangle(params) { + + // x and y are flipped since its rotated + var reduce_rect_width = params.viz.x_scale.rangeBand() * 0.36; + var origin_y = -params.viz.border_width.x; + var start_x = 0; + var final_x = params.viz.x_scale.rangeBand() - reduce_rect_width; + var start_y = -(params.viz.x_scale.rangeBand() - reduce_rect_width + params.viz.border_width.x); + var final_y = -params.viz.border_width.x; + var output_string = 'M ' + origin_y + ',0 L ' + start_y + ',' + start_x + ', L ' + final_y + ',' + final_x + ' Z'; + return output_string; + }; + +/***/ }, +/* 111 */ +/***/ function(module, exports) { + + module.exports = function (params) { + + d3.select(params.viz.viz_svg).append('rect').attr('fill', params.viz.background_color).attr('height', params.viz.super_labels.dim.width + 'px').attr('width', '3000px').classed('super_col_bkg', true).classed('white_bars', true).attr('transform', 'translate(' + params.viz.clust.margin.left + ',' + params.viz.super_labels.margin.top + ')'); + + d3.select(params.viz.viz_svg).append('text').attr('class', 'super_col').text(params.labels.super.col).attr('text-anchor', 'center').attr('transform', function () { + + var inst_text_width = d3.select(this)[0][0].getBBox().width; + + var inst_x = params.viz.clust.dim.width / 2 + params.viz.norm_labels.width.row - inst_text_width / 2; + var inst_y = params.viz.super_labels.dim.width; + return 'translate(' + inst_x + ',' + inst_y + ')'; + }).style('font-size', function () { + var inst_font_size = params.labels.super_label_fs * params.labels.super_label_scale; + return inst_font_size + 'px'; + }).style('font-weight', 300); + + d3.select(params.viz.viz_svg).append('rect').attr('fill', params.viz.background_color).attr('width', params.viz.super_labels.dim.width + 'px').attr('height', '3000px').classed('super_row_bkg', true).classed('white_bars', true).attr('transform', 'translate(' + params.viz.super_labels.margin.left + ',0)'); + + // append super title row group - used to separate translation from rotation + d3.select(params.viz.viz_svg).append('g').classed('super_row', true).attr('transform', function () { + // position in the middle of the clustergram + var inst_x = params.viz.super_labels.dim.width; + var inst_y = params.viz.clust.dim.height / 2 + params.viz.norm_labels.width.col; + return 'translate(' + inst_x + ',' + inst_y + ')'; + }); + + // super row label (rotate the already translated title ) + d3.select(params.root + ' .super_row').append('text').text(params.labels.super.row).attr('text-anchor', 'center').attr('transform', function () { + var inst_text_width = d3.select(this)[0][0].getBBox().width; + var inst_x_offset = inst_text_width / 2 + params.viz.norm_labels.width.col; + var inst_offset = 'translate(0,' + inst_x_offset + '), rotate(-90)'; + return inst_offset; + }).style('font-size', function () { + var inst_font_size = params.labels.super_label_fs * params.labels.super_label_scale; + return inst_font_size + 'px'; + }).style('font-weight', 300) + .attr("dy", "1em"); + }; + +/***/ }, +/* 112 */ +/***/ function(module, exports, __webpack_require__) { + + var get_cat_title = __webpack_require__(113); + var ini_cat_reorder = __webpack_require__(114); + var make_row_cat_super_labels = __webpack_require__(122); + var make_dendro_crop_buttons = __webpack_require__(60); + + module.exports = function Spillover(cgm) { + + var params = cgm.params; + + var viz = params.viz; + + // hide spillover from slanted column labels on right side + d3.select(viz.root + ' .col_container').append('path').style('stroke-width', '0').attr('d', 'M 0,0 L 1000,-1000, L 1000,0 Z').attr('fill', viz.background_color) //!! prog_colors + .attr('class', 'right_slant_triangle').attr('transform', 'translate(' + viz.clust.dim.width + ',' + viz.norm_labels.width.col + ')'); + + // hide spillover from slanted column labels on left side + d3.select(viz.root + ' .col_container').append('path').style('stroke-width', '0').attr('d', 'M 0,0 L 500,-500, L 0,-500 Z').attr('fill', viz.background_color).attr('class', 'left_slant_triangle') + // shift left by 1 px to prevent cutting off labels + .attr('transform', 'translate(-1,' + viz.norm_labels.width.col + ')'); + + var rect_height = viz.clust.margin.top + viz.uni_margin / 5; + // white rect to cover excess labels + d3.select(viz.viz_svg).append('rect').attr('fill', viz.background_color) //!! prog_colors + .attr('width', viz.clust.margin.left).attr('height', rect_height).attr('class', 'top_left_white'); + + var inst_height = viz.cat_room.col + 1.5 * viz.uni_margin; + // white rect to cover excess labels + d3.select(viz.viz_svg).append('rect').attr('fill', viz.background_color).attr('width', 2 * viz.clust.dim.width).attr('height', inst_height).attr('class', 'top_right_white').attr('transform', function () { + var tmp_left = viz.clust.margin.left + viz.clust.dim.width; + var tmp_top = viz.norm_labels.width.col + viz.norm_labels.margin.top - viz.uni_margin; + return 'translate(' + tmp_left + ', ' + tmp_top + ')'; + }); + + x_offset = viz.clust.margin.left + viz.clust.dim.width + viz.uni_margin; + y_offset = viz.norm_labels.margin.top + viz.norm_labels.width.col + 2.5 * viz.uni_margin; + var cat_text_size = 1.15 * viz.cat_room.symbol_width; + var cat_super_opacity = 0.65; + var extra_y_room = 1.25; + + // col category super labels + if (viz.show_categories.col) { + + d3.select(viz.viz_svg).selectAll().data(viz.all_cats.col).enter().append('text').classed('col_cat_super', true).style('font-size', cat_text_size + 'px').style('opacity', cat_super_opacity).style('cursor', 'default').attr('transform', function (d) { + var inst_cat = parseInt(d.split('-')[1], 10); + var inst_y = y_offset + extra_y_room * viz.cat_room.symbol_width * inst_cat; + return 'translate(' + x_offset + ',' + inst_y + ')'; + }).text(function (d) { + return get_cat_title(viz, d, 'col'); + }); + } + + // row category super labels + make_row_cat_super_labels(cgm); + + // white border bottom - prevent clustergram from hitting border + if (viz.show_dendrogram) { + // quick fix to make room for crop buttons + y_offset = viz.clust.margin.top + viz.clust.dim.height + viz.dendro_room.col - 2 * viz.uni_margin; + } else { + y_offset = viz.clust.margin.top + viz.clust.dim.height; + } + + var b_spill_container = d3.select(viz.viz_svg).append('g').classed('bottom_spillover_container', true).attr('transform', function () { + // shift up enough to show the entire border width + return 'translate(0,' + y_offset + ')'; + }); + + b_spill_container.append('rect').attr('class', 'bottom_spillover').attr('fill', viz.background_color) //!! prog_colors + .attr('width', viz.svg_dim.width).attr('height', 2 * viz.svg_dim.height); + + x_offset = viz.clust.margin.left; + y_offset = 0; + b_spill_container.append('g').classed('col_dendro_icons_container', true).attr('transform', 'translate(' + x_offset + ',' + y_offset + ')').append('g').classed('col_dendro_icons_group', true); + + make_dendro_crop_buttons(cgm, 'col'); + + var x_offset = viz.clust.margin.left + viz.clust.dim.width; + var y_offset = viz.clust.margin.top + viz.clust.dim.height; + var tmp_width = viz.cat_room.col + viz.clust.dim.width; + var tmp_height = viz.cat_room.row + 10 * viz.uni_margin; + d3.select(viz.viz_svg).append('rect').attr('fill', viz.background_color).attr('width', tmp_width).attr('height', tmp_height).attr('transform', function () { + return 'translate(' + x_offset + ',' + y_offset + ')'; + }).classed('white_bars', true).classed('dendro_corner_spillover', true); + + // hide spillover left top of col dendrogram + x_offset = 0; + y_offset = viz.clust.margin.top + viz.clust.dim.height; + tmp_width = viz.clust.margin.left; + tmp_height = viz.clust.dim.height * 10; + d3.select(viz.viz_svg).append('rect').attr('fill', viz.background_color).attr('width', tmp_width).attr('height', tmp_height).attr('transform', function () { + return 'translate(' + x_offset + ',' + y_offset + ')'; + }).classed('white_bars', true).classed('dendro_col_spillover', true); + + ini_cat_reorder(cgm); + }; + +/***/ }, +/* 113 */ +/***/ function(module, exports) { + + module.exports = function get_cat_title(viz, inst_cat, inst_rc) { + var cat_title; + + // make default title if none is given + if (viz.cat_names[inst_rc][inst_cat] === inst_cat) { + var inst_num = parseInt(inst_cat.split('-')[1], 10) + 1; + // generate placeholder title + cat_title = 'Category ' + inst_num; + } else { + // make real title + cat_title = viz.cat_names[inst_rc][inst_cat]; + } + + return cat_title; + }; + +/***/ }, +/* 114 */ +/***/ function(module, exports, __webpack_require__) { + + var all_reorder = __webpack_require__(115); + + module.exports = function ini_cat_reorder(cgm) { + /* eslint-disable */ + + var params = cgm.params; + + _.each(['row', 'col'], function (inst_rc) { + + if (params.viz.show_categories[inst_rc]) { + d3.selectAll(params.root + ' .' + inst_rc + '_cat_super').on('dblclick', function () { + + if (params.sim_mat) { + inst_rc = 'both'; + } + + d3.selectAll(params.root + ' .toggle_' + inst_rc + '_order .btn').classed('active', false); + + var order_id = this.__data__.replace('-', '_') + '_index'; + if (params.viz.sim_mat) { + all_reorder(cgm, order_id, 'row'); + all_reorder(cgm, order_id, 'col'); + } else { + all_reorder(cgm, order_id, inst_rc); + } + }); + } + }); + }; + +/***/ }, +/* 115 */ +/***/ function(module, exports, __webpack_require__) { + + var toggle_dendro_view = __webpack_require__(54); + var show_visible_area = __webpack_require__(106); + var ini_zoom_info = __webpack_require__(36); + var calc_downsampled_levels = __webpack_require__(27); + var two_translate_zoom = __webpack_require__(116); + var get_previous_zoom = __webpack_require__(101); + + module.exports = function (cgm, inst_order, inst_rc) { + + var params = cgm.params; + + var prev_zoom = get_previous_zoom(params); + + var delay_reorder = 0; + if (prev_zoom.zoom_y != 1 || prev_zoom.zoom_x != 1) { + // reset zoom before reordering + two_translate_zoom(cgm, 0, 0, 1); + delay_reorder = 1200; + } + + // row/col names are swapped, will improve later + var other_rc; + if (inst_rc === 'row') { + other_rc = 'col'; + } else if (inst_rc === 'col') { + other_rc = 'row'; + } + + params.viz.run_trans = true; + + // save order state + if (other_rc === 'row') { + params.viz.inst_order.row = inst_order; + } else if (other_rc === 'col') { + params.viz.inst_order.col = inst_order; + } + + if (params.viz.show_dendrogram) { + toggle_dendro_view(cgm, inst_rc); + } + + if (other_rc === 'row') { + params.viz.x_scale.domain(params.matrix.orders[params.viz.inst_order.row + '_row']); + } else if (other_rc == 'col') { + params.viz.y_scale.domain(params.matrix.orders[params.viz.inst_order.col + '_col']); + } + + // only animate transition if there are a small number of tiles + var t; + if (d3.selectAll(params.root + ' .tile')[0].length < params.matrix.def_large_matrix) { + t = d3.select(params.root + ' .viz_svg').transition().duration(2500).delay(delay_reorder); + } else { + t = d3.select(params.root + ' .viz_svg'); + } + + var row_nodes_names = params.network_data.row_nodes_names; + var col_nodes_names = params.network_data.col_nodes_names; + + // only update matrix if not downsampled (otherwise rows are updated) + if (params.viz.ds_level === -1) { + + t.selectAll('.row').attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0,' + params.viz.y_scale(inst_index) + ')'; + }).selectAll('.tile').attr('transform', function (d) { + return 'translate(' + params.viz.x_scale(d.pos_x) + ' , 0)'; + }); + + t.selectAll('.tile_up').attr('transform', function (d) { + return 'translate(' + params.viz.x_scale(d.pos_x) + ' , 0)'; + }); + + t.selectAll('.tile_dn').attr('transform', function (d) { + return 'translate(' + params.viz.x_scale(d.pos_x) + ' , 0)'; + }); + } + + // Move Row Labels + t.select('.row_label_zoom_container').selectAll('.row_label_group').attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0,' + params.viz.y_scale(inst_index) + ')'; + }); + + // Move Col Labels + t.select('.col_zoom_container').selectAll('.col_label_text').attr('transform', function (d) { + var inst_index = _.indexOf(col_nodes_names, d.name); + return 'translate(' + params.viz.x_scale(inst_index) + ') rotate(-90)'; + }); + + // reorder row categories + t.selectAll('.row_cat_group').attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0,' + params.viz.y_scale(inst_index) + ')'; + }); + + // reorder col_class groups + t.selectAll('.col_cat_group').attr('transform', function (d) { + var inst_index = _.indexOf(col_nodes_names, d.name); + return 'translate(' + params.viz.x_scale(inst_index) + ',0)'; + }); + + // redefine x and y positions + params.network_data.links.forEach(function (d) { + d.x = params.viz.x_scale(d.target); + d.y = params.viz.y_scale(d.source); + }); + + params.zoom_info = ini_zoom_info(); + + // calculate downsmapling if necessary + if (params.viz.ds_num_levels > 0 && params.viz.ds_level >= 0) { + + calc_downsampled_levels(params); + var zooming_stopped = true; + var zooming_out = true; + var make_all_rows = true; + + // show_visible_area is also run with two_translate_zoom, but at that point + // the parameters were not updated and two_translate_zoom if only run + // if needed to reset zoom + show_visible_area(cgm, zooming_stopped, zooming_out, make_all_rows); + } + + setTimeout(function () { + params.viz.run_trans = false; + }, 2500); + }; + +/***/ }, +/* 116 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + var label_constrain_and_trim = __webpack_require__(117); + var show_visible_area = __webpack_require__(106); + var ini_zoom_info = __webpack_require__(36); + var toggle_grid_lines = __webpack_require__(121); + + module.exports = function two_translate_zoom(cgm, pan_dx, pan_dy, fin_zoom) { + + // console.log('pan_dy: ' + String(pan_dy)) + + var params = cgm.params; + + d3.selectAll(params.viz.root_tips).style('display', 'none'); + + params.zoom_info = ini_zoom_info(); + + show_visible_area(cgm); + + // do not allow while transitioning, e.g. reordering + if (!params.viz.run_trans) { + + // define the commonly used variable half_height + var half_height = params.viz.clust.dim.height / 2; + + // y pan room, the pan room has to be less than half_height since + // zooming in on a gene that is near the top of the clustergram also causes + // panning out of the visible region + var y_pan_room = half_height / fin_zoom; + + // prevent visualization from panning down too much + // when zooming into genes near the top of the clustergram + if (pan_dy >= half_height - y_pan_room) { + + // console.log(' prevent visualization from panning down too much') + + // explanation of panning rules + ///////////////////////////////// + /* + prevent the clustergram from panning down too much + if the amount of panning is equal to the half_height then it needs to be reduced + effectively, the the visualization needs to be moved up (negative) by some factor + of the half-width-of-the-visualization. + If there was no zooming involved, then the + visualization would be centered first, then panned to center the top term + this would require a + correction to re-center it. However, because of the zooming the offset is + reduced by the zoom factor (this is because the panning is occurring on something + that will be zoomed into - this is why the pan_dy value is not scaled in the two + translate transformations, but it has to be scaled afterwards to set the translate + vector) + pan_dy = half_height - (half_height)/fin_zoom + if pan_dy is greater than the pan room, then panning has to be restricted + start by shifting back up (negative) by half_height/fin_zoom then shift back down + by the difference between half_height and pan_dy (so that the top of the clustergram is + visible) + */ + + var shift_top_viz = half_height - pan_dy; + var shift_up_viz = -half_height / fin_zoom + shift_top_viz; + + // reduce pan_dy so that the visualization does not get panned to far down + pan_dy = pan_dy + shift_up_viz; + } + + // prevent visualization from panning up too much + // when zooming into genes at the bottom of the clustergram + if (pan_dy < -(half_height - y_pan_room)) { + + shift_top_viz = half_height + pan_dy; + + shift_up_viz = half_height / fin_zoom - shift_top_viz; //- move_up_one_row; + + // reduce pan_dy so that the visualization does not get panned to far down + pan_dy = pan_dy + shift_up_viz; + } + + // will improve this !! + var zoom_y = fin_zoom; + var zoom_x = 1; + + // search duration - the duration of zooming and panning + var search_duration = 700; + + // center_y + var center_y = -(zoom_y - 1) * half_height; + + // transform clust group + //////////////////////////// + d3.select(params.root + ' .clust_group').transition().duration(search_duration) + // first apply the margin transformation + // then zoom, then apply the final transformation + .attr('transform', 'translate(' + [0, 0 + center_y] + ')' + ' scale(' + zoom_x + ',' + zoom_y + ')' + 'translate(' + [pan_dx, pan_dy] + ')'); + + // transform row labels + d3.select(params.root + ' .row_label_zoom_container').transition().duration(search_duration).attr('transform', 'translate(' + [0, center_y] + ')' + ' scale(' + zoom_y + ',' + zoom_y + ')' + 'translate(' + [0, pan_dy] + ')'); + + // transform row_cat_container + // use the offset saved in params, only zoom in the y direction + d3.select(params.root + ' .row_cat_container').transition().duration(search_duration).attr('transform', 'translate(' + [0, center_y] + ')' + ' scale(' + 1 + ',' + zoom_y + ')' + 'translate(' + [0, pan_dy] + ')'); + + d3.select(params.root + ' .row_dendro_container').transition().duration(search_duration).attr('transform', 'translate(' + [0, center_y] + ')' + ' scale(' + zoom_x + ',' + zoom_y + ')' + 'translate(' + [params.viz.uni_margin / 2, pan_dy] + ')'); + + // toggle crop buttons + var inst_button_opacity; + _.each(['row', 'col'], function (inst_rc) { + + inst_button_opacity = d3.select(params.root + ' .' + inst_rc + '_dendro_crop_buttons').style('opacity'); + d3.selectAll(params.root + ' .' + inst_rc + '_dendro_crop_buttons').style('opacity', 0); + setTimeout(show_crop_buttons, 700, inst_rc, inst_button_opacity); + }); + + // transform col labels + d3.select(params.root + ' .col_zoom_container').transition().duration(search_duration).attr('transform', ' scale(' + zoom_x + ',' + zoom_x + ')' + 'translate(' + [pan_dx, 0] + ')'); + + // transform col_class + d3.select(params.root + ' .col_cat_container').transition().duration(search_duration).attr('transform', ' scale(' + zoom_x + ',' + 1 + ')' + 'translate(' + [pan_dx, 0] + ')'); + + d3.select(params.root + ' .col_dendro_container').transition().duration(search_duration).attr('transform', ' scale(' + zoom_x + ',' + 1 + ')' + 'translate(' + [pan_dx, params.viz.uni_margin / 2] + ')'); + + // set y translate: center_y is positive, positive moves the visualization down + // the translate vector has the initial margin, the first y centering, and pan_dy + // times the scaling zoom_y + var net_y_offset = params.viz.clust.margin.top + center_y + pan_dy * zoom_y; + var net_x_offset = params.viz.clust.margin.left + pan_dx; + + // reset the zoom and translate + params.zoom_behavior.scale(zoom_y).translate([net_x_offset, net_y_offset]); + + label_constrain_and_trim(params); + + // re-size of the highlighting rects + ///////////////////////////////////////// + if (d3.select(params.root + ' .row_label_zoom_container text').empty() === false) { + d3.select(params.root + ' .row_label_zoom_container').each(function () { + // get the bounding box of the row label text + var bbox = d3.select(this).select('text')[0][0].getBBox(); + + // use the bounding box to set the size of the rect + d3.select(this).select('rect').attr('x', bbox.x * 0.5).attr('y', 0).attr('width', bbox.width * 0.5).attr('height', params.viz.y_scale.rangeBand()).style('fill', 'yellow'); + }); + } + + // reset crop button zooming + d3.select(params.root + ' .row_dendro_icons_group').attr('transform', 'translate(' + [0, 0 + center_y] + ')' + ' scale(' + zoom_x + ',' + zoom_y + ')' + 'translate(' + [pan_dx, pan_dy] + ')'); + + d3.select(params.root + ' .row_dendro_icons_group').selectAll('path').attr('transform', function (d) { + var inst_x = params.viz.uni_margin; + var inst_y = d.pos_mid; + return 'translate(' + inst_x + ',' + inst_y + ') ' + 'scale(1, ' + 1 / zoom_y + ')'; + }); + + // console.log('zooming x and y') + // console.log(zoom_x) + // console.log(zoom_y) + + // need to improve behavior + d3.select(params.root + ' .col_dendro_icons_group').attr('transform', function () { + var inst_trans = + // 'translate(' + [0, 0 + center_y] + ')' + + ' scale(' + zoom_x + ',' + zoom_y + ')'; + // + 'translate(' + [pan_dx, pan_dy ] + ')'; + return inst_trans; + }); + + d3.select(params.root + ' .col_dendro_icons_group').selectAll('path').attr('transform', function (d) { + var inst_x = d.pos_mid; + var inst_y = params.viz.uni_margin; + // return 'translate('+ inst_x +',' + inst_y + ') ' + 'scale('+1/zoom_x+',1)'; + return 'translate(' + inst_x + ',' + inst_y + ') ' + 'scale(1,1)'; + }); + + // column value bars + /////////////////////// + // reduce the height of the column value bars based on the zoom applied + // recalculate the height and divide by the zooming scale + // col_label_obj.select('rect') + if (utils.has(params.network_data.col_nodes[0], 'value')) { + + d3.selectAll(params.root + ' .col_bars').attr('width', function (d) { + var inst_value = 0; + if (d.value > 0) { + inst_value = params.labels.bar_scale_col(d.value) / zoom_x; + } + return inst_value; + }); + } + + if (utils.has(params.network_data.row_nodes[0], 'value')) { + + d3.selectAll(params.root + ' .row_bars').transition().duration(search_duration).attr('width', function (d) { + var inst_value = 0; + inst_value = params.labels.bar_scale_row(Math.abs(d.value)) / zoom_y; + return inst_value; + }).attr('x', function (d) { + var inst_value = 0; + inst_value = -params.labels.bar_scale_row(Math.abs(d.value)) / zoom_y; + return inst_value; + }); + } + + toggle_grid_lines(params); + } + + function show_crop_buttons(inst_rc, inst_button_opacity) { + d3.selectAll(params.root + ' .' + inst_rc + '_dendro_crop_buttons').transition().duration(search_duration).style('opacity', inst_button_opacity); + } + }; + +/***/ }, +/* 117 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + var trim_text = __webpack_require__(118); + var constrain_font_size = __webpack_require__(119); + + module.exports = function label_constrain_and_trim(params) { + + // console.log('label_constrain_and_trim'); + + // reset text in rows and columns + d3.selectAll(params.root + ' .row_label_group').select('text').text(function (d) { + return utils.normal_name(d); + }); + + d3.selectAll(params.root + ' .col_label_text').select('text').text(function (d) { + return utils.normal_name(d); + }); + + constrain_font_size(params); + + d3.selectAll(params.root + ' .row_label_group').each(function () { + trim_text(params, this, 'row'); + }); + + d3.selectAll(params.root + ' .col_label_group').each(function () { + trim_text(params, this, 'col'); + }); + }; + +/***/ }, +/* 118 */ +/***/ function(module, exports) { + + + module.exports = function (params, inst_selection, inst_rc) { + if (d3.select(inst_selection).style('display') != 'none') { + + // trim text that is longer than the container + var inst_zoom; + var inst_width; + var trimmed_text; + var current_num_char; + var inst_text; + var original_text; + var keep_num_char; + var i; + + var max_width = params.viz.norm_labels.width[inst_rc]; + + if (inst_rc === 'row') { + if (params.viz.zoom_ratio.y) { + inst_zoom = params.zoom_behavior.scale() / params.viz.zoom_ratio.y; + } else { + inst_zoom = params.zoom_behavior.scale(); + } + // num_trims = params.labels.row_max_char; + } else { + if (params.viz.zoom_ratio.x > 1) { + inst_zoom = params.zoom_behavior.scale() / params.viz.zoom_ratio.x; + } else { + inst_zoom = params.zoom_behavior.scale(); + } + // num_trims = params.labels.col_max_char; + } + + var num_trims; + d3.select(inst_selection).select('text').each(function (d) { + num_trims = d.name.length; + }); + + var tmp_width = d3.select(inst_selection).select('text').node().getBBox().width; + + inst_width = calc_width(tmp_width, inst_zoom); + + if (inst_width > max_width) { + + for (i = 1; i < num_trims; i++) { + if (inst_width > max_width) { + + d3.select(inst_selection).select('text').text(trim); + + tmp_width = d3.select(inst_selection).select('text').node().getBBox().width; + + inst_width = calc_width(tmp_width, inst_zoom); + } + } + } else if (inst_width < max_width * 0.75) { + + for (i = 1; i < num_trims; i++) { + if (inst_width < max_width * 0.75) { + + d3.select(inst_selection).select('text').text(add_back); + + tmp_width = d3.select(inst_selection).select('text').node().getBBox().width; + + inst_width = calc_width(tmp_width, inst_zoom); + } + } + } + } + + function trim() { + inst_text = d3.select(this).text(); + current_num_char = inst_text.length; + keep_num_char = current_num_char - 3; + trimmed_text = inst_text.substring(0, keep_num_char) + '..'; + return trimmed_text; + } + + function add_back(d) { + inst_text = d3.select(this).text(); + if (inst_text.slice(-2) === '..') { + current_num_char = inst_text.length - 2; + } else { + current_num_char = inst_text.length; + } + + original_text = d.name; + keep_num_char = current_num_char + 2; + trimmed_text = original_text.substring(0, keep_num_char) + '..'; + + // if '..' was added to original text + if (trimmed_text.length > original_text.length) { + trimmed_text = original_text; + } + + return trimmed_text; + } + + function calc_width(tmp_width, inst_zoom) { + if (inst_zoom < 1) { + inst_width = tmp_width; + } else { + inst_width = tmp_width * inst_zoom; + } + + return inst_width; + } + }; + +/***/ }, +/* 119 */ +/***/ function(module, exports, __webpack_require__) { + + var calc_real_font_size = __webpack_require__(120); + + module.exports = function constrain_font_size(params) { + + var tmp_font_size = params.labels.default_fs_row; + var inst_zoom; + var min_font_size = 3; + + var real_font_size = calc_real_font_size(params); + + // rows + //////////////////////////////////// + if (real_font_size.row > min_font_size) { + + if (real_font_size.row > params.labels.max_allow_fs) { + + if (params.viz.zoom_ratio.y) { + inst_zoom = params.zoom_behavior.scale() / params.viz.zoom_ratio.y; + } else { + inst_zoom = params.zoom_behavior.scale(); + } + + if (inst_zoom < 1) { + inst_zoom = 1; + } + + tmp_font_size = params.labels.max_allow_fs / inst_zoom; + + d3.selectAll(params.root + ' .row_label_group').select('text').style('font-size', tmp_font_size + 'px').attr('y', params.viz.rect_height * 0.5 + tmp_font_size * 0.35); + } else { + d3.selectAll(params.root + ' .row_label_group').select('text').style('font-size', params.labels.default_fs_row + 'px').attr('y', params.viz.rect_height * 0.5 + params.labels.default_fs_row * 0.35); + } + } + + // columns + ////////////////////////////////////// + if (real_font_size.col > min_font_size) { + + if (real_font_size.col > params.labels.max_allow_fs) { + + if (params.viz.zoom_ratio.x > 1) { + inst_zoom = params.zoom_behavior.scale() / params.viz.zoom_ratio.x; + } else { + inst_zoom = params.zoom_behavior.scale(); + } + + if (inst_zoom < 1) { + inst_zoom = 1; + } + + tmp_font_size = params.labels.max_allow_fs / inst_zoom; + + if (tmp_font_size > 0.7 * params.viz.rect_width) { + tmp_font_size = 0.7 * params.viz.rect_width; + } + + d3.selectAll(params.root + ' .col_label_text').select('text').style('font-size', tmp_font_size + 'px'); + } else { + d3.selectAll(params.root + ' .col_label_text').select('text').style('font-size', params.labels.default_fs_col + 'px'); + } + } + }; + +/***/ }, +/* 120 */ +/***/ function(module, exports) { + + module.exports = function calc_real_font_size(params) { + + var real_font_size = {}; + // zoom_switch behavior has to change with zoom_ratio.y + if (params.viz.zoom_ratio.x > 1) { + real_font_size.row = params.labels.default_fs_row * params.zoom_behavior.scale(); + real_font_size.col = params.labels.default_fs_col * params.zoom_behavior.scale(); + } else { + real_font_size.row = params.labels.default_fs_row * params.zoom_behavior.scale() / params.viz.zoom_ratio.y; + real_font_size.col = params.labels.default_fs_col * params.zoom_behavior.scale(); + } + + return real_font_size; + }; + +/***/ }, +/* 121 */ +/***/ function(module, exports) { + + module.exports = function toggle_grid_lines(params) { + + if (params.zoom_info.zoom_x * params.viz.border_width.x > 1) { + d3.selectAll(params.root + ' .vert_lines').select('line').style('display', 'block').style('opacity', 0).transition().style('opacity', 1); + } else { + d3.selectAll(params.root + ' .vert_lines').select('line').style('display', 'none'); + } + + if (params.zoom_info.zoom_y * params.viz.border_width.y > 1) { + d3.selectAll(params.root + ' .horz_lines').select('line').style('display', 'block').style('opacity', 0).transition().style('opacity', 1); + } else { + d3.selectAll(params.root + ' .horz_lines').select('line').style('display', 'none'); + } + }; + +/***/ }, +/* 122 */ +/***/ function(module, exports, __webpack_require__) { + + var get_cat_title = __webpack_require__(113); + var d3_tip_custom = __webpack_require__(48); + + module.exports = function make_row_cat_super_labels(cgm) { + + var params = cgm.params; + + var viz = params.viz; + var extra_x_room = 2.75; + + if (d3.select(params.root + ' .row_cat_label_container').empty()) { + + d3.select(cgm.params.viz.viz_svg).append('g').classed('row_cat_label_container', true); + + // append background section for optional value-bars (e.g. enrichment pvals) + d3.select(cgm.params.viz.viz_svg + ' .row_cat_label_container').append('g').classed('row_cat_label_bar_container', true); + } + + var x_offset = viz.clust.margin.left + viz.clust.dim.width + viz.uni_margin; + var y_offset = viz.norm_labels.margin.top + viz.norm_labels.width.col + 2.5 * viz.uni_margin; + var cat_text_size = 1.15 * viz.cat_room.symbol_width; + var cat_super_opacity = 0.65; + var extra_y_room = 1.25; + + d3.select(params.root + ' .row_cat_label_container').attr('transform', function () { + x_offset = viz.norm_labels.margin.left + viz.norm_labels.width.row + viz.cat_room.symbol_width + extra_x_room * viz.uni_margin; + y_offset = viz.clust.margin.top - viz.uni_margin; + return 'translate(' + x_offset + ',' + y_offset + ') rotate(-90)'; + }); + + // clear old categories + d3.selectAll(params.root + ' .row_cat_label_container text').remove(); + d3.selectAll(params.root + ' .row_cat_selection_bar').remove(); + // d3.selectAll(params.root+' .row_cat_label_bar_container rect').remove(); + + // remove any old row_cat_super tooltips from this visualization + d3.selectAll(cgm.params.viz.root_tips + '_row_cat_super').remove(); + + // d3-tooltip + var tmp_y_offset = 50; // viz.clust.margin.top - viz.uni_margin; + var tmp_x_offset = -75; + var cat_tip = d3_tip_custom().attr('class', function () { + var root_tip_selector = params.viz.root_tips.replace('.', ''); + var class_string = root_tip_selector + ' d3-tip ' + root_tip_selector + '_row_cat_super'; + return class_string; + }).direction('south_custom').offset([tmp_y_offset, tmp_x_offset]).style('display', 'none').style('opacity', 0).html(function (d) { + + var full_string; + + var tmp_string = params.network_data.row_nodes[0][d]; + + if (tmp_string.indexOf('<p>') > -1) { + + var start_string = tmp_string.split(': ')[0]; + var end_string = tmp_string.split('<p>')[1]; + + full_string = start_string + '<p>' + end_string; + } else { + + full_string = get_cat_title(viz, d, 'row'); + } + + return full_string; + }); + + var unit_length = extra_y_room * viz.cat_room.symbol_width; + var bar_width = unit_length * 0.9; + + // show row label categories even if viewing a simmilarity matrix + + d3.select(params.root + ' .row_cat_label_container').selectAll().data(viz.all_cats.row).enter().append('text').style('width', '100px').style('height', bar_width + 'px').classed('row_cat_super', true).style('font-size', cat_text_size + 'px').style('opacity', cat_super_opacity).style('cursor', 'default').attr('transform', function (d) { + var inst_y = extra_y_room * viz.cat_room.symbol_width * parseInt(d.split('-')[1], 10); + return 'translate(0,' + inst_y + ')'; + }).text(function (d) { + + return get_cat_title(viz, d, 'row'); + }); + + // selection bar + /////////////////////////////// + d3.select(params.root + ' .row_cat_label_container').selectAll().data(viz.all_cats.row).enter().append('rect').classed('row_cat_super', true).classed('row_cat_selection_bar', true).style('height', bar_width + 'px').style('fill', 'green').style('width', '120px').style('opacity', 0).attr('transform', function (d) { + var inst_y = unit_length * (parseInt(d.split('-')[1], 10) - 0.75); + return 'translate(0,' + inst_y + ')'; + }).on('mouseover', function (d) { + + d3.selectAll(params.viz.root_tips + '_row_cat_super').style('display', 'block').style('opacity', 1); + + cat_tip.show(d); + }).on('mouseout', function () { + cat_tip.hide(this); + // might not need + d3.selectAll('.d3-tip').style('display', 'none'); + + d3.selectAll(params.viz.root_tips + '_row_cat_super').style('display', 'none').style('opacity', 0); + }); + + // row category super-label mouseover + ////////////////////////////////////// + if (d3.select(params.root + ' .row_cat_selection_bar').empty() === false) { + d3.selectAll(params.root + ' .row_cat_selection_bar').call(cat_tip); + } + + if (_.has(params.network_data, 'row_cat_bars')) { + + // Enrichrgram title + ///////////////////// + d3.select(params.root + ' .enr_title').remove(); + + var enr_title = d3.select(params.root + ' .viz_svg').append('g').classed('enr_title', true).attr('transform', function () { + var trans = d3.select(params.root + ' .row_cat_label_container').attr('transform').split('(')[1].split(')')[0]; + var x_offset = Number(trans.split(',')[0]) - 10; + + return 'translate(' + String(x_offset) + ', 0)'; + }); + + enr_title.append('rect').attr('width', params.viz.cat_room.row).attr('height', 25).attr('fill', 'white'); + + var library_string = params.network_data.enrichrgram_lib.substring(0, 40); + + enr_title.append('text').attr('transform', 'translate(0, 17)').text(library_string.replace(/_/g, ' ')).style('font-size', '15px').attr('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif'); + + // Enrichr bars + //////////////////// + d3.selectAll(params.root + ' .enrichr_bars').remove(); + + var bar_height = params.viz.clust.margin.top - 35; + var max_score = params.network_data.row_cat_bars[0]; + var bar_scale = d3.scale.linear().domain([0, max_score]).range([0, bar_height]); + + d3.select(params.root + ' .row_cat_label_bar_container').selectAll().data(params.network_data.row_cat_bars).enter().append('rect').classed('enrichr_bars', true).attr('height', bar_width + 'px').attr('fill', 'red').attr('width', function (d) { + var bar_length = bar_scale(d); + return bar_length + 'px'; + }).attr('opacity', 0.4).attr('transform', function (d, i) { + var inst_y = unit_length * (i - 0.75); + return 'translate(0, ' + inst_y + ')'; + }); + } + }; + +/***/ }, +/* 123 */ +/***/ function(module, exports, __webpack_require__) { + + var resize_viz = __webpack_require__(124); + + module.exports = function initialize_resizing(cgm) { + + var params = cgm.params; + + var exp_button; + + // d3.select(window).on('resize', null); + + // // resize window + // if (params.viz.resize) { + // d3.select(window).on('resize', function () { + + // d3.select(params.viz.viz_svg).style('opacity', 0.5); + + // var wait_time = 500; + // if (params.viz.run_trans === true) { + // wait_time = 2500; + // } + + // setTimeout(resize_viz, wait_time, params); + // }); + // } + + // if (params.viz.expand_button) { + + d3.select(params.root + ' .expand_button').on('click', null); + var expand_opacity = 0.4; + + if (d3.select(params.root + ' .expand_button').empty()) { + exp_button = d3.select(params.viz.viz_svg).append('text').attr('class', 'expand_button'); + } else { + exp_button = d3.select(params.root + ' .expand_button'); + } + + exp_button.attr('text-anchor', 'middle').attr('dominant-baseline', 'central').attr('font-family', 'FontAwesome').attr('font-size', '30px').text(function () { + if (params.viz.is_expand === false) { + // expand button + return '\uf0b2'; + } else { + // menu button + return '\uf0c9'; + } + }).attr('y', '25px').attr('x', '25px').style('cursor', 'pointer').style('opacity', expand_opacity).on('mouseover', function () { + d3.select(this).style('opacity', 0.75); + }).on('mouseout', function () { + d3.select(this).style('opacity', expand_opacity); + }).on('click', function () { + + // expand view + if (params.viz.is_expand === false) { + + d3.select(this).text(function () { + // menu button + return '\uf0c9'; + }); + params.viz.is_expand = true; + + d3.selectAll(params.root + ' .borders').style('fill', 'white'); + // d3.select(params.root+' .footer_section').style('display', 'none'); + d3.select(params.root + ' .sidebar_wrapper').style('display', 'none'); + + // contract view + } else { + + d3.select(this).text(function () { + // expand button + return '\uf0b2'; + }); + + params.viz.is_expand = false; + + d3.selectAll(params.root + ' .borders').style('fill', '#eee'); + // d3.select(params.root+' .footer_section').style('display', 'block'); + d3.select(params.root + ' .viz_wrapper').style('width', '100px'); + d3.select(params.root + ' .sidebar_wrapper').style('display', 'block'); + } + + // // resize parent div + // set_viz_wrapper_size(params); + + d3.select(params.viz.viz_svg).style('opacity', 0.5); + var wait_time = 500; + if (params.viz.run_trans == true) { + wait_time = 2500; + } + setTimeout(resize_viz, wait_time, cgm); + }); + // } + }; + +/***/ }, +/* 124 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + var run_zoom = __webpack_require__(125); + var ini_doubleclick = __webpack_require__(133); + var reset_zoom = __webpack_require__(134); + var resize_dendro = __webpack_require__(135); + var resize_super_labels = __webpack_require__(136); + var resize_spillover = __webpack_require__(137); + var resize_borders = __webpack_require__(138); + var resize_row_labels = __webpack_require__(139); + var resize_highlights = __webpack_require__(140); + var resize_row_viz = __webpack_require__(141); + var resize_col_labels = __webpack_require__(142); + var resize_col_text = __webpack_require__(143); + var resize_col_triangle = __webpack_require__(144); + var resize_col_hlight = __webpack_require__(145); + var recalc_params_for_resize = __webpack_require__(146); + var resize_row_tiles = __webpack_require__(147); + var resize_label_bars = __webpack_require__(148); + var label_constrain_and_trim = __webpack_require__(117); + var make_dendro_triangles = __webpack_require__(55); + var toggle_dendro_view = __webpack_require__(54); + var show_visible_area = __webpack_require__(106); + var calc_viz_dimensions = __webpack_require__(18); + var position_play_button = __webpack_require__(149); + var make_row_cat_super_labels = __webpack_require__(122); + var ini_cat_reorder = __webpack_require__(114); + var position_svg_dendro_slider = __webpack_require__(150); + var ini_zoom_info = __webpack_require__(36); + var grid_lines_viz = __webpack_require__(151); + + module.exports = function resize_viz(cgm) { + + var params = cgm.params; + + var cont_dim = calc_viz_dimensions(params); + + d3.select(params.root + ' .play_button'); + // .style('opacity', 0.2); + + + d3.select(params.root + ' .sidebar_wrapper').style('height', cont_dim.height + 'px'); + + d3.select(params.viz.viz_wrapper) + // .style('float', 'left') + .style('margin-top', cont_dim.top + 'px').style('width', cont_dim.width + 'px').style('height', cont_dim.height + 'px'); + + params = recalc_params_for_resize(params); + + params.zoom_info = ini_zoom_info(); + + reset_zoom(params); + + var svg_group = d3.select(params.viz.viz_svg); + + // redefine x and y positions + _.each(params.network_data.links, function (d) { + d.x = params.viz.x_scale(d.target); + d.y = params.viz.y_scale(d.source); + }); + + // disable zoom while transitioning + svg_group.on('.zoom', null); + + params.zoom_behavior.scaleExtent([1, params.viz.square_zoom * params.viz.zoom_ratio.x]).on('zoom', function () { + run_zoom(cgm); + }); + + // reenable zoom after transition + if (params.viz.do_zoom) { + svg_group.call(params.zoom_behavior); + } + + // prevent normal double click zoom etc + ini_doubleclick(cgm); + + svg_group.attr('width', params.viz.svg_dim.width).attr('height', params.viz.svg_dim.height); + + svg_group.select('.super_background').style('width', params.viz.svg_dim.width).style('height', params.viz.svg_dim.height); + + svg_group.select('.grey_background').attr('width', params.viz.clust.dim.width).attr('height', params.viz.clust.dim.height); + + setTimeout(position_play_button, 100, params); + + var row_nodes = params.network_data.row_nodes; + var row_nodes_names = utils.pluck(row_nodes, 'name'); + + resize_row_tiles(params, svg_group); + + svg_group.selectAll('.highlighting_rect').attr('width', params.viz.x_scale.rangeBand() * 0.80).attr('height', params.viz.y_scale.rangeBand() * 0.80); + + resize_highlights(params); + + // resize row labels + /////////////////////////// + + resize_row_labels(params, svg_group); + resize_row_viz(params, svg_group); + + // change the size of the highlighting rects + svg_group.selectAll('.row_label_group').each(function () { + var bbox = d3.select(this).select('text')[0][0].getBBox(); + d3.select(this).select('rect').attr('x', bbox.x).attr('y', 0).attr('width', bbox.width).attr('height', params.viz.rect_height).style('fill', 'yellow').style('opacity', function (d) { + var inst_opacity = 0; + // highlight target genes + if (d.target === 1) { + inst_opacity = 1; + } + return inst_opacity; + }); + }); + + // necessary to properly position row labels vertically + svg_group.selectAll('.row_label_group').select('text').attr('y', params.viz.rect_height * 0.5 + params.labels.default_fs_row * 0.35); + + if (utils.has(params.network_data.row_nodes[0], 'value')) { + resize_label_bars(cgm, svg_group); + } + + svg_group.selectAll('.row_cat_group').attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0, ' + params.viz.y_scale(inst_index) + ')'; + }); + + svg_group.selectAll('.row_cat_group').select('path').attr('d', function () { + var origin_x = params.viz.cat_room.symbol_width - 1; + var origin_y = 0; + var mid_x = 1; + var mid_y = params.viz.rect_height / 2; + var final_x = params.viz.cat_room.symbol_width - 1; + var final_y = params.viz.rect_height; + var output_string = 'M ' + origin_x + ',' + origin_y + ' L ' + mid_x + ',' + mid_y + ', L ' + final_x + ',' + final_y + ' Z'; + return output_string; + }); + + var is_resize = true; + if (params.viz.show_dendrogram) { + make_dendro_triangles(cgm, 'row', is_resize); + make_dendro_triangles(cgm, 'col', is_resize); + resize_dendro(params, svg_group); + + toggle_dendro_view(cgm, 'row', 0); + toggle_dendro_view(cgm, 'col', 0); + } else { + resize_dendro(params, svg_group); + } + + resize_col_labels(params, svg_group); + resize_col_text(params, svg_group); + resize_col_triangle(params, svg_group); + resize_col_hlight(params, svg_group); + + resize_super_labels(params, svg_group); + resize_spillover(params.viz, svg_group); + + grid_lines_viz(params); + + resize_borders(params, svg_group); + + // reset zoom and translate + params.zoom_behavior.scale(1).translate([params.viz.clust.margin.left, params.viz.clust.margin.top]); + + label_constrain_and_trim(params); + + // reposition matrix + d3.select(params.root + ' .clust_container').attr('transform', 'translate(' + params.viz.clust.margin.left + ',' + params.viz.clust.margin.top + ')'); + + // removed, this was causing bugs + if (cgm.params.viz.ds_level === -1) { + show_visible_area(cgm); + } + + make_row_cat_super_labels(cgm); + + d3.select(params.viz.viz_svg).style('opacity', 1); + + ini_cat_reorder(cgm); + + d3.select(cgm.params.root + ' .row_slider_group').style('opacity', 0); + d3.select(cgm.params.root + ' .col_slider_group').style('opacity', 0); + + setTimeout(position_svg_dendro_slider, 500, cgm, 'row'); + setTimeout(position_svg_dendro_slider, 500, cgm, 'col'); + }; + +/***/ }, +/* 125 */ +/***/ function(module, exports, __webpack_require__) { + + var run_transformation = __webpack_require__(126); + var zoom_rules_y = __webpack_require__(131); + var zoom_rules_x = __webpack_require__(132); + + module.exports = function zoomed(cgm) { + + var params = cgm.params; + + var zoom_info = {}; + zoom_info.zoom_x = d3.event.scale; + zoom_info.zoom_y = d3.event.scale; + + // subtract away the margin to easily calculate pan_room etc. + zoom_info.trans_x = params.zoom_behavior.translate()[0] - params.viz.clust.margin.left; + zoom_info.trans_y = params.zoom_behavior.translate()[1] - params.viz.clust.margin.top; + + d3.selectAll(params.viz.root_tips).style('display', 'none'); + + // transfer zoom_info to params + params.zoom_info = zoom_rules_y(params, zoom_info); + params.zoom_info = zoom_rules_x(params, zoom_info); + + // do not run transformation if moving slider + if (params.is_slider_drag === false && params.is_cropping === false) { + + // reset translate vector - add back margins to trans_x and trans_y + var new_x = params.zoom_info.trans_x + params.viz.clust.margin.left; + var new_y = params.zoom_info.trans_y + params.viz.clust.margin.top; + + params.zoom_behavior.translate([new_x, new_y]); + cgm.params = params; + + run_transformation(cgm); + } + }; + +/***/ }, +/* 126 */ +/***/ function(module, exports, __webpack_require__) { + + var constrain_font_size = __webpack_require__(119); + var show_visible_area = __webpack_require__(106); + var resize_label_val_bars = __webpack_require__(127); + var zoom_crop_triangles = __webpack_require__(62); + var get_previous_zoom = __webpack_require__(101); + var run_when_zoom_stopped = __webpack_require__(128); + var check_zoom_stop_status = __webpack_require__(130); + + module.exports = function run_transformation(cgm) { + + var params = cgm.params; + + var zoom_info = params.zoom_info; + + var prev_zoom = get_previous_zoom(params); + + d3.select(params.root + ' .clust_group').attr('transform', 'translate(' + [zoom_info.trans_x, zoom_info.trans_y] + ') scale(' + zoom_info.zoom_x + ',' + zoom_info.zoom_y + ')'); + + d3.select(params.root + ' .row_label_zoom_container').attr('transform', 'translate(' + [0, zoom_info.trans_y] + ') scale(' + zoom_info.zoom_y + ')'); + + d3.select(params.root + ' .col_zoom_container').attr('transform', 'translate(' + [zoom_info.trans_x, 0] + ') scale(' + zoom_info.zoom_x + ')'); + + d3.select(params.root + ' .row_cat_container').attr('transform', 'translate(' + [0, zoom_info.trans_y] + ') scale( 1,' + zoom_info.zoom_y + ')'); + + d3.select(params.root + ' .row_dendro_container').attr('transform', 'translate(' + [params.viz.uni_margin / 2, zoom_info.trans_y] + ') ' + 'scale( 1,' + zoom_info.zoom_y + ')'); + + d3.select(params.root + ' .row_dendro_icons_group').attr('transform', function () { + var inst_y = zoom_info.trans_y; + var inst_translate = 'translate(' + [0, inst_y] + ') '; + var inst_zoom = 'scale(1, ' + zoom_info.zoom_y + ')'; + var transform_string = inst_translate + inst_zoom; + return transform_string; + }); + + d3.select(params.root + ' .col_dendro_icons_group').attr('transform', function () { + var inst_x = zoom_info.trans_x; + var inst_translate = 'translate(' + [inst_x, 0] + ')'; + var inst_zoom = 'scale(' + zoom_info.zoom_x + ', 1)'; + var transform_string = inst_translate + inst_zoom; + return transform_string; + }); + + zoom_crop_triangles(params, zoom_info, 'row'); + zoom_crop_triangles(params, zoom_info, 'col'); + + d3.select(params.root + ' .col_cat_container').attr('transform', 'translate(' + [zoom_info.trans_x, 0] + ') scale(' + zoom_info.zoom_x + ',1)'); + + d3.select(params.root + ' .col_dendro_container').attr('transform', 'translate(' + [zoom_info.trans_x, params.viz.uni_margin / 2] + ') scale(' + zoom_info.zoom_x + ',1)'); + + resize_label_val_bars(params, zoom_info); + + d3.select(params.root + ' .viz_svg').attr('is_zoom', function () { + var inst_zoom = Number(d3.select(params.root + ' .viz_svg').attr('is_zoom')); + d3.select(params.root + ' .viz_svg').attr('stopped_zoom', 1); + return inst_zoom + 1; + }); + + // this function runs with a slight delay and tells the visualization that + // this particular zoom event is over, reducing the total number of zoom + // events that need to finish + var not_zooming = function () { + + d3.select(params.root + ' .viz_svg').attr('is_zoom', function () { + var inst_zoom = Number(d3.select(params.root + ' .viz_svg').attr('is_zoom')); + return inst_zoom - 1; + }); + }; + + constrain_font_size(params); + + if (zoom_info.zoom_y <= prev_zoom.zoom_y) { + + var zooming_out = false; + if (zoom_info.zoom_y < prev_zoom.zoom_y) { + zooming_out = true; + } + + // zooming has not stopped and zooming out is true + var zooming_stopped = false; + show_visible_area(cgm, zooming_stopped, zooming_out); + } + + setTimeout(not_zooming, 50); + setTimeout(check_if_zooming_has_stopped, 100, cgm); + + function check_if_zooming_has_stopped(cgm) { + var params = cgm.params; + + var stop_attributes = check_zoom_stop_status(params); + + if (stop_attributes === true) { + // wait and double check that zooming has stopped + setTimeout(run_when_zoom_stopped, 50, cgm); + } + } + }; + +/***/ }, +/* 127 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + + module.exports = function resize_label_val_bars(params) { + + var zoom_info = params.zoom_info; + + // resize label bars if necessary + if (utils.has(params.network_data.row_nodes[0], 'value')) { + d3.selectAll(params.root + ' .row_bars').attr('width', function (d) { + var inst_value = 0; + inst_value = params.labels.bar_scale_row(Math.abs(d.value)) / zoom_info.zoom_y; + return inst_value; + }).attr('x', function (d) { + var inst_value = 0; + inst_value = -params.labels.bar_scale_row(Math.abs(d.value)) / zoom_info.zoom_y; + return inst_value; + }); + } + + if (utils.has(params.network_data.col_nodes[0], 'value')) { + d3.selectAll(params.root + ' .col_bars').attr('width', function (d) { + var inst_value = 0; + if (d.value > 0) { + inst_value = params.labels.bar_scale_col(d.value) / zoom_info.zoom_x; + } + return inst_value; + }); + } + }; + +/***/ }, +/* 128 */ +/***/ function(module, exports, __webpack_require__) { + + var constrain_font_size = __webpack_require__(119); + var trim_text = __webpack_require__(118); + var num_visible_labels = __webpack_require__(129); + var toggle_grid_lines = __webpack_require__(121); + var show_visible_area = __webpack_require__(106); + var check_zoom_stop_status = __webpack_require__(130); + + module.exports = function run_when_zoom_stopped(cgm) { + + var params = cgm.params; + + var stop_attributes = check_zoom_stop_status(params); + + if (stop_attributes === true) { + + // /////////////////////////////////////////////// + // // zooming has stopped + // /////////////////////////////////////////////// + // console.log('\nZOOMING HAS ACTUALLY STOPPED\n============================'); + // console.log(params.zoom_info.zoom_y) + + _.each(['row', 'col'], function (inst_rc) { + + d3.selectAll(params.root + ' .' + inst_rc + '_label_group').select('text').style('opacity', 1); + + d3.selectAll(params.root + ' .' + inst_rc + '_cat_group').select('path').style('display', 'block'); + }); + + show_visible_area(cgm, true); + + d3.selectAll(params.viz.root_tips).style('display', 'block'); + + d3.selectAll(params.root + ' .row_label_group').select('text').style('display', 'none'); + d3.selectAll(params.root + ' .row_label_group').select('text').style('display', 'block'); + + d3.select(params.root + ' .viz_svg').attr('stopped_zoom', 0); + + d3.selectAll(params.root + ' .row_label_group').select('text').style('display', 'block'); + d3.selectAll(params.root + ' .col_label_group').select('text').style('display', 'block'); + + toggle_grid_lines(params); + + // reset x_offset + cgm.params.viz.x_offset = 0; + + var max_labels_to_trim = 150; + // probably do not need + ///////////////////////// + _.each(['row', 'col'], function (inst_rc) { + + var inst_num_visible = num_visible_labels(params, inst_rc); + + if (inst_num_visible < max_labels_to_trim) { + d3.selectAll(params.root + ' .' + inst_rc + '_label_group').each(function () { + trim_text(params, this, inst_rc); + }); + } + }); + + text_patch(); + + constrain_font_size(params); + + // this makes sure that the text is visible after zooming and trimming + // there is buggy behavior in chrome when zooming into large matrices + // I'm running it twice in quick succession + setTimeout(text_patch, 100); + } + + function text_patch() { + + _.each(['row', 'col'], function (inst_rc) { + + d3.selectAll(params.root + ' .' + inst_rc + '_label_group').filter(function () { + return d3.select(this).style('display') != 'none'; + }).select('text').style('font-size', function () { + var inst_fs = Number(d3.select(this).style('font-size').replace('px', '')); + return inst_fs; + }); + }); + } + }; + +/***/ }, +/* 129 */ +/***/ function(module, exports) { + + module.exports = function num_visible_labels(params, inst_rc) { + + // counting the number of visible labels, probably not necessary + + var num_visible; + if (inst_rc === 'row') { + + // initialize at high number + num_visible = 10000; + + // only count visible rows if no downsampling + if (params.viz.ds_level === -1) { + num_visible = d3.selectAll(params.root + ' .row')[0].length; + } + } else if (inst_rc === 'col') { + + num_visible = d3.selectAll(params.root + ' .' + inst_rc + '_label_text').filter(function () { + return d3.select(this).style('display') != 'none'; + })[0].length; + } + + return num_visible; + }; + +/***/ }, +/* 130 */ +/***/ function(module, exports) { + + module.exports = function check_zoom_stop_status(params) { + + var inst_zoom = Number(d3.select(params.root + ' .viz_svg').attr('is_zoom')); + + var check_stop = Number(d3.select(params.root + ' .viz_svg').attr('stopped_zoom')); + + var stop_attributes = false; + if (inst_zoom === 0 && check_stop != 0) { + stop_attributes = true; + } + + return stop_attributes; + }; + +/***/ }, +/* 131 */ +/***/ function(module, exports) { + + module.exports = function zoom_rules_y(params, zoom_info) { + + var viz = params.viz; + // zoom in the x direction before zooming in the y direction + if (viz.zoom_ratio.y > 1) { + if (zoom_info.zoom_y < viz.zoom_ratio.y) { + zoom_info.trans_y = 0; + zoom_info.zoom_y = 1; + } else { + zoom_info.zoom_y = zoom_info.zoom_y / viz.zoom_ratio.y; + } + } + + // calculate panning room available in the y direction + zoom_info.pan_room_y = (zoom_info.zoom_y - 1) * viz.clust.dim.height; + + // console.log( 'pan_room_y: ' + String(zoom_info.pan_room_y) + ' ' + String(-zoom_info.trans_y)) + + // no positive panning or panning more than pan_room + if (zoom_info.trans_y >= 0) { + zoom_info.trans_y = 0; + // console.log('y no positive panning\n\n') + } else if (zoom_info.trans_y <= -zoom_info.pan_room_y) { + zoom_info.trans_y = -zoom_info.pan_room_y; + // console.log('y restrict pan room \n\n') + } + + return zoom_info; + }; + +/***/ }, +/* 132 */ +/***/ function(module, exports) { + + module.exports = function zoom_rules_x(params, zoom_info) { + + var viz = params.viz; + + // zoom in the y direction before zooming in the x direction + if (viz.zoom_ratio.x > 1) { + + if (zoom_info.zoom_x < viz.zoom_ratio.x) { + + // remove this + // zoom_info.trans_x = - params.viz.clust.margin.left; + + zoom_info.zoom_x = 1; + } else { + zoom_info.zoom_x = zoom_info.zoom_x / viz.zoom_ratio.x; + + // console.log('********* zoom_x: ' + String(zoom_info.zoom_x)) + + // zoom_info.trans_x = zoom_info.trans_x + params.viz.x_offset; + // zoom_info.trans_x = zoom_info.trans_x * (params.zoom_info.zoom_x/params.zoom_info.zoom_y); + } + } + + // calculate panning room available in the x direction + zoom_info.pan_room_x = (zoom_info.zoom_x - 1) * viz.clust.dim.width; + + // console.log( 'pan_room_x: ' + String(zoom_info.pan_room_x) + ' trans_x: ' + String(-zoom_info.trans_x)) + + // no positive panning or panning more than pan_room + if (zoom_info.trans_x > 0) { + zoom_info.trans_x = 0; + // console.log('no positive panning\n\n') + } else if (zoom_info.trans_x <= -zoom_info.pan_room_x) { + zoom_info.trans_x = -zoom_info.pan_room_x; + // console.log('******* restrict pan room\n\n') + } + + return zoom_info; + }; + +/***/ }, +/* 133 */ +/***/ function(module, exports, __webpack_require__) { + + var two_translate_zoom = __webpack_require__(116); + + module.exports = function ini_doubleclick(cgm) { + + var params = cgm.params; + // disable double-click zoom + d3.selectAll(params.viz.zoom_element).on('dblclick.zoom', null); + + d3.select(params.viz.zoom_element).on('dblclick', function () { + two_translate_zoom(cgm, 0, 0, 1); + }); + }; + +/***/ }, +/* 134 */ +/***/ function(module, exports) { + + module.exports = function (params) { + + // reset zoom + ////////////////////////////// + var zoom_y = 1; + // var zoom_x = 1; + var pan_dx = 0; + var pan_dy = 0; + + var half_height = params.viz.clust.dim.height / 2; + var center_y = -(zoom_y - 1) * half_height; + + d3.select(params.root + ' .clust_group').attr('transform', 'translate(' + [0, 0 + center_y] + ')' + ' scale(' + 1 + ',' + zoom_y + ')' + 'translate(' + [pan_dx, pan_dy] + ')'); + + d3.select(params.root + ' .row_label_zoom_container').attr('transform', 'translate(' + [0, center_y] + ')' + ' scale(' + zoom_y + ',' + zoom_y + ')' + 'translate(' + [0, pan_dy] + ')'); + + d3.select(params.root + ' .row_cat_container').attr('transform', 'translate(' + [0, center_y] + ')' + ' scale(' + 1 + ',' + zoom_y + ')' + 'translate(' + [0, pan_dy] + ')'); + + d3.select(params.root + ' .row_dendro_container').attr('transform', 'translate(' + [0, center_y] + ')' + ' scale(' + zoom_y + ',' + zoom_y + ')' + 'translate(' + [params.viz.uni_margin / 2, pan_dy] + ')'); + + d3.select(params.root + ' .col_zoom_container').attr('transform', ' scale(' + 1 + ',' + 1 + ')' + 'translate(' + [pan_dx, 0] + ')'); + + d3.select(params.root + ' .col_cat_container').attr('transform', ' scale(' + 1 + ',' + 1 + ')' + 'translate(' + [pan_dx, 0] + ')'); + + d3.select(params.root + ' .col_dendro_container').attr('transform', ' scale(' + 1 + ',' + 1 + ')' + 'translate(' + [pan_dx, params.viz.uni_margin / 2] + ')'); + + // reset crop button zooming + d3.select(params.root + ' .row_dendro_icons_group').attr('transform', function () { + return 'translate(0,0) scale(1)'; + }); + + d3.select(params.root + ' .row_dendro_icons_group').selectAll('path').attr('transform', function (d) { + var inst_x = 7; + var inst_y = d.pos_mid; + return 'translate(' + inst_x + ',' + inst_y + ') ' + 'scale(1, 1)'; + }); + }; + +/***/ }, +/* 135 */ +/***/ function(module, exports) { + + module.exports = function resize_dendro(params, svg_group, delay_info = false) { + + // resize dendrogram + /////////////////// + + var delays = {}; + + if (delay_info === false) { + delays.run_transition = false; + } else { + delays = delay_info; + } + + var duration = params.viz.duration; + var col_nodes = params.network_data.col_nodes; + var col_nodes_names = params.network_data.col_nodes_names; + + var dendro_group; + if (delays.run_transition) { + + dendro_group = svg_group.transition().delay(delays.update).duration(duration); + + svg_group.selectAll('.col_cat_group') + // data binding needed for loss/gain of columns + .data(col_nodes, function (d) { + return d.name; + }).transition().delay(delays.update).duration(duration).attr('transform', function (d) { + var inst_index = _.indexOf(col_nodes_names, d.name); + return 'translate(' + params.viz.x_scale(inst_index) + ',0)'; + }); + + svg_group.selectAll('.col_dendro_group') + // data binding needed for loss/gain of columns + .data(col_nodes, function (d) { + return d.name; + }).transition().delay(delays.update).duration(duration).attr('transform', function (d) { + var inst_index = _.indexOf(col_nodes_names, d.name); + return 'translate(' + params.viz.x_scale(inst_index) + ',0)'; + }); + } else { + + dendro_group = svg_group; + + svg_group.selectAll('.col_cat_group') + // data binding needed for loss/gain of columns + .data(col_nodes, function (d) { + return d.name; + }).attr('transform', function (d) { + var inst_index = _.indexOf(col_nodes_names, d.name); + return 'translate(' + params.viz.x_scale(inst_index) + ',0)'; + }); + + d3.select(params.root).selectAll('.col_dendro_group') + // data binding needed for loss/gain of columns + .data(col_nodes, function (d) { + return d.name; + }).attr('transform', function (d) { + var inst_index = _.indexOf(col_nodes_names, d.name); + return 'translate(' + params.viz.x_scale(inst_index) + ',0)'; + }); + } + + var i; + var inst_class; + + _.each(['row', 'col'], function (inst_rc) { + + var num_cats = params.viz.all_cats[inst_rc].length; + + for (i = 0; i < num_cats; i++) { + inst_class = '.' + inst_rc + '_cat_rect_' + String(i); + + if (inst_rc === 'row') { + dendro_group.selectAll(inst_class).attr('height', params.viz.y_scale.rangeBand()); + } else { + dendro_group.selectAll(inst_class).attr('width', params.viz.x_scale.rangeBand()); + } + } + }); + + // position row_dendro_outer_container + var x_offset = params.viz.clust.margin.left + params.viz.clust.dim.width; + var y_offset = params.viz.clust.margin.top; + var spillover_width = params.viz.dendro_room.row + params.viz.uni_margin; + + d3.select(params.root + ' .viz_svg').select('row_dendro_outer_container').attr('transform', 'translate(' + x_offset + ',' + y_offset + ')'); + + d3.select(params.root + ' .row_dendro_outer_container').select('.row_dendro_spillover').attr('width', spillover_width + 'px').attr('height', params.viz.svg_dim.height); + + x_offset = params.viz.clust.margin.left; + y_offset = params.viz.clust.margin.top + params.viz.clust.dim.height; + var spillover_height = params.viz.dendro_room.col + params.viz.uni_margin; + + d3.select(params.root + ' .col_dendro_outer_container').select('.col_dendro_spillover').attr('width', params.viz.svg_dim.width).attr('height', spillover_height + 'px'); + + d3.select(params.root + ' .col_dendro_outer_container').select('.col_dendro_spillover_top').attr('width', params.viz.svg_dim.width).attr('height', params.viz.svg_dim.height).attr('transform', 'translate(0,' + params.viz.dendro_room.col + ')'); + + x_offset = params.viz.clust.margin.left; + y_offset = 0; + d3.select(params.root + ' .col_dendro_icons_container').attr('transform', 'translate(' + x_offset + ',' + y_offset + ')'); + }; + +/***/ }, +/* 136 */ +/***/ function(module, exports) { + + module.exports = function resize_super_labels(params, ini_svg_group, delay_info = false) { + + var delays = {}; + var duration = params.viz.duration; + var svg_group; + + if (delay_info === false) { + delays.run_transition = false; + } else { + delays = delay_info; + } + + if (delays.run_transition) { + svg_group = ini_svg_group.transition().delay(delays.update).duration(duration); + } else { + svg_group = ini_svg_group; + } + + svg_group.select('.super_col_bkg').attr('height', params.viz.super_labels.dim.width + 'px').attr('transform', 'translate(' + params.viz.clust.margin.left + ',' + params.viz.grey_border_width + ')'); + + // super col title + svg_group.select('.super_col').attr('transform', function () { + var inst_x = params.viz.clust.dim.width / 2 + params.viz.norm_labels.width.row; + var inst_y = params.viz.super_labels.dim.width; + return 'translate(' + inst_x + ',' + inst_y + ')'; + }); + + svg_group.select('.super_row_bkg').attr('width', params.viz.super_labels.dim.width + 'px').attr('transform', 'translate(' + params.viz.grey_border_width + ',0)'); + + svg_group.select('.super_row').attr('transform', function () { + var inst_x = params.viz.super_labels.dim.width; + var inst_y = params.viz.clust.dim.height / 2 + params.viz.norm_labels.width.col; + return 'translate(' + inst_x + ',' + inst_y + ')'; + }); + }; + +/***/ }, +/* 137 */ +/***/ function(module, exports) { + + module.exports = function resize_spillover(viz, ini_svg_group, delay_info = false) { + + var delays = {}; + var duration = viz.duration; + var svg_group; + + if (delay_info === false) { + delays.run_transition = false; + } else { + delays = delay_info; + } + + if (delays.run_transition) { + svg_group = ini_svg_group.transition().delay(delays.update).duration(duration); + } else { + svg_group = ini_svg_group; + } + + svg_group.select(viz.root + ' .right_slant_triangle').attr('transform', 'translate(' + viz.clust.dim.width + ',' + viz.norm_labels.width.col + ')'); + + svg_group.select(viz.root + ' .left_slant_triangle').attr('transform', 'translate(-1,' + viz.norm_labels.width.col + ')'); + + var rect_height = viz.clust.margin.top + viz.uni_margin / 5; + svg_group.select(viz.root + ' .top_left_white').attr('width', viz.clust.margin.left).attr('height', rect_height); + + var tmp_left = viz.clust.margin.left + viz.clust.dim.width + viz.uni_margin + viz.dendro_room.row; + var tmp_top = viz.norm_labels.margin.top + viz.norm_labels.width.col; + + svg_group.select(viz.root + ' .right_spillover_container').attr('transform', function () { + return 'translate(' + tmp_left + ', 0)'; + }); + + tmp_top = viz.norm_labels.margin.top + viz.norm_labels.width.col; + + svg_group.select(viz.root + ' .right_spillover_container rect').attr('transform', function () { + return 'translate( 0,' + tmp_top + ')'; + }); + + svg_group.select(viz.root + ' .right_spillover').attr('height', viz.svg_dim.height + 'px'); + + // resize dendro spillovers + var x_offset = viz.clust.margin.left + viz.clust.dim.width; + var y_offset = tmp_top; + var tmp_width = viz.dendro_room.row + viz.uni_margin; + var tmp_height = viz.cat_room.col + viz.uni_margin; + d3.select(viz.root + ' .dendro_row_spillover').attr('width', tmp_width).attr('height', tmp_height).attr('transform', function () { + return 'translate(' + x_offset + ',' + y_offset + ')'; + }); + + // hide spillover left top of col dendrogram + x_offset = 0; + y_offset = viz.clust.margin.top + viz.clust.dim.height; + tmp_width = viz.clust.margin.left; + tmp_height = viz.clust.dim.height * 10; + + svg_group.select('.dendro_col_spillover').attr('width', tmp_width).attr('height', tmp_height).attr('transform', function () { + return 'translate(' + x_offset + ',' + y_offset + ')'; + }); + + x_offset = viz.clust.margin.left + viz.clust.dim.width; + y_offset = viz.clust.margin.top + viz.clust.dim.height; + tmp_width = viz.cat_room.col + viz.clust.dim.width; + tmp_height = viz.cat_room.row + viz.uni_margin; + + svg_group.select('.dendro_corner_spillover').attr('width', tmp_width).attr('height', tmp_height).attr('transform', function () { + return 'translate(' + x_offset + ',' + y_offset + ')'; + }); + + x_offset = viz.clust.margin.left + viz.clust.dim.width + viz.uni_margin; + y_offset = viz.norm_labels.margin.top + viz.norm_labels.width.col + 2.5 * viz.uni_margin; + var extra_x_room = 2.75; + var extra_y_room = 1.2; + + // reposition category superlabels + if (viz.show_categories.col) { + + d3.selectAll(viz.root + ' .col_cat_super').attr('transform', function (d) { + var inst_cat = parseInt(d.split('-')[1], 10); + var inst_y = y_offset + extra_y_room * viz.cat_room.symbol_width * inst_cat; + return 'translate(' + x_offset + ',' + inst_y + ')'; + }); + } + + if (viz.show_categories.row) { + d3.select(viz.root + ' .row_cat_label_container').attr('transform', function () { + x_offset = viz.norm_labels.margin.left + viz.norm_labels.width.row + viz.cat_room.symbol_width + extra_x_room * viz.uni_margin; + y_offset = viz.clust.margin.top - viz.uni_margin; + return 'translate(' + x_offset + ',' + y_offset + ') rotate(-90)'; + }); + } + + // white border bottom - prevent clustergram from hitting border + if (viz.show_dendrogram) { + y_offset = viz.clust.margin.top + viz.clust.dim.height + viz.dendro_room.col - 2 * viz.uni_margin; + } else { + y_offset = viz.clust.margin.top + viz.clust.dim.height; + } + + d3.select(viz.root + ' .bottom_spillover_container').attr('transform', function () { + // shift up enough to show the entire border width + return 'translate(0,' + y_offset + ')'; + }); + + svg_group.select(viz.root + ' .bottom_spillover').attr('width', viz.svg_dim.width).attr('height', 2 * viz.svg_dim.height); + + var inst_height = viz.cat_room.col + 1.5 * viz.uni_margin; + // white rect to cover excess labels + d3.select(viz.viz_svg + ' .top_right_white').attr('fill', viz.background_color).attr('width', 2 * viz.clust.dim.width).attr('height', inst_height).attr('transform', function () { + var tmp_left = viz.clust.margin.left + viz.clust.dim.width; + var tmp_top = viz.norm_labels.width.col + viz.norm_labels.margin.top - viz.uni_margin; + return 'translate(' + tmp_left + ', ' + tmp_top + ')'; + }); + }; + +/***/ }, +/* 138 */ +/***/ function(module, exports) { + + module.exports = function resize_borders(params, svg_group) { + + // left border + svg_group.select('.left_border').attr('width', params.viz.grey_border_width).attr('height', params.viz.svg_dim.height).attr('transform', 'translate(0,0)'); + + // right border + svg_group.select('.right_border').attr('width', params.viz.grey_border_width).attr('height', params.viz.svg_dim.height).attr('transform', function () { + var inst_offset = params.viz.svg_dim.width - params.viz.grey_border_width; + return 'translate(' + inst_offset + ',0)'; + }); + + // top border + svg_group.select('.top_border').attr('width', params.viz.svg_dim.width).attr('height', params.viz.grey_border_width).attr('transform', function () { + var inst_offset = 0; + return 'translate(' + inst_offset + ',0)'; + }); + + // bottom border + svg_group.select('.bottom_border').attr('width', params.viz.svg_dim.width).attr('height', params.viz.grey_border_width).attr('transform', function () { + var inst_offset = params.viz.svg_dim.height - params.viz.grey_border_width; + return 'translate(0,' + inst_offset + ')'; + }); + }; + +/***/ }, +/* 139 */ +/***/ function(module, exports) { + + module.exports = function resize_row_labels(params, ini_svg_group, delay_info = false) { + + var delays = {}; + var duration = params.viz.duration; + var svg_group; + + var row_nodes = params.network_data.row_nodes; + var row_nodes_names = params.network_data.row_nodes_names; + + if (delay_info === false) { + delays.run_transition = false; + } else { + delays = delay_info; + } + + if (delays.run_transition) { + + ini_svg_group.selectAll('.row_label_group') + // data bind necessary for loss/gain of rows + .data(row_nodes, function (d) { + return d.name; + }).transition().delay(delays.update).duration(duration).attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0,' + params.viz.y_scale(inst_index) + ')'; + }).attr('y', params.viz.rect_height * 0.5 + params.labels.default_fs_row * 0.35); + + svg_group = ini_svg_group.transition().delay(delays.update).duration(duration); + } else { + + ini_svg_group.selectAll('.row_label_group') + // data bind necessary for loss/gain of rows + .data(row_nodes, function (d) { + return d.name; + }).attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0,' + params.viz.y_scale(inst_index) + ')'; + }).attr('y', params.viz.rect_height * 0.5 + params.labels.default_fs_row * 0.35); + + svg_group = ini_svg_group; + } + + svg_group.select(params.root + ' .row_container').attr('transform', 'translate(' + params.viz.norm_labels.margin.left + ',' + params.viz.clust.margin.top + ')'); + + svg_group.select(params.root + ' .row_container').select('.white_bars').attr('width', params.viz.label_background.row).attr('height', 30 * params.viz.clust.dim.height + 'px'); + + svg_group.select(params.root + ' .row_container').select('.row_label_container').attr('transform', 'translate(' + params.viz.norm_labels.width.row + ',0)'); + }; + +/***/ }, +/* 140 */ +/***/ function(module, exports) { + + module.exports = function resize_highlights(params) { + + // reposition tile highlight + //////////////////////////////// + + var rel_width_hlight = 6; + // var opacity_hlight = 0.85; + var hlight_width = rel_width_hlight * params.viz.border_width.x; + var hlight_height = rel_width_hlight * params.viz.border_width.y; + + // top highlight + d3.select(params.root + ' .top_hlight').attr('width', params.viz.rect_width).attr('height', hlight_height).attr('transform', function () { + return 'translate(' + params.viz.x_scale(params.matrix.click_hlight_x) + ',0)'; + }); + + // left highlight + d3.select(params.root + ' .left_hlight').attr('width', hlight_width).attr('height', params.viz.rect_width - hlight_height * 0.99).attr('transform', function () { + return 'translate(' + params.viz.x_scale(params.matrix.click_hlight_x) + ',' + hlight_height * 0.99 + ')'; + }); + + // right highlight + d3.select(params.root + ' .right_hlight').attr('width', hlight_width).attr('height', params.viz.rect_height - hlight_height * 0.99).attr('transform', function () { + var tmp_translate = params.viz.x_scale(params.matrix.click_hlight_x) + params.viz.rect_width - hlight_width; + return 'translate(' + tmp_translate + ',' + hlight_height * 0.99 + ')'; + }); + + // bottom highlight + d3.select(params.root + ' .bottom_hlight').attr('width', function () { + return params.viz.rect_width - 1.98 * hlight_width; + }).attr('height', hlight_height).attr('transform', function () { + var tmp_translate_x = params.viz.x_scale(params.matrix.click_hlight_x) + hlight_width * 0.99; + var tmp_translate_y = params.viz.rect_height - hlight_height; + return 'translate(' + tmp_translate_x + ',' + tmp_translate_y + ')'; + }); + + // resize row highlight + ///////////////////////// + d3.select(params.root + ' .row_top_hlight').attr('width', params.viz.svg_dim.width).attr('height', hlight_height); + + d3.select(params.root + ' .row_bottom_hlight').attr('width', params.viz.svg_dim.width).attr('height', hlight_height).attr('transform', function () { + var tmp_translate_y = params.viz.rect_height - hlight_height; + return 'translate(0,' + tmp_translate_y + ')'; + }); + + // resize col highlight + ///////////////////////// + d3.select(params.root + ' .col_top_hlight').attr('width', params.viz.clust.dim.height).attr('height', hlight_width).attr('transform', function () { + var tmp_translate_y = 0; + var tmp_translate_x = -(params.viz.clust.dim.height + params.viz.cat_room.col + params.viz.uni_margin); + return 'translate(' + tmp_translate_x + ',' + tmp_translate_y + ')'; + }); + + d3.select(params.root + ' .col_bottom_hlight').attr('width', params.viz.clust.dim.height).attr('height', hlight_width).attr('transform', function () { + var tmp_translate_y = params.viz.rect_width - hlight_width; + var tmp_translate_x = -(params.viz.clust.dim.height + params.viz.cat_room.col + params.viz.uni_margin); + return 'translate(' + tmp_translate_x + ',' + tmp_translate_y + ')'; + }); + }; + +/***/ }, +/* 141 */ +/***/ function(module, exports) { + + module.exports = function resize_row_viz(params, ini_svg_group, delay_info = false) { + + var delays = {}; + var duration = params.viz.duration; + var svg_group; + + if (delay_info === false) { + delays.run_transition = false; + } else { + delays = delay_info; + } + + if (delays.run_transition) { + svg_group = ini_svg_group.transition().delay(delays.update).duration(duration); + } else { + svg_group = ini_svg_group; + } + + svg_group.select('.row_cat_outer_container').attr('transform', 'translate(' + params.viz.norm_labels.width.row + ',0)').select('white_bars').attr('width', params.viz.cat_room.row + 'px').attr('height', function () { + var inst_height = params.viz.clust.dim.height; + return inst_height; + }); + + var x_offset = params.viz.clust.margin.left + params.viz.clust.dim.width; + var y_offset = params.viz.clust.margin.top; + svg_group.select('.row_dendro_outer_container').attr('transform', 'translate(' + x_offset + ',' + y_offset + ')'); + + // !! tmp resize col dendro + x_offset = params.viz.clust.margin.left; + y_offset = params.viz.clust.margin.top + params.viz.clust.dim.height; + + svg_group.select(' .col_dendro_outer_container').attr('transform', function () { + return 'translate(' + x_offset + ',' + y_offset + ')'; + }); + }; + +/***/ }, +/* 142 */ +/***/ function(module, exports) { + + module.exports = function (params, ini_svg_group, delay_info = false) { + + var delays = {}; + var duration = params.viz.duration; + var svg_group; + + var col_nodes = params.network_data.col_nodes; + var col_nodes_names = params.network_data.col_nodes_names; + + if (delay_info === false) { + delays.run_transition = false; + } else { + delays = delay_info; + } + + if (delays.run_transition) { + svg_group = ini_svg_group.transition().delay(delays.update).duration(duration); + + ini_svg_group.selectAll('.col_label_text').data(col_nodes, function (d) { + return d.name; + }).transition().delay(delays.update).duration(duration).attr('transform', function (d) { + var inst_index = _.indexOf(col_nodes_names, d.name); + return 'translate(' + params.viz.x_scale(inst_index) + ', 0) rotate(-90)'; + }); + } else { + svg_group = ini_svg_group; + + ini_svg_group.selectAll('.col_label_text').data(col_nodes, function (d) { + return d.name; + }).attr('transform', function (d) { + var inst_index = _.indexOf(col_nodes_names, d.name); + return 'translate(' + params.viz.x_scale(inst_index) + ', 0) rotate(-90)'; + }); + } + + // offset click group column label + var x_offset_click = params.viz.x_scale.rangeBand() / 2 + params.viz.border_width.x; + + svg_group.select(params.root + ' .col_container').attr('transform', 'translate(' + params.viz.clust.margin.left + ',' + params.viz.norm_labels.margin.top + ')'); + + svg_group.select(params.root + ' .col_container').select('.white_bars').attr('width', 30 * params.viz.clust.dim.width + 'px').attr('height', params.viz.label_background.col); + + svg_group.select(params.root + ' .col_container').select('.col_label_outer_container').attr('transform', 'translate(0,' + params.viz.norm_labels.width.col + ')'); + + svg_group.selectAll('.col_label_group').attr('transform', 'translate(' + params.viz.x_scale.rangeBand() / 2 + ',' + x_offset_click + ') rotate(45)'); + + svg_group.selectAll('.col_label_group').select('text').attr('y', params.viz.x_scale.rangeBand() * 0.60).attr('dx', 2 * params.viz.border_width.x); + }; + +/***/ }, +/* 143 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + + module.exports = function resize_col_text(params, svg_group) { + svg_group.selectAll('.col_label_group').select('text').style('font-size', params.labels.default_fs_col + 'px').text(function (d) { + return utils.normal_name(d); + }); + + svg_group.selectAll('.col_label_group').each(function () { + d3.select(this).select('text')[0][0].getBBox(); + }); + }; + +/***/ }, +/* 144 */ +/***/ function(module, exports, __webpack_require__) { + + var col_viz_aid_triangle = __webpack_require__(110); + + module.exports = function resize_col_triangle(params, ini_svg_group, delay_info = false) { + + // resize column triangle + var ini_triangle_group = ini_svg_group.selectAll('.col_label_group').select('path'); + + var delays = {}; + var duration = params.viz.duration; + + if (delay_info === false) { + delays.run_transition = false; + } else { + delays = delay_info; + } + + var triangle_group; + if (delays.run_transition) { + triangle_group = ini_triangle_group.transition().delay(delays.update).duration(duration); + } else { + triangle_group = ini_triangle_group; + } + + triangle_group.attr('d', function () { + return col_viz_aid_triangle(params); + }).attr('fill', '#eee'); + }; + +/***/ }, +/* 145 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + + module.exports = function resize_col_hlight(params, svg_group, delay_info = false) { + + var delays = {}; + // var duration = params.viz.duration; + + if (delay_info === false) { + delays.run_transition = false; + } else { + delays = delay_info; + } + + if (utils.has(params.network_data.col_nodes[0], 'value')) { + + svg_group.selectAll('.col_bars').data(params.network_data.col_nodes, function (d) { + return d.name; + }).attr('width', function (d) { + + var inst_value = 0; + + if (d.value > 0) { + inst_value = params.labels.bar_scale_col(d.value); + } + return inst_value; + }) + // rotate labels - reduce width if rotating + .attr('height', params.viz.rect_width * 0.66); + } + }; + +/***/ }, +/* 146 */ +/***/ function(module, exports, __webpack_require__) { + + var get_svg_dim = __webpack_require__(19); + var calc_clust_height = __webpack_require__(22); + var calc_clust_width = __webpack_require__(21); + var calc_default_fs = __webpack_require__(31); + var calc_zoom_switching = __webpack_require__(30); + + module.exports = function recalc_params_for_resize(params) { + + // Resetting some visualization parameters + params = get_svg_dim(params); + params.viz = calc_clust_width(params.viz); + params.viz = calc_clust_height(params.viz); + + if (params.sim_mat) { + if (params.viz.clust.dim.width <= params.viz.clust.dim.height) { + params.viz.clust.dim.height = params.viz.clust.dim.width; + } else { + params.viz.clust.dim.width = params.viz.clust.dim.height; + } + } + + params.viz = calc_zoom_switching(params.viz); + + // redefine x_scale and y_scale rangeBands + params.viz.x_scale.rangeBands([0, params.viz.clust.dim.width]); + params.viz.y_scale.rangeBands([0, params.viz.clust.dim.height]); + + // redefine border width + params.viz.border_width.x = params.viz.x_scale.rangeBand() / params.viz.border_fraction; + params.viz.border_width.y = params.viz.y_scale.rangeBand() / params.viz.border_fraction; + + params.viz.rect_width = params.viz.x_scale.rangeBand() - params.viz.border_width.x; + params.viz.rect_height = params.viz.y_scale.rangeBand() - params.viz.border_width.y; + + // for downsampling + if (params.viz.ds != null) { + for (var i; i < params.viz.ds.length; i++) { + params.viz.ds[i].rect_height = params.viz.ds[i].y_scale.rangeBand() - params.viz.border_width.y; + } + } + + // recalc downsampled y_scale if necessary + if (params.viz.ds_num_levels > 0) { + _.each(params.viz.ds, function (inst_ds) { + + // y_scale + ///////////////////////// + inst_ds.y_scale = d3.scale.ordinal().rangeBands([0, params.viz.clust.dim.height]); + inst_ds.y_scale.domain(d3.range(inst_ds.num_rows + 1)); + + inst_ds.rect_height = inst_ds.y_scale.rangeBand() - params.viz.border_width.y; + }); + } + + // redefine zoom extent + params.viz.square_zoom = params.viz.norm_labels.width.col / (params.viz.rect_width / 2); + + // the default font sizes are set here + params = calc_default_fs(params); + + return params; + }; + +/***/ }, +/* 147 */ +/***/ function(module, exports, __webpack_require__) { + + var draw_up_tile = __webpack_require__(43); + var draw_dn_tile = __webpack_require__(44); + var fine_position_tile = __webpack_require__(47); + + module.exports = function resize_row_tiles(params, svg_group) { + + var row_nodes_names = params.network_data.row_nodes_names; + + if (params.viz.ds_level === -1) { + + // no downsampling + /////////////////////// + + // resize rows + svg_group.selectAll('.row').attr('transform', function (d) { + var tmp_index = _.indexOf(row_nodes_names, d.name); + var inst_y = params.viz.y_scale(tmp_index); + return 'translate(0,' + inst_y + ')'; + }); + + // resize tiles + svg_group.selectAll('.row').selectAll('.tile').attr('transform', function (d) { + return fine_position_tile(params, d); + }).attr('width', params.viz.rect_width).attr('height', params.viz.rect_height); + + // resize tile_up + svg_group.selectAll('.row').selectAll('.tile_up').attr('d', function () { + return draw_up_tile(params); + }).attr('transform', function (d) { + return fine_position_tile(params, d); + }); + + // resize tile_dn + svg_group.selectAll('.row').selectAll('.tile_dn').attr('d', function () { + return draw_dn_tile(params); + }).attr('transform', function (d) { + return fine_position_tile(params, d); + }); + } else { + + // downsampling + ///////////////////////// + + var ds_level = params.viz.ds_level; + var row_class = '.ds' + String(ds_level) + '_row'; + var ds_rect_height = params.viz.ds[ds_level].rect_height; + + svg_group.selectAll(row_class).attr('transform', function (d) { + var inst_y = params.viz.ds[ds_level].y_scale(d.row_index); + return 'translate(0,' + inst_y + ')'; + }); + + // reset ds-tiles + svg_group.selectAll(row_class).selectAll('.tile').attr('transform', function (d) { + return fine_position_tile(params, d); + }).attr('width', params.viz.rect_width).attr('height', ds_rect_height); + } + }; + +/***/ }, +/* 148 */ +/***/ function(module, exports, __webpack_require__) { + + var calc_val_max = __webpack_require__(23); + + module.exports = function resize_label_bars(cgm, svg_group) { + var params = cgm.params; + + // // set bar scale + // var val_max = Math.abs(_.max( params.network_data.row_nodes, function(d) { + // return Math.abs(d.value); + // } ).value) ; + + // params.labels.bar_scale_row = d3.scale + // .linear() + // .domain([0, val_max]) + // .range([0, params.viz.norm_labels.width.row ]); + + params = calc_val_max(params); + + svg_group.selectAll('.row_bars') + // .transition().delay(delays.update).duration(duration) + .attr('width', function (d) { + var inst_value = 0; + inst_value = params.labels.bar_scale_row(Math.abs(d.value)); + return inst_value; + }).attr('x', function (d) { + var inst_value = 0; + inst_value = -params.labels.bar_scale_row(Math.abs(d.value)); + return inst_value; + }).attr('height', params.viz.y_scale.rangeBand()); + }; + +/***/ }, +/* 149 */ +/***/ function(module, exports) { + + module.exports = function position_play_button(params) { + + var clust_transform = d3.select(params.root + ' .clust_container').attr('transform'); + + var clust_x = Number(clust_transform.split('(')[1].split(',')[0]); + var clust_y = Number(clust_transform.split(',')[1].replace(')', '')); + var trans_x = clust_x + params.viz.clust.dim.width / 2; + var trans_y = clust_y + params.viz.clust.dim.height / 2; + + d3.select(params.root + ' .play_button').attr('transform', function () { + return 'translate(' + trans_x + ',' + trans_y + ')'; + }); + }; + +/***/ }, +/* 150 */ +/***/ function(module, exports) { + + module.exports = function position_svg_dendro_slider(cgm, inst_rc) { + + var viz = cgm.params.viz; + var tmp_left; + var tmp_top; + if (inst_rc === 'row') { + + // row dendrogram + /////////////////////// + + // keep slider near clustergram + var max_room = viz.svg_dim.width - 3 * viz.uni_margin; + + // position close to row dendrogram trapezoids + tmp_left = viz.clust.margin.left + viz.clust.dim.width + 5 * viz.dendro_room.row; + + if (tmp_left > max_room) { + tmp_left = max_room; + } + + tmp_top = viz.clust.margin.top + 3 * viz.uni_margin; + } else { + + // column dendrogram + /////////////////////// + tmp_left = 2 * viz.uni_margin; + // tmp_top = viz.svg_dim.height - 2.5 * viz.uni_margin; + tmp_top = viz.clust.margin.top + viz.clust.dim.height + viz.dendro_room.col - 2 * viz.uni_margin; + } + + d3.select(cgm.params.root + ' .' + inst_rc + '_slider_group').attr('transform', function () { + var inst_translation; + if (inst_rc === 'row') { + inst_translation = 'translate(' + tmp_left + ',' + tmp_top + ')'; + } else { + inst_translation = 'translate(' + tmp_left + ',' + tmp_top + '), rotate(-90)'; + } + return inst_translation; + }).style('opacity', 1); + }; + +/***/ }, +/* 151 */ +/***/ function(module, exports) { + + module.exports = function grid_lines_viz(params, duration = 0) { + + var delay = 0; + if (duration > 0) { + delay = 2000; + } + + var horz_lines = d3.selectAll(params.root + ' .horz_lines'); + var vert_lines = d3.selectAll(params.root + ' .vert_lines'); + + horz_lines.style('opacity', 0).attr('transform', function (d) { + var inst_index = d.row_index; + var inst_trans = params.viz.y_scale(inst_index); + return 'translate( 0,' + inst_trans + ') rotate(0)'; + }).transition().duration(duration).delay(delay).style('opacity', 1); + + horz_lines.append('line').attr('x1', 0).attr('x2', params.viz.clust.dim.width).style('stroke-width', function () { + var inst_width = params.viz.border_width.y; + return inst_width + 'px'; + }); + + vert_lines.style('opacity', 0).attr('transform', function (d) { + var inst_index = d.col_index; + var inst_trans = params.viz.x_scale(inst_index); + return 'translate(' + inst_trans + ') rotate(-90)'; + }).transition().duration(duration).delay(delay).style('opacity', 1); + + vert_lines.append('line').attr('x1', 0).attr('x2', -params.viz.clust.dim.height).style('stroke-width', function () { + var inst_width = params.viz.border_width.x; + return inst_width + 'px'; + }); + }; + +/***/ }, +/* 152 */ +/***/ function(module, exports, __webpack_require__) { + + var cat_tooltip_text = __webpack_require__(153); + var d3_tip_custom = __webpack_require__(48); + var reset_cat_opacity = __webpack_require__(154); + var ini_cat_opacity = __webpack_require__(155); + var click_filter_cats = __webpack_require__(156); + var get_cat_names = __webpack_require__(157); + + module.exports = function make_col_cat(cgm) { + + var params = cgm.params; + + // make or reuse outer container + if (d3.select(params.root + ' .col_cat_outer_container').empty()) { + d3.select(params.root + ' .col_container').append('g').attr('class', 'col_cat_outer_container').attr('transform', function () { + var inst_offset = params.viz.norm_labels.width.col + 2; + return 'translate(0,' + inst_offset + ')'; + }).append('g').attr('class', 'col_cat_container'); + } else { + d3.select(params.root + ' .col_container').select('col_cat_outer_container').attr('transform', function () { + var inst_offset = params.viz.norm_labels.width.col + 2; + return 'translate(0,' + inst_offset + ')'; + }); + } + + // remove old col_cat_tips + d3.selectAll(params.viz.root_tips + '_col_cat_tip').remove(); + + // d3-tooltip + var cat_tip = d3_tip_custom().attr('class', function () { + var root_tip_selector = params.viz.root_tips.replace('.', ''); + var class_string = root_tip_selector + ' d3-tip ' + root_tip_selector + '_col_cat_tip'; + return class_string; + }).direction('s').offset([5, 0]).style('display', 'none').html(function (d) { + return cat_tooltip_text(params, d, this, 'col'); + }); + + // append groups - each will hold classification rects + d3.select(params.root + ' .col_cat_container').selectAll('g').data(params.network_data.col_nodes, function (d) { + return d.name; + }).enter().append('g').attr('class', 'col_cat_group').attr('transform', function (d) { + var inst_index = _.indexOf(params.network_data.col_nodes_names, d.name); + // return 'translate(' + params.viz.x_scale(d.col_index) + ',0)'; + return 'translate(' + params.viz.x_scale(inst_index) + ',0)'; + }); + + d3.select(params.root + ' .col_cat_container').selectAll('.col_cat_group').call(cat_tip); + + // add category rects + d3.selectAll(params.root + ' .col_cat_group').each(function () { + + var inst_selection = this; + var cat_rect; + + _.each(params.viz.all_cats.col, function (inst_cat) { + + var inst_num = parseInt(inst_cat.split('-')[1], 10); + var cat_rect_class = 'col_cat_rect_' + String(inst_num); + + if (d3.select(inst_selection).select('.' + cat_rect_class).empty()) { + cat_rect = d3.select(inst_selection).append('rect').attr('class', cat_rect_class).attr('cat', inst_cat).attr('transform', function () { + var cat_room = params.viz.cat_room.symbol_width + params.viz.cat_room.separation; + var inst_shift = inst_num * cat_room; + return 'translate(0,' + inst_shift + ')'; + }).on('click', function (d) { + + if (d3.select(this).classed('cat_strings')) { + + if (d3.event.shiftKey === true) { + click_filter_cats_db(cgm, d, this, 'col'); + } else { + + var found_names = get_cat_names(params, d, this, 'col'); + + $(params.root + ' .dendro_info').modal('toggle'); + var group_string = found_names.join(', '); + d3.select(params.root + ' .dendro_info input').attr('value', group_string); + } + } + }); + } else { + cat_rect = d3.select(inst_selection).select('.' + cat_rect_class); + } + + cat_rect.attr('width', params.viz.x_scale.rangeBand()).attr('height', params.viz.cat_room.symbol_width).style('fill', function (d) { + var cat_name = d[inst_cat]; + var inst_color = params.viz.cat_colors.col[inst_cat][cat_name]; + return inst_color; + }).on('mouseover', cat_tip.show).on('mouseout', function () { + cat_tip.hide(this); + reset_cat_opacity(params); + d3.select(this).classed('hovering', false); + + d3.selectAll('.d3-tip').style('display', 'none'); + }); + + ini_cat_opacity(params.viz, 'col', cat_rect, inst_cat); + }); + }); + + var click_filter_cats_db = _.debounce(click_filter_cats, 1500); + }; + +/***/ }, +/* 153 */ +/***/ function(module, exports, __webpack_require__) { + + var get_cat_title = __webpack_require__(113); + + module.exports = function cat_tooltip_text(params, inst_data, inst_selection, inst_rc) { + + d3.selectAll(params.viz.root_tips + '_col_cat_tip').style('display', 'block'); + + d3.selectAll(params.viz.root_tips + '_row_cat_tip').style('display', 'block'); + + // category index + var inst_cat = d3.select(inst_selection).attr('cat'); + var cat_title = get_cat_title(params.viz, inst_cat, inst_rc); + var cat_name = inst_data[inst_cat]; + + if (typeof cat_name === 'string') { + if (cat_name.indexOf(': ') >= 0) { + cat_name = cat_name.split(': ')[1]; + } + } + + var cat_string = cat_title + ': ' + cat_name; + + d3.select(inst_selection).classed('hovering', true); + + setTimeout(highlight_categories, 500); + + return cat_string; + + function highlight_categories() { + + var run_highlighting = false; + + if (d3.select(inst_selection).classed('hovering')) { + + var node_types = [inst_rc]; + + if (params.viz.sim_mat) { + node_types = ['row', 'col']; + } + + _.each(node_types, function (tmp_rc) { + + // only highlight string categories that are not 'false' categories + if (typeof cat_name === 'string') { + if (cat_name.indexOf('Not ') < 0 && cat_name != 'false') { + run_highlighting = true; + } + } + + if (run_highlighting) { + + d3.selectAll(params.root + ' .' + tmp_rc + '_cat_group').selectAll('rect').style('opacity', function (d) { + + var inst_opacity = d3.select(this).style('opacity'); + + if (d3.select(this).classed('cat_strings') && d3.select(this).classed('filtered_cat') === false) { + + var tmp_name; + var tmp_cat = d3.select(this).attr('cat'); + + if (d[tmp_cat].indexOf(': ') >= 0) { + tmp_name = d[tmp_cat].split(': ')[1]; + } else { + tmp_name = d[tmp_cat]; + } + + if (tmp_cat === inst_cat && tmp_name === cat_name) { + inst_opacity = params.viz.cat_colors.active_opacity; + } else { + inst_opacity = params.viz.cat_colors.opacity / 4; + } + } + + return inst_opacity; + }); + } + }); + } + } + }; + +/***/ }, +/* 154 */ +/***/ function(module, exports) { + + module.exports = function reset_cat_opacity(params) { + + _.each(['row', 'col'], function (inst_rc) { + + d3.selectAll(params.root + ' .' + inst_rc + '_cat_group').selectAll('rect').style('opacity', function () { + + var inst_opacity = d3.select(this).style('opacity'); + + if (d3.select(this).classed('cat_strings') && d3.select(this).classed('filtered_cat') === false) { + inst_opacity = params.viz.cat_colors.opacity; + } + + return inst_opacity; + }); + }); + }; + +/***/ }, +/* 155 */ +/***/ function(module, exports) { + + module.exports = function ini_cat_opacity(viz, inst_rc, cat_rect, inst_cat, updating = false) { + + // debugger; + + var super_string = ': '; + var inst_type = viz.cat_info[inst_rc][inst_cat].type; + + // set opacity based on string or value cats + if (inst_type === 'cat_strings') { + + // optionally have categories transition in + if (updating) { + cat_rect.classed('cat_strings', true).style('opacity', 0).transition().duration(1000).style('opacity', viz.cat_colors.opacity); + } else { + // opacity is fixed + cat_rect.classed('cat_strings', true).style('opacity', viz.cat_colors.opacity); + } + } else { + + // opacity varies based on value + cat_rect.classed('cat_values', true).style('opacity', function (d) { + + var unprocessed_val = d[inst_cat]; + + var cat_value = get_cat_value(unprocessed_val); + + return viz.cat_info[inst_rc][inst_cat].cat_scale(Math.abs(cat_value)); + }).style('fill', function (d) { + var inst_color; + + var cat_value = get_cat_value(d[inst_cat]); + + // get positive and negative colors + if (cat_value > 0) { + inst_color = viz.cat_value_colors[0]; + } else { + inst_color = viz.cat_value_colors[1]; + } + + return inst_color; + }); + } + + function get_cat_value(unprocessed_value) { + if (typeof unprocessed_value === 'string') { + + if (unprocessed_value.indexOf(super_string) > -1) { + unprocessed_value = unprocessed_value.split(super_string)[1]; + } + } + + var cat_value = parseFloat(unprocessed_value); + + return cat_value; + } + }; + +/***/ }, +/* 156 */ +/***/ function(module, exports, __webpack_require__) { + + var get_cat_names = __webpack_require__(157); + + module.exports = function click_filter_cats(cgm, inst_data, inst_selection, inst_rc) { + + var params = cgm.params; + + var inst_cat = d3.select(inst_selection).attr('cat'); + var cat_name = inst_data[inst_cat]; + + var found_names = get_cat_names(params, inst_data, inst_selection, inst_rc); + + var switch_rc = { 'row': 'col', 'col': 'row' }; + var other_rc = switch_rc[inst_rc]; + + var filter_names = {}; + filter_names[inst_rc] = found_names; + + if (cgm.params.cat_filter[inst_rc] === false) { + + if (cgm.params.dendro_filter.row === false && cgm.params.dendro_filter.col === false && cgm.params.cat_filter[other_rc] === false) { + + var tmp_names = cgm.params.network_data.col_nodes_names; + + // keep a backup of the inst_view + var inst_row_nodes = cgm.params.network_data.row_nodes; + var inst_col_nodes = cgm.params.network_data.col_nodes; + + // run filtering using found names + cgm.filter_viz_using_names(filter_names); + + // overwrite with backup of original nodes + cgm.params.inst_nodes.row_nodes = inst_row_nodes; + cgm.params.inst_nodes.col_nodes = inst_col_nodes; + + // must set this after filtering has been run + cgm.params.cat_filter[inst_rc] = tmp_names; + + highlight_filtered_cat(inst_rc, inst_cat, cat_name); + } + } else { + + // get backup of names + filter_names = cgm.params.cat_filter[inst_rc]; + + // reset filter + cgm.filter_viz_using_names(filter_names); + // must set this after filtering has been run + cgm.params.cat_filter[inst_rc] = false; + + // there are no filtered cats + d3.selectAll(params.root + ' .' + inst_rc + '_cat_group').selectAll('rect').classed('filtered_cat', false); + } + + function highlight_filtered_cat(inst_rc, inst_cat, cat_name) { + + d3.selectAll(params.root + ' .' + inst_rc + '_cat_group').selectAll('rect').style('opacity', function (d) { + + var inst_opacity = d3.select(this).style('opacity'); + + if (d3.select(this).classed('cat_strings')) { + + var tmp_name; + var tmp_cat = d3.select(this).attr('cat'); + + // no need to filter out title + tmp_name = d[tmp_cat]; + + if (tmp_cat === inst_cat && tmp_name === cat_name) { + inst_opacity = 1; + + d3.select(this).classed('filtered_cat', true); + } + // else { + // inst_opacity = params.viz.cat_colors.opacity/4; + // } + } + + return inst_opacity; + }); + } + }; + +/***/ }, +/* 157 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + + module.exports = function get_cat_names(params, inst_data, inst_selection, inst_rc) { + + // category index + var inst_cat = d3.select(inst_selection).attr('cat'); + var cat_name = inst_data[inst_cat]; + var tmp_nodes = params.network_data[inst_rc + '_nodes']; + + var found_nodes = _.filter(tmp_nodes, function (d) { + return d[inst_cat] == cat_name; + }); + + var found_names = utils.pluck(found_nodes, 'name'); + + return found_names; + }; + +/***/ }, +/* 158 */ +/***/ function(module, exports, __webpack_require__) { + + var cat_tooltip_text = __webpack_require__(153); + var d3_tip_custom = __webpack_require__(48); + var reset_cat_opacity = __webpack_require__(154); + var ini_cat_opacity = __webpack_require__(155); + var click_filter_cats = __webpack_require__(156); + var get_cat_names = __webpack_require__(157); + + module.exports = function make_row_cat(cgm, updating = false) { + + // console.log('make_row_cat') + + var params = cgm.params; + + // make or reuse outer container + if (d3.select(params.root + ' .row_cat_outer_container').empty()) { + d3.select(params.root + ' .row_container').append('g').attr('class', 'row_cat_outer_container').attr('transform', 'translate(' + params.viz.norm_labels.width.row + ',0)').append('g').attr('class', 'row_cat_container'); + } else { + d3.select(params.root + ' .row_container').select('row_cat_outer_container').attr('transform', 'translate(' + params.viz.norm_labels.width.row + ',0)'); + } + + // white background + if (d3.select(params.root + ' .row_cat_container').select('.white_bars').empty()) { + d3.select(params.root + ' .row_cat_container').append('rect').attr('class', 'white_bars').attr('fill', params.viz.background_color).attr('width', params.viz.cat_room.row + 'px').attr('height', function () { + var inst_height = params.viz.clust.dim.height; + return inst_height; + }); + } else { + d3.select(params.root + ' .row_cat_container').select('.white_bars').attr('fill', params.viz.background_color).attr('width', params.viz.cat_room.row + 'px').attr('height', function () { + var inst_height = params.viz.clust.dim.height; + return inst_height; + }); + } + + // remove old col_cat_tips + d3.selectAll(params.viz.root_tips + '_row_cat_tip').remove(); + + // d3-tooltip + var cat_tip = d3_tip_custom().attr('class', function () { + var root_tip_selector = params.viz.root_tips.replace('.', ''); + var class_string = root_tip_selector + ' d3-tip ' + root_tip_selector + '_row_cat_tip'; + return class_string; + }).direction('e').offset([5, 0]).style('display', 'none').html(function (d) { + return cat_tooltip_text(params, d, this, 'row'); + }); + + // groups that hold classification triangle and colorbar rect + d3.select(params.root + ' .row_cat_container').selectAll('g').data(params.network_data.row_nodes, function (d) { + // console.log('-------------') + // console.log(d['cat-0']) + // console.log('-------------') + return d.name; + }).enter().append('g').attr('class', 'row_cat_group').attr('transform', function (d) { + var inst_index = _.indexOf(params.network_data.row_nodes_names, d.name); + return 'translate(0, ' + params.viz.y_scale(inst_index) + ')'; + }); + + d3.select(params.root + ' .row_cat_container').selectAll('.row_cat_group').call(cat_tip); + + // add row visual-aid triangles (if no downsampling) + // if (params.viz.ds_level === -1){ + // d3.selectAll(params.root+' .row_cat_group') + // .append('path') + // .attr('d', function() { + // var origin_x = params.viz.cat_room.symbol_width - 1; + // var origin_y = 0; + // var mid_x = 1; + // var mid_y = params.viz.y_scale.rangeBand() / 2; + // var final_x = params.viz.cat_room.symbol_width - 1; + // var final_y = params.viz.y_scale.rangeBand(); + // var output_string = 'M ' + origin_x + ',' + origin_y + ' L ' + + // mid_x + ',' + mid_y + ', L ' + final_x + ',' + final_y + ' Z'; + // return output_string; + // }) + // .attr('fill', '#eee') + // .style('opacity', params.viz.triangle_opacity); + // } + + var cat_rect; + var inst_selection; + + d3.selectAll(params.root + ' .row_cat_group rect').remove(); + + if (params.viz.show_categories.row) { + + d3.selectAll(params.root + ' .row_cat_group').each(function () { + + inst_selection = this; + + _.each(params.viz.all_cats.row, function (inst_cat) { + + var inst_num = parseInt(inst_cat.split('-')[1], 10); + var cat_rect_class = 'row_cat_rect_' + String(inst_num); + + if (d3.select(inst_selection).select('.' + cat_rect_class).empty()) { + cat_rect = d3.select(inst_selection).append('rect').attr('class', cat_rect_class).attr('cat', inst_cat); + } else { + cat_rect = d3.select(inst_selection).select('.' + cat_rect_class); + } + + cat_rect.attr('width', params.viz.cat_room.symbol_width).attr('height', params.viz.y_scale.rangeBand()).style('fill', function (d) { + var cat_name = d[inst_cat]; + + // if (cat_name.indexOf(': ') >= 0){ + // cat_name = cat_name.split(': ')[1]; + // } + + // console.log(cat_name) + + var inst_color = params.viz.cat_colors.row[inst_cat][cat_name]; + + // console.log('inst_color: ' + String(inst_color)); + return inst_color; + }).attr('x', function () { + var inst_offset = params.viz.cat_room.symbol_width + params.viz.uni_margin / 2; + return inst_offset + 'px'; + }).attr('transform', function () { + var cat_room = params.viz.cat_room.symbol_width + params.viz.cat_room.separation; + var inst_shift = inst_num * cat_room; + return 'translate(' + inst_shift + ',0)'; + }).on('click', function (d) { + + if (d3.select(this).classed('cat_strings')) { + + if (d3.event.shiftKey === true) { + click_filter_cats_db(cgm, d, this, 'row'); + } else { + + var found_names = get_cat_names(params, d, this, 'row'); + + $(params.root + ' .dendro_info').modal('toggle'); + var group_string = found_names.join(', '); + d3.select(params.root + ' .dendro_info input').attr('value', group_string); + } + } + }).on('mouseover', cat_tip.show).on('mouseout', function () { + cat_tip.hide(this); + reset_cat_opacity(params); + d3.select(this).classed('hovering', false); + + d3.selectAll('.d3-tip').style('display', 'none'); + }); + + ini_cat_opacity(params.viz, 'row', cat_rect, inst_cat, updating); + }); + }); + } + + var click_filter_cats_db = _.debounce(click_filter_cats, 1500); + }; + +/***/ }, +/* 159 */ +/***/ function(module, exports, __webpack_require__) { + + var make_dendro_triangles = __webpack_require__(55); + + module.exports = function make_row_dendro(cgm) { + + var params = cgm.params; + + var spillover_width = params.viz.dendro_room.row + params.viz.uni_margin; + + // position row_dendro_outer_container + var x_offset = params.viz.clust.margin.left + params.viz.clust.dim.width; + var y_offset = params.viz.clust.margin.top; + + // make or reuse outer container + if (d3.select(params.root + ' .row_dendro_outer_container').empty()) { + + d3.select(params.root + ' .viz_svg').append('g').attr('class', 'row_dendro_outer_container').attr('transform', 'translate(' + x_offset + ',' + y_offset + ')'); + + d3.select(params.root + ' .row_dendro_outer_container').append('rect').classed('row_dendro_spillover', true).attr('fill', params.viz.background_color).attr('width', spillover_width + 'px').attr('height', params.viz.svg_dim.height); + + d3.select(params.root + ' .row_dendro_outer_container').append('g').attr('class', 'row_dendro_container').attr('transform', 'translate(' + params.viz.uni_margin / 2 + ',0)'); + } else { + d3.select(params.root + ' .viz_svg').select('row_dendro_outer_container').attr('transform', 'translate(' + x_offset + ',' + y_offset + ')'); + + d3.select(params.root + ' .row_dendro_outer_container').select('.row_dendro_spillover').attr('width', spillover_width + 'px').attr('height', params.viz.svg_dim.height); + } + + make_dendro_triangles(cgm, 'row', false); + + if (params.viz.inst_order.col != 'clust') { + d3.selectAll(params.root + ' .row_dendro_group').remove(); + } + }; + +/***/ }, +/* 160 */ +/***/ function(module, exports, __webpack_require__) { + + var make_dendro_triangles = __webpack_require__(55); + + module.exports = function make_col_dendro(cgm) { + + var params = cgm.params; + + // position col_dendro_outer_container + var x_offset = params.viz.clust.margin.left; + var y_offset = params.viz.clust.margin.top + params.viz.clust.dim.height; + var spillover_height = params.viz.dendro_room.col + params.viz.uni_margin; + + // make or reuse outer container + if (d3.select(params.root + ' .col_dendro_outer_container').empty()) { + + d3.select(params.root + ' .viz_svg').append('g').attr('class', 'col_dendro_outer_container').attr('transform', 'translate(' + x_offset + ',' + y_offset + ')'); + + d3.select(params.root + ' .col_dendro_outer_container').append('rect').classed('col_dendro_spillover', true).attr('fill', params.viz.background_color).attr('width', params.viz.svg_dim.width).attr('height', spillover_height + 'px'); + + d3.select(params.root + ' .col_dendro_outer_container').append('g').attr('class', 'col_dendro_container').attr('transform', 'translate(0,' + params.viz.uni_margin / 2 + ')'); + + d3.select(params.root + ' .col_dendro_outer_container').append('rect').classed('col_dendro_spillover_top', true).attr('fill', params.viz.background_color).attr('width', params.viz.svg_dim.width).attr('height', params.viz.svg_dim.height).attr('transform', 'translate(0,' + params.viz.dendro_room.col + ')'); + } else { + + d3.select(params.root + ' .viz_svg').select('col_dendro_outer_container').attr('transform', 'translate(' + x_offset + ',' + y_offset + ')'); + + d3.select(params.root + ' .col_dendro_outer_container').select('.col_dendro_spillover').attr('width', params.viz.svg_dim.width).attr('height', spillover_height + 'px'); + } + + make_dendro_triangles(cgm, 'col', false); + + if (params.viz.inst_order.row != 'clust') { + d3.selectAll(params.root + ' .col_dendro_group').remove(); + } + }; + +/***/ }, +/* 161 */ +/***/ function(module, exports, __webpack_require__) { + + var build_svg_dendro_slider = __webpack_require__(162); + + module.exports = function make_svg_dendro_sliders(cgm) { + + build_svg_dendro_slider(cgm, 'row'); + build_svg_dendro_slider(cgm, 'col'); + }; + +/***/ }, +/* 162 */ +/***/ function(module, exports, __webpack_require__) { + + var change_groups = __webpack_require__(163); + var position_svg_dendro_slider = __webpack_require__(150); + + module.exports = function build_svg_dendro_slider(cgm, inst_rc) { + + var slider_length = 100; + + var drag = d3.behavior.drag().on("drag", dragging).on('dragend', function () { + cgm.params.is_slider_drag = false; + }); + + var slider_group = d3.select(cgm.params.root + ' .viz_svg').append('g').classed(inst_rc + '_slider_group', true); + + position_svg_dendro_slider(cgm, inst_rc); + + var rect_height = slider_length + 20; + var rect_width = 30; + slider_group.append('rect').classed(inst_rc + '_slider_background', true).attr('height', rect_height + 'px').attr('width', rect_width + 'px').attr('fill', cgm.params.viz.background_color).attr('transform', function () { + var translate_string = 'translate(-10, -5)'; + return translate_string; + }).style('opacity', 0); + + slider_group.append("line").style('stroke-width', slider_length / 7 + 'px').style('stroke', 'black').style('stroke-linecap', 'round').style('opacity', 0.0).attr("y1", 0).attr("y2", function () { + return slider_length - 2; + }).on('click', click_dendro_slider); + + var offset_triangle = -slider_length / 40; + slider_group.append('path').style('fill', 'black').attr('transform', 'translate(' + offset_triangle + ', 0)').attr('d', function () { + + // up triangle + var start_x = 0; + var start_y = 0; + + var mid_x = 0; + var mid_y = slider_length; + + var final_x = slider_length / 10; + var final_y = 0; + + var output_string = 'M' + start_x + ',' + start_y + ', L' + mid_x + ', ' + mid_y + ', L' + final_x + ',' + final_y + ' Z'; + + return output_string; + }).style('opacity', 0.35).on('click', click_dendro_slider); + + var default_opacity = 0.35; + var high_opacity = 0.6; + slider_group.append('circle').classed(inst_rc + '_group_circle', true).attr('r', slider_length * 0.08).attr('transform', function () { + return 'translate(0, ' + slider_length / 2 + ')'; + }).style('fill', 'blue').style('opacity', default_opacity).on('mouseover', function () { + d3.select(this).style('opacity', high_opacity); + }).on('mouseout', function () { + d3.select(this).style('opacity', default_opacity); + }).call(drag); + + function dragging() { + + cgm.params.is_slider_drag = true; + + // d[0] = d3.event.x; + var slider_pos = d3.event.y; + + if (slider_pos < 0) { + slider_pos = 0; + } + + if (slider_pos > slider_length) { + slider_pos = slider_length; + } + + if (this.nextSibling) { + this.parentNode.appendChild(this); + } + + slider_pos = d3.round(slider_pos, -1); + + var slider_value = 10 - slider_pos / 10; + + d3.select(this).attr("transform", "translate(0, " + slider_pos + ")"); + + change_groups(cgm, inst_rc, slider_value); + } + + function click_dendro_slider() { + + var clicked_line_position = d3.mouse(this); + + var rel_pos = d3.round(clicked_line_position[1], -1); + + d3.select(cgm.params.root + ' .' + inst_rc + '_group_circle').attr('transform', 'translate(0, ' + rel_pos + ')'); + + var slider_value = 10 - rel_pos / 10; + + change_groups(cgm, inst_rc, slider_value); + } + }; + +/***/ }, +/* 163 */ +/***/ function(module, exports, __webpack_require__) { + + // var build_color_groups = require('./build_color_groups'); + var make_dendro_triangles = __webpack_require__(55); + + /* Changes the groupings (x- and y-axis color bars). + */ + module.exports = function (cgm, inst_rc, inst_index) { + + var params = cgm.params; + + if (inst_rc === 'row') { + params.group_level.row = inst_index; + } else if (inst_rc === 'col') { + params.group_level.col = inst_index; + } + + var is_change_group = true; + + make_dendro_triangles(cgm, inst_rc, is_change_group); + }; + +/***/ }, +/* 164 */ +/***/ function(module, exports, __webpack_require__) { + + var make_dendro_crop_buttons = __webpack_require__(60); + + module.exports = function make_row_dendro_spillover(cgm) { + + var viz = cgm.params.viz; + + // hide spillover from right + var tmp_left = viz.clust.margin.left + viz.clust.dim.width + viz.uni_margin + viz.dendro_room.row; + + var r_spill_container = d3.select(viz.viz_svg).append('g').classed('right_spillover_container', true).attr('transform', function () { + return 'translate(' + tmp_left + ', 0)'; + }); + + var tmp_top = viz.norm_labels.margin.top + viz.norm_labels.width.col; + + r_spill_container.append('rect').attr('fill', viz.background_color) //!! prog_colors + .attr('width', 10 * viz.clust.dim.width).attr('height', viz.svg_dim.height + 'px').attr('class', 'white_bars').attr('class', 'right_spillover').attr('transform', function () { + return 'translate( 0,' + tmp_top + ')'; + }); + + var x_offset = 0; + var y_offset = viz.clust.margin.top; + r_spill_container.append('g').classed('row_dendro_icons_container', true).attr('transform', 'translate(' + x_offset + ',' + y_offset + ')').append('g').classed('row_dendro_icons_group', true); + + make_dendro_crop_buttons(cgm, 'row'); + + // hide spillover from top of row dendrogram + x_offset = viz.clust.margin.left + viz.clust.dim.width; + y_offset = tmp_top; + + var tmp_width = viz.dendro_room.row + viz.uni_margin; + var tmp_height = viz.cat_room.col + viz.uni_margin; + d3.select(viz.viz_svg).append('rect').attr('fill', viz.background_color).attr('width', tmp_width).attr('height', tmp_height).attr('transform', function () { + return 'translate(' + x_offset + ',' + y_offset + ')'; + }).classed('white_bars', true).classed('dendro_row_spillover', true); + }; + +/***/ }, +/* 165 */ +/***/ function(module, exports, __webpack_require__) { + + /* eslint-disable */ + + var run_segment = __webpack_require__(166); + var play_intro = __webpack_require__(167); + var play_zoom = __webpack_require__(169); + var play_reset_zoom = __webpack_require__(170); + var play_reorder_row = __webpack_require__(172); + var play_reorder_buttons = __webpack_require__(173); + var play_search = __webpack_require__(175); + var play_filter = __webpack_require__(176); + var quick_cluster = __webpack_require__(199); + var play_groups = __webpack_require__(200); + var play_categories = __webpack_require__(201); + var play_conclusion = __webpack_require__(202); + var toggle_play_button = __webpack_require__(203); + var play_menu_button = __webpack_require__(204); + + module.exports = function play_demo() { + + var cgm = this; + var params = cgm.params; + + if (d3.select(params.root + ' .running_demo').empty()) { + + // prevent more than one demo from running at once + d3.select(params.root + ' .play_button').classed('running_demo', true); + + toggle_play_button(params, false); + + // prevent user interaction while playing + $.blockUI({ css: { + border: 'none', + padding: '15px', + backgroundColor: '#000', + '-webkit-border-radius': '10px', + '-moz-border-radius': '10px', + opacity: 0, + color: '#fff', + cursor: 'default' + } }); + + d3.selectAll('.blockUI').style('opacity', 0); + + // intro text + var inst_time = 750; + + if (cgm.params.viz.is_expand === false) { + inst_time = run_segment(params, inst_time, quick_cluster); + inst_time = inst_time - 1500; + } + + // clustergram interaction + /////////////////////////////////// + inst_time = run_segment(params, inst_time, play_intro); + inst_time = run_segment(params, inst_time, play_zoom); + inst_time = run_segment(cgm, inst_time, play_reset_zoom); + inst_time = run_segment(params, inst_time, play_categories); + inst_time = run_segment(params, inst_time, play_reorder_row); + + // sidebar interaction + /////////////////////////////////// + inst_time = run_segment(params, inst_time, play_menu_button); + inst_time = run_segment(params, inst_time, play_groups); + inst_time = run_segment(params, inst_time, play_reorder_buttons); + inst_time = run_segment(params, inst_time, play_search); + inst_time = run_segment(cgm, inst_time, play_filter); + + // conclusion + /////////////////////////////////// + inst_time = run_segment(params, inst_time, quick_cluster); + inst_time = run_segment(params, inst_time, play_conclusion); + } + }; + +/***/ }, +/* 166 */ +/***/ function(module, exports) { + + + module.exports = function run_segment(segment_data, inst_time, inst_segment) { + /* eslint-disable */ + + var timer = setTimeout(inst_segment().run, inst_time, segment_data); + + // set up kill demo that will stop setTimeouts + ////////////////////////////////////////////////// + // if (clear_timer){ + // clearTimeout(timer); + // } + + var inst_duration = inst_segment().get_duration(); + inst_time = inst_time + inst_duration; + + return inst_time; + }; + +/***/ }, +/* 167 */ +/***/ function(module, exports, __webpack_require__) { + + var demo_text = __webpack_require__(168); + + module.exports = function play_intro() { + + var speed_up = 1; + + function run(params) { + var text_1 = 'Clustergrammer allows users to generate\ninteractive and ' + 'sharable visualizations\nby uploading a matrix'; + var text_2 = "This demo will quickly overview some\nof Clustergrammer's " + "interactive features"; + + setTimeout(demo_text, 0, params, text_1, 4500 / speed_up); + setTimeout(demo_text, 4500 / speed_up, params, text_2, 4500 / speed_up); + } + + function get_duration() { + return 10000 / speed_up; + } + + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 168 */ +/***/ function(module, exports) { + + module.exports = function demo_text(params, text, read_duration) { + + var split_text = text.split('\n'); + + if (split_text.length < 3) { + split_text.push(''); + } + + d3.select(params.root + ' .demo_group').style('opacity', 0).transition().duration(250).style('opacity', 1).transition().duration(250).delay(read_duration).style('opacity', 0); + + for (var i = 0; i < split_text.length; i++) { + + var inst_text_num = i + 1; + + // make text box + ////////////////// + var inst_text_obj = d3.select(params.root + ' .demo_group').select('#text_' + inst_text_num).text(split_text[i]); + var bbox = inst_text_obj[0][0].getBBox(); + + var box_opacity = 0.9; + + var tmp_fs = Number(d3.select('.demo_group').select('text').style('font-size').replace('px', '')); + var shift_height = tmp_fs * 1.3; + + d3.select(params.root + ' .demo_group').select('.rect_' + inst_text_num).style('fill', 'white').attr('width', bbox.width + 20).attr('height', bbox.height).attr('x', -10).attr('y', bbox.y + i * shift_height).style('opacity', box_opacity); + } + }; + +/***/ }, +/* 169 */ +/***/ function(module, exports, __webpack_require__) { + + var demo_text = __webpack_require__(168); + var two_translate_zoom = __webpack_require__(116); + + module.exports = function play_zoom() { + + function run(cgm) { + + var params = cgm.params; + var text = 'Zoom and pan by\nscrolling and dragging'; + demo_text(params, text, 4000); + + setTimeout(two_translate_zoom, 1500, cgm, 0, 0, 4); + } + + function get_duration() { + return 4000; + } + + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 170 */ +/***/ function(module, exports, __webpack_require__) { + + var demo_text = __webpack_require__(168); + var two_translate_zoom = __webpack_require__(116); + var sim_click = __webpack_require__(171); + + module.exports = function play_reset_zoom() { + + function run(cgm) { + + var params = cgm.params; + + var text = 'Reset zoom by double-clicking\n'; + demo_text(params, text, 4000); + + setTimeout(sim_click, 2000, params, 'double', 300, 300); + setTimeout(two_translate_zoom, 2400, cgm, 0, 0, 1); + } + + function get_duration() { + return 4500; + } + + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 171 */ +/***/ function(module, exports) { + + module.exports = function sim_click(params, single_double, pos_x, pos_y) { + + var click_duration = 200; + + var click_circle = d3.select(params.root + ' .viz_svg').append('circle').attr('cx', pos_x).attr('cy', pos_y).attr('r', 25).style('stroke', 'black').style('stroke-width', '3px').style('fill', '#007f00').style('opacity', 0.5); + + if (single_double === 'double') { + click_circle.transition().duration(click_duration).style('opacity', 0.0).transition().duration(50).style('opacity', 0.5).transition().duration(click_duration).style('opacity', 0.0).remove(); + } else { + click_circle.transition().duration(click_duration).style('opacity', 0.0).transition().duration(250).remove(); + } + }; + +/***/ }, +/* 172 */ +/***/ function(module, exports, __webpack_require__) { + + var demo_text = __webpack_require__(168); + var sim_click = __webpack_require__(171); + + module.exports = function play_reorder_row() { + /* eslint-disable */ + + function run(params) { + + var text = 'Reorder the matrix based on a single\nrow or column by double-clicking a\nlabel'; + demo_text(params, text, 7000); + + var inst_element = get_row_element(params, 'EGFR'); + + var group_trans = d3.select(inst_element).attr('transform'); + + var container_trans = d3.select(params.root + ' .clust_container').attr('transform').split(',')[1].replace(')', ''); + + var x_trans = params.viz.norm_labels.width.row * 0.9; + + var row_trans = group_trans.split(',')[1].replace(')', ''); + var y_trans = String(Number(row_trans) + Number(container_trans) + params.viz.rect_height / 2); + + var wait_click = 4000; + setTimeout(sim_click, wait_click, params, 'double', x_trans, y_trans); + var wait_reorder = wait_click + 300; + setTimeout(fire_double_click_row, wait_reorder, params, inst_element); + } + + function get_duration() { + return 8000; + } + + function get_row_element(params, inst_row) { + + var inst_element = d3.selectAll(params.root + ' .row_label_group').filter(function () { + var inst_data = this.__data__; + return inst_data.name == inst_row; + })[0][0]; + + return inst_element; + } + + function fire_double_click_row(params, inst_element) { + + $(inst_element).d3DblClick(); + } + + // allows doubleclicking on d3 element + jQuery.fn.d3DblClick = function () { + this.each(function (i, e) { + var evt = document.createEvent("MouseEvents"); + evt.initMouseEvent("dblclick", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + e.dispatchEvent(evt); + }); + }; + + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 173 */ +/***/ function(module, exports, __webpack_require__) { + + var demo_text = __webpack_require__(168); + var highlight_sidebar_element = __webpack_require__(174); + + module.exports = function play_reorder_buttons() { + /* eslint-disable */ + + function run(params) { + + var text = 'Reorder all rows and columns\nby clicking the reorder\n buttons'; + demo_text(params, text, 9000); + + setTimeout(highlight_sidebar_element, 3000, params, 'toggle_col_order'); + setTimeout(click_reorder_button, 3500, params, 'col', 'rank'); + + setTimeout(highlight_sidebar_element, 7000, params, 'toggle_row_order'); + setTimeout(click_reorder_button, 7500, params, 'row', 'rank'); + } + + function get_duration() { + return 11000; + } + + function click_reorder_button(params, inst_rc, inst_order) { + var inst_button = d3.selectAll('.toggle_' + inst_rc + '_order .btn').filter(function () { + return this.__data__ == inst_order; + })[0]; + + $(inst_button).click(); + } + + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 174 */ +/***/ function(module, exports) { + + module.exports = function highlight_sidebar_element(params, highlight_class, duration = 4000) { + + if (highlight_class.indexOf('slider') < 0) { + d3.select(params.root + ' .' + highlight_class).style('background', '#007f00').style('box-shadow', '0px 0px 10px 5px #007f00').transition().duration(1).delay(duration).style('background', '#FFFFFF').style('box-shadow', 'none'); + } else { + d3.select(params.root + ' .' + highlight_class).style('box-shadow', '0px 0px 10px 5px #007f00').transition().duration(1).delay(duration).style('box-shadow', 'none'); + } + }; + +/***/ }, +/* 175 */ +/***/ function(module, exports, __webpack_require__) { + + var demo_text = __webpack_require__(168); + var highlight_sidebar_element = __webpack_require__(174); + var two_translate_zoom = __webpack_require__(116); + + module.exports = function play_search() { + + function run(cgm) { + + var params = cgm.params; + var text = 'Search for rows using\nthe search box'; + demo_text(params, text, 5000); + + var ini_delay = 2500; + setTimeout(highlight_sidebar_element, ini_delay, params, 'gene_search_container'); + + // manually mimic typing and autocomplete + setTimeout(type_out_search, ini_delay + 1000, params, 'E'); + setTimeout(type_out_search, ini_delay + 1500, params, 'EG'); + setTimeout(type_out_search, ini_delay + 2000, params, 'EGF'); + setTimeout(type_out_search, ini_delay + 2500, params, 'EGFR'); + + setTimeout(run_search, 5500, params); + + setTimeout(two_translate_zoom, 7500, cgm, 0, 0, 1); + } + + function get_duration() { + return 10000; + } + + function type_out_search(params, inst_string) { + $(params.root + ' .gene_search_box').val(inst_string); + $(params.root + ' .gene_search_box').autocomplete("search", inst_string); + } + + function run_search(params) { + $(params.root + ' .submit_gene_button').click(); + $(params.root + ' .gene_search_box').autocomplete("search", ''); + } + + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 176 */ +/***/ function(module, exports, __webpack_require__) { + + var demo_text = __webpack_require__(168); + var highlight_sidebar_element = __webpack_require__(174); + var update_viz_with_view = __webpack_require__(177); + + module.exports = function play_filter() { + + function run(cgm) { + var params = cgm.params; + + var text = 'Filter rows based on sum or\nvariance using the sliders'; + demo_text(params, text, 4000); + + var filter_type = 'N_row_sum'; + + setTimeout(highlight_sidebar_element, 5000, params, 'slider_' + filter_type, 13000); + + text = 'Filter: Top 20 rows by sum'; + setTimeout(demo_text, 5000, params, text, 4000); + setTimeout(run_update, 5300, cgm, filter_type, 20, 1); + + text = 'Filter: Top 10 rows by sum'; + setTimeout(demo_text, 10000, params, text, 4000); + setTimeout(run_update, 10300, cgm, filter_type, 10, 2); + + text = 'Filter: All rows'; + setTimeout(demo_text, 15000, params, text, 4000); + setTimeout(run_update, 15300, cgm, filter_type, 'all', 0); + } + + function get_duration() { + return 19500; + } + + function run_update(cgm, filter_type, filter_value, filter_index) { + + var params = cgm.params; + + var requested_view = {}; + requested_view[filter_type] = filter_value; + update_viz_with_view(cgm, requested_view); + + // quick fix for slider + $(params.root + ' .slider_' + filter_type).slider("value", filter_index); + + var unit_name; + if (filter_type === 'N_row_sum') { + unit_name = 'sum'; + } else { + unit_name = 'variance'; + } + + d3.select(params.root + ' .title_' + filter_type).text('Top rows ' + unit_name + ': ' + filter_value); + } + + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 177 */ +/***/ function(module, exports, __webpack_require__) { + + var make_network_using_view = __webpack_require__(10); + var disable_sidebar = __webpack_require__(178); + var update_viz_with_network = __webpack_require__(179); + + module.exports = function update_viz_with_view(cgm, requested_view) { + + disable_sidebar(cgm.params); + + // make new_network_data by filtering the original network data + var new_network_data = make_network_using_view(cgm.config, cgm.params, requested_view); + + // reset crop button + d3.select(cgm.params.root + ' .crop_button').style('color', '#337ab7').classed('fa-crop', true).classed('fa-undo', false).classed('active_cropping', false); + + // reset dendrogram filtering when updating with a new view + // e.g. with the row filter sliders + _.each(['row', 'col'], function (inst_rc) { + + // set class to reflect that no filtering was ran + d3.select(cgm.params.root + ' .' + inst_rc + '_dendro_icons_group').classed('ran_filter', false); + + // display all crop buttons when cropping has not been done + d3.select(cgm.params.root + ' .' + inst_rc + '_dendro_icons_container').style('display', 'block'); + }); + + update_viz_with_network(cgm, new_network_data); + }; + +/***/ }, +/* 178 */ +/***/ function(module, exports) { + + module.exports = function disable_sidebar(params) { + + d3.selectAll(params.root + ' .btn').attr('disabled', true); + d3.select(params.viz.viz_svg).style('opacity', 0.70); + }; + +/***/ }, +/* 179 */ +/***/ function(module, exports, __webpack_require__) { + + var make_params = __webpack_require__(9); + var define_enter_exit_delays = __webpack_require__(180); + var enter_exit_update = __webpack_require__(181); + var initialize_resizing = __webpack_require__(123); + var make_col_cat = __webpack_require__(152); + var make_row_cat = __webpack_require__(158); + var make_row_dendro = __webpack_require__(159); + var make_col_dendro = __webpack_require__(160); + var ini_sidebar = __webpack_require__(192); + var enable_sidebar = __webpack_require__(194); + var ini_doubleclick = __webpack_require__(133); + var update_reorder_buttons = __webpack_require__(195); + var make_row_cat_super_labels = __webpack_require__(122); + var modify_row_node_cats = __webpack_require__(196); + var run_zoom = __webpack_require__(125); + var ds_enter_exit_update = __webpack_require__(198); + var make_cat_params = __webpack_require__(32); + + module.exports = function update_viz_with_network(cgm, new_network_data) { + + // console.log('UPDATE VIZ WITH NETWORK') + + // set runnning_update class, prevents multiple update from running at once + d3.select(cgm.params.viz.viz_svg).classed('running_update', true); + + // remove downsampled rows always + d3.selectAll(cgm.params.root + ' .ds' + String(cgm.params.viz.ds_level) + '_row').remove(); + + // run optional callback function + // console.log('before and after matrix_update_callback') + // console.log(new_network_data.row_nodes[0]['cat-0']) + if (cgm.params.matrix_update_callback != null) { + cgm.params.matrix_update_callback(); + } + // console.log(new_network_data.row_nodes[0]['cat-0']) + + var inst_group_level = cgm.params.group_level; + var inst_crop_fitler = cgm.params.crop_filter_nodes; + + // make tmp config to make new params + var tmp_config = jQuery.extend(true, {}, cgm.config); + + var new_row_cats = null; + + // bring in 'new' category data + if (cgm.params.new_row_cats != null) { + modify_row_node_cats(cgm.params.new_row_cats, new_network_data.row_nodes); + new_row_cats = cgm.params.new_row_cats; + cgm.params.new_row_cats = new_row_cats; + // do not preserve the updated (row) cats + var predefined_cat_colors = true; + cgm.params.viz = make_cat_params(cgm.params, cgm.params.viz, predefined_cat_colors); + } + + tmp_config.network_data = new_network_data; + tmp_config.inst_order = cgm.params.viz.inst_order; + tmp_config.input_domain = cgm.params.matrix.opacity_scale.domain()[1]; + + update_reorder_buttons(tmp_config, cgm.params); + + // tmp_config.ini_expand = false; + tmp_config.ini_view = null; + tmp_config.current_col_cat = cgm.params.current_col_cat; + + // disabled, causing problems when cropping + // always preserve category colors when updating + tmp_config.cat_colors = cgm.params.viz.cat_colors; + + var new_params = make_params(tmp_config); + + // this function is sensitive to further updates, so run here + var delays = define_enter_exit_delays(cgm.params, new_params); + + // pass the newly calcluated params back to the cgm object + cgm.params = new_params; + + // 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); + }); + + // have persistent group levels while updating + cgm.params.group_level = inst_group_level; + + // have persistent crop_filter_nodes while updating + cgm.params.crop_filter_nodes = inst_crop_fitler; + + // only run enter-exit-updates if there is no downsampling + if (cgm.params.viz.ds_num_levels === 0) { + // new_network_data is necessary + enter_exit_update(cgm, new_network_data, delays); + } else { + ds_enter_exit_update(cgm); + } + + // reduce opacity during update + d3.select(cgm.params.viz.viz_svg).style('opacity', 0.70); + + make_row_cat(cgm); + make_row_cat_super_labels(cgm); + + if (cgm.params.viz.show_categories.col) { + make_col_cat(cgm); + } + + if (cgm.params.viz.show_dendrogram) { + make_row_dendro(cgm); + make_col_dendro(cgm); + } + + initialize_resizing(cgm); + + d3.select(cgm.params.viz.viz_svg).call(cgm.params.zoom_behavior); + + ini_doubleclick(cgm); + + ini_sidebar(cgm); + + cgm.params.viz.run_trans = true; + + // d3.selectAll(cgm.params.viz.root_tips) + // .style('opacity',0); + + setTimeout(enable_sidebar, 2500, cgm.params); + + // remove all dendro shadows + setTimeout(remove_shadows, 50); + setTimeout(remove_shadows, 100); + setTimeout(remove_shadows, 500); + setTimeout(remove_shadows, 1000); + setTimeout(remove_shadows, 1500); + + function remove_shadows() { + d3.selectAll('.dendro_shadow').remove(); + } + + function finish_update() { + d3.select(cgm.params.viz.viz_svg).transition().duration(250).style('opacity', 1.0); + + setTimeout(finish_update_class, 1000); + } + + setTimeout(finish_update, delays.enter); + + function finish_update_class() { + d3.select(cgm.params.viz.viz_svg).classed('running_update', false); + } + }; + +/***/ }, +/* 180 */ +/***/ function(module, exports) { + + module.exports = function (old_params, params) { + + // exit, update, enter + + // check if exit or enter or both are required + var old_row_nodes = old_params.network_data.row_nodes; + var old_col_nodes = old_params.network_data.col_nodes; + var old_row = _.map(old_row_nodes, function (d) { + return d.name; + }); + var old_col = _.map(old_col_nodes, function (d) { + return d.name; + }); + var all_old_nodes = old_row.concat(old_col); + + var row_nodes = params.network_data.row_nodes; + var col_nodes = params.network_data.col_nodes; + var row = _.map(row_nodes, function (d) { + return d.name; + }); + var col = _.map(col_nodes, function (d) { + return d.name; + }); + var all_nodes = row.concat(col); + + var exit_nodes = _.difference(all_old_nodes, all_nodes).length; + var enter_nodes = _.difference(all_nodes, all_old_nodes).length; + + var delays = {}; + + if (exit_nodes > 0) { + delays.update = 1000; + } else { + delays.update = 0; + } + + if (enter_nodes > 0) { + delays.enter = 1000; + } else { + delays.enter = 0; + } + + delays.enter = delays.enter + delays.update; + + delays.run_transition = true; + + var old_num_links = old_params.network_data.links.length; + var new_num_links = params.network_data.links.length; + var cutoff_num_links = 0.5 * params.matrix.def_large_matrix; + + if (old_num_links > cutoff_num_links || new_num_links > cutoff_num_links) { + delays.run_transition = false; + delays.update = 0; + delays.enter = 0; + } + + return delays; + }; + +/***/ }, +/* 181 */ +/***/ function(module, exports, __webpack_require__) { + + var reset_size_after_update = __webpack_require__(182); + var make_row_label_container = __webpack_require__(49); + var make_col_label_container = __webpack_require__(103); + var eeu_existing_row = __webpack_require__(183); + var exit_components = __webpack_require__(187); + var draw_gridlines = __webpack_require__(39); + var enter_row_groups = __webpack_require__(188); + var resize_containers = __webpack_require__(191); + var label_constrain_and_trim = __webpack_require__(117); + var d3_tip_custom = __webpack_require__(48); + + module.exports = function enter_exit_update(cgm, network_data, delays) { + + var params = cgm.params; + + // remove old tooltips + d3.selectAll(params.viz.root_tips).remove(); + + // d3-tooltip - for tiles + var tip = d3_tip_custom().attr('class', function () { + var root_tip_selector = params.viz.root_tips.replace('.', ''); + var class_string = root_tip_selector + ' d3-tip ' + root_tip_selector + '_tile_tip'; + return class_string; + }).direction('nw').offset([0, 0]).style('display', 'none').html(function (d) { + var inst_value = String(d.value.toFixed(3)); + var tooltip_string; + + if (params.keep_orig) { + var orig_value = String(d.value_orig.toFixed(3)); + tooltip_string = '<p>' + d.row_name + ' and ' + d.col_name + '</p>' + '<p> normalized value: ' + inst_value + '</p>' + '<div> original value: ' + orig_value + '</div>'; + } else { + tooltip_string = '<p>' + d.row_name + ' and ' + d.col_name + '</p>' + '<div> value: ' + inst_value + '</div>'; + } + + return tooltip_string; + }); + + d3.select(params.root + ' .clust_group').call(tip); + + // necessary for repositioning clust, col and col-cat containers + resize_containers(params); + + var duration = 1000; + + // make global so that names can be accessed + var row_nodes = network_data.row_nodes; + var col_nodes = network_data.col_nodes; + var links = network_data.links; + + // + var tile_data = links; + + // add name to links for object constancy + for (var i = 0; i < tile_data.length; i++) { + var d = tile_data[i]; + tile_data[i].name = row_nodes[d.source].name + '_' + col_nodes[d.target].name; + } + + // move rows + var move_rows = d3.select(params.root + ' .clust_group').selectAll('.row').data(params.matrix.matrix, function (d) { + return d.name; + }); + + if (delays.run_transition) { + move_rows.transition().delay(delays.update).duration(duration).attr('transform', function (d) { + var tmp_index = d.row_index; + return 'translate(0,' + params.viz.y_scale(tmp_index) + ')'; + }); + } else { + move_rows.attr('transform', function (d) { + var tmp_index = d.row_index; + return 'translate(0,' + params.viz.y_scale(tmp_index) + ')'; + }); + } + + // update existing rows - enter, exit, update tiles in existing row + d3.select(params.root + ' .clust_group').selectAll('.row').each(function (d) { + // TODO add tip back to arguments + var inst_selection = this; + eeu_existing_row(params, d, delays, duration, inst_selection, tip); + }); + + d3.selectAll(params.root + ' .horz_lines').remove(); + d3.selectAll(params.root + ' .vert_lines').remove(); + + // exit + //////////// + exit_components(params, delays, duration); + + // resize clust components using appropriate delays + reset_size_after_update(cgm, duration, delays); + + // enter new elements + ////////////////////////// + enter_row_groups(params, delays, duration, tip); + + // update existing rows + make_row_label_container(cgm, duration); + make_col_label_container(cgm, duration); + + draw_gridlines(params, delays, duration); + + setTimeout(label_constrain_and_trim, 2000, params); + }; + +/***/ }, +/* 182 */ +/***/ function(module, exports, __webpack_require__) { + + var utils = __webpack_require__(2); + var calc_clust_height = __webpack_require__(22); + var get_svg_dim = __webpack_require__(19); + var calc_clust_width = __webpack_require__(21); + var reset_zoom = __webpack_require__(134); + var resize_dendro = __webpack_require__(135); + var resize_super_labels = __webpack_require__(136); + var resize_spillover = __webpack_require__(137); + var resize_row_labels = __webpack_require__(139); + var resize_row_viz = __webpack_require__(141); + var resize_col_labels = __webpack_require__(142); + var resize_col_text = __webpack_require__(143); + var resize_col_triangle = __webpack_require__(144); + var resize_col_hlight = __webpack_require__(145); + var resize_label_bars = __webpack_require__(148); + var calc_default_fs = __webpack_require__(31); + var calc_zoom_switching = __webpack_require__(30); + // var show_visible_area = require('../zoom/show_visible_area'); + var ini_zoom_info = __webpack_require__(36); + + module.exports = function reset_size_after_update(cgm, duration = 0, delays = null) { + + if (delays === null) { + delays = {}; + delays.enter = 0; + delays.update = 0; + delays.run_transition = false; + } + + var params = cgm.params; + + var row_nodes = cgm.params.network_data.row_nodes; + + params.zoom_info = ini_zoom_info(); + + // // not sure if this is necessary + // //////////////////////////// + // show_visible_area(params); + // // quick fix for column filtering + // setTimeout(show_visible_area, 2200, cgm); + + var row_nodes_names = params.network_data.row_nodes_names; + + reset_zoom(params); + + // Resetting some visualization parameters + params = get_svg_dim(params); + params.viz = calc_clust_width(params.viz); + params.viz = calc_clust_height(params.viz); + + if (params.sim_mat) { + if (params.viz.clust.dim.width <= params.viz.clust.dim.height) { + params.viz.clust.dim.height = params.viz.clust.dim.width; + } else { + params.viz.clust.dim.width = params.viz.clust.dim.height; + } + } + + params.viz = calc_zoom_switching(params.viz); + + // redefine x_scale and y_scale rangeBands + params.viz.x_scale.rangeBands([0, params.viz.clust.dim.width]); + params.viz.y_scale.rangeBands([0, params.viz.clust.dim.height]); + + // redefine zoom extent + params.viz.square_zoom = params.viz.norm_labels.width.col / (params.viz.x_scale.rangeBand() / 2); + params.zoom_behavior.scaleExtent([1, params.viz.square_zoom * params.viz.zoom_ratio.x]); + + // redefine border width + params.viz.border_width.x = params.viz.x_scale.rangeBand() / params.viz.border_fraction; + params.viz.border_width.y = params.viz.y_scale.rangeBand() / params.viz.border_fraction; + + params = calc_default_fs(params); + + // resize the svg + /////////////////////// + var svg_group = d3.select(params.viz.viz_wrapper).select('svg'); + + svg_group.select(params.root + ' .grey_background').transition().delay(delays.update).duration(duration).attr('width', params.viz.clust.dim.width).attr('height', params.viz.clust.dim.height); + + resize_row_labels(params, svg_group, delays); + + // do not delay the font size change since this will break the bounding box calc + svg_group.selectAll('.row_label_group').select('text').style('font-size', params.labels.default_fs_row + 'px').text(function (d) { + return utils.normal_name(d); + }); + + // change the size of the highlighting rects + svg_group.selectAll('.row_label_group').each(function () { + var bbox = d3.select(this).select('text')[0][0].getBBox(); + d3.select(this).select('rect').attr('x', bbox.x).attr('y', 0).attr('width', bbox.width).attr('height', params.viz.y_scale.rangeBand()).style('fill', 'yellow').style('opacity', function (d) { + var inst_opacity = 0; + // highlight target genes + if (d.target === 1) { + inst_opacity = 1; + } + return inst_opacity; + }); + }); + + resize_row_viz(params, svg_group, delays); + + if (delays.run_transition) { + + // positioning row text after row text size may have been reduced + svg_group.selectAll('.row_label_group').select('text').transition().delay(delays.update).duration(duration).attr('y', params.viz.rect_height * 0.5 + params.labels.default_fs_row * 0.35); + + svg_group.selectAll('.row_cat_group').data(row_nodes, function (d) { + return d.name; + }).transition().delay(delays.update).duration(duration).attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0, ' + params.viz.y_scale(inst_index) + ')'; + }); + + svg_group.selectAll('.row_cat_group').select('path').transition().delay(delays.update).duration(duration).attr('d', function () { + var origin_x = params.viz.cat_room.symbol_width - 1; + var origin_y = 0; + var mid_x = 1; + var mid_y = params.viz.y_scale.rangeBand() / 2; + var final_x = params.viz.cat_room.symbol_width - 1; + var final_y = params.viz.y_scale.rangeBand(); + var output_string = 'M ' + origin_x + ',' + origin_y + ' L ' + mid_x + ',' + mid_y + ', L ' + final_x + ',' + final_y + ' Z'; + return output_string; + }); + + svg_group.selectAll('.row_dendro_group').data(row_nodes, function (d) { + return d.name; + }).transition().delay(delays.update).duration(duration).attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0, ' + params.viz.y_scale(inst_index) + ')'; + }); + } else { + + // positioning row text after row text size may have been reduced + svg_group.selectAll('.row_label_group').select('text').attr('y', params.viz.rect_height * 0.5 + params.labels.default_fs_row * 0.35); + + svg_group.selectAll('.row_cat_group').data(row_nodes, function (d) { + return d.name; + }).attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0, ' + params.viz.y_scale(inst_index) + ')'; + }); + + svg_group.selectAll('.row_cat_group').select('path').attr('d', function () { + var origin_x = params.viz.cat_room.symbol_width - 1; + var origin_y = 0; + var mid_x = 1; + var mid_y = params.viz.y_scale.rangeBand() / 2; + var final_x = params.viz.cat_room.symbol_width - 1; + var final_y = params.viz.y_scale.rangeBand(); + var output_string = 'M ' + origin_x + ',' + origin_y + ' L ' + mid_x + ',' + mid_y + ', L ' + final_x + ',' + final_y + ' Z'; + return output_string; + }); + + svg_group.selectAll('.row_dendro_group').data(row_nodes, function (d) { + return d.name; + }).attr('transform', function (d) { + var inst_index = _.indexOf(row_nodes_names, d.name); + return 'translate(0, ' + params.viz.y_scale(inst_index) + ')'; + }); + } + + if (utils.has(params.network_data.row_nodes[0], 'value')) { + + resize_label_bars(cgm, svg_group); + } + + // resize col labels + /////////////////////// + // reduce width of rotated rects + + resize_col_labels(params, svg_group, delays); + resize_col_text(params, svg_group); + resize_col_triangle(params, svg_group, delays); + + resize_col_hlight(params, svg_group, delays); + + resize_dendro(params, svg_group, delays); + resize_super_labels(params, svg_group, delays); + resize_spillover(params.viz, svg_group, delays); + + // reset zoom and translate + params.zoom_behavior.scale(1).translate([params.viz.clust.margin.left, params.viz.clust.margin.top]); + }; + +/***/ }, +/* 183 */ +/***/ function(module, exports, __webpack_require__) { + + var exit_existing_row = __webpack_require__(184); + var enter_existing_row = __webpack_require__(185); + var update_split_tiles = __webpack_require__(186); + var mouseover_tile = __webpack_require__(45); + var mouseout_tile = __webpack_require__(46); + var fine_position_tile = __webpack_require__(47); + + // TODO add tip back to arguments + module.exports = function eeu_existing_row(params, ini_inp_row_data, delays, duration, row_selection, tip) { + + var inp_row_data = ini_inp_row_data.row_data; + + // remove zero values from + var row_values = _.filter(inp_row_data, function (num) { + return num.value != 0; + }); + + // bind data to tiles + var cur_row_tiles = d3.select(row_selection).selectAll('.tile').data(row_values, function (d) { + return d.col_name; + }); + + exit_existing_row(params, delays, cur_row_tiles, inp_row_data, row_selection); + + /////////////////////////// + // Update + /////////////////////////// + + // update tiles in x direction + var update_row_tiles = cur_row_tiles.on('mouseover', function (...args) { + mouseover_tile(params, this, tip, args); + }).on('mouseout', function mouseout() { + mouseout_tile(params, this, tip); + }); + + var col_nodes_names = params.network_data.col_nodes_names; + + if (delays.run_transition) { + + update_row_tiles.transition().delay(delays.update).duration(duration).attr('width', params.viz.rect_width).attr('height', params.viz.rect_height).attr('transform', function (d) { + if (_.contains(col_nodes_names, d.col_name)) { + return fine_position_tile(params, d); + } else { + return 'translate(0,0)'; + } + }); + } else { + update_row_tiles.attr('width', params.viz.rect_width).attr('height', params.viz.rect_height).attr('transform', function (d) { + if (_.contains(col_nodes_names, d.col_name)) { + return fine_position_tile(params, d); + } else { + return 'translate(0,0)'; + } + }); + } + + if (params.matrix.tile_type == 'updn') { + update_split_tiles(params, inp_row_data, row_selection, delays, duration, cur_row_tiles, tip); + } + + enter_existing_row(params, delays, duration, cur_row_tiles, tip); + }; + +/***/ }, +/* 184 */ +/***/ function(module, exports) { + + module.exports = function exit_existing_row(params, delays, cur_row_tiles, inp_row_data, row_selection) { + + if (delays.run_transition) { + cur_row_tiles.exit().transition().duration(300).attr('fill-opacity', 0).remove(); + } else { + cur_row_tiles.exit().attr('fill-opacity', 0).remove(); + } + + if (params.matrix.tile_type == 'updn') { + + // value split + var row_split_data = _.filter(inp_row_data, function (num) { + return num.value_up != 0 || num.value_dn != 0; + }); + + // tile_up + var cur_tiles_up = d3.select(row_selection).selectAll('.tile_up').data(row_split_data, function (d) { + return d.col_name; + }); + + if (delays.run_transition) { + cur_tiles_up.exit().transition().duration(300).attr('fill', '0').remove(); + } else { + cur_tiles_up.exit().attr('fill', 0).remove(); + } + + // tile_dn + var cur_tiles_dn = d3.select(row_selection).selectAll('.tile_dn').data(row_split_data, function (d) { + return d.col_name; + }); + + if (delays.run_transition) { + cur_tiles_dn.exit().transition().duration(300).attr('fill', 0).remove(); + } else { + cur_tiles_dn.exit().attr('fill', 0).remove(); + } + } + }; + +/***/ }, +/* 185 */ +/***/ function(module, exports, __webpack_require__) { + + var mouseover_tile = __webpack_require__(45); + var mouseout_tile = __webpack_require__(46); + var fine_position_tile = __webpack_require__(47); + + module.exports = function enter_existing_row(params, delays, duration, cur_row_tiles, tip) { + + // enter new tiles + var new_tiles = cur_row_tiles.enter().append('rect').attr('class', 'tile row_tile').attr('width', params.viz.rect_width).attr('height', params.viz.rect_height).on('mouseover', function (...args) { + mouseover_tile(params, this, tip, args); + }).on('mouseout', function mouseout() { + mouseout_tile(params, this, tip); + }).attr('fill-opacity', 0).attr('transform', function (d) { + return fine_position_tile(params, d); + }); + + if (delays.run_transition) { + new_tiles.transition().delay(delays.enter).duration(duration).style('fill', function (d) { + return d.value > params.matrix.mid_val ? params.matrix.tile_colors[0] : params.matrix.tile_colors[1]; + }).attr('fill-opacity', function (d) { + var op_val = 0, output_opacity = 0; + op_val = params.matrix.mid_val + Math.abs(d.value - params.matrix.mid_val); + output_opacity = params.matrix.opacity_scale(op_val); + return output_opacity; + }); + } else { + new_tiles.style('fill', function (d) { + return d.value > params.matrix.mid_val ? params.matrix.tile_colors[0] : params.matrix.tile_colors[1]; + }).attr('fill-opacity', function (d) { + var op_val = 0, output_opacity = 0; + op_val = params.matrix.mid_val + Math.abs(d.value - params.matrix.mid_val); + output_opacity = params.matrix.opacity_scale(Math.abs(op_val)); + return output_opacity; + }); + } + + // remove new tiles if necessary + new_tiles.each(function (d) { + if (Math.abs(d.value_up) > 0 && Math.abs(d.value_dn) > 0) { + d3.select(this).remove(); + } + }); + }; + +/***/ }, +/* 186 */ +/***/ function(module, exports, __webpack_require__) { + + var draw_up_tile = __webpack_require__(43); + var draw_dn_tile = __webpack_require__(44); + var mouseover_tile = __webpack_require__(45); + var mouseout_tile = __webpack_require__(46); + var fine_position_tile = __webpack_require__(47); + + module.exports = function update_split_tiles(params, inp_row_data, row_selection, delays, duration, cur_row_tiles, tip) { + + // value split + var row_split_data = _.filter(inp_row_data, function (num) { + return num.value_up != 0 || num.value_dn != 0; + }); + + // tile_up + var cur_tiles_up = d3.select(row_selection).selectAll('.tile_up').data(row_split_data, function (d) { + return d.col_name; + }); + + // update split tiles_up + var update_tiles_up = cur_tiles_up.on('mouseover', function (...args) { + mouseover_tile(params, this, tip, args); + }).on('mouseout', function mouseout() { + mouseout_tile(params, this, tip); + }); + + if (delays.run_transition) { + update_tiles_up.transition().delay(delays.update).duration(duration).attr('d', function () { + return draw_up_tile(params); + }).attr('transform', function (d) { + return fine_position_tile(params, d); + }); + } else { + update_tiles_up.attr('d', function () { + return draw_up_tile(params); + }).attr('transform', function (d) { + return fine_position_tile(params, d); + }); + } + + // tile_dn + var cur_tiles_dn = d3.select(row_selection).selectAll('.tile_dn').data(row_split_data, function (d) { + return d.col_name; + }); + + // update split tiles_dn + var update_tiles_dn = cur_tiles_dn.on('mouseover', function (...args) { + mouseover_tile(params, this, tip, args); + }).on('mouseout', function mouseout() { + mouseout_tile(params, this, tip); + }); + + if (delays.run_transition) { + update_tiles_dn.transition().delay(delays.update).duration(duration).attr('d', function () { + return draw_dn_tile(params); + }).attr('transform', function (d) { + return fine_position_tile(params, d); + }); + } else { + update_tiles_dn.attr('d', function () { + return draw_dn_tile(params); + }).attr('transform', function (d) { + return fine_position_tile(params, d); + }); + } + + // remove tiles when splitting is done + cur_row_tiles.selectAll('.tile').each(function (d) { + if (Math.abs(d.value_up) > 0 && Math.abs(d.value_dn) > 0) { + d3.select(this).remove(); + } + }); + }; + +/***/ }, +/* 187 */ +/***/ function(module, exports) { + + module.exports = function exit_components(params, delays, duration) { + + var row_nodes = params.network_data.row_nodes; + var col_nodes = params.network_data.col_nodes; + + // remove entire rows + var exiting_rows = d3.select(params.root + ' .clust_group').selectAll('.row').data(params.matrix.matrix, function (d) { + return d.name; + }).exit(); + + if (delays.run_transition) { + exiting_rows.transition().duration(duration).style('opacity', 0).remove(); + } else { + exiting_rows.style('opacity', 0).remove(); + } + + // remove row labels + d3.selectAll(params.root + ' .row_label_group').data(row_nodes, function (d) { + return d.name; + }).exit().transition().duration(duration).style('opacity', 0).remove(); + + // remove column labels + d3.selectAll(params.root + ' .col_label_group').data(col_nodes, function (d) { + return d.name; + }).exit().transition().duration(duration).style('opacity', 0).remove(); + + // remove row triangles and colorbars + d3.selectAll(params.root + ' .row_cat_group').data(row_nodes, function (d) { + return d.name; + }).exit().transition().duration(duration).style('opacity', 0).remove(); + + // remove row triangles and colorbars + d3.selectAll(params.root + ' .row_dendro_group').data(row_nodes, function (d) { + return d.name; + }).exit().transition().duration(duration).style('opacity', 0).remove(); + + d3.selectAll(params.root + ' .col_label_text').data(col_nodes, function (d) { + return d.name; + }).exit().transition().duration(duration).style('opacity', 0).remove(); + + d3.selectAll(params.root + ' .horz_lines').data(row_nodes, function (d) { + return d.name; + }).exit().transition().duration(duration).style('opacity', 0).remove(); + + d3.selectAll(params.root + ' .vert_lines').data(col_nodes, function (d) { + return d.name; + }).exit().transition().duration(duration).style('opacity', 0).remove(); + + // remove dendrogram + d3.selectAll(params.root + ' .col_cat_group').data(col_nodes, function (d) { + return d.name; + }).exit().transition().duration(duration).style('opacity', 0).remove(); + + d3.selectAll(params.root + ' .col_dendro_group').data(col_nodes, function (d) { + return d.name; + }).exit().transition().duration(duration).style('opacity', 0).remove(); + }; + +/***/ }, +/* 188 */ +/***/ function(module, exports, __webpack_require__) { + + var enter_new_rows = __webpack_require__(189); + + module.exports = function enter_row_groups(params, delays, duration, tip) { + + // enter new rows + var new_row_groups = d3.select(params.root + ' .clust_group').selectAll('.row').data(params.matrix.matrix, function (d) { + return d.name; + }).enter().append('g').classed('row', true).attr('transform', function (d) { + return 'translate(0,' + params.viz.y_scale(d.row_index) + ')'; + }); + + new_row_groups.each(function (d) { + enter_new_rows(params, d, delays, duration, tip, this); + }); + }; + +/***/ }, +/* 189 */ +/***/ function(module, exports, __webpack_require__) { + + var enter_split_tiles = __webpack_require__(190); + var mouseover_tile = __webpack_require__(45); + var mouseout_tile = __webpack_require__(46); + var fine_position_tile = __webpack_require__(47); + + // make each row in the clustergram + module.exports = function enter_new_rows(params, ini_inp_row_data, delays, duration, tip, row_selection) { + + var inp_row_data = ini_inp_row_data.row_data; + + // remove zero values to make visualization faster + var row_data = _.filter(inp_row_data, function (num) { + return num.value !== 0; + }); + + // update tiles + //////////////////////////////////////////// + var tile = d3.select(row_selection).selectAll('rect').data(row_data, function (d) { + return d.col_name; + }).enter().append('rect').attr('class', 'tile row_tile').attr('width', params.viz.rect_width).attr('height', params.viz.rect_height) + // switch the color based on up/dn value + .style('fill', function (d) { + return d.value > params.matrix.mid_val ? params.matrix.tile_colors[0] : params.matrix.tile_colors[1]; + }).on('mouseover', function (...args) { + mouseover_tile(params, this, tip, args); + }).on('mouseout', function mouseout() { + mouseout_tile(params, this, tip); + }); + + tile.style('fill-opacity', 0).transition().delay(delays.enter).duration(duration).style('fill-opacity', function (d) { + // calculate output opacity using the opacity scale + var op_val = 0, output_opacity = 0; + op_val = params.matrix.mid_val + Math.abs(d.value - params.matrix.mid_val); + output_opacity = params.matrix.opacity_scale(Math.abs(op_val)); + return output_opacity; + }); + + tile.attr('transform', function (d) { + return fine_position_tile(params, d); + }); + + if (params.matrix.tile_type == 'updn') { + enter_split_tiles(params, inp_row_data, row_selection, tip, delays, duration, tile); + } + }; + +/***/ }, +/* 190 */ +/***/ function(module, exports, __webpack_require__) { + + var draw_up_tile = __webpack_require__(43); + var draw_dn_tile = __webpack_require__(44); + var fine_position_tile = __webpack_require__(47); + + module.exports = function enter_split_tiles(params, inp_row_data, row_selection, tip, delays, duration, tile) { + + // value split + var row_split_data = _.filter(inp_row_data, function (num) { + return num.value_up != 0 || num.value_dn != 0; + }); + + // tile_up + var new_tiles_up = d3.select(row_selection).selectAll('.tile_up').data(row_split_data, function (d) { + return d.col_name; + }).enter().append('path').attr('class', 'tile_up').attr('d', function () { + return draw_up_tile(params); + }).attr('transform', function (d) { + return fine_position_tile(params, d); + }).style('fill', function () { + return params.matrix.tile_colors[0]; + }).on('mouseover', function (p) { + // highlight row - set text to active if + d3.selectAll(params.root + ' .row_label_group text').classed('active', function (d) { + return p.row_name === d.name; + }); + + d3.selectAll(params.root + ' .col_label_text text').classed('active', function (d) { + return p.col_name === d.name; + }); + if (params.matrix.show_tile_tooltips) { + tip.show(p); + } + }).on('mouseout', function () { + d3.selectAll(params.root + ' text').classed('active', false); + if (params.matrix.show_tile_tooltips) { + tip.hide(); + } + }); + + new_tiles_up.style('fill-opacity', 0).transition().delay(delays.enter).duration(duration).style('fill-opacity', function (d) { + var inst_opacity = 0; + if (Math.abs(d.value_dn) > 0) { + var op_val = params.matrix.mid_val + Math.abs(d.value_up - params.matrix.mid_val); + inst_opacity = params.matrix.opacity_scale(op_val); + } + return inst_opacity; + }); + + // tile_dn + var new_tiles_dn = d3.select(row_selection).selectAll('.tile_dn').data(row_split_data, function (d) { + return d.col_name; + }).enter().append('path').attr('class', 'tile_dn').attr('d', function () { + return draw_dn_tile(params); + }).attr('transform', function (d) { + return fine_position_tile(params, d); + }).style('fill', function () { + return params.matrix.tile_colors[1]; + }).on('mouseover', function (p) { + // highlight row - set text to active if + d3.selectAll(params.root + ' .row_label_group text').classed('active', function (d) { + return p.row_name === d.name; + }); + + d3.selectAll(params.root + ' .col_label_text text').classed('active', function (d) { + return p.col_name === d.name; + }); + if (params.matrix.show_tile_tooltips) { + tip.show(p); + } + }).on('mouseout', function () { + d3.selectAll(params.root + ' text').classed('active', false); + if (params.matrix.show_tile_tooltips) { + tip.hide(); + } + }); + + new_tiles_dn.style('fill-opacity', 0).transition().delay(delays.enter).duration(duration).style('fill-opacity', function (d) { + var inst_opacity = 0; + if (Math.abs(d.value_up) > 0) { + var op_val = params.matrix.mid_val + Math.abs(d.value_dn - params.matrix.mid_val); + inst_opacity = params.matrix.opacity_scale(op_val); + } + return inst_opacity; + }); + + // remove tiles when splitting is done + tile.each(function (d) { + if (Math.abs(d.value_up) > 0 && Math.abs(d.value_dn) > 0) { + d3.select(this).remove(); + } + }); + }; + +/***/ }, +/* 191 */ +/***/ function(module, exports) { + + module.exports = function resize_containers(params) { + + // reposition matrix + d3.select(params.root + ' .clust_container').attr('transform', 'translate(' + params.viz.clust.margin.left + ',' + params.viz.clust.margin.top + ')'); + + // reposition col container + d3.select(params.root + ' .col_label_outer_container').attr('transform', 'translate(0,' + params.viz.norm_labels.width.col + ')'); + + // reposition col_viz container + d3.select(params.root + ' .col_cat_outer_container').attr('transform', function () { + var inst_offset = params.viz.norm_labels.width.col + 2; + return 'translate(0,' + inst_offset + ')'; + }); + }; + +/***/ }, +/* 192 */ +/***/ function(module, exports, __webpack_require__) { + + /* eslint-disable */ + + var change_groups = __webpack_require__(163); + var all_reorder = __webpack_require__(115); + var ini_cat_reorder = __webpack_require__(114); + var run_row_search = __webpack_require__(193); + + module.exports = function ini_sidebar(cgm) { + + var params = cgm.params; + + var input = d3.select(params.root + ' .gene_search_box')[0][0]; + var awesomplete = new Awesomplete(input, { minChars: 1, maxItems: 15 }); + var entities = cgm.params.network_data.row_nodes_names; + awesomplete.list = entities; + + // position awesomplete list elements above other elements in the page + d3.selectAll('.awesomplete ul').style('z-index', 99); + + // submit genes button + $(params.root + ' .gene_search_box').keyup(function (e) { + if (e.keyCode === 13) { + var search_gene = $(params.root + ' .gene_search_box').val(); + run_row_search(cgm, search_gene, entities); + } + }); + + $(params.root + ' .submit_gene_button').off().click(function () { + var search_gene = $(params.root + ' .gene_search_box').val(); + run_row_search(cgm, search_gene, entities); + }); + + var reorder_types; + if (params.sim_mat) { + reorder_types = ['both']; + } else { + reorder_types = ['row', 'col']; + } + + _.each(reorder_types, function (inst_rc) { + + // reorder buttons + $(params.root + ' .toggle_' + inst_rc + '_order .btn').off().click(function (evt) { + + var order_id = $(evt.target).attr('name').replace('_row', '').replace('_col', ''); + + d3.selectAll(params.root + ' .toggle_' + inst_rc + '_order .btn').classed('active', false); + + d3.select(this).classed('active', true); + + if (inst_rc != 'both') { + all_reorder(cgm, order_id, inst_rc); + } else { + all_reorder(cgm, order_id, 'row'); + all_reorder(cgm, order_id, 'col'); + } + }); + }); + + ini_cat_reorder(cgm); + + // Opacity Slider + ////////////////////////////////////////////////////////////////////// + if (d3.select(cgm.params.root + ' .opacity_slider').select('#handle-one').empty()) { + + var slider_fun = d3.slider().snap(true).value(1).min(0.1).max(1.9).step(0.1).on('slide', function (evt, value) { + run_on_opacity_slide(evt, value); + }); + + d3.select(cgm.params.root + ' .opacity_slider').call(slider_fun); + } + + function run_on_dendro_slide(evt, value, inst_rc) { + $("#amount").val("$" + value); + var inst_index = value * 10; + // var inst_rc; + + if (inst_rc != 'both') { + change_groups(cgm, inst_rc, inst_index); + } else { + change_groups(cgm, 'row', inst_index); + change_groups(cgm, 'col', inst_index); + } + } + + function run_on_opacity_slide(evt, value) { + + var inst_index = 2 - value; + var scaled_max = cgm.params.matrix.abs_max_val * inst_index; + + cgm.params.matrix.opacity_scale.domain([0, scaled_max]); + + d3.selectAll(cgm.params.root + ' .tile').style('fill-opacity', function (d) { + // calculate output opacity using the opacity scale + var op_val = 0, output_opacity = 0; + op_val = cgm.params.matrix.mid_val + Math.abs(d.value - cgm.params.matrix.mid_val); + var output_opacity = cgm.params.matrix.opacity_scale(op_val); + return output_opacity; + }); + } + }; + +/***/ }, +/* 193 */ +/***/ function(module, exports, __webpack_require__) { + + var two_translate_zoom = __webpack_require__(116); + + module.exports = function run_row_search(cgm, search_term, entities) { + + var prop = 'name'; + + if (entities.indexOf(search_term) !== -1) { + + // unhighlight + d3.selectAll(cgm.params.root + ' .row_label_group').select('rect').style('opacity', 0); + + // calc pan_dy + var idx = _.indexOf(entities, search_term); + var inst_y_pos = cgm.params.viz.y_scale(idx); + var pan_dy = cgm.params.viz.clust.dim.height / 2 - inst_y_pos; + + var inst_zoom = cgm.params.viz.zoom_ratio.x; + + // working on improving zoom behavior + /////////////////////////////////////////////////// + /////////////////////////////////////////////////// + + // // increase zoom + // inst_zoom = 3 * inst_zoom; + + // // move visualization down less + // pan_dy = pan_dy - 5; + + two_translate_zoom(cgm, 0, pan_dy, inst_zoom); + + // set y zoom to zoom_switch + cgm.params.zoom_info.zoom_y = inst_zoom; + + // highlight + d3.selectAll(cgm.params.root + ' .row_label_group').filter(function (d) { + return d[prop] === search_term; + }).select('rect').style('opacity', 1); + } + }; + +/***/ }, +/* 194 */ +/***/ function(module, exports) { + + module.exports = function enable_sidebar(params) { + + /* only enable dendrogram sliders if there has been no dendro_filtering */ + + // only enable reordering if params.dendro_filter.row === false + if (params.dendro_filter.row === false) { + + // orders are switched! + if (params.viz.inst_order.col === 'clust') { + d3.select(params.root + ' .row_slider_group').style('opacity', 1).style('pointer-events', 'all'); + } + } + + d3.selectAll(params.root + ' .toggle_row_order .btn').attr('disabled', null); + + if (params.dendro_filter.col === false) { + + // orders are switched! + if (params.viz.inst_order.row === 'clust') { + d3.select(params.root + ' .col_slider_group').style('opacity', 1).style('pointer-events', 'all'); + } + } + + d3.selectAll(params.root + ' .toggle_col_order .btn').attr('disabled', null); + + d3.selectAll(params.root + ' .gene_search_button .btn').attr('disabled', null); + + params.viz.run_trans = false; + }; + +/***/ }, +/* 195 */ +/***/ function(module, exports) { + + module.exports = function update_reorder_buttons(tmp_config, params) { + _.each(['row', 'col'], function (inst_rc) { + + var other_rc; + if (inst_rc === 'row') { + other_rc = 'col'; + } else { + other_rc = 'row'; + } + + d3.selectAll(params.root + ' .toggle_' + other_rc + '_order .btn').filter(function () { + return d3.select(this).attr('name') === tmp_config.inst_order[inst_rc]; + }).classed('active', true); + }); + }; + +/***/ }, +/* 196 */ +/***/ function(module, exports, __webpack_require__) { + + var remove_node_cats = __webpack_require__(197); + var utils = __webpack_require__(2); + + module.exports = function modify_row_node_cats(cat_data, inst_nodes, strip_names = false) { + + // console.log('MODIFY ROW NODE CATS') + // console.log('CAT_DATA') + // console.log(cat_data) + + var cat_type_num = 0; + var inst_index = 0; + var inst_cat_title; + var inst_cats; + var inst_members; + var inst_name; + var inst_category; + var inst_cat_name; + var inst_full_cat; + var inst_cat_num; + + // loop through row nodes + ////////////////////////// + _.each(inst_nodes, function (inst_node) { + + inst_name = inst_node.name; + + // not sure if this is needed + // inst_name = inst_name.toUpperCase(); + + if (strip_names === true) { + // only consider first part of inst_name + //////////////////////////////////////////// + // may improve this + if (inst_name.indexOf(' ')) { + inst_name = inst_name.split(' ')[0]; + } else if (inst_name.indexOf('_')) { + inst_name = inst_name.split('_')[0]; + } + } + + cat_type_num = 0; + + remove_node_cats(inst_node); + + // loop through each category type + _.each(cat_data, function (inst_cat_data) { + + inst_cat_title = inst_cat_data.cat_title; + inst_cats = inst_cat_data.cats; + + // initialize with no category + inst_category = 'false'; + inst_index = -1; + + inst_cat_num = 0; + + // loop through each category in the category-type + _.each(inst_cats, function (inst_cat) { + + inst_cat_name = inst_cat.cat_name; + inst_members = inst_cat.members; + + // add category if node is a member + if (_.contains(inst_members, inst_name)) { + + inst_category = inst_cat_name; + inst_index = inst_cat_num; + } + + inst_cat_num = inst_cat_num + 1; + }); + + if (utils.has(inst_cat_data, 'pval')) { + + var inst_pval = inst_cat_data.pval.toExponential(); + inst_full_cat = inst_cat_title + ': ' + inst_category + '<p> Pval ' + String(inst_pval) + '</p>'; + } else { + + if (inst_cat_title.indexOf('cat-') === -1) { + inst_full_cat = inst_cat_title + ': ' + inst_category; + } else { + inst_full_cat = inst_category; + } + } + + inst_node['cat-' + String(cat_type_num)] = inst_full_cat; + inst_node['cat_' + String(cat_type_num) + '_index'] = inst_index; + + cat_type_num = cat_type_num + 1; + }); + }); + }; + +/***/ }, +/* 197 */ +/***/ function(module, exports) { + + module.exports = function remove_node_cats(inst_node) { + + var all_props = _.keys(inst_node); + + _.each(all_props, function (inst_prop) { + + if (inst_prop.indexOf('cat-') > -1) { + delete inst_node[inst_prop]; + } + + if (inst_prop.indexOf('cat_') > -1) { + delete inst_node[inst_prop]; + } + }); + }; + +/***/ }, +/* 198 */ +/***/ function(module, exports, __webpack_require__) { + + var reset_size_after_update = __webpack_require__(182); + var make_col_label_container = __webpack_require__(103); + var show_visible_area = __webpack_require__(106); + var resize_containers = __webpack_require__(191); + + module.exports = function ds_enter_exit_update(cgm) { + + // console.log('======== ds_enter_exit_update ==============='); + + // remove row labels, remove non-downsampled rows, and add downsampled rows + d3.selectAll(cgm.params.root + ' .row_cat_group').remove(); + d3.selectAll(cgm.params.root + ' .row_label_group').remove(); + d3.selectAll(cgm.params.root + ' .row').remove(); + + // no need to re-calculate the downsampled layers + // calc_downsampled_levels(params); + var zooming_stopped = true; + var zooming_out = true; + var make_all_rows = true; + + // show_visible_area is also run with two_translate_zoom, but at that point + // the parameters were not updated and two_translate_zoom if only run + // if needed to reset zoom + show_visible_area(cgm, zooming_stopped, zooming_out, make_all_rows); + + make_col_label_container(cgm); + + var col_nodes = cgm.params.network_data.col_nodes; + + // remove column labels + d3.selectAll(cgm.params.root + ' .col_label_group').data(col_nodes, function (d) { + return d.name; + }).exit().style('opacity', 0).remove(); + + d3.selectAll(cgm.params.root + ' .col_label_text').data(col_nodes, function (d) { + return d.name; + }).exit().style('opacity', 0).remove(); + + d3.selectAll(cgm.params.root + ' .col_cat_group').data(col_nodes, function (d) { + return d.name; + }).exit().style('opacity', 0).remove(); + + d3.selectAll(cgm.params.root + ' .col_dendro_group').data(col_nodes, function (d) { + return d.name; + }).exit().style('opacity', 0).remove(); + + // necessary for repositioning clust, col and col-cat containers + resize_containers(cgm.params); + + // seeing if this fixes resizing issue + var delays = {}; + delays.enter = 0; + delays.update = 0; + delays.run_transition = false; + var duration = 0; + reset_size_after_update(cgm, duration, delays); + }; + +/***/ }, +/* 199 */ +/***/ function(module, exports, __webpack_require__) { + + var sim_click = __webpack_require__(171); + + module.exports = function quick_cluster() { + /* eslint-disable */ + + function run(params) { + + var x_trans = Number(d3.select(params.root + ' .expand_button').attr('x').replace('px', '')); + var y_trans = Number(d3.select(params.root + ' .expand_button').attr('y').replace('px', '')); + + var wait_click = 0; + var wait_real_click = 400; + setTimeout(sim_click, wait_click, params, 'single', x_trans, y_trans); + setTimeout(click_menu_button, wait_real_click, params); + + setTimeout(reset_cluster_order, 1500, params); + } + + function get_duration() { + return 3500; + } + + function click_menu_button(params) { + $(params.root + ' .expand_button').d3Click(); + }; + + function reset_cluster_order(params) { + click_reorder_button(params, 'row', 'clust'); + click_reorder_button(params, 'col', 'clust'); + } + + function click_reorder_button(params, inst_rc, inst_order) { + var inst_button = d3.selectAll('.toggle_' + inst_rc + '_order .btn').filter(function () { + return this.__data__ == inst_order; + })[0]; + + $(inst_button).click(); + } + + // allows doubleclicking on d3 element + jQuery.fn.d3Click = function () { + this.each(function (i, e) { + var evt = document.createEvent("MouseEvents"); + evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + e.dispatchEvent(evt); + }); + }; + + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 200 */ +/***/ function(module, exports, __webpack_require__) { + + var demo_text = __webpack_require__(168); + var highlight_sidebar_element = __webpack_require__(174); + var change_groups = __webpack_require__(163); + + module.exports = function play_groups() { + /* eslint-disable */ + + function run(params) { + + var text = 'Identify row and column groups\nof varying sizes using ' + ' the\nsliders and dendrogram'; + demo_text(params, text, 10000); + + setTimeout(highlight_sidebar_element, 3000, params, 'slider_col', 7000); + + setTimeout(change_group_slider, 4000, params, 'row', 3); + setTimeout(change_group_slider, 5000, params, 'row', 4); + setTimeout(change_group_slider, 6000, params, 'row', 5); + setTimeout(change_group_slider, 7000, params, 'row', 6); + setTimeout(change_group_slider, 8000, params, 'row', 7); + setTimeout(change_group_slider, 9000, params, 'row', 5); + } + + function get_duration() { + return 11000; + } + + function change_group_slider(params, inst_rc, inst_value) { + $(cgm.params.root + ' .slider_col').slider("value", inst_value / 10); + change_groups(cgm, inst_rc, inst_value); + } + + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 201 */ +/***/ function(module, exports, __webpack_require__) { + + var demo_text = __webpack_require__(168); + var sim_click = __webpack_require__(171); + + module.exports = function play_category() { + /* eslint-disable */ + + function run(params) { + + var text = 'Row and column categories\ncan be use to reorder\nby double-clicking'; + demo_text(params, text, 7000); + + var inst_element = d3.selectAll(params.root + ' .col_cat_super').filter(function () { + return this.__data__ === 'cat-1'; + })[0]; + + var tmp_pos = d3.select('.col_cat_super').attr('transform'); + var x_trans = Number(tmp_pos.split('(')[1].split(',')[0].replace(')', '')) + 20; + var y_trans = Number(tmp_pos.split(',')[1].replace(')', '')); + + var wait_click = 4000; + setTimeout(sim_click, wait_click, params, 'double', x_trans, y_trans); + + var wait_reorder = wait_click + 300; + setTimeout(fire_double_click_row, wait_reorder, params, inst_element); + } + + function get_duration() { + return 8000; + } + + function fire_double_click_row(params, inst_element) { + $(inst_element).d3DblClick(); + } + + // allows doubleclicking on d3 element + jQuery.fn.d3DblClick = function () { + this.each(function (i, e) { + var evt = document.createEvent("MouseEvents"); + evt.initMouseEvent("dblclick", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + e.dispatchEvent(evt); + }); + }; + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 202 */ +/***/ function(module, exports, __webpack_require__) { + + var demo_text = __webpack_require__(168); + var toggle_play_button = __webpack_require__(203); + + module.exports = function play_conclusion() { + + function run(params) { + var text_1 = "Clustergrammer is built with gene\nexpression data in mind" + " and interfaces\nwith several Ma'ayan lab web tools"; + var text_2 = "The example data being visualized is\ngene expression data" + " obtained from the\nCancer Cell Line Encyclopedia"; + var text_3 = "For more information please view\nthe help documentation"; + + setTimeout(demo_text, 0, params, text_1, 4500); + setTimeout(demo_text, 4500, params, text_2, 4500); + setTimeout(demo_text, 9000, params, text_3, 4500); + + setTimeout(reset_demo, 14000, params); + } + + function reset_demo(params) { + + // prevent more than one demo from running at once + d3.select(params.root + ' .play_button').classed('running_demo', false); + + toggle_play_button(params, true); + } + + function get_duration() { + return 12000; + } + + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 203 */ +/***/ function(module, exports) { + + module.exports = function toggle_play_button(params, show) { + + if (show === false) { + d3.select(params.root + ' .play_button').transition().duration(500).style('opacity', 0); + } else { + d3.select(params.root + ' .play_button').transition().duration(500).style('opacity', 1); + + $.unblockUI(); + } + }; + +/***/ }, +/* 204 */ +/***/ function(module, exports, __webpack_require__) { + + var demo_text = __webpack_require__(168); + var sim_click = __webpack_require__(171); + + module.exports = function play_menu_button() { + /* eslint-disable */ + + function run(params) { + + var text = 'View additional controls\nby clicking the menu button'; + demo_text(params, text, 4000); + + // var inst_element = get_row_element(params, 'EGFR'); + + // var group_trans = d3.select(inst_element).attr('transform'); + + // var container_trans = d3.select(params.root+' .clust_container') + // .attr('transform') + // .split(',')[1].replace(')',''); + + // var x_trans = params.viz.norm_labels.width.row * 0.9; + + // var row_trans = group_trans.split(',')[1].replace(')',''); + // var y_trans = String(Number(row_trans) + Number(container_trans) + + // params.viz.rect_height/2); + + var x_trans = Number(d3.select(params.root + ' .expand_button').attr('x').replace('px', '')); + var y_trans = Number(d3.select(params.root + ' .expand_button').attr('y').replace('px', '')); + + var wait_click = 3000; + var wait_real_click = 3400; + setTimeout(sim_click, wait_click, params, 'single', x_trans, y_trans); + setTimeout(click_menu_button, wait_real_click, params); + } + + function get_duration() { + return 5000; + } + + function click_menu_button(params) { + $(params.root + ' .expand_button').d3Click(); + }; + + function get_row_element(params, inst_row) { + + var inst_element = d3.selectAll(params.root + ' .row_label_group').filter(function () { + var inst_data = this.__data__; + return inst_data.name == inst_row; + })[0][0]; + + return inst_element; + } + + // allows doubleclicking on d3 element + jQuery.fn.d3Click = function () { + this.each(function (i, e) { + var evt = document.createEvent("MouseEvents"); + evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + e.dispatchEvent(evt); + }); + }; + + // allows doubleclicking on d3 element + jQuery.fn.d3DblClick = function () { + this.each(function (i, e) { + var evt = document.createEvent("MouseEvents"); + evt.initMouseEvent("dblclick", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + e.dispatchEvent(evt); + }); + }; + return { + run: run, + get_duration: get_duration + }; + }; + +/***/ }, +/* 205 */ +/***/ function(module, exports, __webpack_require__) { + + var make_play_button = __webpack_require__(206); + var make_demo_text_containers = __webpack_require__(207); + + module.exports = function ini_demo() { + + var cgm = this; + var params = cgm.params; + + make_play_button(cgm); + + var demo_text_size = 30; + make_demo_text_containers(params, demo_text_size); + }; + +/***/ }, +/* 206 */ +/***/ function(module, exports, __webpack_require__) { + + var position_play_button = __webpack_require__(149); + + module.exports = function make_play_button(cgm) { + + var params = cgm.params; + + if (d3.select(params.root + ' .play_button').empty()) { + + var play_button = d3.select(params.root + ' .viz_svg').append('g').classed('play_button', true).classed('running_demo', false); + + position_play_button(params); + + play_button.append('circle').style('r', 45).style('fill', 'white').style('stroke', 'black').style('stroke-width', '3px').style('opacity', 0.5); + + play_button.append('path').attr('d', function () { + + var tri_w = 40; + var tri_h = 22; + var tri_offset = 15; + + return 'M-' + tri_offset + ',-' + tri_h + ' l ' + tri_w + ',' + tri_h + ' l -' + tri_w + ',' + tri_h + ' z '; + }).style('fill', 'black').style('opacity', 0.5); + + // mouseover behavior + play_button.on('mouseover', function () { + d3.select(this).select('path').style('fill', 'red').style('opacity', 1); + + d3.select(this).select('circle').style('opacity', 1); + }).on('mouseout', function () { + d3.select(this).select('path').style('fill', 'black').style('opacity', 0.5); + d3.select(this).select('circle').style('opacity', 0.5); + }).on('click', function () { + // running from anonymous function to keep this defined correctly + cgm.play_demo(); + }); + } + }; + +/***/ }, +/* 207 */ +/***/ function(module, exports) { + + module.exports = function make_demo_text_containers(params, demo_text_size) { + + if (d3.select(params.root + ' .demo_group').empty()) { + + var clust_transform = d3.select(params.root + ' .clust_container').attr('transform'); + var clust_x = Number(clust_transform.split('(')[1].split(',')[0]); + var clust_y = Number(clust_transform.split(',')[1].replace(')', '')); + + // demo text container + var demo_group = d3.select(params.root + ' .viz_svg').append('g').classed('demo_group', true).attr('transform', function () { + var pos_x = clust_x + 20; + var pos_y = clust_y + 40; + return 'translate(' + pos_x + ',' + pos_y + ')'; + }); + + demo_group.append('rect').classed('rect_1', true); + + demo_group.append('rect').classed('rect_2', true); + + demo_group.append('rect').classed('rect_3', true); + + var shift_height = 1.3 * demo_text_size; + + demo_group.append('text').attr('id', 'text_1').attr('font-size', demo_text_size + 'px').attr('font-weight', 1000).attr('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif'); + + demo_group.append('text').attr('id', 'text_2').attr('font-size', demo_text_size + 'px').attr('font-weight', 1000).attr('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif').attr('transform', function () { + return 'translate(0,' + String(shift_height) + ')'; + }); + + demo_group.append('text').attr('id', 'text_3').attr('font-size', demo_text_size + 'px').attr('font-weight', 1000).attr('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif').attr('transform', function () { + return 'translate(0,' + String(2 * shift_height) + ')'; + }); + } + }; + +/***/ }, +/* 208 */ +/***/ function(module, exports, __webpack_require__) { + + var filter_network_using_new_nodes = __webpack_require__(11); + var update_viz_with_network = __webpack_require__(179); + + module.exports = function filter_viz_using_nodes(new_nodes) { + + var new_network_data = filter_network_using_new_nodes(this.config, new_nodes); + update_viz_with_network(this, new_network_data); + }; + +/***/ }, +/* 209 */ +/***/ function(module, exports, __webpack_require__) { + + var filter_network_using_new_nodes = __webpack_require__(11); + var update_viz_with_network = __webpack_require__(179); + + module.exports = function filter_viz_using_names(names, external_cgm = false) { + + // names is an object with row and column names that will be used to filter + // the matrix + + var cgm; + if (external_cgm === false) { + cgm = this; + } else { + cgm = external_cgm; + } + + var params = cgm.params; + var new_nodes = {}; + var found_nodes; + + _.each(['row', 'col'], function (inst_rc) { + + var orig_nodes = params.inst_nodes[inst_rc + '_nodes']; + + if (_.has(names, inst_rc)) { + + if (names[inst_rc].length > 0) { + var inst_names = names[inst_rc]; + found_nodes = $.grep(orig_nodes, function (d) { + return $.inArray(d.name, inst_names) > -1; + }); + } else { + + found_nodes = orig_nodes; + } + } else { + + found_nodes = orig_nodes; + } + + new_nodes[inst_rc + '_nodes'] = found_nodes; + }); + + // keep backup of the nodes for resetting filtering + var inst_row_nodes = cgm.params.network_data.row_nodes; + var inst_col_nodes = cgm.params.network_data.col_nodes; + + var new_network_data = filter_network_using_new_nodes(cgm.config, new_nodes); + + // takes entire cgm object + // last argument tells it to not preserve categoty colors + update_viz_with_network(cgm, new_network_data); + + // only keep backup if previous number of nodes were larger than current number + // of nodes + if (inst_row_nodes.length > cgm.params.inst_nodes.row_nodes.length) { + cgm.params.inst_nodes.row_nodes = inst_row_nodes; + } + + if (inst_col_nodes.length > cgm.params.inst_nodes.col_nodes.length) { + cgm.params.inst_nodes.col_nodes = inst_col_nodes; + } + }; + +/***/ }, +/* 210 */ +/***/ function(module, exports, __webpack_require__) { + + var make_row_cat = __webpack_require__(158); + var calc_viz_params = __webpack_require__(15); + var resize_viz = __webpack_require__(124); + var modify_row_node_cats = __webpack_require__(196); + + module.exports = function update_cats(cgm, cat_data) { + + // Only accessible from the cgm API, cat_data is provided by externally + /////////////////////////////////////////////////////////////////////////// + + if (cgm.params.cat_update_callback != null) { + cgm.params.cat_update_callback(this); + } + + // do not change column category info + var col_cat_colors = cgm.params.viz.cat_colors.col; + + modify_row_node_cats(cat_data, cgm.params.network_data.row_nodes, true); + // modify the current inst copy of nodes + modify_row_node_cats(cat_data, cgm.params.inst_nodes.row_nodes, true); + + // recalculate the visualization parameters using the updated network_data + cgm.params = calc_viz_params(cgm.params, false); + + make_row_cat(cgm, true); + resize_viz(cgm); + + cgm.params.new_row_cats = cat_data; + + cgm.params.viz.cat_colors.col = col_cat_colors; + }; + +/***/ }, +/* 211 */ +/***/ function(module, exports, __webpack_require__) { + + var make_row_cat = __webpack_require__(158); + var calc_viz_params = __webpack_require__(15); + var resize_viz = __webpack_require__(124); + var modify_row_node_cats = __webpack_require__(196); + var generate_cat_data = __webpack_require__(212); + + module.exports = function reset_cats(run_resize_viz = true) { + + // console.log('RESET CATS') + + var cgm = this; + + var cat_data = generate_cat_data(cgm); + + // do not change column category info + var col_cat_colors = cgm.params.viz.cat_colors.col; + + modify_row_node_cats(cat_data, cgm.params.network_data.row_nodes); + // modify the current inst copy of nodes + modify_row_node_cats(cat_data, cgm.params.inst_nodes.row_nodes); + + cgm.params.new_row_cats = cat_data; + cgm.params.viz.cat_colors.col = col_cat_colors; + + if (run_resize_viz) { + + // resize visualizatino + //////////////////////////// + // recalculate the visualization parameters using the updated network_data + var predefine_cat_colors = true; + cgm.params = calc_viz_params(cgm.params, predefine_cat_colors); + + make_row_cat(cgm, true); + resize_viz(cgm); + } + }; + +/***/ }, +/* 212 */ +/***/ function(module, exports) { + + module.exports = function generate_cat_data(cgm) { + + // only row category resetting is supported currently + + // get row_nodes from config, since this is has the original network + var row_nodes = cgm.config.network_data.row_nodes; + var title_sep = ': '; + + // contains all the category information stored as an array of + // cat_type + var cat_data = []; + var cat_type; + var cat_info; + var found_cat_title; + var found_cat_name; + var cat_name; + + // console.log('generate_cat_data') + // console.log(cgm.params.viz.cat_names.row) + + // get current list of cateories + var check_node = row_nodes[0]; + var node_keys = _.keys(check_node); + var current_cats = {}; + var tmp_cat; + var tmp_title; + var cat_index; + _.each(node_keys, function (inst_prop) { + + if (inst_prop.indexOf('cat-') >= 0) { + + // generate titles from cat info + tmp_cat = check_node[inst_prop]; + + cat_index = parseInt(inst_prop.split('cat-')[1], 10); + + // use given title + if (tmp_cat.indexOf(title_sep) >= 0) { + tmp_title = tmp_cat.split(title_sep)[0]; + } else { + tmp_title = inst_prop; + } + + // current_cats.push(tmp_title); + + current_cats[cat_index] = tmp_title; + } + }); + + // console.log('current_cats') + // console.log(current_cats) + + // initialize cat_data with categories in the correct order + var all_index = _.keys(current_cats).sort(); + + var inst_data; + _.each(all_index, function (inst_index) { + + inst_data = {}; + inst_data.cat_title = current_cats[inst_index]; + inst_data.cats = []; + + cat_data.push(inst_data); + }); + + // // initialize cat_data (keep original order) + // var found_title; + // _.each(cgm.params.viz.cat_names.row, function(inst_title){ + + // found_title = false; + + // console.log('inst_title -> ' + String(inst_title)) + + // if (current_cats.indexOf(inst_title) >= 0){ + // found_title = true; + // } + + // // only track cats that are found in the incoming nodes + // if (found_title){ + // var inst_data = {}; + // inst_data.cat_title = inst_title; + // inst_data.cats = []; + // cat_data.push(inst_data); + // } + + // }); + + // console.log('cat_data after cross checking with current cats') + // console.log(cat_data) + // console.log('-------------------------\n') + + _.each(row_nodes, function (inst_node) { + + var all_props = _.keys(inst_node); + + _.each(all_props, function (inst_prop) { + + if (inst_prop.indexOf('cat-') > -1) { + + cat_name = inst_node[inst_prop]; + + cat_index = parseInt(inst_prop.split('cat-')[1], 10); + + // default title and name + var cat_title = inst_prop; + cat_name = inst_node[inst_prop]; + var cat_string = inst_node[inst_prop]; + var cat_row_name = inst_node.name; + + // console.log('cat_string: '+String(cat_string)) + // found actual title + if (cat_string.indexOf(title_sep) > -1) { + cat_title = cat_string.split(title_sep)[0]; + cat_name = cat_string.split(title_sep)[1]; + } else { + // cat_title = 'Category-'+String(parseInt(inst_prop.split('-')[1]) + 1) + cat_title = inst_prop; + cat_name = cat_string; + } + + // console.log('cat_index -> ' + String(cat_index)) + // console.log('cat_name '+cat_name) + // console.log('cat_title ' + cat_title) + // console.log('--------') + + // cat_data is empty + if (cat_data.length === 0) { + + add_new_cat_type(cat_title, cat_name, cat_row_name); + + // cat_data is not empty + } else { + + // look for cat_title in cat_data + found_cat_title = false; + _.each(cat_data, function (inst_cat_type) { + + // console.log('inst_cat_data title ' + inst_cat_type.cat_title) + + // check each cat_type object for a matching title + if (cat_title === inst_cat_type.cat_title) { + found_cat_title = true; + + // check if cat_name is in cats + found_cat_name = false; + _.each(inst_cat_type.cats, function (inst_cat_obj) { + + // found category name, add cat_row_name to members + if (cat_name === inst_cat_obj.cat_name) { + found_cat_name = true; + + // add cat_row_name to members + inst_cat_obj.members.push(cat_row_name); + } + }); + + // did not find cat name in cat_type - add cat_info for new + // category + if (found_cat_name === false) { + cat_info = {}; + cat_info.cat_name = cat_name; + cat_info.members = []; + cat_info.members.push(cat_row_name); + inst_cat_type.cats.push(cat_info); + } + } + }); + + // did not find category type, initialize category type object + if (found_cat_title === false) { + + // console.log('did not find cat_title: ' + String(cat_title)) + // add_new_cat_type(cat_title, cat_name, cat_row_name); + + } + } + } + }); + }); + + function add_new_cat_type(cat_title, cat_name, cat_row_name) { + + // initialize cat_type object to push to cat_data + cat_type = {}; + cat_type.cat_title = cat_title; + cat_type.cats = []; + + // initialize cat_info (e.g. 'true' category has members [...]) + cat_info = {}; + cat_info.cat_name = cat_name; + cat_info.members = []; + cat_info.members.push(cat_row_name); + + cat_type.cats.push(cat_info); + + cat_data.push(cat_type); + } + + // console.log('RETURNING CAT DATA') + // console.log(cat_data) + + return cat_data; + }; + +/***/ }, +/* 213 */ +/***/ function(module, exports, __webpack_require__) { + + var update_viz_with_view = __webpack_require__(177); + var reset_other_filter_sliders = __webpack_require__(214); + + module.exports = function external_update_view(filter_type, inst_state) { + + // add something to control slider position + ///////////////////////////////////////////// + + var cgm = this; + + var requested_view = {}; + requested_view[filter_type] = inst_state; + update_viz_with_view(this, requested_view); + + reset_other_filter_sliders(cgm, filter_type, inst_state); + }; + +/***/ }, +/* 214 */ +/***/ function(module, exports, __webpack_require__) { + + var make_filter_title = __webpack_require__(215); + + module.exports = function reset_other_filter_sliders(cgm, filter_type, inst_state) { + + var params = cgm.params; + var inst_rc; + var reset_rc; + + d3.select(params.root + ' .slider_' + filter_type).attr('current_state', inst_state); + + _.each(_.keys(params.viz.possible_filters), function (reset_filter) { + + if (filter_type.indexOf('row') > -1) { + inst_rc = 'row'; + } else if (filter_type.indexOf('col') > -1) { + inst_rc = 'col'; + } else { + inst_rc = 'neither'; + } + + if (reset_filter.indexOf('row') > -1) { + reset_rc = 'row'; + } else if (reset_filter.indexOf('col') > -1) { + reset_rc = 'col'; + } else { + reset_rc = 'neither'; + } + + if (filter_type != reset_filter && inst_rc != 'neither') { + + if (inst_rc == reset_rc) { + + var tmp_title = make_filter_title(params, reset_filter); + + cgm.slider_functions[reset_filter].value(0); + + d3.select(params.root + ' .title_' + reset_filter).text(tmp_title.text + tmp_title.state); + + d3.select(params.root + ' .slider_' + reset_filter).attr('current_state', tmp_title.state); + } + } + }); + + var filter_title = make_filter_title(params, filter_type); + + d3.select(params.root + ' .title_' + filter_type).text(filter_title.text + inst_state + filter_title.suffix); + }; + +/***/ }, +/* 215 */ +/***/ function(module, exports, __webpack_require__) { + + var get_filter_default_state = __webpack_require__(5); + + module.exports = function make_filter_title(params, filter_type) { + + var filter_title = {}; + var title = {}; + var type = {}; + + filter_title.state = get_filter_default_state(params.viz.filter_data, filter_type); + + type.top = filter_type.split('_')[0]; + type.node = filter_type.split('_')[1]; + type.measure = filter_type.split('_')[2]; + + if (type.node === 'row') { + title.node = 'rows'; + } else { + title.node = 'columns'; + } + + if (type.top === 'N') { + // filter_title.suffix = ' '+title.node; + filter_title.suffix = ''; + } + + if (type.top === 'pct') { + filter_title.suffix = '%'; + } + + if (type.measure == 'sum') { + title.measure = 'sum'; + } else if (type.measure == 'var') { + title.measure = 'variance'; + } + + if (type.measure === 'sum') { + filter_title.text = 'Top ' + title.node + ' ' + title.measure + ': '; + } + + if (type.measure === 'var') { + filter_title.text = 'Top ' + title.node + ' ' + title.measure + ': '; + } + + // Enrichr specific rules + if (_.keys(params.viz.possible_filters).indexOf('enr_score_type') > -1) { + if (type.node === 'col') { + filter_title.text = 'Top Enriched Terms: '; + filter_title.suffix = ''; + } + } + + return filter_title; + }; + +/***/ }, +/* 216 */ +/***/ function(module, exports, __webpack_require__) { + + var file_saver = __webpack_require__(217); + var make_matrix_string = __webpack_require__(218); + + module.exports = function save_matrix() { + + var saveAs = file_saver(); + + var params = this.params; + + var matrix_string = make_matrix_string(params); + + var blob = new Blob([matrix_string], { type: 'text/plain;charset=utf-8' }); + saveAs(blob, 'clustergrammer.txt'); + }; + +/***/ }, +/* 217 */ +/***/ function(module, exports) { + + module.exports = function file_saver() { + /* eslint-disable */ + /* FileSaver.js + * A saveAs() FileSaver implementation. + * 2013-01-23 + * + * By Eli Grey, http://eligrey.com + * License: X11/MIT + * See LICENSE.md + */ + + /*global self */ + /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, + plusplus: true */ + + /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ + + var saveAs = saveAs || navigator.msSaveBlob && navigator.msSaveBlob.bind(navigator) || function (view) { + "use strict"; + + var doc = view.document + // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet + , + get_URL = function () { + return view.URL || view.webkitURL || view; + }, + URL = view.URL || view.webkitURL || view, + save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"), + can_use_save_link = "download" in save_link, + click = function (node) { + var event = doc.createEvent("MouseEvents"); + event.initMouseEvent("click", true, false, view, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + node.dispatchEvent(event); + }, + webkit_req_fs = view.webkitRequestFileSystem, + req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem, + throw_outside = function (ex) { + (view.setImmediate || view.setTimeout)(function () { + throw ex; + }, 0); + }, + force_saveable_type = "application/octet-stream", + fs_min_size = 0, + deletion_queue = [], + process_deletion_queue = function () { + var i = deletion_queue.length; + while (i--) { + var file = deletion_queue[i]; + if (typeof file === "string") { + // file is an object URL + URL.revokeObjectURL(file); + } else { + // file is a File + file.remove(); + } + } + deletion_queue.length = 0; // clear queue + }, + dispatch = function (filesaver, event_types, event) { + event_types = [].concat(event_types); + var i = event_types.length; + while (i--) { + var listener = filesaver["on" + event_types[i]]; + if (typeof listener === "function") { + try { + listener.call(filesaver, event || filesaver); + } catch (ex) { + throw_outside(ex); + } + } + } + }, + FileSaver = function (blob, name) { + // First try a.download, then web filesystem, then object URLs + var filesaver = this, + type = blob.type, + blob_changed = false, + object_url, + target_view, + get_object_url = function () { + var object_url = get_URL().createObjectURL(blob); + deletion_queue.push(object_url); + return object_url; + }, + dispatch_all = function () { + dispatch(filesaver, "writestart progress write writeend".split(" ")); + } + // on any filesys errors revert to saving with object URLs + , + fs_error = function () { + // don't create more object URLs than needed + if (blob_changed || !object_url) { + object_url = get_object_url(blob); + } + if (target_view) { + target_view.location.href = object_url; + } + filesaver.readyState = filesaver.DONE; + dispatch_all(); + }, + abortable = function (func) { + return function () { + if (filesaver.readyState !== filesaver.DONE) { + return func.apply(this, arguments); + } + }; + }, + create_if_not_found = { create: true, exclusive: false }, + slice; + filesaver.readyState = filesaver.INIT; + if (!name) { + name = "download"; + } + if (can_use_save_link) { + object_url = get_object_url(blob); + save_link.href = object_url; + save_link.download = name; + click(save_link); + filesaver.readyState = filesaver.DONE; + dispatch_all(); + return; + } + // Object and web filesystem URLs have a problem saving in Google Chrome when + // viewed in a tab, so I force save with application/octet-stream + // http://code.google.com/p/chromium/issues/detail?id=91158 + if (view.chrome && type && type !== force_saveable_type) { + slice = blob.slice || blob.webkitSlice; + blob = slice.call(blob, 0, blob.size, force_saveable_type); + blob_changed = true; + } + // Since I can't be sure that the guessed media type will trigger a download + // in WebKit, I append .download to the filename. + // https://bugs.webkit.org/show_bug.cgi?id=65440 + if (webkit_req_fs && name !== "download") { + name += ".download"; + } + if (type === force_saveable_type || webkit_req_fs) { + target_view = view; + } else { + target_view = view.open(); + } + if (!req_fs) { + fs_error(); + return; + } + fs_min_size += blob.size; + req_fs(view.TEMPORARY, fs_min_size, abortable(function (fs) { + fs.root.getDirectory("saved", create_if_not_found, abortable(function (dir) { + var save = function () { + dir.getFile(name, create_if_not_found, abortable(function (file) { + file.createWriter(abortable(function (writer) { + writer.onwriteend = function (event) { + target_view.location.href = file.toURL(); + deletion_queue.push(file); + filesaver.readyState = filesaver.DONE; + dispatch(filesaver, "writeend", event); + }; + writer.onerror = function () { + var error = writer.error; + if (error.code !== error.ABORT_ERR) { + fs_error(); + } + }; + "writestart progress write abort".split(" ").forEach(function (event) { + writer["on" + event] = filesaver["on" + event]; + }); + writer.write(blob); + filesaver.abort = function () { + writer.abort(); + filesaver.readyState = filesaver.DONE; + }; + filesaver.readyState = filesaver.WRITING; + }), fs_error); + }), fs_error); + }; + dir.getFile(name, { create: false }, abortable(function (file) { + // delete file if it already exists + file.remove(); + save(); + }), abortable(function (ex) { + if (ex.code === ex.NOT_FOUND_ERR) { + save(); + } else { + fs_error(); + } + })); + }), fs_error); + }), fs_error); + }, + FS_proto = FileSaver.prototype, + saveAs = function (blob, name) { + return new FileSaver(blob, name); + }; + FS_proto.abort = function () { + var filesaver = this; + filesaver.readyState = filesaver.DONE; + dispatch(filesaver, "abort"); + }; + FS_proto.readyState = FS_proto.INIT = 0; + FS_proto.WRITING = 1; + FS_proto.DONE = 2; + + FS_proto.error = FS_proto.onwritestart = FS_proto.onprogress = FS_proto.onwrite = FS_proto.onabort = FS_proto.onerror = FS_proto.onwriteend = null; + + view.addEventListener("unload", process_deletion_queue, false); + return saveAs; + }(self); + + return saveAs; + }; + +/***/ }, +/* 218 */ +/***/ function(module, exports, __webpack_require__) { + + var make_full_name = __webpack_require__(219); + + module.exports = function make_matrix_string(params) { + + var inst_matrix = params.matrix; + + // get order indexes + var order_indexes = {}; + var inst_name; + _.each(['row', 'col'], function (tmp_rc) { + + var inst_rc; + // row/col names are reversed in saved orders + if (tmp_rc === 'row') { + inst_rc = 'col'; + } else { + inst_rc = 'row'; + } + + // use tmp_rc + inst_name = params.inst_order[tmp_rc]; + + // use tmp_rc + order_indexes[inst_rc] = inst_matrix.orders[inst_name + '_' + tmp_rc]; + }); + + var matrix_string = '\t'; + var row_nodes = params.network_data.row_nodes; + var col_nodes = params.network_data.col_nodes; + + // alternate column entry + for (var c_i = 0; c_i < order_indexes.col.length; c_i++) { + + var inst_index = order_indexes.col[c_i]; + + var inst_col = col_nodes[inst_index]; + var col_name = make_full_name(params, inst_col, 'col'); + + if (c_i < order_indexes.col.length - 1) { + matrix_string = matrix_string + col_name + '\t'; + } else { + matrix_string = matrix_string + col_name; + } + } + + var row_data; + matrix_string = matrix_string + '\n'; + + _.each(order_indexes.row, function (inst_index) { + + // row names + row_data = inst_matrix.matrix[inst_index].row_data; + + // var row_name = inst_matrix.matrix[inst_index].name; + var inst_row = row_nodes[inst_index]; + + // var row_name = inst_row.name; + var row_name = make_full_name(params, inst_row, 'row'); + + matrix_string = matrix_string + row_name + '\t'; + + // alternate data entry + for (var r_i = 0; r_i < order_indexes.col.length; r_i++) { + + // get the order + var col_index = order_indexes.col[r_i]; + + if (r_i < order_indexes.col.length - 1) { + matrix_string = matrix_string + String(row_data[col_index].value) + '\t'; + } else { + matrix_string = matrix_string + String(row_data[col_index].value); + } + } + + matrix_string = matrix_string + '\n'; + }); + + return matrix_string; + }; + +/***/ }, +/* 219 */ +/***/ function(module, exports) { + + module.exports = function make_full_name(params, inst_node, inst_rc) { + + var cat_name; + var inst_name = inst_node.name; + var num_cats = params.viz.all_cats[inst_rc].length; + + // make tuple if necessary + if (num_cats > 0) { + + inst_name = "('" + inst_name + "'"; + + for (var cat_index = 0; cat_index < num_cats; cat_index++) { + cat_name = 'cat-' + String(cat_index); + + inst_name = inst_name + ", '" + String(inst_node[cat_name]) + "'"; + } + + inst_name = inst_name + ')'; + } else { + + // always make names strings + inst_name = String(inst_name); + } + + return inst_name; + }; + +/***/ }, +/* 220 */ +/***/ function(module, exports, __webpack_require__) { + + var deactivate_cropping = __webpack_require__(221); + + module.exports = function brush_crop_matrix() { + + // get rows/cols from brush-extent + // works for differnt brushing directions (e.g. start end sites) + + var cgm = this; + var params = cgm.params; + + var clust_width = params.viz.clust.dim.width; + var clust_height = params.viz.clust.dim.height; + + var x = d3.scale.linear().domain([0, clust_width]).range([0, clust_width]); + var y = d3.scale.linear().domain([0, clust_height]).range([0, clust_height]); + + // make brush group + d3.select(params.root + ' .clust_container').append('g').classed('brush_group', true); + + cgm.params.is_cropping = true; + + var brush = d3.svg.brush().x(x).y(y).on("brushend", brushend); + + d3.select(params.root + ' .brush_group').call(brush); + + function brushend() { + + // do not display dendro crop buttons when cropping with brushing + d3.select(cgm.params.root + ' .col_dendro_icons_container').style('display', 'none'); + d3.select(cgm.params.root + ' .row_dendro_icons_container').style('display', 'none'); + + var brushing_extent = brush.extent(); + var brush_start = brushing_extent[0]; + var brush_end = brushing_extent[1]; + + var x_start = brush_start[0]; + var x_end = brush_end[0]; + + var y_start = brush_start[1]; + var y_end = brush_end[1]; + + if (x_start != x_end && y_start != y_end) { + + setTimeout(deactivate_cropping, 500, cgm); + + // find cropped nodes + var found_nodes = find_cropped_nodes(x_start, x_end, y_start, y_end, brush_start, brush_end); + + cgm.filter_viz_using_names(found_nodes); + + d3.select(params.root + ' .crop_button').style('color', '#337ab7').classed('fa-crop', false).classed('fa-undo', true); + } + } + + function find_cropped_nodes(x_start, x_end, y_start, y_end, brush_start, brush_end) { + + // reverse if necessary (depending on how brushing was done) + if (x_start > x_end) { + x_start = brush_end[0]; + x_end = brush_start[0]; + } + + if (y_start > y_end) { + y_start = brush_end[1]; + y_end = brush_start[1]; + } + + // add room to brushing + y_start = y_start - params.viz.rect_height; + x_start = x_start - params.viz.rect_width; + + var found_nodes = {}; + found_nodes.row = []; + found_nodes.col = []; + + // d3.selectAll(params.root+' .row_label_group') + // .each(function(inst_row){ + + // // there is already bound data on the rows + // var inst_trans = d3.select(this) + // .attr('transform'); + + // var y_trans = Number(inst_trans.split(',')[1].split(')')[0]); + + // if (y_trans > y_start && y_trans < y_end){ + + // found_nodes.row.push(inst_row.name); + + // } + + // }); + + _.each(params.matrix.matrix, function (row_data) { + var y_trans = params.viz.y_scale(row_data.row_index); + + if (y_trans > y_start && y_trans < y_end) { + found_nodes.row.push(row_data.name); + } + }); + + d3.selectAll(params.root + ' .col_label_text').each(function (inst_col) { + + // there is already bound data on the cols + var inst_trans = d3.select(this).attr('transform'); + + var x_trans = Number(inst_trans.split(',')[0].split('(')[1]); + + if (x_trans > x_start && x_trans < x_end) { + + found_nodes.col.push(inst_col.name); + } + }); + + return found_nodes; + } + + d3.selectAll(params.root + ' .extent').style('opacity', 0.2).style('fill', 'black'); + }; + +/***/ }, +/* 221 */ +/***/ function(module, exports) { + + module.exports = function deactivate_cropping(cgm) { + + d3.select(cgm.params.root + ' .brush_group').transition().style('opacity', 0).remove(); + + cgm.params.is_cropping = false; + }; + +/***/ }, +/* 222 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* + D3.js Slider + Inspired by jQuery UI Slider + Copyright (c) 2013, Bjorn Sandvik - http://blog.thematicmapping.org + BSD license: http://opensource.org/licenses/BSD-3-Clause + */ + (function (root, factory) { + if (true) { + // AMD. Register as an anonymous module. + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(223)], __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 === 'object') { + if (process.browser) { + // Browserify. Import css too using cssify. + require('./d3.slider.css'); + } + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(require('d3')); + } else { + // Browser globals (root is window) + root.d3.slider = factory(root.d3); + } + })(this, function (d3) { + return function module() { + "use strict"; + + // Public variables width default settings + + var min = 0, + max = 100, + step = 0.01, + animate = false, + orientation = "horizontal", + axis = false, + margin = 50, + value, + active = 1, + snap = false, + scale; + + // Private variables + var axisScale, + dispatch = d3.dispatch("slide", "slideend"), + formatPercent = d3.format(".2%"), + tickFormat = d3.format(".0"), + handle1, + handle2 = null, + divRange, + sliderLength; + + function slider(selection) { + selection.each(function () { + + // Create scale if not defined by user + if (!scale) { + scale = d3.scale.linear().domain([min, max]); + } + + // Start value + value = value || scale.domain()[0]; + + // DIV container + var div = d3.select(this).classed("d3-slider d3-slider-" + orientation, true); + + var drag = d3.behavior.drag(); + drag.on('dragend', function () { + dispatch.slideend(d3.event, value); + }); + + // Slider handle + //if range slider, create two + // var divRange; + + if (toType(value) == "array" && value.length == 2) { + handle1 = div.append("a").classed("d3-slider-handle", true).attr("xlink:href", "#").attr('id', "handle-one").on("click", stopPropagation).call(drag); + handle2 = div.append("a").classed("d3-slider-handle", true).attr('id', "handle-two").attr("xlink:href", "#").on("click", stopPropagation).call(drag); + } else { + handle1 = div.append("a").classed("d3-slider-handle", true).attr("xlink:href", "#").attr('id', "handle-one").on("click", stopPropagation).call(drag); + } + + // Horizontal slider + if (orientation === "horizontal") { + + div.on("click", onClickHorizontal); + + if (toType(value) == "array" && value.length == 2) { + divRange = d3.select(this).append('div').classed("d3-slider-range", true); + + handle1.style("left", formatPercent(scale(value[0]))); + divRange.style("left", formatPercent(scale(value[0]))); + drag.on("drag", onDragHorizontal); + + var width = 100 - parseFloat(formatPercent(scale(value[1]))); + handle2.style("left", formatPercent(scale(value[1]))); + divRange.style("right", width + "%"); + drag.on("drag", onDragHorizontal); + } else { + handle1.style("left", formatPercent(scale(value))); + drag.on("drag", onDragHorizontal); + } + + sliderLength = parseInt(div.style("width"), 10); + } else { + // Vertical + + div.on("click", onClickVertical); + drag.on("drag", onDragVertical); + if (toType(value) == "array" && value.length == 2) { + divRange = d3.select(this).append('div').classed("d3-slider-range-vertical", true); + + handle1.style("bottom", formatPercent(scale(value[0]))); + divRange.style("bottom", formatPercent(scale(value[0]))); + drag.on("drag", onDragVertical); + + var top = 100 - parseFloat(formatPercent(scale(value[1]))); + handle2.style("bottom", formatPercent(scale(value[1]))); + divRange.style("top", top + "%"); + drag.on("drag", onDragVertical); + } else { + handle1.style("bottom", formatPercent(scale(value))); + drag.on("drag", onDragVertical); + } + + sliderLength = parseInt(div.style("height"), 10); + } + + if (axis) { + createAxis(div); + } + + function createAxis(dom) { + + // Create axis if not defined by user + if (typeof axis === "boolean") { + + axis = d3.svg.axis().ticks(Math.round(sliderLength / 100)).tickFormat(tickFormat).orient(orientation === "horizontal" ? "bottom" : "right"); + } + + // Copy slider scale to move from percentages to pixels + axisScale = scale.ticks ? scale.copy().range([0, sliderLength]) : scale.copy().rangePoints([0, sliderLength], 0.5); + axis.scale(axisScale); + + // Create SVG axis container + var svg = dom.append("svg").classed("d3-slider-axis d3-slider-axis-" + axis.orient(), true).on("click", stopPropagation); + + var g = svg.append("g"); + + // Horizontal axis + if (orientation === "horizontal") { + + svg.style("margin-left", -margin + "px"); + + svg.attr({ + width: sliderLength + margin * 2, + height: margin + }); + + if (axis.orient() === "top") { + svg.style("top", -margin + "px"); + g.attr("transform", "translate(" + margin + "," + margin + ")"); + } else { + // bottom + g.attr("transform", "translate(" + margin + ",0)"); + } + } else { + // Vertical + + svg.style("top", -margin + "px"); + + svg.attr({ + width: margin, + height: sliderLength + margin * 2 + }); + + if (axis.orient() === "left") { + svg.style("left", -margin + "px"); + g.attr("transform", "translate(" + margin + "," + margin + ")"); + } else { + // right + g.attr("transform", "translate(" + 0 + "," + margin + ")"); + } + } + + g.call(axis); + } + + function onClickHorizontal() { + if (toType(value) != "array") { + var pos = Math.max(0, Math.min(sliderLength, d3.event.offsetX || d3.event.layerX)); + moveHandle(scale.invert ? stepValue(scale.invert(pos / sliderLength)) : nearestTick(pos / sliderLength)); + } + } + + function onClickVertical() { + if (toType(value) != "array") { + var pos = sliderLength - Math.max(0, Math.min(sliderLength, d3.event.offsetY || d3.event.layerY)); + moveHandle(scale.invert ? stepValue(scale.invert(pos / sliderLength)) : nearestTick(pos / sliderLength)); + } + } + + function onDragHorizontal() { + if (d3.event.sourceEvent.target.id === "handle-one") { + active = 1; + } else if (d3.event.sourceEvent.target.id == "handle-two") { + active = 2; + } + var pos = Math.max(0, Math.min(sliderLength, d3.event.x)); + moveHandle(scale.invert ? stepValue(scale.invert(pos / sliderLength)) : nearestTick(pos / sliderLength)); + } + + function onDragVertical() { + if (d3.event.sourceEvent.target.id === "handle-one") { + active = 1; + } else if (d3.event.sourceEvent.target.id == "handle-two") { + active = 2; + } + var pos = sliderLength - Math.max(0, Math.min(sliderLength, d3.event.y)); + moveHandle(scale.invert ? stepValue(scale.invert(pos / sliderLength)) : nearestTick(pos / sliderLength)); + } + + function stopPropagation() { + d3.event.stopPropagation(); + } + }); + } + + // Move slider handle on click/drag + function moveHandle(newValue) { + var currentValue = toType(value) == "array" && value.length == 2 ? value[active - 1] : value, + oldPos = formatPercent(scale(stepValue(currentValue))), + newPos = formatPercent(scale(stepValue(newValue))), + position = orientation === "horizontal" ? "left" : "bottom"; + if (oldPos !== newPos) { + + if (toType(value) == "array" && value.length == 2) { + value[active - 1] = newValue; + if (d3.event) { + dispatch.slide(d3.event, value); + }; + } else { + if (d3.event) { + dispatch.slide(d3.event.sourceEvent || d3.event, value = newValue); + }; + } + + if (value[0] >= value[1]) return; + if (active === 1) { + if (toType(value) == "array" && value.length == 2) { + position === "left" ? divRange.style("left", newPos) : divRange.style("bottom", newPos); + } + + if (animate) { + handle1.transition().styleTween(position, function () { + return d3.interpolate(oldPos, newPos); + }).duration(typeof animate === "number" ? animate : 250); + } else { + handle1.style(position, newPos); + } + } else { + + var width = 100 - parseFloat(newPos); + var top = 100 - parseFloat(newPos); + + position === "left" ? divRange.style("right", width + "%") : divRange.style("top", top + "%"); + + if (animate) { + handle2.transition().styleTween(position, function () { + return d3.interpolate(oldPos, newPos); + }).duration(typeof animate === "number" ? animate : 250); + } else { + handle2.style(position, newPos); + } + } + } + } + + // Calculate nearest step value + function stepValue(val) { + + if (val === scale.domain()[0] || val === scale.domain()[1]) { + return val; + } + + var alignValue = val; + if (snap) { + alignValue = nearestTick(scale(val)); + } else { + var valModStep = (val - scale.domain()[0]) % step; + alignValue = val - valModStep; + + if (Math.abs(valModStep) * 2 >= step) { + alignValue += valModStep > 0 ? step : -step; + } + }; + + return alignValue; + } + + // Find the nearest tick + function nearestTick(pos) { + var ticks = scale.ticks ? scale.ticks() : scale.domain(); + var dist = ticks.map(function (d) { + return pos - scale(d); + }); + var i = -1, + index = 0, + r = scale.ticks ? scale.range()[1] : scale.rangeExtent()[1]; + do { + i++; + if (Math.abs(dist[i]) < r) { + r = Math.abs(dist[i]); + index = i; + }; + } while (dist[i] > 0 && i < dist.length - 1); + + return ticks[index]; + }; + + // Return the type of an object + function toType(v) { + return {}.toString.call(v).match(/\s([a-zA-Z]+)/)[1].toLowerCase(); + }; + + // Getter/setter functions + slider.min = function (_) { + if (!arguments.length) return min; + min = _; + return slider; + }; + + slider.max = function (_) { + if (!arguments.length) return max; + max = _; + return slider; + }; + + slider.step = function (_) { + if (!arguments.length) return step; + step = _; + return slider; + }; + + slider.animate = function (_) { + if (!arguments.length) return animate; + animate = _; + return slider; + }; + + slider.orientation = function (_) { + if (!arguments.length) return orientation; + orientation = _; + return slider; + }; + + slider.axis = function (_) { + if (!arguments.length) return axis; + axis = _; + return slider; + }; + + slider.margin = function (_) { + if (!arguments.length) return margin; + margin = _; + return slider; + }; + + slider.value = function (_) { + if (!arguments.length) return value; + if (value) { + moveHandle(stepValue(_)); + }; + value = _; + return slider; + }; + + slider.snap = function (_) { + if (!arguments.length) return snap; + snap = _; + return slider; + }; + + slider.scale = function (_) { + if (!arguments.length) return scale; + scale = _; + return slider; + }; + + d3.rebind(slider, dispatch, "on"); + + return slider; + }; + }); + +/***/ }, +/* 223 */ +/***/ function(module, exports) { + + module.exports = d3; + +/***/ }, +/* 224 */ +/***/ function(module, exports) { + + /** + * Simple, lightweight, usable local autocomplete library for modern browsers + * Because there weren’t enough autocomplete scripts in the world? Because I’m completely insane and have NIH syndrome? Probably both. :P + * @author Lea Verou http://leaverou.github.io/awesomplete + * MIT license + */ + + (function () { + + var _ = function (input, o) { + var me = this; + + // Setup + + this.input = $(input); + this.input.setAttribute("autocomplete", "off"); + this.input.setAttribute("aria-autocomplete", "list"); + + o = o || {}; + + configure(this, { + minChars: 2, + maxItems: 10, + autoFirst: false, + data: _.DATA, + filter: _.FILTER_CONTAINS, + sort: _.SORT_BYLENGTH, + item: _.ITEM, + replace: _.REPLACE + }, o); + + this.index = -1; + + // Create necessary elements + + this.container = $.create("div", { + className: "awesomplete", + around: input + }); + + this.ul = $.create("ul", { + hidden: "hidden", + inside: this.container + }); + + this.status = $.create("span", { + className: "visually-hidden", + role: "status", + "aria-live": "assertive", + "aria-relevant": "additions", + inside: this.container + }); + + // Bind events + + $.bind(this.input, { + "input": this.evaluate.bind(this), + "blur": this.close.bind(this, { reason: "blur" }), + "keydown": function (evt) { + var c = evt.keyCode; + + // If the dropdown `ul` is in view, then act on keydown for the following keys: + // Enter / Esc / Up / Down + if (me.opened) { + if (c === 13 && me.selected) { + // Enter + evt.preventDefault(); + me.select(); + } else if (c === 27) { + // Esc + me.close({ reason: "esc" }); + } else if (c === 38 || c === 40) { + // Down/Up arrow + evt.preventDefault(); + me[c === 38 ? "previous" : "next"](); + } + } + } + }); + + $.bind(this.input.form, { "submit": this.close.bind(this, { reason: "submit" }) }); + + $.bind(this.ul, { "mousedown": function (evt) { + var li = evt.target; + + if (li !== this) { + + while (li && !/li/i.test(li.nodeName)) { + li = li.parentNode; + } + + if (li && evt.button === 0) { + // Only select on left click + evt.preventDefault(); + me.select(li, evt.target); + } + } + } }); + + if (this.input.hasAttribute("list")) { + this.list = "#" + this.input.getAttribute("list"); + this.input.removeAttribute("list"); + } else { + this.list = this.input.getAttribute("data-list") || o.list || []; + } + + _.all.push(this); + }; + + _.prototype = { + set list(list) { + if (Array.isArray(list)) { + this._list = list; + } else if (typeof list === "string" && list.indexOf(",") > -1) { + this._list = list.split(/\s*,\s*/); + } else { + // Element or CSS selector + list = $(list); + + if (list && list.children) { + var items = []; + slice.apply(list.children).forEach(function (el) { + if (!el.disabled) { + var text = el.textContent.trim(); + var value = el.value || text; + var label = el.label || text; + if (value !== "") { + items.push({ label: label, value: value }); + } + } + }); + this._list = items; + } + } + + if (document.activeElement === this.input) { + this.evaluate(); + } + }, + + get selected() { + return this.index > -1; + }, + + get opened() { + return !this.ul.hasAttribute("hidden"); + }, + + close: function (o) { + if (!this.opened) { + return; + } + + this.ul.setAttribute("hidden", ""); + this.index = -1; + + $.fire(this.input, "awesomplete-close", o || {}); + }, + + open: function () { + this.ul.removeAttribute("hidden"); + + if (this.autoFirst && this.index === -1) { + this.goto(0); + } + + $.fire(this.input, "awesomplete-open"); + }, + + next: function () { + var count = this.ul.children.length; + + this.goto(this.index < count - 1 ? this.index + 1 : -1); + }, + + previous: function () { + var count = this.ul.children.length; + + this.goto(this.selected ? this.index - 1 : count - 1); + }, + + // Should not be used, highlights specific item without any checks! + goto: function (i) { + var lis = this.ul.children; + + if (this.selected) { + lis[this.index].setAttribute("aria-selected", "false"); + } + + this.index = i; + + if (i > -1 && lis.length > 0) { + lis[i].setAttribute("aria-selected", "true"); + this.status.textContent = lis[i].textContent; + + $.fire(this.input, "awesomplete-highlight", { + text: this.suggestions[this.index] + }); + } + }, + + select: function (selected, origin) { + if (selected) { + this.index = $.siblingIndex(selected); + } else { + selected = this.ul.children[this.index]; + } + + if (selected) { + var suggestion = this.suggestions[this.index]; + + var allowed = $.fire(this.input, "awesomplete-select", { + text: suggestion, + origin: origin || selected + }); + + if (allowed) { + this.replace(suggestion); + this.close({ reason: "select" }); + $.fire(this.input, "awesomplete-selectcomplete", { + text: suggestion + }); + } + } + }, + + evaluate: function () { + var me = this; + var value = this.input.value; + + if (value.length >= this.minChars && this._list.length > 0) { + this.index = -1; + // Populate list with options that match + this.ul.innerHTML = ""; + + this.suggestions = this._list.map(function (item) { + return new Suggestion(me.data(item, value)); + }).filter(function (item) { + return me.filter(item, value); + }).sort(this.sort).slice(0, this.maxItems); + + this.suggestions.forEach(function (text) { + me.ul.appendChild(me.item(text, value)); + }); + + if (this.ul.children.length === 0) { + this.close({ reason: "nomatches" }); + } else { + this.open(); + } + } else { + this.close({ reason: "nomatches" }); + } + } + }; + + // Static methods/properties + + _.all = []; + + _.FILTER_CONTAINS = function (text, input) { + return RegExp($.regExpEscape(input.trim()), "i").test(text); + }; + + _.FILTER_STARTSWITH = function (text, input) { + return RegExp("^" + $.regExpEscape(input.trim()), "i").test(text); + }; + + _.SORT_BYLENGTH = function (a, b) { + if (a.length !== b.length) { + return a.length - b.length; + } + + return a < b ? -1 : 1; + }; + + _.ITEM = function (text, input) { + var html = input === '' ? text : text.replace(RegExp($.regExpEscape(input.trim()), "gi"), "<mark>$&</mark>"); + return $.create("li", { + innerHTML: html, + "aria-selected": "false" + }); + }; + + _.REPLACE = function (text) { + this.input.value = text.value; + }; + + _.DATA = function (item /*, input*/) { + return item; + }; + + // Private functions + + function Suggestion(data) { + var o = Array.isArray(data) ? { label: data[0], value: data[1] } : typeof data === "object" && "label" in data && "value" in data ? data : { label: data, value: data }; + + this.label = o.label || o.value; + this.value = o.value; + } + Object.defineProperty(Suggestion.prototype = Object.create(String.prototype), "length", { + get: function () { + return this.label.length; + } + }); + Suggestion.prototype.toString = Suggestion.prototype.valueOf = function () { + return "" + this.label; + }; + + function configure(instance, properties, o) { + for (var i in properties) { + var initial = properties[i], + attrValue = instance.input.getAttribute("data-" + i.toLowerCase()); + + if (typeof initial === "number") { + instance[i] = parseInt(attrValue); + } else if (initial === false) { + // Boolean options must be false by default anyway + instance[i] = attrValue !== null; + } else if (initial instanceof Function) { + instance[i] = null; + } else { + instance[i] = attrValue; + } + + if (!instance[i] && instance[i] !== 0) { + instance[i] = i in o ? o[i] : initial; + } + } + } + + // Helpers + + var slice = Array.prototype.slice; + + function $(expr, con) { + return typeof expr === "string" ? (con || document).querySelector(expr) : expr || null; + } + + function $$(expr, con) { + return slice.call((con || document).querySelectorAll(expr)); + } + + $.create = function (tag, o) { + var element = document.createElement(tag); + + for (var i in o) { + var val = o[i]; + + if (i === "inside") { + $(val).appendChild(element); + } else if (i === "around") { + var ref = $(val); + ref.parentNode.insertBefore(element, ref); + element.appendChild(ref); + } else if (i in element) { + element[i] = val; + } else { + element.setAttribute(i, val); + } + } + + return element; + }; + + $.bind = function (element, o) { + if (element) { + for (var event in o) { + var callback = o[event]; + + event.split(/\s+/).forEach(function (event) { + element.addEventListener(event, callback); + }); + } + } + }; + + $.fire = function (target, type, properties) { + var evt = document.createEvent("HTMLEvents"); + + evt.initEvent(type, true, true); + + for (var j in properties) { + evt[j] = properties[j]; + } + + return target.dispatchEvent(evt); + }; + + $.regExpEscape = function (s) { + return s.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); + }; + + $.siblingIndex = function (el) { + /* eslint-disable no-cond-assign */ + for (var i = 0; el = el.previousElementSibling; i++); + return i; + }; + + // Initialization + + function init() { + $$("input.awesomplete").forEach(function (input) { + new _(input); + }); + } + + // Are we in a browser? Check for Document constructor + if (typeof Document !== "undefined") { + // DOM already loaded? + if (document.readyState !== "loading") { + init(); + } else { + // Wait for it + document.addEventListener("DOMContentLoaded", init); + } + } + + _.$ = $; + _.$$ = $$; + + // Make sure to export Awesomplete on self when in a browser + if (typeof self !== "undefined") { + self.Awesomplete = _; + } + + // Expose Awesomplete as a CJS module + if (typeof module === "object" && module.exports) { + module.exports = _; + } + + return _; + })(); + +/***/ }, +/* 225 */ +/***/ function(module, exports, __webpack_require__) { + + // style-loader: Adds some css to the DOM by adding a <style> tag + + // load the styles + var content = __webpack_require__(226); + if(typeof content === 'string') content = [[module.id, content, '']]; + // add the styles to the DOM + var update = __webpack_require__(228)(content, {}); + if(content.locals) module.exports = content.locals; + // Hot Module Replacement + if(false) { + // When the styles change, update the <style> tags + if(!content.locals) { + module.hot.accept("!!./../../node_modules/css-loader/index.js!./d3.slider.css", function() { + var newContent = require("!!./../../node_modules/css-loader/index.js!./d3.slider.css"); + if(typeof newContent === 'string') newContent = [[module.id, newContent, '']]; + update(newContent); + }); + } + // When the module is disposed, remove the <style> tags + module.hot.dispose(function() { update(); }); + } + +/***/ }, +/* 226 */ +/***/ function(module, exports, __webpack_require__) { + + exports = module.exports = __webpack_require__(227)(); + // imports + + + // module + exports.push([module.id, ".d3-slider {\n position: relative;\n font-family: Verdana,Arial,sans-serif;\n font-size: 1.1em;\n border: 1px solid #aaaaaa;\n z-index: 2;\n}\n\n.d3-slider-horizontal {\n height: .8em;\n} \n\n.d3-slider-range {\n background:#2980b9;\n left:0px;\n right:0px;\n height: 0.8em;\n position: absolute;\n}\n\n.d3-slider-range-vertical {\n background:#2980b9;\n left:0px;\n right:0px;\n position: absolute;\n top:0;\n}\n\n.d3-slider-vertical {\n width: .8em;\n height: 100px;\n} \n\n.d3-slider-handle {\n position: absolute;\n width: 1.2em;\n height: 1.2em;\n border: 1px solid #d3d3d3;\n border-radius: 4px;\n background: #eee;\n background: linear-gradient(to bottom, #eee 0%, #ddd 100%);\n z-index: 3;\n}\n\n.d3-slider-handle:hover {\n border: 1px solid #999999;\n}\n\n.d3-slider-horizontal .d3-slider-handle {\n top: -.3em;\n margin-left: -.6em;\n}\n\n.d3-slider-axis {\n position: relative;\n z-index: 1; \n}\n\n.d3-slider-axis-bottom {\n top: .8em;\n}\n\n.d3-slider-axis-right {\n left: .8em;\n}\n\n.d3-slider-axis path {\n stroke-width: 0;\n fill: none;\n}\n\n.d3-slider-axis line {\n fill: none;\n stroke: #aaa;\n shape-rendering: crispEdges;\n}\n\n.d3-slider-axis text {\n font-size: 11px;\n}\n\n.d3-slider-vertical .d3-slider-handle {\n left: -.25em;\n margin-left: 0;\n margin-bottom: -.6em; \n}", ""]); + + // exports + + +/***/ }, +/* 227 */ +/***/ function(module, exports) { + + /* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + */ + // css base code, injected by the css-loader + module.exports = function () { + var list = []; + + // return the list of modules as css string + list.toString = function toString() { + var result = []; + for (var i = 0; i < this.length; i++) { + var item = this[i]; + if (item[2]) { + result.push("@media " + item[2] + "{" + item[1] + "}"); + } else { + result.push(item[1]); + } + } + return result.join(""); + }; + + // import a list of modules into the list + list.i = function (modules, mediaQuery) { + if (typeof modules === "string") modules = [[null, modules, ""]]; + var alreadyImportedModules = {}; + for (var i = 0; i < this.length; i++) { + var id = this[i][0]; + if (typeof id === "number") alreadyImportedModules[id] = true; + } + for (i = 0; i < modules.length; i++) { + var item = modules[i]; + // skip already imported module + // this implementation is not 100% perfect for weird media query combinations + // when a module is imported multiple times with different media queries. + // I hope this will never occur (Hey this way we have smaller bundles) + if (typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) { + if (mediaQuery && !item[2]) { + item[2] = mediaQuery; + } else if (mediaQuery) { + item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"; + } + list.push(item); + } + } + }; + return list; + }; + +/***/ }, +/* 228 */ +/***/ function(module, exports, __webpack_require__) { + + /* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra + */ + var stylesInDom = {}, + memoize = function(fn) { + var memo; + return function () { + if (typeof memo === "undefined") memo = fn.apply(this, arguments); + return memo; + }; + }, + isOldIE = memoize(function() { + return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase()); + }), + getHeadElement = memoize(function () { + return document.head || document.getElementsByTagName("head")[0]; + }), + singletonElement = null, + singletonCounter = 0, + styleElementsInsertedAtTop = []; + + module.exports = function(list, options) { + if(false) { + if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment"); + } + + options = options || {}; + // Force single-tag solution on IE6-9, which has a hard limit on the # of <style> + // tags it will allow on a page + if (typeof options.singleton === "undefined") options.singleton = isOldIE(); + + // By default, add <style> tags to the bottom of <head>. + if (typeof options.insertAt === "undefined") options.insertAt = "bottom"; + + var styles = listToStyles(list); + addStylesToDom(styles, options); + + return function update(newList) { + var mayRemove = []; + for(var i = 0; i < styles.length; i++) { + var item = styles[i]; + var domStyle = stylesInDom[item.id]; + domStyle.refs--; + mayRemove.push(domStyle); + } + if(newList) { + var newStyles = listToStyles(newList); + addStylesToDom(newStyles, options); + } + for(var i = 0; i < mayRemove.length; i++) { + var domStyle = mayRemove[i]; + if(domStyle.refs === 0) { + for(var j = 0; j < domStyle.parts.length; j++) + domStyle.parts[j](); + delete stylesInDom[domStyle.id]; + } + } + }; + } + + function addStylesToDom(styles, options) { + for(var i = 0; i < styles.length; i++) { + var item = styles[i]; + var domStyle = stylesInDom[item.id]; + if(domStyle) { + domStyle.refs++; + for(var j = 0; j < domStyle.parts.length; j++) { + domStyle.parts[j](item.parts[j]); + } + for(; j < item.parts.length; j++) { + domStyle.parts.push(addStyle(item.parts[j], options)); + } + } else { + var parts = []; + for(var j = 0; j < item.parts.length; j++) { + parts.push(addStyle(item.parts[j], options)); + } + stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts}; + } + } + } + + function listToStyles(list) { + var styles = []; + var newStyles = {}; + for(var i = 0; i < list.length; i++) { + var item = list[i]; + var id = item[0]; + var css = item[1]; + var media = item[2]; + var sourceMap = item[3]; + var part = {css: css, media: media, sourceMap: sourceMap}; + if(!newStyles[id]) + styles.push(newStyles[id] = {id: id, parts: [part]}); + else + newStyles[id].parts.push(part); + } + return styles; + } + + function insertStyleElement(options, styleElement) { + var head = getHeadElement(); + var lastStyleElementInsertedAtTop = styleElementsInsertedAtTop[styleElementsInsertedAtTop.length - 1]; + if (options.insertAt === "top") { + if(!lastStyleElementInsertedAtTop) { + head.insertBefore(styleElement, head.firstChild); + } else if(lastStyleElementInsertedAtTop.nextSibling) { + head.insertBefore(styleElement, lastStyleElementInsertedAtTop.nextSibling); + } else { + head.appendChild(styleElement); + } + styleElementsInsertedAtTop.push(styleElement); + } else if (options.insertAt === "bottom") { + head.appendChild(styleElement); + } else { + throw new Error("Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'."); + } + } + + function removeStyleElement(styleElement) { + styleElement.parentNode.removeChild(styleElement); + var idx = styleElementsInsertedAtTop.indexOf(styleElement); + if(idx >= 0) { + styleElementsInsertedAtTop.splice(idx, 1); + } + } + + function createStyleElement(options) { + var styleElement = document.createElement("style"); + styleElement.type = "text/css"; + insertStyleElement(options, styleElement); + return styleElement; + } + + function createLinkElement(options) { + var linkElement = document.createElement("link"); + linkElement.rel = "stylesheet"; + insertStyleElement(options, linkElement); + return linkElement; + } + + function addStyle(obj, options) { + var styleElement, update, remove; + + if (options.singleton) { + var styleIndex = singletonCounter++; + styleElement = singletonElement || (singletonElement = createStyleElement(options)); + update = applyToSingletonTag.bind(null, styleElement, styleIndex, false); + remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true); + } else if(obj.sourceMap && + typeof URL === "function" && + typeof URL.createObjectURL === "function" && + typeof URL.revokeObjectURL === "function" && + typeof Blob === "function" && + typeof btoa === "function") { + styleElement = createLinkElement(options); + update = updateLink.bind(null, styleElement); + remove = function() { + removeStyleElement(styleElement); + if(styleElement.href) + URL.revokeObjectURL(styleElement.href); + }; + } else { + styleElement = createStyleElement(options); + update = applyToTag.bind(null, styleElement); + remove = function() { + removeStyleElement(styleElement); + }; + } + + update(obj); + + return function updateStyle(newObj) { + if(newObj) { + if(newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) + return; + update(obj = newObj); + } else { + remove(); + } + }; + } + + var replaceText = (function () { + var textStore = []; + + return function (index, replacement) { + textStore[index] = replacement; + return textStore.filter(Boolean).join('\n'); + }; + })(); + + function applyToSingletonTag(styleElement, index, remove, obj) { + var css = remove ? "" : obj.css; + + if (styleElement.styleSheet) { + styleElement.styleSheet.cssText = replaceText(index, css); + } else { + var cssNode = document.createTextNode(css); + var childNodes = styleElement.childNodes; + if (childNodes[index]) styleElement.removeChild(childNodes[index]); + if (childNodes.length) { + styleElement.insertBefore(cssNode, childNodes[index]); + } else { + styleElement.appendChild(cssNode); + } + } + } + + function applyToTag(styleElement, obj) { + var css = obj.css; + var media = obj.media; + + if(media) { + styleElement.setAttribute("media", media) + } + + if(styleElement.styleSheet) { + styleElement.styleSheet.cssText = css; + } else { + while(styleElement.firstChild) { + styleElement.removeChild(styleElement.firstChild); + } + styleElement.appendChild(document.createTextNode(css)); + } + } + + function updateLink(linkElement, obj) { + var css = obj.css; + var sourceMap = obj.sourceMap; + + if(sourceMap) { + // http://stackoverflow.com/a/26603875 + css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */"; + } + + var blob = new Blob([css], { type: "text/css" }); + + var oldSrc = linkElement.href; + + linkElement.href = URL.createObjectURL(blob); + + if(oldSrc) + URL.revokeObjectURL(oldSrc); + } + + +/***/ }, +/* 229 */ +/***/ function(module, exports, __webpack_require__) { + + // style-loader: Adds some css to the DOM by adding a <style> tag + + // load the styles + var content = __webpack_require__(230); + if(typeof content === 'string') content = [[module.id, content, '']]; + // add the styles to the DOM + var update = __webpack_require__(228)(content, {}); + if(content.locals) module.exports = content.locals; + // Hot Module Replacement + if(false) { + // When the styles change, update the <style> tags + if(!content.locals) { + module.hot.accept("!!./../css-loader/index.js!./awesomplete.css", function() { + var newContent = require("!!./../css-loader/index.js!./awesomplete.css"); + if(typeof newContent === 'string') newContent = [[module.id, newContent, '']]; + update(newContent); + }); + } + // When the module is disposed, remove the <style> tags + module.hot.dispose(function() { update(); }); + } + +/***/ }, +/* 230 */ +/***/ function(module, exports, __webpack_require__) { + + exports = module.exports = __webpack_require__(227)(); + // imports + + + // module + exports.push([module.id, "[hidden] { display: none; }\n\n.visually-hidden {\n\tposition: absolute;\n\tclip: rect(0, 0, 0, 0);\n}\n\ndiv.awesomplete {\n\tdisplay: inline-block;\n\tposition: relative;\n}\n\ndiv.awesomplete > input {\n\tdisplay: block;\n}\n\ndiv.awesomplete > ul {\n\tposition: absolute;\n\tleft: 0;\n\tz-index: 1;\n\tmin-width: 100%;\n\tbox-sizing: border-box;\n\tlist-style: none;\n\tpadding: 0;\n\tborder-radius: .3em;\n\tmargin: .2em 0 0;\n\tbackground: hsla(0,0%,100%,.9);\n\tbackground: linear-gradient(to bottom right, white, hsla(0,0%,100%,.8));\n\tborder: 1px solid rgba(0,0,0,.3);\n\tbox-shadow: .05em .2em .6em rgba(0,0,0,.2);\n\ttext-shadow: none;\n}\n\ndiv.awesomplete > ul[hidden],\ndiv.awesomplete > ul:empty {\n\tdisplay: none;\n}\n\n@supports (transform: scale(0)) {\n\tdiv.awesomplete > ul {\n\t\ttransition: .3s cubic-bezier(.4,.2,.5,1.4);\n\t\ttransform-origin: 1.43em -.43em;\n\t}\n\t\n\tdiv.awesomplete > ul[hidden],\n\tdiv.awesomplete > ul:empty {\n\t\topacity: 0;\n\t\ttransform: scale(0);\n\t\tdisplay: block;\n\t\ttransition-timing-function: ease;\n\t}\n}\n\n\t/* Pointer */\n\tdiv.awesomplete > ul:before {\n\t\tcontent: \"\";\n\t\tposition: absolute;\n\t\ttop: -.43em;\n\t\tleft: 1em;\n\t\twidth: 0; height: 0;\n\t\tpadding: .4em;\n\t\tbackground: white;\n\t\tborder: inherit;\n\t\tborder-right: 0;\n\t\tborder-bottom: 0;\n\t\t-webkit-transform: rotate(45deg);\n\t\ttransform: rotate(45deg);\n\t}\n\n\tdiv.awesomplete > ul > li {\n\t\tposition: relative;\n\t\tpadding: .2em .5em;\n\t\tcursor: pointer;\n\t}\n\t\n\tdiv.awesomplete > ul > li:hover {\n\t\tbackground: hsl(200, 40%, 80%);\n\t\tcolor: black;\n\t}\n\t\n\tdiv.awesomplete > ul > li[aria-selected=\"true\"] {\n\t\tbackground: hsl(205, 40%, 40%);\n\t\tcolor: white;\n\t}\n\t\n\t\tdiv.awesomplete mark {\n\t\t\tbackground: hsl(65, 100%, 50%);\n\t\t}\n\t\t\n\t\tdiv.awesomplete li:hover mark {\n\t\t\tbackground: hsl(68, 100%, 41%);\n\t\t}\n\t\t\n\t\tdiv.awesomplete li[aria-selected=\"true\"] mark {\n\t\t\tbackground: hsl(86, 100%, 21%);\n\t\t\tcolor: inherit;\n\t\t}", ""]); + + // exports + + +/***/ }, +/* 231 */ +/***/ function(module, exports, __webpack_require__) { + + var ini_sidebar = __webpack_require__(192); + var set_up_filters = __webpack_require__(232); + var set_up_search = __webpack_require__(237); + var set_up_reorder = __webpack_require__(238); + var set_sidebar_ini_view = __webpack_require__(239); + var make_icons = __webpack_require__(240); + var make_modals = __webpack_require__(242); + var set_up_opacity_slider = __webpack_require__(244); + var make_colorbar = __webpack_require__(245); + + /* Represents sidebar with controls. + */ + module.exports = function sidebar(cgm) { + + var params = cgm.params; + + var sidebar = d3.select(params.root + ' .sidebar_wrapper'); + + // console.log('is_expand ',params.viz.is_expand) + + if (params.viz.is_expand) { + sidebar.style('display', 'none'); + } + + sidebar.append('div').classed('title_section', true); + + if (params.sidebar.title != null) { + sidebar.select('.title_section').append('h4') + // .style('margin-left', params.sidebar.title_margin_left+'px') + .style('margin-left', '20px').style('margin-top', '5px').style('margin-bottom', '0px').text(params.sidebar.title); + } + + sidebar.append('div').style('padding-right', '2px').classed('about_section', true); + + if (params.sidebar.about != null) { + + sidebar.select('.about_section').append('h5').classed('sidebar_text', true).style('margin-left', '7px').style('margin-top', '5px').style('margin-bottom', '2px').style('text-align', 'justify').html(params.sidebar.about); + } + + sidebar.append('div').classed('icons_section', true).style('text-align', 'center'); + + if (cgm.params.make_modals) { + make_modals(params); + } + + if (params.sidebar.icons) { + make_icons(cgm, sidebar); + } + + set_up_reorder(params, sidebar); + + set_up_search(sidebar, params); + + set_up_opacity_slider(sidebar); + + var possible_filter_names = _.keys(params.viz.possible_filters); + + if (possible_filter_names.indexOf('enr_score_type') > -1) { + possible_filter_names.sort(function (a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()); + }); + } + + cgm.slider_functions = {}; + + _.each(possible_filter_names, function (inst_filter) { + set_up_filters(cgm, inst_filter); + }); + + ini_sidebar(cgm); + + // when initializing the visualization using a view + if (params.ini_view !== null) { + + set_sidebar_ini_view(params); + + params.ini_view = null; + } + + make_colorbar(cgm); + }; + +/***/ }, +/* 232 */ +/***/ function(module, exports, __webpack_require__) { + + var make_slider_filter = __webpack_require__(233); + var make_button_filter = __webpack_require__(236); + + module.exports = function set_up_filters(cgm, filter_type) { + + var params = cgm.params; + + var div_filters = d3.select(params.root + ' .sidebar_wrapper').append('div').classed('div_filters', true).style('padding-left', '10px').style('padding-right', '10px'); + + if (params.viz.possible_filters[filter_type] == 'numerical') { + make_slider_filter(cgm, filter_type, div_filters); + } else if (params.viz.possible_filters[filter_type] == 'categorical') { + make_button_filter(cgm, filter_type, div_filters); + } + }; + +/***/ }, +/* 233 */ +/***/ function(module, exports, __webpack_require__) { + + var make_filter_title = __webpack_require__(215); + var run_filter_slider = __webpack_require__(234); + var get_filter_default_state = __webpack_require__(5); + var get_subset_views = __webpack_require__(12); + + d3.slider = __webpack_require__(222); + + module.exports = function make_slider_filter(cgm, filter_type, div_filters) { + + var params = cgm.params; + var inst_view = {}; + + var possible_filters = _.keys(params.viz.possible_filters); + + _.each(possible_filters, function (tmp_filter) { + if (tmp_filter != filter_type) { + var default_state = get_filter_default_state(params.viz.filter_data, tmp_filter); + inst_view[tmp_filter] = default_state; + } + }); + + var filter_title = make_filter_title(params, filter_type); + + div_filters.append('div').classed('title_' + filter_type, true).classed('sidebar_text', true).classed('slider_description', true).style('margin-top', '5px').style('margin-bottom', '3px').text(filter_title.text + filter_title.state + filter_title.suffix); + + div_filters.append('div').classed('slider_' + filter_type, true).classed('slider', true).attr('current_state', filter_title.state); + + var views = params.network_data.views; + + var available_views = get_subset_views(params, views, inst_view); + + // sort available views by filter_type value + available_views = available_views.sort(function (a, b) { + return b[filter_type] - a[filter_type]; + }); + + var inst_max = available_views.length - 1; + + var ini_value = 0; + // change the starting position of the slider if necessary + if (params.requested_view !== null && filter_type in params.requested_view) { + + var inst_filter_value = params.requested_view[filter_type]; + + if (inst_filter_value != 'all') { + + var found_value = available_views.map(function (e) { + return e[filter_type]; + }).indexOf(inst_filter_value); + + if (found_value > 0) { + ini_value = found_value; + } + } + } + + // Filter Slider + ////////////////////////////////////////////////////////////////////// + var slide_filter_fun = d3.slider().value(ini_value).min(0).max(inst_max).step(1).on('slide', function (evt, value) { + run_filter_slider_db(cgm, filter_type, available_views, value); + }).on('slideend', function (evt, value) { + run_filter_slider_db(cgm, filter_type, available_views, value); + }); + + // save slider function in order to reset value later + cgm.slider_functions[filter_type] = slide_filter_fun; + + d3.select(cgm.params.root + ' .slider_' + filter_type).call(slide_filter_fun); + + ////////////////////////////////////////////////////////////////////// + + var run_filter_slider_db = _.debounce(run_filter_slider, 800); + }; + +/***/ }, +/* 234 */ +/***/ function(module, exports, __webpack_require__) { + + var update_viz_with_view = __webpack_require__(177); + var reset_other_filter_sliders = __webpack_require__(214); + var get_current_orders = __webpack_require__(235); + var make_requested_view = __webpack_require__(14); + + module.exports = function run_filter_slider(cgm, filter_type, available_views, inst_index) { + + // only update if not running update + if (d3.select(cgm.params.viz.viz_svg).classed('running_update') === false) { + + var params = cgm.params; + + // get value + var inst_state = available_views[inst_index][filter_type]; + + reset_other_filter_sliders(cgm, filter_type, inst_state); + + params = get_current_orders(params); + + var requested_view = {}; + requested_view[filter_type] = inst_state; + + requested_view = make_requested_view(params, requested_view); + + if (_.has(available_views[0], 'enr_score_type')) { + var enr_state = d3.select(params.root + ' .toggle_enr_score_type').attr('current_state'); + + requested_view.enr_score_type = enr_state; + } + + update_viz_with_view(cgm, requested_view); + } + }; + +/***/ }, +/* 235 */ +/***/ function(module, exports) { + + module.exports = function get_current_orders(params) { + + // get current orders + var other_rc; + _.each(['row', 'col'], function (inst_rc) { + + if (inst_rc === 'row') { + other_rc = 'col'; + } else { + other_rc = 'row'; + } + + if (d3.select(params.root + ' .toggle_' + other_rc + '_order .active').empty() === false) { + + params.viz.inst_order[inst_rc] = d3.select(params.root + ' .toggle_' + other_rc + '_order').select('.active').attr('name'); + } else { + + // default to cluster ordering + params.viz.inst_order[inst_rc] = 'clust'; + } + }); + + return params; + }; + +/***/ }, +/* 236 */ +/***/ function(module, exports, __webpack_require__) { + + // var update_network = require('../network/update_network'); + var make_requested_view = __webpack_require__(14); + + module.exports = function make_button_filter(config, params, filter_type, div_filters) { + + /* + Enrichr specific code + */ + + var buttons = div_filters.append('div').classed('categorical_filter', true).classed('toggle_' + filter_type, true).classed('btn-group-vertical', true).style('width', '100%').style('margin-top', '10px').attr('current_state', 'combined_score'); + + var filter_options = params.viz.filter_data[filter_type]; + + var button_dict = { + 'combined_score': 'Combined Score', + 'pval': 'P-Value', + 'zscore': 'Z-score' + }; + + buttons.selectAll('button').data(filter_options).enter().append('button').attr('type', 'button').classed('btn', true).classed('btn-primary', true).classed('.filter_button', true).classed('active', function (d) { + var is_active = false; + if (d == 'combined_score') { + is_active = true; + } + return is_active; + }).attr('name', function (d) { + return d; + }).html(function (d) { + return button_dict[d]; + }); + + $(params.root + ' .categorical_filter .btn').off().click(function () { + + d3.selectAll(params.root + ' .categorical_filter .btn').classed('active', false); + + d3.select(this).classed('active', true); + + var inst_state = d3.select(this).attr('name'); + + var requested_view = { 'enr_score_type': inst_state }; + + make_requested_view(params, requested_view); + + d3.select(params.root + ' .toggle_enr_score_type').attr('current_state', inst_state); + }); + }; + +/***/ }, +/* 237 */ +/***/ function(module, exports) { + + module.exports = function set_up_search(sidebar, params) { + + var search_container = sidebar.append('div') + // .classed('row',true) + .classed('gene_search_container', true).style('padding-left', '10px').style('padding-right', '10px').style('margin-top', '10px'); + + search_container.append('input').classed('form-control', true).classed('gene_search_box', true).classed('sidebar_text', true).attr('type', 'text').attr('placeholder', params.sidebar.row_search.placeholder).style('height', params.sidebar.row_search.box.height + 'px').style('margin-top', '10px'); + + search_container.append('div').classed('gene_search_button', true).style('margin-top', '5px').attr('data-toggle', 'buttons').append('button').classed('sidebar_text', true).html('Search').attr('type', 'button').classed('btn', true).classed('btn-primary', true).classed('submit_gene_button', true).style('width', '100%').style('font-size', '14px'); + }; + +/***/ }, +/* 238 */ +/***/ function(module, exports) { + + // var get_cat_title = require('../categories/get_cat_title'); + + module.exports = function set_up_reorder(params, sidebar) { + + var button_dict; + var tmp_orders; + var rc_dict = { 'row': 'Row', 'col': 'Column', 'both': '' }; + var is_active; + var inst_reorder; + // var all_cats; + // var inst_order_label; + + var reorder_section = sidebar.append('div').style('padding-left', '10px').style('padding-right', '10px').classed('reorder_section', true); + + var reorder_types; + if (params.sim_mat) { + reorder_types = ['both']; + } else { + reorder_types = ['row', 'col']; + } + + _.each(reorder_types, function (inst_rc) { + + button_dict = { + 'clust': 'Cluster', + 'rank': 'Rank by Sum', + 'rankvar': 'Rank by Variance', + 'ini': 'Initial Order', + 'alpha': 'Alphabetically' + }; + + var other_rc; + if (inst_rc === 'row') { + other_rc = 'col'; + } else { + other_rc = 'row'; + } + + tmp_orders = Object.keys(params.matrix.orders); + + var possible_orders = []; + + _.each(tmp_orders, function (inst_name) { + + if (inst_name.indexOf(other_rc) > -1) { + inst_name = inst_name.replace('_row', '').replace('_col', ''); + + if (inst_name.indexOf('cat_') < 0) { + possible_orders.push(inst_name); + } + } + }); + + // specific to Enrichr + if (_.keys(params.viz.filter_data).indexOf('enr_score_type') > -1) { + possible_orders = ['clust', 'rank']; + } + + possible_orders = _.uniq(possible_orders); + + possible_orders = possible_orders.sort(); + + var reorder_text; + if (inst_rc != 'both') { + reorder_text = ' Order'; + } else { + reorder_text = 'Reorder Matrix'; + } + + reorder_section.append('div').classed('sidebar_button_text', true).style('clear', 'both').style('margin-top', '10px').html(rc_dict[inst_rc] + reorder_text); + + inst_reorder = reorder_section.append('div').classed('btn-group-vertical', true).style('width', '100%').classed('toggle_' + inst_rc + '_order', true).attr('role', 'group'); + + inst_reorder.selectAll('.button').data(possible_orders).enter().append('button').attr('type', 'button').classed('btn', true).classed('btn-primary', true).classed('sidebar_button_text', true).classed('active', function (d) { + is_active = false; + if (d == params.viz.inst_order[other_rc]) { + is_active = true; + } + return is_active; + }).attr('name', function (d) { + return d; + }).html(function (d) { + return button_dict[d]; + }); + }); + }; + +/***/ }, +/* 239 */ +/***/ function(module, exports, __webpack_require__) { + + var make_filter_title = __webpack_require__(215); + + module.exports = function set_sidebar_ini_view(params) { + + _.each(_.keys(params.ini_view), function (inst_filter) { + + // initialize filter slider using ini_view + var inst_value = params.ini_view[inst_filter]; + + var filter_type = params.viz.possible_filters[inst_filter]; + + if (filter_type === 'numerical') { + + if (inst_value != 'all') { + inst_value = parseInt(inst_value, 10); + } + + if (params.viz.filter_data[inst_filter].indexOf(inst_value) <= -1) { + inst_value = 'all'; + } + + var filter_title = make_filter_title(params, inst_filter); + + d3.select(params.root + ' .title_' + inst_filter).text(filter_title.text + inst_value + filter_title.suffix); + + d3.select(params.root + ' .slider_' + inst_filter).attr('current_state', inst_value); + } else { + + // set up button initialization + + } + }); + }; + +/***/ }, +/* 240 */ +/***/ function(module, exports, __webpack_require__) { + + var file_saver = __webpack_require__(217); + var two_translate_zoom = __webpack_require__(116); + var deactivate_cropping = __webpack_require__(221); + var save_svg_png = __webpack_require__(241); + + module.exports = function make_icons(cgm, sidebar) { + + var params = cgm.params; + // var saveSvgAsPng = save_svg_png(); + var saveAs = file_saver(); + + var row = sidebar.select('.icons_section').style('margin-top', '7px').style('margin-left', '5%'); + + var width_pct = '22%'; + var padding_left = '0px'; + var padding_right = '0px'; + + row.append('div').classed('clust_icon', true).style('float', 'left').style('width', width_pct).style('padding-left', padding_left).style('padding-right', padding_right).append('i').classed('fa', true).classed('fa-share-alt', true).classed('icon_buttons', true).style('font-size', '25px').on('click', function () { + $(params.root + ' .share_info').modal('toggle'); + $('.share_url').val(window.location.href); + }).classed('sidebar_tooltip', true).append('span').classed('sidebar_tooltip_text', true).html('Share').style('left', '0%'); + + row.append('div').classed('clust_icon', true).style('float', 'left').style('width', width_pct).style('padding-left', padding_left).style('padding-right', padding_right).append('i').classed('fa', true).classed('fa-camera', true).classed('icon_buttons', true).style('font-size', '25px').on('click', function () { + + $(params.root + ' .picture_info').modal('toggle'); + }).classed('sidebar_tooltip', true).append('span').classed('sidebar_tooltip_text', true).html('Take snapshot').style('left', '-100%'); + + row.append('div').classed('clust_icon', true).style('float', 'left').style('width', width_pct).style('padding-left', padding_left).style('padding-right', padding_right).append('i').classed('fa', true).classed('fa fa-cloud-download', true).classed('icon_buttons', true).style('font-size', '25px').on('click', function () { + + cgm.save_matrix(); + }).classed('sidebar_tooltip', true).append('span').classed('sidebar_tooltip_text', true).html('Download matrix').style('left', '-200%'); + + row.append('div').classed('clust_icon', true).style('float', 'left').style('width', width_pct).style('padding-left', padding_left).style('padding-right', '-5px').append('i').classed('fa', true).classed('fa-crop', true).classed('crop_button', true).classed('icon_buttons', true).style('font-size', '25px').on('click', function () { + + // do nothing if dendro filtering has been done + if (cgm.params.dendro_filter.row === false && cgm.params.dendro_filter.col === false) { + + var is_crop = d3.select(this).classed('fa-crop'); + + var is_undo = d3.select(this).classed('fa-undo'); + + // press crop button (can be active/incative) + if (is_crop) { + + // keep list of names to return to state + cgm.params.crop_filter_nodes = {}; + cgm.params.crop_filter_nodes.row_nodes = cgm.params.network_data.row_nodes; + cgm.params.crop_filter_nodes.col_nodes = cgm.params.network_data.col_nodes; + + cgm.brush_crop_matrix(); + + if (d3.select(this).classed('active_cropping') === false) { + + // set active_cropping (button turns red) + d3.select(this).classed('active_cropping', true).style('color', 'red'); + } else { + // deactivate cropping (button turns blue) + d3.select(this).classed('active_cropping', false).style('color', '#337ab7'); + + deactivate_cropping(cgm); + } + } + + // press undo button + if (is_undo) { + + d3.select(params.root + ' .crop_button').style('color', '#337ab7').classed('fa-crop', true).classed('fa-undo', false); + + // cgm.filter_viz_using_names(cgm.params.crop_filter_nodes); + cgm.filter_viz_using_nodes(cgm.params.crop_filter_nodes); + + // show dendro crop buttons after brush-cropping has been undone + d3.select(cgm.params.root + ' .col_dendro_icons_container').style('display', 'block'); + d3.select(cgm.params.root + ' .row_dendro_icons_container').style('display', 'block'); + } + + two_translate_zoom(cgm, 0, 0, 1); + } + }).classed('sidebar_tooltip', true).append('span').classed('sidebar_tooltip_text', true).html('Crop matrix').style('left', '-400%'); + + // save svg: example from: http://bl.ocks.org/pgiraud/8955139#profile.json + //////////////////////////////////////////////////////////////////////////// + function save_clust_svg() { + + d3.select(params.root + ' .expand_button').style('opacity', 0); + + var html = d3.select(params.root + " .viz_svg").attr("title", "test2").attr("version", 1.1).attr("xmlns", "http://www.w3.org/2000/svg").node().parentNode.innerHTML; + + var blob = new Blob([html], { type: "image/svg+xml" }); + + saveAs(blob, "clustergrammer.svg"); + + d3.select(params.root + ' .expand_button').style('opacity', 0.4); + } + + d3.select(params.root + ' .download_buttons').append('p').append('a').html('Download SVG').on('click', function () { + save_clust_svg(); + }); + + var svg_id = 'svg_' + params.root.replace('#', ''); + + // save as PNG + ///////////////////////////////////////// + d3.select(params.root + ' .download_buttons').append('p').append('a').html('Download PNG').on('click', function () { + d3.select(params.root + ' .expand_button').style('opacity', 0); + // saveSvgAsPng(document.getElementById(svg_id), "clustergrammer.png"); + save_svg_png.saveSvgAsPng(document.getElementById(svg_id), "clustergrammer.png"); + d3.select(params.root + ' .expand_button').style('opacity', 0.4); + }); + }; + +/***/ }, +/* 241 */ +/***/ function(module, exports, __webpack_require__) { + + var __WEBPACK_AMD_DEFINE_RESULT__;(function () { + var out$ = typeof exports != 'undefined' && exports || "function" != 'undefined' && {} || this; + + var doctype = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [<!ENTITY nbsp " ">]>'; + + function isElement(obj) { + return obj instanceof HTMLElement || obj instanceof SVGElement; + } + + function requireDomNode(el) { + if (!isElement(el)) { + throw new Error('an HTMLElement or SVGElement is required; got ' + el); + } + } + + function isExternal(url) { + return url && url.lastIndexOf('http', 0) == 0 && url.lastIndexOf(window.location.host) == -1; + } + + function inlineImages(el, callback) { + requireDomNode(el); + + var images = el.querySelectorAll('image'), + left = images.length, + checkDone = function () { + if (left === 0) { + callback(); + } + }; + + checkDone(); + for (var i = 0; i < images.length; i++) { + (function (image) { + var href = image.getAttributeNS("http://www.w3.org/1999/xlink", "href"); + if (href) { + if (isExternal(href.value)) { + console.warn("Cannot render embedded images linking to external hosts: " + href.value); + return; + } + } + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + var img = new Image(); + img.crossOrigin = "anonymous"; + href = href || image.getAttribute('href'); + if (href) { + img.src = href; + img.onload = function () { + canvas.width = img.width; + canvas.height = img.height; + ctx.drawImage(img, 0, 0); + image.setAttributeNS("http://www.w3.org/1999/xlink", "href", canvas.toDataURL('image/png')); + left--; + checkDone(); + }; + img.onerror = function () { + console.log("Could not load " + href); + left--; + checkDone(); + }; + } else { + left--; + checkDone(); + } + })(images[i]); + } + } + + function styles(el, options, cssLoadedCallback) { + var selectorRemap = options.selectorRemap; + var modifyStyle = options.modifyStyle; + var css = ""; + // each font that has extranl link is saved into queue, and processed + // asynchronously + var fontsQueue = []; + var sheets = document.styleSheets; + for (var i = 0; i < sheets.length; i++) { + try { + var rules = sheets[i].cssRules; + } catch (e) { + console.warn("Stylesheet could not be loaded: " + sheets[i].href); + continue; + } + + if (rules != null) { + for (var j = 0, match; j < rules.length; j++, match = null) { + var rule = rules[j]; + if (typeof rule.style != "undefined") { + var selectorText; + + try { + selectorText = rule.selectorText; + } catch (err) { + console.warn('The following CSS rule has an invalid selector: "' + rule + '"', err); + } + + try { + if (selectorText) { + match = el.querySelector(selectorText); + } + } catch (err) { + console.warn('Invalid CSS selector "' + selectorText + '"', err); + } + + if (match) { + var selector = selectorRemap ? selectorRemap(rule.selectorText) : rule.selectorText; + var cssText = modifyStyle ? modifyStyle(rule.style.cssText) : rule.style.cssText; + css += selector + " { " + cssText + " }\n"; + } else if (rule.cssText.match(/^@font-face/)) { + // below we are trying to find matches to external link. E.g. + // @font-face { + // // ... + // src: local('Abel'), url(https://fonts.gstatic.com/s/abel/v6/UzN-iejR1VoXU2Oc-7LsbvesZW2xOQ-xsNqO47m55DA.woff2); + // } + // + // This regex will save extrnal link into first capture group + var fontUrlRegexp = /url\(["']?(.+?)["']?\)/; + // TODO: This needs to be changed to support multiple url declarations per font. + var fontUrlMatch = rule.cssText.match(fontUrlRegexp); + + var externalFontUrl = fontUrlMatch && fontUrlMatch[1] || ''; + var fontUrlIsDataURI = externalFontUrl.match(/^data:/); + if (fontUrlIsDataURI) { + // We should ignore data uri - they are already embedded + externalFontUrl = ''; + } + + if (externalFontUrl) { + // okay, we are lucky. We can fetch this font later + fontsQueue.push({ + text: rule.cssText, + // Pass url regex, so that once font is downladed, we can run `replace()` on it + fontUrlRegexp: fontUrlRegexp, + format: getFontMimeTypeFromUrl(externalFontUrl), + url: externalFontUrl + }); + } else { + // otherwise, use previous logic + css += rule.cssText + '\n'; + } + } + } + } + } + } + + // Now all css is processed, it's time to handle scheduled fonts + processFontQueue(fontsQueue); + + function getFontMimeTypeFromUrl(fontUrl) { + var supportedFormats = { + 'woff2': 'font/woff2', + 'woff': 'font/woff', + 'otf': 'application/x-font-opentype', + 'ttf': 'application/x-font-ttf', + 'eot': 'application/vnd.ms-fontobject', + 'sfnt': 'application/font-sfnt', + 'svg': 'image/svg+xml' + }; + var extensions = Object.keys(supportedFormats); + for (var i = 0; i < extensions.length; ++i) { + var extension = extensions[i]; + // TODO: This is not bullet proof, it needs to handle edge cases... + if (fontUrl.indexOf('.' + extension) > 0) { + return supportedFormats[extension]; + } + } + + // If you see this error message, you probably need to update code above. + console.error('Unknown font format for ' + fontUrl + '; Fonts may not be working correctly'); + return 'application/octet-stream'; + } + + function processFontQueue(queue) { + if (queue.length > 0) { + // load fonts one by one until we have anything in the queue: + var font = queue.pop(); + processNext(font); + } else { + // no more fonts to load. + cssLoadedCallback(css); + } + + function processNext(font) { + // TODO: This could benefit from caching. + var oReq = new XMLHttpRequest(); + oReq.addEventListener('load', fontLoaded); + oReq.addEventListener('error', transferFailed); + oReq.addEventListener('abort', transferFailed); + oReq.open('GET', font.url); + oReq.responseType = 'arraybuffer'; + oReq.send(); + + function fontLoaded() { + // TODO: it may be also worth to wait until fonts are fully loaded before + // attempting to rasterize them. (e.g. use https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet ) + var fontBits = oReq.response; + var fontInBase64 = arrayBufferToBase64(fontBits); + updateFontStyle(font, fontInBase64); + } + + function transferFailed(e) { + console.warn('Failed to load font from: ' + font.url); + console.warn(e); + css += font.text + '\n'; + processFontQueue(); + } + + function updateFontStyle(font, fontInBase64) { + var dataUrl = 'url("data:' + font.format + ';base64,' + fontInBase64 + '")'; + css += font.text.replace(font.fontUrlRegexp, dataUrl) + '\n'; + + // schedule next font download on next tick. + setTimeout(function () { + processFontQueue(queue); + }, 0); + } + } + } + + function arrayBufferToBase64(buffer) { + var binary = ''; + var bytes = new Uint8Array(buffer); + var len = bytes.byteLength; + + for (var i = 0; i < len; i++) { + binary += String.fromCharCode(bytes[i]); + } + + return window.btoa(binary); + } + } + + function getDimension(el, clone, dim) { + var v = el.viewBox && el.viewBox.baseVal && el.viewBox.baseVal[dim] || clone.getAttribute(dim) !== null && !clone.getAttribute(dim).match(/%$/) && parseInt(clone.getAttribute(dim)) || el.getBoundingClientRect()[dim] || parseInt(clone.style[dim]) || parseInt(window.getComputedStyle(el).getPropertyValue(dim)); + return typeof v === 'undefined' || v === null || isNaN(parseFloat(v)) ? 0 : v; + } + + function reEncode(data) { + data = encodeURIComponent(data); + data = data.replace(/%([0-9A-F]{2})/g, function (match, p1) { + var c = String.fromCharCode('0x' + p1); + return c === '%' ? '%25' : c; + }); + return decodeURIComponent(data); + } + + out$.prepareSvg = function (el, options, cb) { + requireDomNode(el); + + options = options || {}; + options.scale = options.scale || 1; + options.responsive = options.responsive || false; + var xmlns = "http://www.w3.org/2000/xmlns/"; + + inlineImages(el, function () { + var outer = document.createElement("div"); + var clone = el.cloneNode(true); + var width, height; + if (el.tagName == 'svg') { + width = options.width || getDimension(el, clone, 'width'); + height = options.height || getDimension(el, clone, 'height'); + } else if (el.getBBox) { + var box = el.getBBox(); + width = box.x + box.width; + height = box.y + box.height; + clone.setAttribute('transform', clone.getAttribute('transform').replace(/translate\(.*?\)/, '')); + + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.appendChild(clone); + clone = svg; + } else { + console.error('Attempted to render non-SVG element', el); + return; + } + + clone.setAttribute("version", "1.1"); + if (!clone.getAttribute('xmlns')) { + clone.setAttributeNS(xmlns, "xmlns", "http://www.w3.org/2000/svg"); + } + if (!clone.getAttribute('xmlns:xlink')) { + clone.setAttributeNS(xmlns, "xmlns:xlink", "http://www.w3.org/1999/xlink"); + } + + if (options.responsive) { + clone.removeAttribute('width'); + clone.removeAttribute('height'); + clone.setAttribute('preserveAspectRatio', 'xMinYMin meet'); + } else { + clone.setAttribute("width", width * options.scale); + clone.setAttribute("height", height * options.scale); + } + + clone.setAttribute("viewBox", [options.left || 0, options.top || 0, width, height].join(" ")); + + var fos = clone.querySelectorAll('foreignObject > *'); + for (var i = 0; i < fos.length; i++) { + if (!fos[i].getAttribute('xmlns')) { + fos[i].setAttributeNS(xmlns, "xmlns", "http://www.w3.org/1999/xhtml"); + } + } + + outer.appendChild(clone); + + // In case of custom fonts we need to fetch font first, and then inline + // its url into data-uri format (encode as base64). That's why style + // processing is done asynchonously. Once all inlining is finshed + // cssLoadedCallback() is called. + styles(el, options, cssLoadedCallback); + + function cssLoadedCallback(css) { + // here all fonts are inlined, so that we can render them properly. + var s = document.createElement('style'); + s.setAttribute('type', 'text/css'); + s.innerHTML = "<![CDATA[\n" + css + "\n]]>"; + var defs = document.createElement('defs'); + defs.appendChild(s); + clone.insertBefore(defs, clone.firstChild); + + if (cb) { + var outHtml = outer.innerHTML; + outHtml = outHtml.replace(/NS\d+:href/gi, 'xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href'); + cb(outHtml, width, height); + } + } + }); + }; + + out$.svgAsDataUri = function (el, options, cb) { + out$.prepareSvg(el, options, function (svg) { + var uri = 'data:image/svg+xml;base64,' + window.btoa(reEncode(doctype + svg)); + if (cb) { + cb(uri); + } + }); + }; + + out$.svgAsPngUri = function (el, options, cb) { + requireDomNode(el); + + options = options || {}; + options.encoderType = options.encoderType || 'image/png'; + options.encoderOptions = options.encoderOptions || 0.8; + + var convertToPng = function (src, w, h) { + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + canvas.width = w; + canvas.height = h; + + if (options.canvg) { + options.canvg(canvas, src); + } else { + context.drawImage(src, 0, 0); + } + + if (options.backgroundColor) { + context.globalCompositeOperation = 'destination-over'; + context.fillStyle = options.backgroundColor; + context.fillRect(0, 0, canvas.width, canvas.height); + } + + var png; + try { + png = canvas.toDataURL(options.encoderType, options.encoderOptions); + } catch (e) { + if (typeof SecurityError !== 'undefined' && e instanceof SecurityError || e.name == "SecurityError") { + console.error("Rendered SVG images cannot be downloaded in this browser."); + return; + } else { + throw e; + } + } + cb(png); + }; + + if (options.canvg) { + out$.prepareSvg(el, options, convertToPng); + } else { + out$.svgAsDataUri(el, options, function (uri) { + var image = new Image(); + + image.onload = function () { + convertToPng(image, image.width, image.height); + }; + + image.onerror = function () { + console.error('There was an error loading the data URI as an image on the following SVG\n', window.atob(uri.slice(26)), '\n', "Open the following link to see browser's diagnosis\n", uri); + }; + + image.src = uri; + }); + } + }; + + out$.download = function (name, uri) { + if (navigator.msSaveOrOpenBlob) { + navigator.msSaveOrOpenBlob(uriToBlob(uri), name); + } else { + var saveLink = document.createElement('a'); + var downloadSupported = 'download' in saveLink; + if (downloadSupported) { + saveLink.download = name; + saveLink.href = uri; + saveLink.style.display = 'none'; + document.body.appendChild(saveLink); + saveLink.click(); + document.body.removeChild(saveLink); + } else { + window.open(uri, '_temp', 'menubar=no,toolbar=no,status=no'); + } + } + }; + + function uriToBlob(uri) { + var byteString = window.atob(uri.split(',')[1]); + var mimeString = uri.split(',')[0].split(':')[1].split(';')[0]; + var buffer = new ArrayBuffer(byteString.length); + var intArray = new Uint8Array(buffer); + for (var i = 0; i < byteString.length; i++) { + intArray[i] = byteString.charCodeAt(i); + } + return new Blob([buffer], { type: mimeString }); + } + + out$.saveSvg = function (el, name, options) { + requireDomNode(el); + + options = options || {}; + out$.svgAsDataUri(el, options, function (uri) { + out$.download(name, uri); + }); + }; + + out$.saveSvgAsPng = function (el, name, options) { + requireDomNode(el); + + options = options || {}; + out$.svgAsPngUri(el, options, function (uri) { + out$.download(name, uri); + }); + }; + + // if define is defined create as an AMD module + if (true) { + !(__WEBPACK_AMD_DEFINE_RESULT__ = function () { + return out$; + }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + } + })(); + +/***/ }, +/* 242 */ +/***/ function(module, exports, __webpack_require__) { + + var make_modal_skeleton = __webpack_require__(243); + + module.exports = function ini_modals(params) { + + // share modal + /////////////////////////////////////// + var share_modal = make_modal_skeleton(params, 'share_info'); + + share_modal.header.append('a').attr('target', '_blank').attr('href', '/clustergrammer/'); + + share_modal.header.append('h4').classed('modal-title', true).html('Share the visualization using the current URL:'); + + share_modal.body.append('input').classed('bootstrap_highlight', true).classed('share_url', true); + + // picture modal + /////////////////////////////////////// + var screenshot_modal = make_modal_skeleton(params, 'picture_info'); + + screenshot_modal.header.append('h4').classed('modal-title', true).html('Save a snapshot of the visualization'); + + screenshot_modal.body.append('div').classed('download_buttons', true); + + // dendro modal + /////////////////////////////////////// + var dendro_modal = make_modal_skeleton(params, 'dendro_info'); + + dendro_modal.header.append('h4').classed('modal-title', true).html('Cluster Information'); + + dendro_modal.body.append('g').classed('cluster_info_container', true); + + dendro_modal.body.append('div').classed('dendro_text', true).append('input').classed('bootstrap_highlight', true).classed('current_names', true).style('width', '100%'); + }; + +/***/ }, +/* 243 */ +/***/ function(module, exports) { + + module.exports = function make_modal_skeleton(params, modal_class) { + + var modal_skeleton = {}; + + var modal = d3.select(params.root).append('div').classed('modal', true).classed('fade', true).classed(modal_class, true).attr('role', 'dialog'); + + var modal_dialog = modal.append('div').classed('modal-dialog', true); + + var modal_content = modal_dialog.append('div').classed('modal-content', true); + + modal_skeleton.header = modal_content.append('div').classed('modal-header', true); + + modal_skeleton.header.append('button').attr('type', 'button').classed('close', true).attr('data-dismiss', 'modal').html('×'); + + modal_skeleton.body = modal_content.append('div').classed('modal-body', true); + + return modal_skeleton; + }; + +/***/ }, +/* 244 */ +/***/ function(module, exports) { + + module.exports = function set_up_opacity_slider(sidebar) { + + var slider_container = sidebar.append('div').classed('opacity_slider_container', true).style('margin-top', '5px').style('padding-left', '10px').style('padding-right', '10px'); + + slider_container.append('div').classed('sidebar_text', true).classed('opacity_slider_text', true).style('margin-bottom', '3px').text('Opacity Slider'); + + slider_container.append('div').classed('slider', true).classed('opacity_slider', true); + }; + +/***/ }, +/* 245 */ +/***/ function(module, exports) { + + module.exports = function make_colorbar(cgm) { + + var params = cgm.params; + + d3.select(params.root + ' .sidebar_wrapper').append('div').classed('sidebar_text', true).style('padding-left', '10px').style('padding-top', '5px').text('Matrix Values'); + + var colorbar_width = params.sidebar.width - 20; + var colorbar_height = 13; + var svg_height = 3 * colorbar_height; + var svg_width = 1.2 * colorbar_width; + var low_left_margin = 10; + var top_margin = 33; + var high_left_margin = colorbar_width + 10; + var bar_margin_left = 10; + var bar_margin_top = 3; + + var network_data = params.network_data; + +/* var max_link = _.max(network_data.links, function (d) { + return d.value; + }).value; + + var min_link = _.min(network_data.links, function (d) { + return d.value; + }).value; +*/ + var main_svg = d3.select(params.root + ' .sidebar_wrapper').append('svg').attr('height', svg_height + 'px').attr('width', svg_width + 'px'); + + //Append a defs (for definition) element to your SVG + var defs = main_svg.append("defs"); + + //Append a linearGradient element to the defs and give it a unique id + var linearGradient = defs.append("linearGradient").attr("id", "linear-gradient"); + + var special_case = 'none'; + +/* // no negative numbers + if (min_link >= 0) { + + //Set the color for the start (0%) + linearGradient.append("stop").attr("offset", "0%").attr("stop-color", "white"); + + //Set the color for the end (100%) + linearGradient.append("stop").attr("offset", "100%").attr("stop-color", params.tile_colors[0]); + + special_case = 'all_postiive'; + + // no positive numbers + } else if (max_link <= 0) { + + //Set the color for the start (0%) + linearGradient.append("stop").attr("offset", "0%").attr("stop-color", params.tile_colors[1]); + + //Set the color for the end (100%) + linearGradient.append("stop").attr("offset", "100%").attr("stop-color", "white"); + + special_case = 'all_negative'; + } + + // both postive and negative numbers + else {*/ + //Set the color for the start (0%) + linearGradient.append("stop").attr("offset", "0%").attr("stop-color", params.tile_colors[1]); + + //Set the color for the end (100%) + linearGradient.append("stop").attr("offset", "50%").attr("stop-color", "white"); + + //Set the color for the end (100%) + linearGradient.append("stop").attr("offset", "100%").attr("stop-color", params.tile_colors[0]); +// } + // make colorbar + main_svg.append('rect').classed('background', true).attr('height', colorbar_height + 'px').attr('width', colorbar_width + 'px').attr('fill', 'url(#linear-gradient)').attr('transform', 'translate(' + bar_margin_left + ', ' + bar_margin_top + ')').attr('stroke', 'grey').attr('stroke-width', '0.25px'); + + // make title + /////////////// + + var max_abs_val = Math.abs(Math.round(params.matrix.true_max * 10) / 10); + var min_abs_val = Math.abs(Math.round(params.matrix.true_min * 10) / 10); + var font_size = 13; + + main_svg.append('text').text(function () { + var inst_string; + if (params.matrix.true_min < 0) { + inst_string = '-' + min_abs_val.toLocaleString(); + } else { + inst_string = min_abs_val.toLocaleString(); + } + return inst_string; + }).style('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif').style('font-weight', 300).style('font-size', font_size).attr('transform', 'translate(' + low_left_margin + ',' + top_margin + ')').attr('text-anchor', 'start'); + + main_svg.append('text').text(max_abs_val.toLocaleString()).text(function () { + return max_abs_val.toLocaleString(); + }).style('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif').style('font-weight', 300).style('font-size', font_size).attr('transform', 'translate(' + high_left_margin + ',' + top_margin + ')').attr('text-anchor', 'end'); + }; + +/***/ } +/******/ ]); +//# sourceMappingURL=clustergrammer.js.map