├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── LICENSES ├── LICENSE ├── LICENSE_D3_tip ├── LICENSE_FileSaver ├── LICENSE_saveSVGasPng └── LICSNSE_D3 ├── README.md ├── clustergrammer.js ├── clustergrammer.min.js ├── clustergrammer.node.js ├── clustergrammer.node.min.js ├── css └── custom.css ├── img ├── cat_tsv.png ├── clustergrammer_logo.png ├── demo_high-fr.gif ├── demo_screenshot.png └── demo_screenshot_full_screen.png ├── index.html ├── js ├── Enrichrgram.js ├── hzome_functions.js ├── load_clustergram.js ├── load_multiple_clustergrams.js ├── load_scrolling_tour.js ├── scroll_section_functions.js └── send_to_Enrichr.js ├── json ├── mult_view.json ├── mult_view_sim_col.json ├── mult_view_sim_row.json └── tutorial_info.json ├── lib ├── css │ ├── bootstrap.css │ ├── custom_scrolling.css │ └── font-awesome.min.css ├── fonts │ ├── FontAwesome.otf │ ├── fontawesome-webfont.eot │ ├── fontawesome-webfont.svg │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ └── fontawesome-webfont.woff2 └── js │ ├── bootstrap.min.js │ ├── d3.js │ ├── graph-scroll.js │ ├── jquery-1.11.2.min.js │ └── underscore-min.js ├── make_clustergrammer.py ├── multiple_clustergrams.html ├── package-lock.json ├── package.json ├── row_dist_mat_py_cos.txt ├── scrolling_tour.html ├── src ├── Colors.js ├── Utils_clust.js ├── categories │ ├── binom_prop_pval_lookup.js │ ├── binom_test.js │ ├── calc_cat_cluster_breakdown.js │ ├── cat_breakdown_bars.js │ ├── cat_breakdown_values.js │ ├── cat_tooltip_text.js │ ├── click_filter_cats.js │ ├── get_cat_names.js │ ├── get_cat_title.js │ ├── ini_cat_opacity.js │ ├── make_cat_breakdown_graph.js │ ├── make_col_cat.js │ ├── make_row_cat.js │ └── reset_cat_opacity.js ├── clusterfck_local │ ├── clusterfck.js │ ├── distance.js │ ├── hcluster.js │ └── kmeans.js ├── config │ ├── check_nodes_for_categories.js │ ├── check_sim_mat.js │ └── set_defaults.js ├── d3.slider │ ├── .npmignore │ ├── LICENSE │ ├── README.md │ ├── d3.slider.css │ ├── d3.slider.js │ ├── index.html │ └── package.json ├── demo │ ├── demo_text.js │ ├── highlight_sidebar_element.js │ ├── ini_demo.js │ ├── make_demo_text_containers.js │ ├── make_play_button.js │ ├── play_categories.js │ ├── play_conclusion.js │ ├── play_demo.js │ ├── play_filter.js │ ├── play_groups.js │ ├── play_intro.js │ ├── play_menu_button.js │ ├── play_reorder_buttons.js │ ├── play_reorder_row.js │ ├── play_reset_zoom.js │ ├── play_search.js │ ├── play_zoom.js │ ├── position_play_button.js │ ├── quick_cluster.js │ ├── run_segment.js │ ├── sim_click.js │ └── toggle_play_button.js ├── dendrogram │ ├── build_dendro_sliders.js │ ├── build_single_dendro_slider.js │ ├── calc_col_dendro_triangles.js │ ├── calc_row_dendro_triangles.js │ ├── change_groups.js │ ├── dendro_group_highlight.js │ ├── dendro_shade_bars.js │ ├── get_inst_group.js │ ├── make_col_dendro.js │ ├── make_dendro_crop_buttons.js │ ├── make_dendro_triangles.js │ ├── make_row_dendro.js │ ├── position_dendro_slider.js │ ├── run_dendro_filter.js │ └── toggle_dendro_view.js ├── enter │ ├── draw_dn_tile.js │ ├── draw_up_tile.js │ ├── ds_enter_exit_update.js │ ├── eeu_existing_row.js │ ├── enter_existing_row.js │ ├── enter_exit_update.js │ ├── enter_new_rows.js │ ├── enter_row_groups.js │ └── enter_split_tiles.js ├── exit │ ├── exit_components.js │ └── exit_existing_row.js ├── filters │ ├── get_current_orders.js │ ├── get_filter_default_state.js │ ├── get_subset_views.js │ ├── make_button_filter.js │ ├── make_filter_title.js │ ├── make_requested_view.js │ ├── make_slider_filter.js │ ├── reset_other_filter_sliders.js │ ├── run_filter_slider.js │ └── set_up_filters.js ├── initialize_matrix.js ├── initialize_resizing.js ├── labels │ ├── add_col_click_hlight.js │ ├── add_row_click_hlight.js │ ├── col_viz_aid_triangle.js │ ├── label_constrain_and_trim.js │ ├── make_col_label_container.js │ ├── make_col_tooltips.js │ ├── make_row_cat_super_labels.js │ ├── make_row_label_container.js │ ├── make_row_labels.js │ ├── make_row_tooltips.js │ ├── make_row_visual_aid_triangles.js │ └── super_labels.js ├── main.js ├── make_config.js ├── make_viz.js ├── matrix │ ├── add_click_hlight.js │ ├── brush_crop_matrix.js │ ├── calc_downsampled_levels.js │ ├── calc_downsampled_matrix.js │ ├── deactivate_cropping.js │ ├── draw_gridlines.js │ ├── fine_position_tile.js │ ├── grid_lines_viz.js │ ├── index.js │ ├── make_full_name.js │ ├── make_matrix_rows.js │ ├── make_matrix_string.js │ ├── make_simple_rows.js │ ├── mouseout_tile.js │ ├── mouseover_tile.js │ ├── save_matrix.js │ ├── sum_rows_mat.js │ └── toggle_grid_lines.js ├── menus │ ├── build_filter_icon.js │ ├── build_tree_icon.js │ ├── make_filter_menu.js │ ├── make_menu_button_section.js │ ├── make_menu_update_button.js │ ├── make_tree_menu.js │ ├── position_filter_icon.js │ ├── position_filter_menu.js │ ├── position_tree_icon.js │ ├── position_tree_menu.js │ └── toggle_menu.js ├── modal │ └── make_modal_skeleton.js ├── network │ ├── change_category.js │ ├── define_enter_exit_delays.js │ ├── filter_network_using_new_nodes.js │ ├── filter_viz_using_names.js │ ├── filter_viz_using_nodes.js │ ├── make_network_using_view.js │ ├── transpose_network.js │ └── update_viz_with_view.js ├── params │ ├── calc_cat_params.js │ ├── calc_clust_height.js │ ├── calc_clust_width.js │ ├── calc_default_fs.js │ ├── calc_label_params.js │ ├── calc_matrix_params.js │ ├── calc_val_max.js │ ├── calc_viz_dimensions.js │ ├── calc_viz_params.js │ ├── check_if_value_cats.js │ ├── get_available_filters.js │ ├── get_svg_dim.js │ ├── ini_label_params.js │ ├── ini_matrix_params.js │ ├── ini_sidebar_params.js │ ├── make_cat_params.js │ ├── make_params.js │ └── set_zoom_params.js ├── recluster │ ├── distance_functions.js │ ├── get_max_distance_in_dm.js │ ├── get_order_and_groups_clusterfck_tree.js │ └── recluster.js ├── reorder │ ├── all_reorder.js │ ├── col_reorder.js │ ├── ini_cat_reorder.js │ ├── reposition_tile_highlight.js │ ├── row_reorder.js │ └── update_reorder_buttons.js ├── reset_size │ ├── recalc_params_for_resize.js │ ├── reset_size_after_update.js │ ├── resize_borders.js │ ├── resize_col_hlight.js │ ├── resize_col_labels.js │ ├── resize_col_text.js │ ├── resize_col_triangle.js │ ├── resize_containers.js │ ├── resize_dendro.js │ ├── resize_highlights.js │ ├── resize_label_bars.js │ ├── resize_row_labels.js │ ├── resize_row_tiles.js │ ├── resize_row_viz.js │ ├── resize_spillover.js │ ├── resize_super_labels.js │ └── resize_viz.js ├── screenshot │ └── file_saver.js ├── search │ └── run_row_search.js ├── set_viz_wrapper_size.js ├── sidebar │ ├── disable_sidebar.js │ ├── enable_sidebar.js │ ├── index.js │ ├── ini_sidebar.js │ ├── make_colorbar.js │ ├── make_icons.js │ ├── make_modals.js │ ├── set_sidebar_ini_view.js │ ├── set_up_opacity_slider.js │ ├── set_up_reorder.js │ └── set_up_search.js ├── spillover │ ├── main_spillover.js │ └── make_row_dendro_spillover.js ├── tooltip │ └── d3_tip_custom.js ├── update │ ├── generate_cat_data.js │ ├── modify_row_node_cats.js │ ├── remove_node_cats.js │ ├── reset_cats.js │ ├── update_cats.js │ ├── update_split_tiles.js │ ├── update_view.js │ └── update_viz_with_network.js └── zoom │ ├── calc_real_font_size.js │ ├── calc_zoom_switching.js │ ├── check_zoom_stop_status.js │ ├── constrain_font_size.js │ ├── find_viz_rows.js │ ├── get_previous_zoom.js │ ├── ini_doubleclick.js │ ├── ini_zoom_info.js │ ├── num_visible_labels.js │ ├── reset_zoom.js │ ├── resize_label_val_bars.js │ ├── run_transformation.js │ ├── run_when_zoom_stopped.js │ ├── run_zoom.js │ ├── show_visible_area.js │ ├── trim_text.js │ ├── two_translate_zoom.js │ ├── zoom_crop_triangles.js │ ├── zoom_rules_x.js │ └── zoom_rules_y.js ├── tests ├── Compare_Front_and_Back_End_Clustering.ipynb └── output_1.13819231887 ├── txt ├── GO_Biological_Process_2015.txt ├── KEA_matrix.txt ├── ccle_example.txt ├── example_tsv.txt ├── mat_1mb.txt ├── missing_values.txt ├── mnist.txt ├── number_labels.txt ├── rc_two_cats.txt ├── rc_val_cats.txt └── tuple_cats.txt └── webpack.config.js /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | node_modules 23 | 24 | # Logs and databases # 25 | ###################### 26 | *.log 27 | *.sql 28 | *.sqlite 29 | 30 | # OS generated files # 31 | ###################### 32 | .DS_Store 33 | .DS_Store? 34 | ._* 35 | .Spotlight-V100 36 | .Trashes 37 | ehthumbs.db 38 | Thumbs.db 39 | 40 | # cache files for sublime text 41 | *.tmlanguage.cache 42 | *.tmPreferences.cache 43 | *.stTheme.cache 44 | 45 | # workspace files are user-specific 46 | *.sublime-workspace 47 | *.sublime-project 48 | *.idea 49 | *.swo 50 | *.swp 51 | 52 | # sftp configuration file 53 | sftp-config.json 54 | 55 | #TernJS 56 | .tern-port 57 | 58 | # webpack 59 | *.js.map 60 | .eslint* 61 | 62 | # python 63 | *.ipynb_checkpoints 64 | *.pyc 65 | clustergrammer 66 | 67 | # # eslint 68 | # .eslint* 69 | 70 | # how to retroactively use 71 | ############################ 72 | # git rm -r --cached . 73 | # git add . 74 | # git commit -m "fixing .gitignore" 75 | 76 | # Word temporary 77 | ~$*.doc* 78 | 79 | # Excel temporary 80 | ~$*.xls* 81 | 82 | # Excel Backup File 83 | *.xlk -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Ma'ayan Lab 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSES/LICENSE_D3_tip: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2013 Justin Palmer 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /LICENSES/LICENSE_FileSaver: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright © 2016 Eli Grey. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /LICENSES/LICENSE_saveSVGasPng: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Eric Shull 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSES/LICSNSE_D3: -------------------------------------------------------------------------------- 1 | Copyright 2010-2016 Mike Bostock 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the author nor the names of contributors may be used to 15 | endorse or promote products derived from this software without specific prior 16 | written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /img/cat_tsv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaayanLab/clustergrammer/12a8f1caac6e9707475fe005a00bd60935ea4161/img/cat_tsv.png -------------------------------------------------------------------------------- /img/clustergrammer_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaayanLab/clustergrammer/12a8f1caac6e9707475fe005a00bd60935ea4161/img/clustergrammer_logo.png -------------------------------------------------------------------------------- /img/demo_high-fr.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaayanLab/clustergrammer/12a8f1caac6e9707475fe005a00bd60935ea4161/img/demo_high-fr.gif -------------------------------------------------------------------------------- /img/demo_screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaayanLab/clustergrammer/12a8f1caac6e9707475fe005a00bd60935ea4161/img/demo_screenshot.png -------------------------------------------------------------------------------- /img/demo_screenshot_full_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaayanLab/clustergrammer/12a8f1caac6e9707475fe005a00bd60935ea4161/img/demo_screenshot_full_screen.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Clustergrammer.js 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 |

Please wait ...

26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /js/hzome_functions.js: -------------------------------------------------------------------------------- 1 | function ini_hzome(root_id){ 2 | 3 | // save gene data to global variable 4 | gene_data = {}; 5 | 6 | function get_mouseover(root_tip, gene_symbol){ 7 | 8 | // not sure if this is necessary 9 | if ( d3.select(root_tip + '_row_tip').classed(gene_symbol) ){ 10 | get_request(root_tip, gene_symbol); 11 | } 12 | 13 | } 14 | 15 | function get_request(root_tip, ini_gene_symbol){ 16 | 17 | var gene_symbol; 18 | if (ini_gene_symbol.indexOf(' ') > 0){ 19 | gene_symbol = ini_gene_symbol.split(' ')[0]; 20 | } else if (ini_gene_symbol.indexOf('_') > 0){ 21 | gene_symbol = ini_gene_symbol.split('_')[0]; 22 | } 23 | else { 24 | gene_symbol = ini_gene_symbol; 25 | } 26 | 27 | var base_url = 'https://amp.pharm.mssm.edu/Harmonizome/api/1.0/gene/'; 28 | var url = base_url + gene_symbol; 29 | 30 | $.get(url, function(data) { 31 | 32 | data = JSON.parse(data); 33 | 34 | // save data for repeated use 35 | gene_data[gene_symbol] = {} 36 | gene_data[gene_symbol].name = data.name; 37 | gene_data[gene_symbol].description = data.description; 38 | 39 | set_tooltip(data, root_tip, ini_gene_symbol); 40 | 41 | return data; 42 | 43 | }); 44 | } 45 | 46 | function set_tooltip(data, root_tip, gene_symbol){ 47 | 48 | if (data.name != undefined){ 49 | 50 | d3.selectAll(root_tip + '_row_tip') 51 | .html(function(){ 52 | var sym_name = gene_symbol + ': ' + data.name; 53 | var full_html = '

' + sym_name + '

' + '

' + 54 | data.description + '

'; 55 | return full_html; 56 | }); 57 | } 58 | } 59 | 60 | 61 | function gene_info(root_tip, gene_info){ 62 | 63 | var gene_symbol = gene_info.name; 64 | 65 | if (_.has(gene_data, gene_symbol)){ 66 | var inst_data = gene_data[gene_symbol]; 67 | set_tooltip(inst_data, root_tip, gene_symbol); 68 | } else{ 69 | setTimeout(get_mouseover, 250, root_tip, gene_symbol); 70 | } 71 | 72 | } 73 | 74 | hzome = {} 75 | 76 | hzome.gene_info = gene_info; 77 | hzome.gene_data = gene_data; 78 | hzome.get_mouseover = get_mouseover; 79 | hzome.get_request = get_request; 80 | 81 | return hzome; 82 | 83 | } 84 | -------------------------------------------------------------------------------- /js/send_to_Enrichr.js: -------------------------------------------------------------------------------- 1 | function send_to_Enrichr(options) { // http://amp.pharm.mssm.edu/Enrichr/#help 2 | var defaultOptions = { 3 | description: "", 4 | popup: false 5 | }; 6 | 7 | if (typeof options.description == 'undefined') 8 | options.description = defaultOptions.description; 9 | if (typeof options.popup == 'undefined') 10 | options.popup = defaultOptions.popup; 11 | if (typeof options.list == 'undefined') 12 | alert('No genes defined.'); 13 | 14 | var form = document.createElement('form'); 15 | form.setAttribute('method', 'post'); 16 | form.setAttribute('action', 'https://amp.pharm.mssm.edu/Enrichr/enrich'); 17 | if (options.popup) 18 | form.setAttribute('target', '_blank'); 19 | form.setAttribute('enctype', 'multipart/form-data'); 20 | 21 | var listField = document.createElement('input'); 22 | listField.setAttribute('type', 'hidden'); 23 | listField.setAttribute('name', 'list'); 24 | listField.setAttribute('value', options.list); 25 | form.appendChild(listField); 26 | 27 | var descField = document.createElement('input'); 28 | descField.setAttribute('type', 'hidden'); 29 | descField.setAttribute('name', 'description'); 30 | descField.setAttribute('value', options.description); 31 | form.appendChild(descField); 32 | 33 | document.body.appendChild(form); 34 | form.submit(); 35 | document.body.removeChild(form); 36 | } -------------------------------------------------------------------------------- /lib/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaayanLab/clustergrammer/12a8f1caac6e9707475fe005a00bd60935ea4161/lib/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /lib/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaayanLab/clustergrammer/12a8f1caac6e9707475fe005a00bd60935ea4161/lib/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /lib/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaayanLab/clustergrammer/12a8f1caac6e9707475fe005a00bd60935ea4161/lib/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /lib/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaayanLab/clustergrammer/12a8f1caac6e9707475fe005a00bd60935ea4161/lib/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /lib/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaayanLab/clustergrammer/12a8f1caac6e9707475fe005a00bd60935ea4161/lib/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /make_clustergrammer.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Python 2.7 3 | The clustergrammer python module can be installed using pip: 4 | pip install clustergrammer 5 | 6 | or by getting the code from the repo: 7 | https://github.com/MaayanLab/clustergrammer-py 8 | ''' 9 | 10 | from clustergrammer import Network 11 | net = Network() 12 | 13 | # load matrix tsv file 14 | net.load_file('txt/rc_two_cats.txt') 15 | # net.load_file('txt/ccle_example.txt') 16 | # net.load_file('txt/rc_val_cats.txt') 17 | # net.load_file('txt/number_labels.txt') 18 | # net.load_file('txt/mnist.txt') 19 | # net.load_file('txt/tuple_cats.txt') 20 | # net.load_file('txt/example_tsv.txt') 21 | 22 | # net.enrichrgram('KEA_2015') 23 | 24 | # optional filtering and normalization 25 | ########################################## 26 | # net.filter_sum('row', threshold=20) 27 | # net.normalize(axis='col', norm_type='zscore', keep_orig=True) 28 | # net.filter_N_top('row', 250, rank_type='sum') 29 | # net.filter_threshold('row', threshold=3.0, num_occur=4) 30 | # net.swap_nan_for_zero() 31 | # net.set_cat_color('col', 1, 'Category: one', 'blue') 32 | 33 | # net.make_clust() 34 | # net.dendro_cats('row', 5) 35 | 36 | net.cluster(dist_type='cos',views=['N_row_sum', 'N_row_var'] , dendro=True, 37 | sim_mat=True, filter_sim=0.1, calc_cat_pval=False, enrichrgram= 38 | False, run_clustering=True) 39 | 40 | # write jsons for front-end visualizations 41 | net.write_json_to_file('viz', 'json/mult_view.json', 'indent') 42 | net.write_json_to_file('sim_row', 'json/mult_view_sim_row.json', 'no-indent') 43 | net.write_json_to_file('sim_col', 'json/mult_view_sim_col.json', 'no-indent') 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "clustergrammer", 3 | "version": "v1.19.5", 4 | "description": "This is a clustergram implemented in D3.js. I started from the example http://bost.ocks.org/mike/miserables/ and added the following features", 5 | "main": "clustergrammer.node.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/MaayanLab/clustergrammer.git" 12 | }, 13 | "author": "Nicolas Fernandez", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/MaayanLab/clustergrammer/issues" 17 | }, 18 | "homepage": "https://github.com/MaayanLab/clustergrammer#readme", 19 | "devDependencies": { 20 | "babel-core": "^6.14.0", 21 | "babel-eslint": "^4.1.8", 22 | "babel-loader": "^6.2.5", 23 | "babel-preset-es2015": "^6.14.0", 24 | "browser-sync": "^2.18.13", 25 | "browser-sync-webpack-plugin": "^1.2.0", 26 | "css-loader": "^0.23.1", 27 | "eslint": "^2.1.0", 28 | "expose-loader": "^0.7.1", 29 | "less-loader": "^2.2.3", 30 | "object-assign": "^4.1.0", 31 | "webpack": "^1.13.2" 32 | }, 33 | "dependencies": { 34 | "awesomplete": "1.1.1", 35 | "d3": "^3.5.15", 36 | "jquery": "1.11.0", 37 | "mathjs": "3.17.0", 38 | "save-svg-as-png": "^1.1.0", 39 | "style-loader": "^0.13.1", 40 | "underscore": "1.8.3" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /scrolling_tour.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 |
16 | 17 |
18 |
19 | 20 |
21 | 22 |
23 | 24 |
25 |
26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/Colors.js: -------------------------------------------------------------------------------- 1 | // colors from http://graphicdesign.stackexchange.com/revisions/3815/8 2 | var all_colors; 3 | 4 | all_colors = [ "#393b79", "#aec7e8", "#ff7f0e", "#ffbb78", "#98df8a", "#bcbd22", 5 | "#404040", "#ff9896", "#c5b0d5", "#8c564b", "#1f77b4", "#5254a3", "#FFDB58", 6 | "#c49c94", "#e377c2", "#7f7f7f", "#2ca02c", "#9467bd", "#dbdb8d", "#17becf", 7 | "#637939", "#6b6ecf", "#9c9ede", "#d62728", "#8ca252", "#8c6d31", "#bd9e39", 8 | "#e7cb94", "#843c39", "#ad494a", "#d6616b", "#7b4173", "#a55194", "#ce6dbd", 9 | "#de9ed6"]; 10 | 11 | // too light colors 12 | // "#e7969c", 13 | // "#c7c7c7", 14 | // "#f7b6d2", 15 | // "#cedb9c", 16 | // "#9edae5", 17 | 18 | function get_default_color() { 19 | return '#EEE'; 20 | } 21 | 22 | function get_random_color(i) { 23 | return all_colors[i % get_num_colors()]; 24 | } 25 | 26 | function get_num_colors() { 27 | return all_colors.length; 28 | } 29 | 30 | module.exports = { 31 | get_default_color: get_default_color, 32 | get_random_color: get_random_color, 33 | get_num_colors: get_num_colors 34 | }; 35 | -------------------------------------------------------------------------------- /src/Utils_clust.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | /* Utility functions 4 | * ----------------------------------------------------------------------- */ 5 | module.exports = { 6 | normal_name: function(d) { 7 | var inst_name = d.name.replace(/_/g, ' ').split('#')[0]; 8 | return inst_name; 9 | }, 10 | is_supported_order: function(order) { 11 | return order === 'ini' || order === 'clust' || order === 'rank_var' || order === 'rank' || order === 'class' || order == 'alpha'; 12 | }, 13 | 14 | /* Returns whether or not an object has a certain property. 15 | */ 16 | has: function(obj, key) { 17 | return obj != null && hasOwnProperty.call(obj, key); 18 | }, 19 | 20 | property: function(key) { 21 | return function(obj) { 22 | return obj == null ? void 0 : obj[key]; 23 | }; 24 | }, 25 | 26 | // Convenience version of a common use case of `map`: fetching a property. 27 | pluck: function(arr, key) { 28 | var self = this; 29 | // Double check that we have lodash or underscore available 30 | if (window._) { 31 | // Underscore provides a pluck function. Use that. 32 | if (typeof underscore.pluck === 'function') { 33 | return underscore.pluck(arr, key); 34 | } else if (typeof underscore.map === 'function') { 35 | // Lodash does not have a pluck function. 36 | // Use underscore.map with the property function defined above. 37 | return underscore.map(arr, self.property(key)); 38 | } 39 | } else if (arr.map && typeof arr.map === 'function') { 40 | // If lodash or underscore not available, check to see if the native arr.map is available. 41 | // If so, use it with the property function defined above. 42 | return arr.map(self.property(key)); 43 | } 44 | }, 45 | 46 | /* Returns true if the object is undefined. 47 | */ 48 | is_undefined: function(obj) { 49 | return obj === void 0; 50 | }, 51 | 52 | /* Mixes two objects in together, overwriting a target with a source. 53 | */ 54 | extend: function(target, source) { 55 | target = target || {}; 56 | for (var prop in source) { 57 | if (typeof source[prop] === 'object') { 58 | target[prop] = this.extend(target[prop], source[prop]); 59 | } else { 60 | target[prop] = source[prop]; 61 | } 62 | } 63 | return target; 64 | } 65 | }; 66 | -------------------------------------------------------------------------------- /src/categories/binom_test.js: -------------------------------------------------------------------------------- 1 | 2 | // Load the math.js core 3 | // Create a new, empty math.js instance 4 | // It will only contain methods `import` and `config` 5 | // math.import(require('mathjs/lib/type/fraction')); 6 | var p_dict = require('./binom_prop_pval_lookup'); 7 | var core = require('mathjs/core'); 8 | var math = core.create(); 9 | 10 | math.import(require('mathjs/lib/function/probability/factorial')); 11 | 12 | module.exports = function binom_test(actual_k, n, p){ 13 | 14 | var fact = math.factorial; 15 | var pval; 16 | 17 | function binom_dist(k, n, p){ 18 | var bin_coeff = (fact(n))/( fact(k) * fact(n-k) ); 19 | p = bin_coeff * (Math.pow(p, k) * Math.pow((1 - p), (n-k)) ); 20 | return p; 21 | } 22 | 23 | function my_binom_test_2(actual_k, n, p){ 24 | var cp = 0; 25 | var k; 26 | var dp; 27 | for (var inst_k=actual_k; inst_k < n+1; inst_k++ ){ 28 | k = inst_k; 29 | dp = binom_dist(k, n, p); 30 | cp = cp + dp; 31 | } 32 | 33 | return cp; 34 | 35 | } 36 | 37 | // look up p-value from z-score using table 38 | function binom_prop_table(actual_k, n, p){ 39 | 40 | // expected average number of successes 41 | var mu = n * p; 42 | 43 | // standard deviation 44 | var sigma = Math.sqrt(n * p * (1 - p)); 45 | 46 | // how many standard deviations is the actual_k away 47 | // from the expected value 48 | var z = (actual_k - mu)/sigma; 49 | 50 | var z_vals = p_dict.z; 51 | var p_vals = p_dict.p; 52 | 53 | var found_index = -1; 54 | var found = false; 55 | 56 | for (var index=0; index < z_vals.length; index++){ 57 | var inst_z = z_vals[index]; 58 | 59 | // increasing inst_z until z is less than inst_z 60 | if (z < inst_z && found === false){ 61 | found_index = index; 62 | found = true; 63 | } 64 | } 65 | 66 | // give it the smallest p-val if the z-score was larger than 67 | // any in the table 68 | if (found_index === -1){ 69 | found_index = z_vals.length - 1; 70 | } 71 | pval = p_vals[found_index]; 72 | 73 | return pval; 74 | 75 | } 76 | 77 | // calculate pval 78 | pval = my_binom_test_2(actual_k, n, p); 79 | if ( isNaN(pval) ){ 80 | pval = binom_prop_table(actual_k, n, p); 81 | } 82 | 83 | return pval; 84 | 85 | }; -------------------------------------------------------------------------------- /src/categories/get_cat_names.js: -------------------------------------------------------------------------------- 1 | var utils = require('../Utils_clust'); 2 | var underscore = require('underscore'); 3 | 4 | module.exports = function get_cat_names(params, inst_data, inst_selection, inst_rc){ 5 | 6 | // category index 7 | var inst_cat = d3.select(inst_selection).attr('cat'); 8 | var cat_name = inst_data[inst_cat]; 9 | var tmp_nodes = params.network_data[inst_rc+'_nodes']; 10 | 11 | var found_nodes = underscore.filter(tmp_nodes, function(d){ 12 | return d[inst_cat] == cat_name; 13 | }); 14 | 15 | var found_names = utils.pluck(found_nodes, 'name'); 16 | 17 | return found_names; 18 | }; -------------------------------------------------------------------------------- /src/categories/get_cat_title.js: -------------------------------------------------------------------------------- 1 | module.exports = function get_cat_title(viz, inst_cat, inst_rc){ 2 | var cat_title; 3 | 4 | // make default title if none is given 5 | if(viz.cat_names[inst_rc][inst_cat] === inst_cat){ 6 | var inst_num = parseInt( inst_cat.split('-')[1], 10) + 1; 7 | // generate placeholder title 8 | cat_title = 'Category ' + inst_num; 9 | } else { 10 | // make real title 11 | cat_title = viz.cat_names[inst_rc][inst_cat]; 12 | } 13 | 14 | return cat_title; 15 | 16 | }; -------------------------------------------------------------------------------- /src/categories/ini_cat_opacity.js: -------------------------------------------------------------------------------- 1 | module.exports = function ini_cat_opacity(viz, inst_rc, cat_rect, inst_cat, updating=false){ 2 | 3 | // debugger; 4 | 5 | var super_string = ': '; 6 | var inst_type = viz.cat_info[inst_rc][inst_cat].type; 7 | 8 | // set opacity based on string or value cats 9 | if (inst_type === 'cat_strings'){ 10 | 11 | // optionally have categories transition in 12 | if (updating){ 13 | cat_rect 14 | .classed('cat_strings', true) 15 | .style('opacity', 0) 16 | .transition() 17 | .duration(1000) 18 | .style('opacity', viz.cat_colors.opacity); 19 | 20 | } else { 21 | // opacity is fixed 22 | cat_rect 23 | .classed('cat_strings', true) 24 | .style('opacity', viz.cat_colors.opacity); 25 | 26 | } 27 | 28 | 29 | 30 | } else { 31 | 32 | // opacity varies based on value 33 | cat_rect 34 | .classed('cat_values', true) 35 | .style('opacity', function(d){ 36 | 37 | var unprocessed_val = d[inst_cat]; 38 | 39 | var cat_value = get_cat_value(unprocessed_val); 40 | 41 | return viz.cat_info[inst_rc][inst_cat].cat_scale(Math.abs(cat_value)); 42 | }) 43 | .style('fill', function(d){ 44 | var inst_color; 45 | 46 | var cat_value = get_cat_value(d[inst_cat]); 47 | 48 | // get positive and negative colors 49 | if (cat_value > 0){ 50 | inst_color = viz.cat_value_colors[0]; 51 | } else { 52 | inst_color = viz.cat_value_colors[1]; 53 | } 54 | 55 | return inst_color; 56 | }); 57 | } 58 | 59 | function get_cat_value(unprocessed_value){ 60 | if (typeof unprocessed_value === 'string'){ 61 | 62 | if ( unprocessed_value.indexOf(super_string) > -1 ){ 63 | unprocessed_value = unprocessed_value.split(super_string)[1]; 64 | } 65 | } 66 | 67 | var cat_value = parseFloat(unprocessed_value); 68 | 69 | return cat_value; 70 | } 71 | 72 | }; -------------------------------------------------------------------------------- /src/categories/reset_cat_opacity.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function reset_cat_opacity(params){ 4 | 5 | underscore.each(['row','col'], function(inst_rc){ 6 | 7 | d3.selectAll(params.root+' .'+inst_rc+'_cat_group') 8 | .selectAll('rect') 9 | .style('opacity', function(){ 10 | 11 | var inst_opacity = d3.select(this).style('opacity'); 12 | 13 | if (d3.select(this).classed('cat_strings') && d3.select(this).classed('filtered_cat') === false){ 14 | inst_opacity = params.viz.cat_colors.opacity; 15 | } 16 | 17 | return inst_opacity; 18 | }); 19 | 20 | }); 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /src/clusterfck_local/clusterfck.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2011 Heather Arthur 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | */ 25 | 26 | /* eslint-disable */ 27 | 28 | module.exports = { 29 | hcluster: require("./hcluster"), 30 | Kmeans: require("./kmeans"), 31 | kmeans: require("./kmeans").kmeans 32 | }; -------------------------------------------------------------------------------- /src/clusterfck_local/distance.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | euclidean: function(v1, v2) { 3 | var total = 0; 4 | for (var i = 0; i < v1.length; i++) { 5 | total = total + Math.pow(v2[i] - v1[i], 2); 6 | } 7 | return Math.sqrt(total); 8 | }, 9 | manhattan: function(v1, v2) { 10 | var total = 0; 11 | for (var i = 0; i < v1.length ; i++) { 12 | total = total + Math.abs(v2[i] - v1[i]); 13 | } 14 | return total; 15 | }, 16 | max: function(v1, v2) { 17 | var max = 0; 18 | for (var i = 0; i < v1.length; i++) { 19 | max = Math.max(max , Math.abs(v2[i] - v1[i])); 20 | } 21 | return max; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /src/config/check_nodes_for_categories.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function check_nodes_for_categories(nodes){ 4 | 5 | var super_string = ': '; 6 | var has_cat = true; 7 | 8 | underscore.each(nodes, function(inst_node){ 9 | var inst_name = String(inst_node.name); 10 | if (inst_name.indexOf(super_string) < 0){ 11 | has_cat = false; 12 | } 13 | }); 14 | 15 | return has_cat; 16 | 17 | }; -------------------------------------------------------------------------------- /src/config/check_sim_mat.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function check_sim_mat(config){ 4 | 5 | var sim_mat = false; 6 | 7 | var num_rows = config.network_data.row_nodes_names.length; 8 | var num_cols = config.network_data.col_nodes_names.length; 9 | 10 | if (num_rows == num_cols){ 11 | 12 | // the sort here was causing errors 13 | var rows = config.network_data.row_nodes_names; 14 | var cols = config.network_data.col_nodes_names; 15 | sim_mat = true; 16 | 17 | underscore.each(rows, function(inst_row){ 18 | var inst_index = rows.indexOf(inst_row); 19 | if (inst_row !== cols[inst_index]){ 20 | sim_mat = false; 21 | } 22 | }); 23 | 24 | } 25 | 26 | if (sim_mat){ 27 | config.expand_button = false; 28 | } 29 | 30 | return sim_mat; 31 | }; -------------------------------------------------------------------------------- /src/config/set_defaults.js: -------------------------------------------------------------------------------- 1 | module.exports = function set_defaults(){ 2 | 3 | var defaults = { 4 | // Label options 5 | row_label_scale: 1, 6 | col_label_scale: 1, 7 | super_labels: false, 8 | super: {}, 9 | show_label_tooltips: true, 10 | show_tile_tooltips: true, 11 | // matrix options 12 | transpose: false, 13 | tile_colors: ['#FF0000', '#1C86EE'], 14 | bar_colors: ['#FF0000', '#1C86EE'], 15 | // value-cat colors 16 | // cat_value_colors: ['#2F4F4F', '#8A2BE2'], 17 | cat_value_colors: ['#2F4F4F', '#9370DB'], 18 | outline_colors: ['orange','black'], 19 | highlight_color: '#FFFF00', 20 | tile_title: false, 21 | // Default domain is set to 0: the domain will be set automatically 22 | input_domain: 0, 23 | opacity_scale: 'linear', 24 | do_zoom: true, 25 | is_zoom:0, 26 | is_slider_drag:false, 27 | is_cropping:false, 28 | background_color: '#FFFFFF', 29 | super_border_color: '#F5F5F5', 30 | outer_margins: { 31 | top: 0, 32 | bottom: 0, 33 | left: 0, 34 | right: 0 35 | }, 36 | ini_expand: false, 37 | grey_border_width: 2, 38 | tile_click_hlight: false, 39 | super_label_scale: 1, 40 | make_tile_tooltip: function(d) { return d.info; }, 41 | // initialize view, e.g. initialize with row filtering 42 | ini_view: null, 43 | // record of requested views 44 | requested_view: null, 45 | use_sidebar: true, 46 | title:null, 47 | about:null, 48 | sidebar_width:160, 49 | sidebar_icons:true, 50 | row_search_placeholder:'Row', 51 | buffer_width:10, 52 | show_sim_mat:false, 53 | cat_colors:null, 54 | resize:true, 55 | clamp_opacity:0.85, 56 | expand_button:true, 57 | max_allow_fs: 20, 58 | dendro_filter:{'row':false, 'col':false}, 59 | cat_filter:{'row':false, 'col':false}, 60 | crop_filter_nodes:{'row':false, 'col':false}, 61 | row_tip_callback:null, 62 | col_tip_callback:null, 63 | tile_tip_callback:null, 64 | matrix_update_callback:null, 65 | cat_update_callback: null, 66 | dendro_callback:null, 67 | dendro_click_callback:null, 68 | new_row_cats:null, 69 | make_modals:true, 70 | show_viz_border:false, 71 | }; 72 | 73 | return defaults; 74 | }; -------------------------------------------------------------------------------- /src/d3.slider/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log -------------------------------------------------------------------------------- /src/d3.slider/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Bjorn Sandvik 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /src/d3.slider/README.md: -------------------------------------------------------------------------------- 1 | D3.js Slider 2 | ============ 3 | 4 | This is a pure D3.js slider inspired by the jQuery UI Slider. Supports D3’s axis component. Feel free to contribute! 5 | 6 | Examples 7 | -------------------------------------------------------------------------------- /src/d3.slider/d3.slider.css: -------------------------------------------------------------------------------- 1 | .d3-slider { 2 | position: relative; 3 | font-family: Verdana,Arial,sans-serif; 4 | font-size: 1.1em; 5 | border: 1px solid #aaaaaa; 6 | z-index: 2; 7 | } 8 | 9 | .d3-slider-horizontal { 10 | height: .8em; 11 | } 12 | 13 | .d3-slider-range { 14 | background:#2980b9; 15 | left:0px; 16 | right:0px; 17 | height: 0.8em; 18 | position: absolute; 19 | } 20 | 21 | .d3-slider-range-vertical { 22 | background:#2980b9; 23 | left:0px; 24 | right:0px; 25 | position: absolute; 26 | top:0; 27 | } 28 | 29 | .d3-slider-vertical { 30 | width: .8em; 31 | height: 100px; 32 | } 33 | 34 | .d3-slider-handle { 35 | position: absolute; 36 | width: 1.2em; 37 | height: 1.2em; 38 | border: 1px solid #d3d3d3; 39 | border-radius: 4px; 40 | background: #eee; 41 | background: linear-gradient(to bottom, #eee 0%, #ddd 100%); 42 | z-index: 3; 43 | } 44 | 45 | .d3-slider-handle:hover { 46 | border: 1px solid #999999; 47 | } 48 | 49 | .d3-slider-horizontal .d3-slider-handle { 50 | top: -.3em; 51 | margin-left: -.6em; 52 | } 53 | 54 | .d3-slider-axis { 55 | position: relative; 56 | z-index: 1; 57 | } 58 | 59 | .d3-slider-axis-bottom { 60 | top: .8em; 61 | } 62 | 63 | .d3-slider-axis-right { 64 | left: .8em; 65 | } 66 | 67 | .d3-slider-axis path { 68 | stroke-width: 0; 69 | fill: none; 70 | } 71 | 72 | .d3-slider-axis line { 73 | fill: none; 74 | stroke: #aaa; 75 | shape-rendering: crispEdges; 76 | } 77 | 78 | .d3-slider-axis text { 79 | font-size: 11px; 80 | } 81 | 82 | .d3-slider-vertical .d3-slider-handle { 83 | left: -.25em; 84 | margin-left: 0; 85 | margin-bottom: -.6em; 86 | } -------------------------------------------------------------------------------- /src/demo/demo_text.js: -------------------------------------------------------------------------------- 1 | module.exports = function demo_text(params, text, read_duration){ 2 | 3 | var split_text = text.split('\n'); 4 | 5 | if (split_text.length < 3){ 6 | split_text.push(''); 7 | } 8 | 9 | d3.select(params.root+' .demo_group') 10 | .style('opacity',0) 11 | .transition().duration(250) 12 | .style('opacity',1) 13 | .transition().duration(250).delay(read_duration) 14 | .style('opacity',0); 15 | 16 | for (var i=0; i triangle_info[tmp_group].pos_bot){ 38 | triangle_info[tmp_group].name_bot = d.name; 39 | triangle_info[tmp_group].pos_bot = inst_bot; 40 | triangle_info[tmp_group].pos_mid = (triangle_info[tmp_group].pos_top + inst_bot)/2; 41 | } 42 | 43 | }); 44 | 45 | var group_info = []; 46 | 47 | underscore.each(triangle_info, function(d){ 48 | group_info.push(d); 49 | }); 50 | 51 | return group_info; 52 | 53 | }; -------------------------------------------------------------------------------- /src/dendrogram/calc_row_dendro_triangles.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function calc_row_dendro_triangles(params){ 4 | 5 | var triangle_info = {}; 6 | var inst_level = params.group_level.row; 7 | var row_nodes = params.network_data.row_nodes; 8 | var row_nodes_names = params.network_data.row_nodes_names; 9 | 10 | underscore.each(row_nodes, function(d){ 11 | 12 | // console.log('row_node '+d.name) 13 | 14 | var tmp_group = d.group[inst_level]; 15 | var inst_index = underscore.indexOf(row_nodes_names, d.name); 16 | var inst_top = params.viz.y_scale(inst_index); 17 | var inst_bot = inst_top + params.viz.y_scale.rangeBand(); 18 | 19 | if ( underscore.has(triangle_info, tmp_group) === false ){ 20 | triangle_info[tmp_group] = {}; 21 | triangle_info[tmp_group].name_top = d.name; 22 | triangle_info[tmp_group].name_bot = d.name; 23 | triangle_info[tmp_group].pos_top = inst_top; 24 | triangle_info[tmp_group].pos_bot = inst_bot; 25 | triangle_info[tmp_group].pos_mid = (inst_top + inst_bot)/2; 26 | triangle_info[tmp_group].name = tmp_group; 27 | triangle_info[tmp_group].all_names = []; 28 | triangle_info[tmp_group].inst_rc = 'row'; 29 | } 30 | 31 | triangle_info[tmp_group].all_names.push(d.name); 32 | 33 | if (inst_top < triangle_info[tmp_group].pos_top){ 34 | triangle_info[tmp_group].name_top = d.name; 35 | triangle_info[tmp_group].pos_top = inst_top; 36 | triangle_info[tmp_group].pos_mid = (inst_top + triangle_info[tmp_group].pos_bot)/2; 37 | } 38 | 39 | if (inst_bot > triangle_info[tmp_group].pos_bot){ 40 | triangle_info[tmp_group].name_bot = d.name; 41 | triangle_info[tmp_group].pos_bot = inst_bot; 42 | triangle_info[tmp_group].pos_mid = (triangle_info[tmp_group].pos_top + inst_bot)/2; 43 | } 44 | 45 | }); 46 | 47 | var group_info = []; 48 | 49 | underscore.each(triangle_info, function(d){ 50 | group_info.push(d); 51 | }); 52 | 53 | return group_info; 54 | }; -------------------------------------------------------------------------------- /src/dendrogram/change_groups.js: -------------------------------------------------------------------------------- 1 | var make_dendro_triangles = require('./make_dendro_triangles'); 2 | 3 | /* Changes the groupings (x- and y-axis color bars). 4 | */ 5 | module.exports = function (cgm, inst_rc, inst_index) { 6 | 7 | var params = cgm.params; 8 | 9 | if (inst_rc==='row'){ 10 | params.group_level.row = inst_index; 11 | } else if (inst_rc==='col'){ 12 | params.group_level.col = inst_index; 13 | } 14 | 15 | var is_change_group = true; 16 | 17 | make_dendro_triangles(cgm, inst_rc, is_change_group); 18 | 19 | }; 20 | -------------------------------------------------------------------------------- /src/dendrogram/dendro_group_highlight.js: -------------------------------------------------------------------------------- 1 | var dendro_shade_bars = require('./dendro_shade_bars'); 2 | 3 | module.exports = function dendro_group_highlight(params, inst_selection, inst_data, inst_rc){ 4 | 5 | // only make shadows if there is more than one crop button 6 | if (d3.selectAll(params.root+' .'+ inst_rc +'_dendro_crop_buttons')[0].length > 1){ 7 | setTimeout(still_hovering, 500); 8 | } else { 9 | d3.selectAll(params.root+' .dendro_shadow') 10 | .remove(); 11 | } 12 | 13 | function still_hovering(){ 14 | 15 | // check that user is still hovering over dendrogram group 16 | if (d3.select(inst_selection).classed('hovering')){ 17 | 18 | // check that user is not using dendrogram slider 19 | if (params.is_slider_drag === false){ 20 | 21 | d3.select(inst_selection) 22 | .style('opacity', 0.7); 23 | 24 | if (d3.select(params.viz.viz_svg).classed('running_update') === false){ 25 | make_shadow_bars(); 26 | } 27 | 28 | } 29 | 30 | } 31 | } 32 | 33 | function make_shadow_bars(){ 34 | 35 | if (inst_rc === 'row'){ 36 | 37 | // row and col labling are reversed 38 | if (params.viz.inst_order.col === 'clust'){ 39 | dendro_shade_bars(params, inst_selection, inst_rc, inst_data); 40 | } 41 | 42 | } else if (inst_rc === 'col') { 43 | 44 | // row and col labeling are reversed 45 | if (params.viz.inst_order.row === 'clust'){ 46 | dendro_shade_bars(params, inst_selection, inst_rc, inst_data); 47 | } 48 | 49 | } else if (inst_rc === 'both'){ 50 | 51 | if (params.viz.inst_order.col === 'clust'){ 52 | dendro_shade_bars(params, inst_selection, 'row', inst_data); 53 | } 54 | if (params.viz.inst_order.row === 'clust'){ 55 | dendro_shade_bars(params, inst_selection, 'col', inst_data); 56 | } 57 | 58 | } 59 | 60 | 61 | 62 | } 63 | }; -------------------------------------------------------------------------------- /src/dendrogram/dendro_shade_bars.js: -------------------------------------------------------------------------------- 1 | module.exports = function dendro_shade_bars(params, inst_selection, inst_rc, inst_data){ 2 | 3 | var inst_opacity = 0.2; 4 | var bot_height; 5 | 6 | d3.selectAll(params.root+' .dendro_shadow') 7 | .remove(); 8 | 9 | if (inst_rc == 'row'){ 10 | 11 | // top shade 12 | d3.select(params.root+' .clust_group') 13 | .append('rect') 14 | .attr('width', params.viz.clust.dim.width+'px') 15 | .attr('height', inst_data.pos_top+'px') 16 | .attr('fill','black') 17 | .classed('dendro_shadow',true) 18 | .attr('opacity', inst_opacity); 19 | 20 | bot_height = params.viz.clust.dim.height - inst_data.pos_bot; 21 | // bottom shade 22 | d3.select(params.root+' .clust_group') 23 | .append('rect') 24 | .attr('width', params.viz.clust.dim.width+'px') 25 | .attr('height', bot_height+'px') 26 | .attr('transform','translate(0,'+inst_data.pos_bot+')') 27 | .attr('fill','black') 28 | .classed('dendro_shadow',true) 29 | .attr('opacity', inst_opacity); 30 | 31 | } else if (inst_rc === 'col'){ 32 | 33 | // top shade 34 | d3.select(params.root+' .clust_group') 35 | .append('rect') 36 | .attr('width', inst_data.pos_top+'px') 37 | .attr('height', params.viz.clust.dim.height+'px') 38 | .attr('fill','black') 39 | .classed('dendro_shadow',true) 40 | .attr('opacity', inst_opacity); 41 | 42 | // bottom shade 43 | bot_height = params.viz.clust.dim.width - inst_data.pos_bot; 44 | d3.select(params.root+' .clust_group') 45 | .append('rect') 46 | .attr('width', bot_height+'px') 47 | .attr('height', params.viz.clust.dim.height+'px') 48 | .attr('transform','translate('+inst_data.pos_bot+',0)') 49 | .attr('fill','black') 50 | .classed('dendro_shadow',true) 51 | .attr('opacity',inst_opacity); 52 | 53 | } 54 | 55 | }; -------------------------------------------------------------------------------- /src/dendrogram/get_inst_group.js: -------------------------------------------------------------------------------- 1 | module.exports = function(params, inst_rc, d) { 2 | var inst_level; 3 | var inst_nodes; 4 | 5 | if (inst_rc === 'col') { 6 | inst_level = params.group_level.col; 7 | inst_nodes = params.network_data.col_nodes; 8 | } else if (inst_rc === 'row') { 9 | inst_level = params.group_level.row; 10 | inst_nodes = params.network_data.row_nodes; 11 | } 12 | 13 | var inst_group = d.group[inst_level]; 14 | var group_nodes_list = []; 15 | 16 | inst_nodes.forEach(function(node) { 17 | if (node.group[inst_level] === inst_group){ 18 | group_nodes_list.push(node.name); 19 | } 20 | }); 21 | 22 | return group_nodes_list; 23 | }; 24 | -------------------------------------------------------------------------------- /src/dendrogram/make_col_dendro.js: -------------------------------------------------------------------------------- 1 | var make_dendro_triangles = require('./make_dendro_triangles'); 2 | 3 | module.exports = function make_col_dendro(cgm) { 4 | 5 | var params = cgm.params; 6 | 7 | // position col_dendro_outer_container 8 | var x_offset = params.viz.clust.margin.left; 9 | var y_offset = params.viz.clust.margin.top + params.viz.clust.dim.height; 10 | var spillover_height = params.viz.dendro_room.col + params.viz.uni_margin; 11 | 12 | // make or reuse outer container 13 | if (d3.select(params.root+' .col_dendro_outer_container').empty()){ 14 | 15 | d3.select(params.root+' .viz_svg') 16 | .append('g') 17 | .attr('class', 'col_dendro_outer_container') 18 | .attr('transform', 'translate('+x_offset+','+y_offset+')'); 19 | 20 | d3.select(params.root+' .col_dendro_outer_container') 21 | .append('rect') 22 | .classed('col_dendro_spillover',true) 23 | .attr('fill', params.viz.background_color) 24 | .attr('width', params.viz.svg_dim.width) 25 | .attr('height', spillover_height+'px'); 26 | 27 | d3.select(params.root+' .col_dendro_outer_container') 28 | .append('g') 29 | .attr('class', 'col_dendro_container') 30 | .attr('transform', 'translate(0,'+params.viz.uni_margin/2+')'); 31 | 32 | d3.select(params.root+' .col_dendro_outer_container') 33 | .append('rect') 34 | .classed('col_dendro_spillover_top',true) 35 | .attr('fill', params.viz.background_color) 36 | .attr('width', params.viz.svg_dim.width) 37 | .attr('height', params.viz.svg_dim.height) 38 | .attr('transform', 'translate(0,'+params.viz.dendro_room.col+')'); 39 | 40 | } else { 41 | 42 | d3.select(params.root+' .viz_svg') 43 | .select('col_dendro_outer_container') 44 | .attr('transform', 'translate('+x_offset+','+y_offset+')'); 45 | 46 | d3.select(params.root+' .col_dendro_outer_container') 47 | .select('.col_dendro_spillover') 48 | .attr('width', params.viz.svg_dim.width) 49 | .attr('height', spillover_height+'px'); 50 | 51 | } 52 | 53 | make_dendro_triangles(cgm, 'col', false); 54 | 55 | if (params.viz.inst_order.row != 'clust'){ 56 | d3.selectAll(params.root+' .col_dendro_group').remove(); 57 | } 58 | 59 | }; 60 | -------------------------------------------------------------------------------- /src/dendrogram/make_row_dendro.js: -------------------------------------------------------------------------------- 1 | var make_dendro_triangles = require('./make_dendro_triangles'); 2 | 3 | module.exports = function make_row_dendro(cgm){ 4 | 5 | var params = cgm.params; 6 | 7 | var spillover_width = params.viz.dendro_room.row + params.viz.uni_margin; 8 | 9 | // position row_dendro_outer_container 10 | var x_offset = params.viz.clust.margin.left + params.viz.clust.dim.width; 11 | var y_offset = params.viz.clust.margin.top; 12 | 13 | // make or reuse outer container 14 | if (d3.select(params.root+' .row_dendro_outer_container').empty()){ 15 | 16 | d3.select(params.root+' .viz_svg') 17 | .append('g') 18 | .attr('class','row_dendro_outer_container') 19 | .attr('transform', 'translate(' + x_offset + ','+ y_offset +')'); 20 | 21 | d3.select(params.root+' .row_dendro_outer_container') 22 | .append('rect') 23 | .classed('row_dendro_spillover',true) 24 | .attr('fill', params.viz.background_color) 25 | .attr('width', spillover_width + 'px') 26 | .attr('height', params.viz.svg_dim.height); 27 | 28 | d3.select(params.root+' .row_dendro_outer_container') 29 | .append('g') 30 | .attr('class', 'row_dendro_container') 31 | .attr('transform', 'translate('+params.viz.uni_margin/2+',0)'); 32 | 33 | } else { 34 | d3.select(params.root+' .viz_svg') 35 | .select('row_dendro_outer_container') 36 | .attr('transform', 'translate(' + x_offset + ','+y_offset+')'); 37 | 38 | d3.select(params.root+' .row_dendro_outer_container') 39 | .select('.row_dendro_spillover') 40 | .attr('width', spillover_width + 'px') 41 | .attr('height', params.viz.svg_dim.height); 42 | } 43 | 44 | make_dendro_triangles(cgm, 'row', false); 45 | 46 | if (params.viz.inst_order.col != 'clust'){ 47 | d3.selectAll(params.root+' .row_dendro_group').remove(); 48 | } 49 | 50 | }; 51 | -------------------------------------------------------------------------------- /src/dendrogram/position_dendro_slider.js: -------------------------------------------------------------------------------- 1 | module.exports = function position_dendro_slider(cgm, inst_rc='row'){ 2 | 3 | var viz = cgm.params.viz; 4 | var tmp_left; 5 | var tmp_top; 6 | if (inst_rc === 'row'){ 7 | 8 | // row dendrogram 9 | /////////////////////// 10 | 11 | // keep slider near clustergram 12 | var max_room = viz.svg_dim.width - 3 * viz.uni_margin; 13 | 14 | // position close to row dendrogram trapezoids 15 | tmp_left = viz.clust.margin.left + viz.clust.dim.width + 5.25 * viz.dendro_room.row + 2; 16 | 17 | if (tmp_left > max_room){ 18 | tmp_left = max_room; 19 | } 20 | 21 | // tmp_top = viz.clust.margin.top + 3 * viz.uni_margin - 50; 22 | // 135 is a magic number that moves the slider down to make room for the 23 | // reordering tree (use 75 when enabling reclustering icon) 24 | tmp_top = viz.clust.margin.top + 3 * viz.uni_margin + 30; 25 | 26 | } else { 27 | 28 | // column dendrogram 29 | /////////////////////// 30 | tmp_left = 2 * viz.uni_margin; 31 | // tmp_top = viz.svg_dim.height - 2.5 * viz.uni_margin; 32 | tmp_top = viz.clust.margin.top + viz.clust.dim.height + viz.dendro_room.col - 2*viz.uni_margin; 33 | 34 | } 35 | 36 | // reposiiton slider 37 | d3.select(cgm.params.root + ' .' + inst_rc + '_slider_group') 38 | .attr('transform', function() { 39 | var inst_translation; 40 | if (inst_rc === 'row'){ 41 | tmp_left = tmp_left + 0.8 * viz.dendro_room.row; 42 | inst_translation = 'translate(' + tmp_left + ',' + tmp_top + ')'; 43 | } else { 44 | inst_translation = 'translate(' + tmp_left + ',' + tmp_top + 45 | '), rotate(-90)'; 46 | } 47 | return inst_translation; 48 | }) 49 | .style('opacity', 1); 50 | 51 | }; -------------------------------------------------------------------------------- /src/dendrogram/run_dendro_filter.js: -------------------------------------------------------------------------------- 1 | module.exports = function run_dendro_filter(cgm, d, inst_rc){ 2 | 3 | var names = {}; 4 | 5 | if (cgm.params.dendro_filter.row === false && 6 | cgm.params.dendro_filter.col === false && 7 | cgm.params.cat_filter.row === false && 8 | cgm.params.cat_filter.col === false 9 | ){ 10 | 11 | d3.select(cgm.params.root+' .'+inst_rc+'_slider_group') 12 | .style('opacity', 0.35) 13 | .style('pointer-events','none'); 14 | 15 | names[inst_rc] = d.all_names; 16 | 17 | var tmp_names = cgm.params.network_data[inst_rc+'_nodes_names']; 18 | 19 | // keep a backup of the inst_view 20 | var inst_row_nodes = cgm.params.network_data.row_nodes; 21 | var inst_col_nodes = cgm.params.network_data.col_nodes; 22 | 23 | cgm.filter_viz_using_names(names); 24 | 25 | // overwrite with backup of original nodes 26 | cgm.params.inst_nodes.row_nodes = inst_row_nodes; 27 | cgm.params.inst_nodes.col_nodes = inst_col_nodes; 28 | 29 | d3.selectAll(cgm.params.root+' .dendro_shadow') 30 | .transition() 31 | .duration(1000) 32 | .style('opacity',0) 33 | .remove(); 34 | 35 | // keep the names of all the nodes 36 | cgm.params.dendro_filter[inst_rc] = tmp_names; 37 | 38 | /* reset filter */ 39 | } else { 40 | 41 | names[inst_rc] = cgm.params.dendro_filter[inst_rc]; 42 | 43 | cgm.filter_viz_using_names(names); 44 | cgm.params.dendro_filter[inst_rc] = false; 45 | 46 | } 47 | 48 | }; -------------------------------------------------------------------------------- /src/dendrogram/toggle_dendro_view.js: -------------------------------------------------------------------------------- 1 | var make_dendro_triangles = require('../dendrogram/make_dendro_triangles'); 2 | 3 | module.exports = function toggle_dendro_view(cgm, inst_rc, wait_time = 1500){ 4 | 5 | var params = cgm.params; 6 | 7 | // row and col are reversed 8 | if (inst_rc === 'row'){ 9 | if (params.viz.inst_order.col === 'clust'){ 10 | // the last true tells the viz that I'm chaning group size and not to 11 | // delay the change in dendro 12 | setTimeout( make_dendro_triangles, wait_time, cgm, 'row', true); 13 | } 14 | } 15 | 16 | if (inst_rc === 'col'){ 17 | if (params.viz.inst_order.row === 'clust'){ 18 | setTimeout( make_dendro_triangles, wait_time, cgm, 'col', true); 19 | } 20 | } 21 | 22 | if (params.viz.inst_order.row != 'clust' && params.viz.dendro_filter.col === false){ 23 | d3.selectAll(params.root+' .col_dendro_group') 24 | .style('opacity',0) 25 | .on('mouseover',null) 26 | .on('mouseout',null); 27 | 28 | d3.select(params.root+' .col_slider_group') 29 | .style('opacity', 0); 30 | 31 | // toggle crop buttons 32 | d3.selectAll(params.root+' .col_dendro_crop_buttons') 33 | .style('opacity',0) 34 | .on('mouseover', null) 35 | .on('mouseout', null); 36 | 37 | } 38 | 39 | if (params.viz.inst_order.col != 'clust' && params.viz.dendro_filter.row === false){ 40 | 41 | d3.selectAll(params.root+' .row_dendro_group') 42 | .style('opacity',0) 43 | .on('mouseover',null) 44 | .on('mouseout',null) 45 | .on('click', null); 46 | 47 | d3.select(params.root+' .row_slider_group') 48 | .style('opacity', 0); 49 | 50 | // toggle crop buttons 51 | d3.selectAll(params.root+' .row_dendro_crop_buttons') 52 | .style('opacity',0) 53 | .on('mouseover', null) 54 | .on('mouseout', null); 55 | 56 | } 57 | }; -------------------------------------------------------------------------------- /src/enter/draw_dn_tile.js: -------------------------------------------------------------------------------- 1 | module.exports = function draw_dn_tile(params){ 2 | 3 | var start_x = 0; 4 | var final_x = params.viz.x_scale.rangeBand() - params.viz.border_width.x; 5 | var start_y = params.viz.y_scale.rangeBand() - params.viz.border_width.y; 6 | var final_y = params.viz.y_scale.rangeBand() - params.viz.border_width.y; 7 | 8 | var output_string = 'M' + start_x + ', ' + start_y + ' L' + 9 | final_x + ', ' + final_y + ' L' + final_x + ',0 Z'; 10 | 11 | return output_string; 12 | }; -------------------------------------------------------------------------------- /src/enter/draw_up_tile.js: -------------------------------------------------------------------------------- 1 | module.exports = function draw_up_tile(params){ 2 | 3 | var start_x = 0; 4 | var final_x = params.viz.x_scale.rangeBand() - params.viz.border_width.x; 5 | var start_y = 0; 6 | var final_y = params.viz.y_scale.rangeBand()- params.viz.border_width.y; 7 | 8 | var output_string = 'M' + start_x + ',' + start_y + ' L' + 9 | start_x + ', ' + final_y + ' L' + final_x + ',0 Z'; 10 | 11 | return output_string; 12 | }; -------------------------------------------------------------------------------- /src/enter/ds_enter_exit_update.js: -------------------------------------------------------------------------------- 1 | var reset_size_after_update = require('../reset_size/reset_size_after_update'); 2 | var make_col_label_container = require('../labels/make_col_label_container'); 3 | var show_visible_area = require('../zoom/show_visible_area'); 4 | var resize_containers = require('../reset_size/resize_containers'); 5 | 6 | module.exports = function ds_enter_exit_update(cgm){ 7 | 8 | // console.log('======== ds_enter_exit_update ==============='); 9 | 10 | // remove row labels, remove non-downsampled rows, and add downsampled rows 11 | d3.selectAll(cgm.params.root+' .row_cat_group') 12 | .remove(); 13 | d3.selectAll(cgm.params.root+' .row_label_group') 14 | .remove(); 15 | d3.selectAll(cgm.params.root+' .row') 16 | .remove(); 17 | 18 | // no need to re-calculate the downsampled layers 19 | // calc_downsampled_levels(params); 20 | var zooming_stopped = true; 21 | var zooming_out = true; 22 | var make_all_rows = true; 23 | 24 | // show_visible_area is also run with two_translate_zoom, but at that point 25 | // the parameters were not updated and two_translate_zoom if only run 26 | // if needed to reset zoom 27 | show_visible_area(cgm, zooming_stopped, zooming_out, make_all_rows); 28 | 29 | make_col_label_container(cgm); 30 | 31 | var col_nodes = cgm.params.network_data.col_nodes; 32 | 33 | // remove column labels 34 | d3.selectAll(cgm.params.root+' .col_label_group') 35 | .data(col_nodes, function(d){return d.name;}) 36 | .exit() 37 | .style('opacity',0) 38 | .remove(); 39 | 40 | d3.selectAll(cgm.params.root+' .col_label_text') 41 | .data(col_nodes, function(d){return d.name;}) 42 | .exit() 43 | .style('opacity',0) 44 | .remove(); 45 | 46 | d3.selectAll(cgm.params.root+' .col_cat_group') 47 | .data(col_nodes, function(d){return d.name;}) 48 | .exit() 49 | .style('opacity',0) 50 | .remove(); 51 | 52 | d3.selectAll(cgm.params.root+' .col_dendro_group') 53 | .data(col_nodes, function(d){return d.name;}) 54 | .exit() 55 | .style('opacity',0) 56 | .remove(); 57 | 58 | // necessary for repositioning clust, col and col-cat containers 59 | resize_containers(cgm.params); 60 | 61 | // seeing if this fixes resizing issue 62 | var delays = {}; 63 | delays.enter = 0; 64 | delays.update = 0; 65 | delays.run_transition = false; 66 | var duration = 0; 67 | reset_size_after_update(cgm, duration, delays); 68 | 69 | }; -------------------------------------------------------------------------------- /src/enter/enter_existing_row.js: -------------------------------------------------------------------------------- 1 | var mouseover_tile = require('../matrix/mouseover_tile'); 2 | var mouseout_tile = require('../matrix/mouseout_tile'); 3 | var fine_position_tile = require('../matrix/fine_position_tile'); 4 | 5 | module.exports = function enter_existing_row(params, delays, duration, cur_row_tiles, tip){ 6 | 7 | // enter new tiles 8 | var new_tiles = cur_row_tiles 9 | .enter() 10 | .append('rect') 11 | .attr('class', 'tile row_tile') 12 | .attr('width', params.viz.rect_width) 13 | .attr('height', params.viz.rect_height) 14 | .on('mouseover', function(...args) { 15 | mouseover_tile(params, this, tip, args); 16 | }) 17 | .on('mouseout', function mouseout() { 18 | mouseout_tile(params, this, tip); 19 | }) 20 | .attr('fill-opacity',0) 21 | .attr('transform', function(d){ 22 | return fine_position_tile(params, d); 23 | }); 24 | 25 | 26 | if (delays.run_transition){ 27 | new_tiles 28 | .transition().delay(delays.enter).duration(duration) 29 | .style('fill', function(d) { 30 | return d.value > 0 ? params.matrix.tile_colors[0] : params.matrix.tile_colors[1]; 31 | }) 32 | .attr('fill-opacity',function(d){ 33 | var output_opacity = params.matrix.opacity_scale(Math.abs(d.value)); 34 | return output_opacity; 35 | }); 36 | } else { 37 | new_tiles 38 | .style('fill', function(d) { 39 | return d.value > 0 ? params.matrix.tile_colors[0] : params.matrix.tile_colors[1]; 40 | }) 41 | .attr('fill-opacity',function(d){ 42 | var output_opacity = params.matrix.opacity_scale(Math.abs(d.value)); 43 | return output_opacity; 44 | }); 45 | } 46 | 47 | // remove new tiles if necessary 48 | new_tiles 49 | .each(function(d){ 50 | if (Math.abs(d.value_up) > 0 && Math.abs(d.value_dn) > 0) { 51 | d3.select(this) 52 | .remove(); 53 | } 54 | }); 55 | }; -------------------------------------------------------------------------------- /src/enter/enter_new_rows.js: -------------------------------------------------------------------------------- 1 | var enter_split_tiles = require('./enter_split_tiles'); 2 | var mouseover_tile = require('../matrix/mouseover_tile'); 3 | var mouseout_tile = require('../matrix/mouseout_tile'); 4 | var fine_position_tile = require('../matrix/fine_position_tile'); 5 | var underscore = require('underscore'); 6 | 7 | // make each row in the clustergram 8 | module.exports = function enter_new_rows(params, ini_inp_row_data, delays, duration, tip, row_selection) { 9 | 10 | var inp_row_data = ini_inp_row_data.row_data; 11 | 12 | // remove zero values to make visualization faster 13 | var row_data = underscore.filter(inp_row_data, function(num) { 14 | return num.value !== 0; 15 | }); 16 | 17 | // update tiles 18 | //////////////////////////////////////////// 19 | var tile = d3.select(row_selection) 20 | .selectAll('rect') 21 | .data(row_data, function(d){ return d.col_name; }) 22 | .enter() 23 | .append('rect') 24 | .attr('class', 'tile row_tile') 25 | .attr('width', params.viz.rect_width) 26 | .attr('height', params.viz.rect_height) 27 | // switch the color based on up/dn value 28 | .style('fill', function(d) { 29 | return d.value > 0 ? params.matrix.tile_colors[0] : params.matrix.tile_colors[1]; 30 | }) 31 | .on('mouseover', function(...args) { 32 | mouseover_tile(params, this, tip, args); 33 | }) 34 | .on('mouseout', function mouseout() { 35 | mouseout_tile(params, this, tip); 36 | }); 37 | 38 | tile 39 | .style('fill-opacity',0) 40 | .transition().delay(delays.enter) 41 | .duration(duration) 42 | .style('fill-opacity', function(d) { 43 | // calculate output opacity using the opacity scale 44 | var output_opacity = params.matrix.opacity_scale(Math.abs(d.value)); 45 | return output_opacity; 46 | }); 47 | 48 | tile 49 | .attr('transform', function(d) { 50 | return fine_position_tile(params, d); 51 | }); 52 | 53 | if (params.matrix.tile_type == 'updn'){ 54 | enter_split_tiles(params, inp_row_data, row_selection, tip, delays, duration, tile); 55 | } 56 | 57 | }; -------------------------------------------------------------------------------- /src/enter/enter_row_groups.js: -------------------------------------------------------------------------------- 1 | var enter_new_rows = require('./enter_new_rows'); 2 | 3 | module.exports = function enter_row_groups(params, delays, duration, tip){ 4 | 5 | // enter new rows 6 | var new_row_groups = d3.select(params.root+' .clust_group') 7 | .selectAll('.row') 8 | .data(params.matrix.matrix, function(d){return d.name;}) 9 | .enter() 10 | .append('g') 11 | .classed('row', true) 12 | .attr('transform', function(d) { 13 | return 'translate(0,' + params.viz.y_scale(d.row_index) + ')'; 14 | }) ; 15 | 16 | new_row_groups 17 | .each( function(d){ 18 | enter_new_rows(params, d, delays, duration, tip, this); 19 | } ); 20 | 21 | }; -------------------------------------------------------------------------------- /src/exit/exit_existing_row.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function exit_existing_row(params, delays, cur_row_tiles, inp_row_data, row_selection){ 4 | 5 | if (delays.run_transition){ 6 | cur_row_tiles 7 | .exit() 8 | .transition().duration(300) 9 | .attr('fill-opacity',0) 10 | .remove(); 11 | } else { 12 | cur_row_tiles 13 | .exit() 14 | .attr('fill-opacity',0) 15 | .remove(); 16 | } 17 | 18 | if (params.matrix.tile_type == 'updn'){ 19 | 20 | // value split 21 | var row_split_data = underscore.filter(inp_row_data, function(num){ 22 | return num.value_up != 0 || num.value_dn !=0 ; 23 | }); 24 | 25 | // tile_up 26 | var cur_tiles_up = d3.select(row_selection) 27 | .selectAll('.tile_up') 28 | .data(row_split_data, function(d){return d.col_name;}); 29 | 30 | if (delays.run_transition){ 31 | cur_tiles_up 32 | .exit() 33 | .transition().duration(300) 34 | .attr('fill','0') 35 | .remove(); 36 | } else { 37 | cur_tiles_up 38 | .exit() 39 | .attr('fill',0) 40 | .remove(); 41 | } 42 | 43 | // tile_dn 44 | var cur_tiles_dn = d3.select(row_selection) 45 | .selectAll('.tile_dn') 46 | .data(row_split_data, function(d){return d.col_name;}); 47 | 48 | if (delays.run_transition){ 49 | cur_tiles_dn 50 | .exit() 51 | .transition().duration(300) 52 | .attr('fill',0) 53 | .remove(); 54 | } else { 55 | cur_tiles_dn 56 | .exit() 57 | .attr('fill',0) 58 | .remove(); 59 | } 60 | 61 | } 62 | 63 | 64 | 65 | }; -------------------------------------------------------------------------------- /src/filters/get_current_orders.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function get_current_orders(params){ 4 | 5 | // get current orders 6 | var other_rc; 7 | underscore.each(['row','col'], function(inst_rc){ 8 | 9 | if (inst_rc === 'row'){ 10 | other_rc = 'col'; 11 | } else { 12 | other_rc = 'row'; 13 | } 14 | 15 | if (d3.select(params.root+' .toggle_'+other_rc+'_order .active').empty() === false){ 16 | 17 | params.viz.inst_order[inst_rc] = d3.select(params.root+' .toggle_'+other_rc+'_order') 18 | .select('.active').attr('name'); 19 | 20 | } else { 21 | 22 | // default to cluster ordering 23 | params.viz.inst_order[inst_rc] = 'clust'; 24 | 25 | } 26 | 27 | }); 28 | 29 | return params; 30 | }; -------------------------------------------------------------------------------- /src/filters/get_filter_default_state.js: -------------------------------------------------------------------------------- 1 | module.exports = function get_filter_default_state(filter_data, filter_type){ 2 | 3 | var default_state = filter_data[filter_type] 4 | .sort(function(a, b){return b-a;})[0]; 5 | 6 | default_state = String(default_state); 7 | 8 | return default_state; 9 | }; -------------------------------------------------------------------------------- /src/filters/make_button_filter.js: -------------------------------------------------------------------------------- 1 | // var update_network = require('../network/update_network'); 2 | var make_requested_view = require('./make_requested_view'); 3 | 4 | module.exports = function make_button_filter(config, params, filter_type, div_filters){ 5 | 6 | /* 7 | Enrichr specific code 8 | */ 9 | 10 | var buttons = div_filters 11 | .append('div') 12 | .classed('categorical_filter',true) 13 | .classed('toggle_'+filter_type,true) 14 | .classed('btn-group-vertical',true) 15 | .style('width', '100%') 16 | .style('margin-top','10px') 17 | .attr('current_state','combined_score'); 18 | 19 | var filter_options = params.viz.filter_data[filter_type]; 20 | 21 | var button_dict = { 22 | 'combined_score':'Combined Score', 23 | 'pval':'P-Value', 24 | 'zscore':'Z-score' 25 | }; 26 | 27 | buttons 28 | .selectAll('button') 29 | .data(filter_options) 30 | .enter() 31 | .append('button') 32 | .attr('type','button') 33 | .classed('btn',true) 34 | .classed('btn-primary',true) 35 | .classed('.filter_button',true) 36 | .classed('active', function(d){ 37 | var is_active = false; 38 | if (d == 'combined_score'){ 39 | is_active = true; 40 | } 41 | return is_active; 42 | }) 43 | .attr('name', function(d){ 44 | return d; 45 | }) 46 | .html(function(d){ 47 | return button_dict[d]; 48 | }); 49 | 50 | $(params.root+ ' .categorical_filter .btn') 51 | .off() 52 | .click(function(){ 53 | 54 | d3.selectAll(params.root+' .categorical_filter .btn') 55 | .classed('active',false); 56 | 57 | d3.select(this) 58 | .classed('active',true); 59 | 60 | var inst_state = d3.select(this) 61 | .attr('name'); 62 | 63 | var requested_view = {'enr_score_type':inst_state}; 64 | 65 | make_requested_view(params, requested_view); 66 | 67 | d3.select(params.root+' .toggle_enr_score_type') 68 | .attr('current_state', inst_state); 69 | 70 | }); 71 | 72 | }; 73 | -------------------------------------------------------------------------------- /src/filters/make_filter_title.js: -------------------------------------------------------------------------------- 1 | var get_filter_default_state = require('./get_filter_default_state'); 2 | var underscore = require('underscore'); 3 | 4 | module.exports = function make_filter_title(params, filter_type){ 5 | 6 | var filter_title = {}; 7 | var title = {}; 8 | var type = {}; 9 | 10 | filter_title.state = get_filter_default_state(params.viz.filter_data, filter_type); 11 | 12 | type.top = filter_type.split('_')[0]; 13 | type.node = filter_type.split('_')[1]; 14 | type.measure = filter_type.split('_')[2]; 15 | 16 | if (type.node === 'row'){ 17 | title.node = 'rows'; 18 | } else { 19 | title.node = 'columns'; 20 | } 21 | 22 | if (type.top === 'N'){ 23 | // filter_title.suffix = ' '+title.node; 24 | filter_title.suffix = ''; 25 | } 26 | 27 | if (type.top === 'pct'){ 28 | filter_title.suffix = '%'; 29 | } 30 | 31 | if (type.measure == 'sum'){ 32 | title.measure = 'sum'; 33 | } else if (type.measure == 'var'){ 34 | title.measure = 'variance'; 35 | } 36 | 37 | if (type.measure === 'sum'){ 38 | filter_title.text = 'Top '+ title.node + ' ' + title.measure+': '; 39 | } 40 | 41 | if (type.measure === 'var'){ 42 | filter_title.text = 'Top '+ title.node + ' ' + title.measure+': '; 43 | } 44 | 45 | // Enrichr specific rules 46 | if ( underscore.keys(params.viz.possible_filters).indexOf('enr_score_type') > -1 ){ 47 | if (type.node === 'col'){ 48 | filter_title.text = 'Top Enriched Terms: '; 49 | filter_title.suffix = ''; 50 | } 51 | } 52 | 53 | return filter_title; 54 | }; -------------------------------------------------------------------------------- /src/filters/make_requested_view.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function make_view_request(params, requested_view){ 4 | 5 | // this will add all necessary information to a view request 6 | // it will grab necessary view information from the sliders 7 | 8 | // only one component will be changed at a time 9 | var changed_component = underscore.keys(requested_view)[0]; 10 | 11 | // add additional filter information from othe possible filters 12 | underscore.each( underscore.keys(params.viz.possible_filters), function(inst_filter){ 13 | 14 | if (inst_filter != changed_component){ 15 | 16 | if (!d3.select(params.root+' .slider_'+inst_filter).empty()){ 17 | 18 | var inst_state = d3.select(params.root+' .slider_'+inst_filter) 19 | .attr('current_state'); 20 | 21 | requested_view[inst_filter] = inst_state; 22 | } 23 | 24 | } 25 | 26 | }); 27 | 28 | return requested_view; 29 | 30 | }; -------------------------------------------------------------------------------- /src/filters/reset_other_filter_sliders.js: -------------------------------------------------------------------------------- 1 | var make_filter_title = require('./make_filter_title'); 2 | var underscore = require('underscore'); 3 | 4 | module.exports = function reset_other_filter_sliders(cgm, filter_type, inst_state){ 5 | 6 | var params = cgm.params; 7 | var inst_rc; 8 | var reset_rc; 9 | 10 | d3.select(params.root+' .slider_'+filter_type) 11 | .attr('current_state', inst_state); 12 | 13 | underscore.each( underscore.keys(params.viz.possible_filters), function(reset_filter){ 14 | 15 | if ( filter_type.indexOf('row') > -1 ){ 16 | inst_rc = 'row'; 17 | } else if ( filter_type.indexOf('col') > -1 ){ 18 | inst_rc = 'col'; 19 | } else { 20 | inst_rc = 'neither'; 21 | } 22 | 23 | if ( reset_filter.indexOf('row') > -1 ){ 24 | reset_rc = 'row'; 25 | } else if ( reset_filter.indexOf('col') > -1 ){ 26 | reset_rc = 'col'; 27 | } else { 28 | reset_rc = 'neither'; 29 | } 30 | 31 | if (filter_type != reset_filter && inst_rc != 'neither'){ 32 | 33 | if (inst_rc == reset_rc){ 34 | 35 | var tmp_title = make_filter_title(params, reset_filter); 36 | 37 | cgm.slider_functions[reset_filter].value(0); 38 | 39 | d3.select(params.root+' .title_'+reset_filter) 40 | .text(tmp_title.text + tmp_title.state); 41 | 42 | d3.select(params.root+' .slider_'+reset_filter) 43 | .attr('current_state', tmp_title.state); 44 | 45 | } 46 | 47 | } 48 | 49 | 50 | }); 51 | 52 | var filter_title = make_filter_title(params, filter_type); 53 | 54 | d3.select(params.root+' .title_'+filter_type) 55 | .text(filter_title.text + inst_state + filter_title.suffix); 56 | 57 | }; -------------------------------------------------------------------------------- /src/filters/run_filter_slider.js: -------------------------------------------------------------------------------- 1 | var update_viz_with_view = require('../network/update_viz_with_view'); 2 | var reset_other_filter_sliders = require('./reset_other_filter_sliders'); 3 | var get_current_orders = require('./get_current_orders'); 4 | var make_requested_view = require('./make_requested_view'); 5 | var underscore = require('underscore'); 6 | 7 | module.exports = function run_filter_slider(cgm, filter_type, available_views, inst_index){ 8 | 9 | // only update if not running update 10 | if (d3.select(cgm.params.viz.viz_svg).classed('running_update') === false){ 11 | 12 | var params = cgm.params; 13 | 14 | // get value 15 | var inst_state = available_views[inst_index][filter_type]; 16 | 17 | reset_other_filter_sliders(cgm, filter_type, inst_state); 18 | 19 | params = get_current_orders(params); 20 | 21 | var requested_view = {}; 22 | requested_view[filter_type] = inst_state; 23 | 24 | requested_view = make_requested_view(params, requested_view); 25 | 26 | if ( underscore.has(available_views[0],'enr_score_type') ){ 27 | var enr_state = d3.select(params.root+' .toggle_enr_score_type') 28 | .attr('current_state'); 29 | 30 | requested_view.enr_score_type = enr_state; 31 | } 32 | 33 | update_viz_with_view(cgm, requested_view); 34 | 35 | } 36 | 37 | }; -------------------------------------------------------------------------------- /src/filters/set_up_filters.js: -------------------------------------------------------------------------------- 1 | var make_slider_filter = require('./make_slider_filter'); 2 | var make_button_filter = require('./make_button_filter'); 3 | 4 | module.exports = function set_up_filters(cgm, filter_type) { 5 | 6 | var params = cgm.params; 7 | 8 | var div_filters = d3.select(params.root+' .sidebar_wrapper') 9 | .append('div') 10 | .classed('div_filters',true) 11 | .style('padding-left', '10px') 12 | .style('padding-right', '10px'); 13 | 14 | if (params.viz.possible_filters[filter_type] == 'numerical'){ 15 | make_slider_filter(cgm, filter_type, div_filters); 16 | } else if (params.viz.possible_filters[filter_type] == 'categorical'){ 17 | make_button_filter(cgm, filter_type, div_filters); 18 | } 19 | 20 | }; 21 | -------------------------------------------------------------------------------- /src/initialize_matrix.js: -------------------------------------------------------------------------------- 1 | var utils = require('./Utils_clust'); 2 | 3 | module.exports = function(network_data) { 4 | var matrix = []; 5 | var ini_object; 6 | 7 | var keep_orig; 8 | if (utils.has(network_data.links[0], 'value_orig')){ 9 | keep_orig = true; 10 | } else { 11 | keep_orig = false; 12 | } 13 | 14 | network_data.row_nodes.forEach(function (tmp, row_index) { 15 | 16 | matrix[row_index] = {}; 17 | matrix[row_index].name = network_data.row_nodes[row_index].name; 18 | matrix[row_index].row_index = row_index; 19 | 20 | matrix[row_index].row_data = d3.range(network_data.col_nodes.length).map( 21 | function (col_index) { 22 | 23 | if (utils.has(network_data.links[0], 'value_up') || utils.has(network_data.links[0], 'value_dn')) { 24 | 25 | ini_object = { 26 | pos_x: col_index, 27 | pos_y: row_index, 28 | value: 0, 29 | value_up: 0, 30 | value_dn: 0, 31 | highlight: 0 32 | }; 33 | 34 | } else { 35 | 36 | ini_object = { 37 | pos_x: col_index, 38 | pos_y: row_index, 39 | value: 0, 40 | highlight: 0 41 | }; 42 | 43 | } 44 | 45 | if (keep_orig){ 46 | ini_object.value_orig = 0; 47 | } 48 | 49 | return ini_object; 50 | }); 51 | 52 | }); 53 | 54 | network_data.links.forEach(function (link) { 55 | 56 | // transfer additional link information is necessary 57 | matrix[link.source].row_data[link.target].value = link.value; 58 | matrix[link.source].row_data[link.target].row_name = link.row_name; 59 | matrix[link.source].row_data[link.target].col_name = link.col_name; 60 | 61 | if (utils.has(link, 'value_up') || utils.has(link, 'value_dn')) { 62 | matrix[link.source].row_data[link.target].value_up = link.value_up; 63 | matrix[link.source].row_data[link.target].value_dn = link.value_dn; 64 | } 65 | 66 | if (keep_orig){ 67 | matrix[link.source].row_data[link.target].value_orig = link.value_orig; 68 | } 69 | 70 | if (link.highlight) { 71 | matrix[link.source].row_data[link.target].highlight = link.highlight; 72 | } 73 | if (link.info) { 74 | matrix[link.source].row_data[link.target].info = link.info; 75 | } 76 | }); 77 | 78 | return matrix; 79 | }; 80 | -------------------------------------------------------------------------------- /src/labels/add_col_click_hlight.js: -------------------------------------------------------------------------------- 1 | module.exports = function(params, clicked_col, id_clicked_col) { 2 | 3 | if (id_clicked_col != params.click_hlight_col){ 4 | 5 | params.click_hlight_col = id_clicked_col; 6 | 7 | var rel_width_hlight = 6; 8 | var opacity_hlight = 0.85; 9 | var hlight_width = rel_width_hlight * params.viz.border_width.x; 10 | 11 | d3.selectAll(params.root+' .click_hlight') 12 | .remove(); 13 | 14 | // // highlight selected column 15 | // /////////////////////////////// 16 | // // unhilight and unbold all columns (already unbolded earlier) 17 | // d3.selectAll('.col_label_text') 18 | // .select('rect') 19 | // .style('opacity', 0); 20 | // // highlight column name 21 | // d3.select(clicked_col) 22 | // .select('rect') 23 | // .style('opacity', 1); 24 | 25 | d3.select(clicked_col) 26 | .append('rect') 27 | .classed('click_hlight',true) 28 | .classed('col_top_hlight',true) 29 | .attr('width',params.viz.clust.dim.height) 30 | .attr('height',hlight_width) 31 | .attr('fill',params.matrix.hlight_color) 32 | .attr('opacity',opacity_hlight) 33 | .attr('transform',function(){ 34 | var tmp_translate_y = 0; 35 | var tmp_translate_x = -(params.viz.clust.dim.height+ 36 | params.viz.cat_room.col+params.viz.uni_margin); 37 | return 'translate('+tmp_translate_x+','+tmp_translate_y+')'; 38 | }); 39 | 40 | d3.select(clicked_col) 41 | .append('rect') 42 | .classed('click_hlight',true) 43 | .classed('col_bottom_hlight',true) 44 | .attr('width',params.viz.clust.dim.height) 45 | .attr('height',hlight_width) 46 | .attr('fill',params.matrix.hlight_color) 47 | .attr('opacity',opacity_hlight) 48 | .attr('transform', function(){ 49 | // reverse x and y since rotated 50 | var tmp_translate_y = params.viz.x_scale.rangeBand() - hlight_width; 51 | var tmp_translate_x = -(params.viz.clust.dim.height + 52 | params.viz.cat_room.col+params.viz.uni_margin); 53 | return 'translate('+tmp_translate_x+','+tmp_translate_y+')'; 54 | }); 55 | } else { 56 | d3.selectAll(params.root+' .click_hlight') 57 | .remove(); 58 | params.click_hlight_col = -666; 59 | } 60 | 61 | }; 62 | -------------------------------------------------------------------------------- /src/labels/add_row_click_hlight.js: -------------------------------------------------------------------------------- 1 | module.exports = function(params, clicked_row, id_clicked_row) { 2 | if (id_clicked_row != params.click_hlight_row){ 3 | 4 | var rel_width_hlight = 6; 5 | var opacity_hlight = 0.85; 6 | var hlight_height = rel_width_hlight * params.viz.border_width.x; 7 | 8 | d3.selectAll(params.root+' .click_hlight') 9 | .remove(); 10 | 11 | // // highlight selected row 12 | // d3.selectAll(params.root+' .row_label_group') 13 | // .select('rect') 14 | // d3.select(this) 15 | // .select('rect') 16 | // .style('opacity', 1); 17 | 18 | d3.select(clicked_row) 19 | .append('rect') 20 | .classed('click_hlight',true) 21 | .classed('row_top_hlight',true) 22 | .attr('width',params.viz.svg_dim.width) 23 | .attr('height',hlight_height) 24 | .attr('fill',params.matrix.hlight_color) 25 | .attr('opacity',opacity_hlight); 26 | 27 | d3.select(clicked_row) 28 | .append('rect') 29 | .classed('click_hlight',true) 30 | .classed('row_bottom_hlight',true) 31 | .attr('width',params.viz.svg_dim.width) 32 | .attr('height',hlight_height) 33 | .attr('fill',params.matrix.hlight_color) 34 | .attr('opacity',opacity_hlight) 35 | .attr('transform', function(){ 36 | var tmp_translate_y = params.viz.y_scale.rangeBand() - hlight_height; 37 | return 'translate(0,'+tmp_translate_y+')'; 38 | }); 39 | } else{ 40 | d3.selectAll(params.root+' .click_hlight') 41 | .remove(); 42 | params.click_hlight_row = -666; 43 | } 44 | 45 | }; 46 | -------------------------------------------------------------------------------- /src/labels/col_viz_aid_triangle.js: -------------------------------------------------------------------------------- 1 | module.exports = function col_viz_aid_triangle(params){ 2 | 3 | // x and y are flipped since its rotated 4 | var reduce_rect_width = params.viz.x_scale.rangeBand() * 0.36; 5 | var origin_y = -params.viz.border_width.x; 6 | var start_x = 0; 7 | var final_x = params.viz.x_scale.rangeBand() - reduce_rect_width; 8 | var start_y = -(params.viz.x_scale.rangeBand() - reduce_rect_width + 9 | params.viz.border_width.x); 10 | var final_y = -params.viz.border_width.x; 11 | var output_string = 'M ' + origin_y + ',0 L ' + start_y + ',' + 12 | start_x + ' L ' + final_y + ',' + final_x + ' Z'; 13 | return output_string; 14 | }; -------------------------------------------------------------------------------- /src/labels/label_constrain_and_trim.js: -------------------------------------------------------------------------------- 1 | var utils = require('../Utils_clust'); 2 | var trim_text = require('../zoom/trim_text'); 3 | var constrain_font_size = require('../zoom/constrain_font_size'); 4 | 5 | module.exports = function label_constrain_and_trim(params){ 6 | 7 | // console.log('label_constrain_and_trim'); 8 | 9 | // reset text in rows and columns 10 | d3.selectAll(params.root+' .row_label_group') 11 | .select('text') 12 | .text(function(d){ return utils.normal_name(d); }); 13 | 14 | d3.selectAll(params.root+' .col_label_text') 15 | .select('text') 16 | .text(function(d){ return utils.normal_name(d); }); 17 | 18 | constrain_font_size(params); 19 | 20 | d3.selectAll(params.root+' .row_label_group' ) 21 | .each(function() { trim_text(params, this, 'row'); }); 22 | 23 | d3.selectAll(params.root+' .col_label_group') 24 | .each(function() { trim_text(params, this, 'col'); }); 25 | 26 | }; -------------------------------------------------------------------------------- /src/labels/make_col_tooltips.js: -------------------------------------------------------------------------------- 1 | var d3_tip_custom = require('../tooltip/d3_tip_custom'); 2 | 3 | module.exports = function make_col_tooltips(params){ 4 | 5 | if (params.labels.show_label_tooltips){ 6 | 7 | // remove old col tooltips 8 | d3.selectAll(params.viz.root_tips + '_col_tip').remove(); 9 | 10 | // d3-tooltip 11 | var col_tip = d3_tip_custom() 12 | .attr('class', function(){ 13 | var root_tip_selector = params.viz.root_tips.replace('.',''); 14 | var class_string = root_tip_selector + ' d3-tip '+ 15 | root_tip_selector + '_col_tip'; 16 | return class_string; 17 | }) 18 | .direction('w') 19 | .offset([20, 0]) 20 | .style('display','none') 21 | .html(function(d) { 22 | var inst_name = d.name.replace(/_/g, ' ').split('#')[0]; 23 | return "" + inst_name + ""; 24 | }); 25 | 26 | d3.select(params.viz.viz_wrapper) 27 | .select('svg') 28 | .select(params.root+' .col_zoom_container') 29 | .selectAll('.col_label_group') 30 | .select('text') 31 | .call(col_tip); 32 | 33 | d3.select(params.root+' .col_zoom_container') 34 | .selectAll('.col_label_group') 35 | .on('mouseover', function(d){ 36 | 37 | d3.selectAll(params.viz.root_tips+'_col_tip') 38 | .style('display', 'block'); 39 | 40 | col_tip.show(d); 41 | if (params.col_tip_callback != null){ 42 | params.col_tip_callback(d); 43 | } 44 | }) 45 | .on('mouseout', function(){ 46 | col_tip.hide(this); 47 | 48 | d3.selectAll(params.viz.root_tips+'_col_tip') 49 | .style('display', 'none'); 50 | 51 | }); 52 | 53 | } 54 | 55 | }; -------------------------------------------------------------------------------- /src/labels/make_row_label_container.js: -------------------------------------------------------------------------------- 1 | var make_row_labels = require('./make_row_labels'); 2 | 3 | module.exports = function make_row_label_container(cgm, text_delay) { 4 | 5 | var params = cgm.params; 6 | 7 | var row_container; 8 | 9 | // row container holds all row text and row visualizations (triangles rects) 10 | //////////////////////////////////////////////////////////////////////////// 11 | if ( d3.select(params.viz.viz_svg + ' .row_container').empty() ){ 12 | row_container = d3.select(params.viz.viz_svg) 13 | .append('g') 14 | .classed('row_container', true) 15 | .attr('transform', 'translate(' + params.viz.norm_labels.margin.left + ',' + 16 | params.viz.clust.margin.top + ')'); 17 | } else { 18 | row_container = d3.select(params.viz.viz_svg) 19 | .select('.row_container') 20 | .attr('transform', 'translate(' + params.viz.norm_labels.margin.left + ',' + 21 | params.viz.clust.margin.top + ')'); 22 | } 23 | 24 | if (d3.select(params.root+' .row_white_background').empty()){ 25 | row_container 26 | .append('rect') 27 | .classed('row_white_background',true) 28 | .classed('white_bars',true) 29 | .attr('fill', params.viz.background_color) 30 | .attr('width', params.viz.label_background.row) 31 | .attr('height', 30*params.viz.clust.dim.height + 'px'); 32 | } 33 | 34 | // add container to hold text row labels if not already there 35 | if ( d3.select(params.root +' .row_label_container').empty() ){ 36 | row_container 37 | .append('g') 38 | .classed('row_label_container', true) 39 | .attr('transform', 'translate(' + params.viz.norm_labels.width.row + ',0)') 40 | .append('g') 41 | .classed('row_label_zoom_container', true); 42 | } else { 43 | row_container 44 | .select(params.root+' .row_label_container') 45 | .attr('transform', 'translate(' + params.viz.norm_labels.width.row + ',0)'); 46 | } 47 | 48 | // make row labels in the container 49 | /////////////////////////////////////// 50 | if (params.viz.ds_level === -1){ 51 | make_row_labels(cgm, 'all', text_delay); 52 | } 53 | 54 | }; 55 | -------------------------------------------------------------------------------- /src/labels/make_row_tooltips.js: -------------------------------------------------------------------------------- 1 | var d3_tip_custom = require('../tooltip/d3_tip_custom'); 2 | 3 | module.exports = function make_row_tooltips(params){ 4 | 5 | if (params.labels.show_label_tooltips){ 6 | 7 | // remove old tooltips 8 | d3.selectAll(params.viz.root_tips + '_row_tip').remove(); 9 | 10 | var root_tip_selector = params.viz.root_tips.replace('.',''); 11 | 12 | // d3-tooltip 13 | var row_tip = d3_tip_custom() 14 | .attr('class', function(){ 15 | var class_string = root_tip_selector + ' d3-tip '+ 16 | root_tip_selector + '_row_tip'; 17 | return class_string; 18 | }) 19 | .direction('e') 20 | .offset([0, 10]) 21 | .style('display','none') 22 | .html(function(d) { 23 | var inst_name = d.name.replace(/_/g, ' ').split('#')[0]; 24 | return "" + inst_name + ""; 25 | }); 26 | 27 | d3.select(params.viz.viz_wrapper) 28 | .select(params.root+' .row_container') 29 | .call(row_tip); 30 | 31 | d3.select(params.root+' .row_label_zoom_container') 32 | .selectAll('g') 33 | .on('mouseover', function(d) { 34 | 35 | d3.select(params.viz.root_tips+'_row_tip') 36 | .classed(d.name, true); 37 | 38 | d3.selectAll(params.viz.root_tips+'_row_tip') 39 | .style('display', 'block'); 40 | 41 | d3.select(this) 42 | .select('text') 43 | .classed('active', true); 44 | 45 | row_tip.show(d); 46 | 47 | if (params.row_tip_callback != null){ 48 | params.row_tip_callback(params.viz.root_tips, d); 49 | } 50 | 51 | }) 52 | .on('mouseout', function mouseout(d) { 53 | 54 | d3.selectAll(params.viz.root_tips+'_row_tip') 55 | .style('display', 'none') 56 | .classed(d.name, false); 57 | 58 | d3.select(this) 59 | .select('text') 60 | .classed('active',false); 61 | 62 | row_tip.hide(d); 63 | }); 64 | 65 | 66 | } else{ 67 | 68 | d3.select(params.root+' .row_label_zoom_container') 69 | .selectAll('g') 70 | .on('mouseover', function() { 71 | d3.select(this) 72 | .select('text') 73 | .classed('active',true); 74 | }) 75 | .on('mouseout', function mouseout() { 76 | d3.select(this) 77 | .select('text') 78 | .classed('active',false); 79 | }); 80 | } 81 | 82 | }; -------------------------------------------------------------------------------- /src/labels/make_row_visual_aid_triangles.js: -------------------------------------------------------------------------------- 1 | module.exports = function make_row_visual_aid_triangles(params){ 2 | 3 | if (d3.select(params.root+' .row_cat_group path').empty() === true){ 4 | d3.selectAll(params.root+' .row_cat_group') 5 | .append('path') 6 | .attr('d', function() { 7 | var origin_x = params.viz.cat_room.symbol_width - 1; 8 | var origin_y = 0; 9 | var mid_x = 1; 10 | var mid_y = params.viz.y_scale.rangeBand() / 2; 11 | var final_x = params.viz.cat_room.symbol_width - 1; 12 | var final_y = params.viz.y_scale.rangeBand(); 13 | var output_string = 'M ' + origin_x + ',' + origin_y + ' L ' + 14 | mid_x + ',' + mid_y + ' L ' + final_x + ',' + final_y + ' Z'; 15 | return output_string; 16 | }) 17 | .attr('fill', '#eee') 18 | .style('opacity', params.viz.triangle_opacity); 19 | } 20 | 21 | }; -------------------------------------------------------------------------------- /src/matrix/calc_downsampled_matrix.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function calc_downsampled_matrix(params, mat, ds_level){ 4 | 5 | var inst_num_rows = params.viz.ds[ds_level].num_rows; 6 | 7 | var num_compressed_rows = params.network_data.row_nodes.length / inst_num_rows; 8 | 9 | // increase ds opacity, as more rows are compressed into a single downsampled 10 | // row, increase the opacity of the downsampled row. 11 | var opacity_factor = params.viz.ds_opacity_scale(num_compressed_rows); 12 | 13 | var mod_val = params.viz.clust.dim.height / inst_num_rows; 14 | 15 | var ds_mat = []; 16 | var inst_obj; 17 | 18 | var len_ds_array = inst_num_rows + 1; 19 | 20 | var i; 21 | var x; 22 | 23 | // initialize array of objects 24 | for (i=0; i < len_ds_array; i++){ 25 | 26 | inst_obj = {}; 27 | inst_obj.row_index = i; 28 | inst_obj.name = String(i); 29 | inst_obj.all_names = []; 30 | 31 | ds_mat.push(inst_obj); 32 | } 33 | 34 | underscore.each(mat, function(inst_row){ 35 | 36 | // row ordering information is contained in y_scale 37 | var inst_y = params.viz.y_scale(inst_row.row_index); 38 | 39 | var ds_index = Math.round(inst_y/mod_val); 40 | 41 | var inst_row_data = inst_row.row_data; 42 | 43 | // gather names 44 | ds_mat[ds_index].all_names.push(inst_row.name); 45 | 46 | // gather row_data 47 | if (_.has(ds_mat[ds_index], 'row_data')){ 48 | 49 | for (x=0; x < inst_row_data.length; x++){ 50 | ds_mat[ds_index].row_data[x].value = ds_mat[ds_index].row_data[x].value + inst_row_data[x].value; 51 | } 52 | 53 | } else { 54 | 55 | var new_data = []; 56 | for (x=0; x < inst_row_data.length; x++){ 57 | new_data[x] = inst_row_data[x]; 58 | } 59 | 60 | ds_mat[ds_index].row_data = new_data; 61 | 62 | } 63 | 64 | }); 65 | 66 | // average the values 67 | underscore.each(ds_mat, function(tmp_ds){ 68 | 69 | var tmp_row_data = tmp_ds.row_data; 70 | 71 | var num_names = tmp_ds.all_names.length; 72 | 73 | underscore.each(tmp_row_data, function(tmp_obj){ 74 | tmp_obj.value = (tmp_obj.value / num_names)*opacity_factor; 75 | }); 76 | 77 | }); 78 | 79 | // all names were found 80 | var all_names = []; 81 | 82 | underscore.each(ds_mat, function(inst_row){ 83 | all_names = all_names.concat(inst_row.all_names); 84 | }); 85 | 86 | return ds_mat; 87 | 88 | }; -------------------------------------------------------------------------------- /src/matrix/deactivate_cropping.js: -------------------------------------------------------------------------------- 1 | module.exports = function deactivate_cropping(cgm){ 2 | 3 | d3.select(cgm.params.root+' .brush_group') 4 | .transition() 5 | .style('opacity', 0) 6 | .remove(); 7 | 8 | cgm.params.is_cropping = false; 9 | 10 | }; -------------------------------------------------------------------------------- /src/matrix/draw_gridlines.js: -------------------------------------------------------------------------------- 1 | // var grid_lines_viz = require('./grid_lines_viz'); 2 | // var toggle_grid_lines = require('./toggle_grid_lines'); 3 | 4 | /* eslint-disable */ 5 | module.exports = function draw_gridlines(params, delays, duration){ 6 | 7 | // var row_nodes = params.network_data.row_nodes; 8 | // var col_nodes = params.network_data.col_nodes; 9 | 10 | // // Fade in new gridlines 11 | // /////////////////////////// 12 | 13 | // // append horizontal line groups 14 | // var horz_lines = d3.select(params.root+' .clust_group') 15 | // .selectAll('.horz_lines') 16 | // .data(row_nodes, function(d){return d.name;}) 17 | // .enter() 18 | // .append('g') 19 | // .attr('class','horz_lines'); 20 | 21 | // // append vertical line groups 22 | // var vert_lines = d3.select(params.root+' .clust_group') 23 | // .selectAll('.vert_lines') 24 | // .data(col_nodes) 25 | // .enter() 26 | // .append('g') 27 | // .attr('class', 'vert_lines'); 28 | 29 | // grid_lines_viz(params, duration); 30 | 31 | // horz_lines 32 | // .select('line') 33 | // .attr('opacity',0) 34 | // .attr('stroke','white') 35 | // .attr('opacity', 1); 36 | 37 | // vert_lines 38 | // .select('line') 39 | // .style('stroke', 'white') 40 | // .attr('opacity',0) 41 | // .transition().delay(delays.enter).duration(2*duration) 42 | // .attr('opacity', 1); 43 | 44 | // toggle_grid_lines(params); 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /src/matrix/fine_position_tile.js: -------------------------------------------------------------------------------- 1 | module.exports = function fine_position_tile(params, d){ 2 | 3 | var offset_x; 4 | 5 | // prevent rows not in x_scale domain from causing errors 6 | if (d.pos_x in params.viz.x_scale.domain()){ 7 | offset_x = params.viz.x_scale(d.pos_x); 8 | } else { 9 | offset_x = 0; 10 | } 11 | 12 | var x_pos = offset_x + 0.5 * params.viz.border_width.x; 13 | var y_pos = 0.5 * params.viz.border_width.y; 14 | return 'translate(' + x_pos + ',' + y_pos + ')'; 15 | }; -------------------------------------------------------------------------------- /src/matrix/grid_lines_viz.js: -------------------------------------------------------------------------------- 1 | module.exports = function grid_lines_viz(params, duration=0){ 2 | 3 | var delay = 0; 4 | if (duration > 0){ 5 | delay = 2000; 6 | } 7 | 8 | var horz_lines = d3.selectAll(params.root+' .horz_lines'); 9 | var vert_lines = d3.selectAll(params.root+' .vert_lines'); 10 | 11 | horz_lines 12 | .style('opacity', 0) 13 | .attr('transform', function(d) { 14 | var inst_index = d.row_index; 15 | var inst_trans = params.viz.y_scale(inst_index); 16 | return 'translate( 0,' + inst_trans + ') rotate(0)'; 17 | }) 18 | .transition() 19 | .duration(duration) 20 | .delay(delay) 21 | .style('opacity', 1); 22 | 23 | horz_lines 24 | .append('line') 25 | .attr('x1',0) 26 | .attr('x2',params.viz.clust.dim.width) 27 | .style('stroke-width', function(){ 28 | var inst_width = params.viz.border_width.y; 29 | return inst_width+'px'; 30 | }); 31 | 32 | vert_lines 33 | .style('opacity', 0) 34 | .attr('transform', function(d) { 35 | var inst_index = d.col_index; 36 | var inst_trans = params.viz.x_scale(inst_index); 37 | return 'translate(' + inst_trans + ') rotate(-90)'; 38 | }) 39 | .transition() 40 | .duration(duration) 41 | .delay(delay) 42 | .style('opacity', 1); 43 | 44 | vert_lines 45 | .append('line') 46 | .attr('x1', 0) 47 | .attr('x2', -params.viz.clust.dim.height) 48 | .style('stroke-width', function(){ 49 | var inst_width = params.viz.border_width.x; 50 | return inst_width + 'px'; 51 | }); 52 | 53 | }; -------------------------------------------------------------------------------- /src/matrix/make_full_name.js: -------------------------------------------------------------------------------- 1 | module.exports = function make_full_name(params, inst_node, inst_rc){ 2 | 3 | var cat_name; 4 | var inst_name = inst_node.name; 5 | var num_cats = params.viz.all_cats[inst_rc].length; 6 | 7 | // make tuple if necessary 8 | if (num_cats>0){ 9 | 10 | inst_name = "('" + inst_name + "'"; 11 | 12 | for (var cat_index= 0; cat_index < num_cats; cat_index++) { 13 | cat_name = 'cat-'+ String(cat_index); 14 | 15 | inst_name = inst_name + ", '" + String(inst_node[cat_name]) + "'"; 16 | 17 | } 18 | 19 | inst_name = inst_name + ')'; 20 | 21 | } else { 22 | 23 | // always make names strings 24 | inst_name = String(inst_name); 25 | 26 | } 27 | 28 | 29 | return inst_name; 30 | }; -------------------------------------------------------------------------------- /src/matrix/make_matrix_string.js: -------------------------------------------------------------------------------- 1 | var make_full_name = require('./make_full_name'); 2 | var underscore = require('underscore'); 3 | 4 | module.exports = function make_matrix_string(params){ 5 | 6 | var inst_matrix = params.matrix; 7 | 8 | // get order indexes 9 | var order_indexes = {}; 10 | var inst_name; 11 | underscore.each(['row', 'col'], function(tmp_rc){ 12 | 13 | var inst_rc; 14 | // row/col names are reversed in saved orders 15 | if (tmp_rc === 'row'){ 16 | inst_rc = 'col'; 17 | } else { 18 | inst_rc = 'row'; 19 | } 20 | 21 | // use tmp_rc 22 | inst_name = params.inst_order[tmp_rc]; 23 | 24 | // use tmp_rc 25 | order_indexes[inst_rc] = inst_matrix.orders[ inst_name+ '_' + tmp_rc ]; 26 | 27 | }); 28 | 29 | var matrix_string = '\t'; 30 | var row_nodes = params.network_data.row_nodes; 31 | var col_nodes = params.network_data.col_nodes; 32 | 33 | // alternate column entry 34 | for (var c_i=0; c_i 1){ 4 | d3.selectAll(params.root+' .vert_lines').select('line') 5 | .style('display','block') 6 | .style('opacity', 0) 7 | .transition() 8 | .style('opacity', 1); 9 | } else { 10 | d3.selectAll(params.root+' .vert_lines').select('line').style('display','none'); 11 | } 12 | 13 | if (params.zoom_info.zoom_y * params.viz.border_width.y > 1){ 14 | d3.selectAll(params.root+' .horz_lines').select('line') 15 | .style('display','block') 16 | .style('opacity', 0) 17 | .transition() 18 | .style('opacity', 1); 19 | } else { 20 | d3.selectAll(params.root+' .horz_lines').select('line').style('display','none'); 21 | } 22 | }; -------------------------------------------------------------------------------- /src/menus/make_menu_update_button.js: -------------------------------------------------------------------------------- 1 | module.exports = function make_menu_update_button(cgm, button_info, update_callback){ 2 | 3 | 4 | var update_button_width = cgm.params.viz.update_button_width; 5 | 6 | // var menu_width = button_info.menu_width; 7 | // var button_x = menu_width/2 + button_info.default_x_offset; 8 | 9 | var default_opacity = 0.35; 10 | var high_opacity = 0.5; 11 | 12 | var update_button = button_info.selection 13 | .append('g') 14 | .classed('update_button', true) 15 | .attr('transform', 'translate('+ button_info.update_x +', ' + button_info.update_y + ')') 16 | .on('click', update_callback) 17 | .on('mouseover', function(){ 18 | d3.select(this) 19 | .select('rect') 20 | .attr('opacity', high_opacity); 21 | }) 22 | .on('mouseout', function(){ 23 | d3.select(this) 24 | .select('rect') 25 | .attr('opacity', default_opacity); 26 | }); 27 | 28 | update_button 29 | .append('rect') 30 | .attr('width', update_button_width + 'px') 31 | .attr('height', '35px') 32 | .attr('fill', 'blue') 33 | .attr('transform', 'translate(0, -23)') 34 | .attr('stroke', '#A3A3A3') 35 | .attr('stroke-width', '1px') 36 | .attr('opacity', default_opacity); 37 | 38 | update_button 39 | .append('text') 40 | .attr('font-family', '"Helvetica Neue", Helvetica, Arial, sans-serif') 41 | .attr('font-size','18px') 42 | .attr('font-weight', 500) 43 | .attr('cursor', 'default') 44 | .text('Update') 45 | .attr('transform', 'translate(18, 0)'); 46 | 47 | }; -------------------------------------------------------------------------------- /src/menus/position_filter_icon.js: -------------------------------------------------------------------------------- 1 | module.exports = function position_filter_icon(cgm){ 2 | 3 | var viz = cgm.params.viz; 4 | var tmp_left; 5 | var tmp_top; 6 | 7 | // keep slider near clustergram 8 | var max_room = viz.svg_dim.width - 3 * viz.uni_margin; 9 | 10 | // position close to row dendrogram trapezoids 11 | tmp_left = viz.clust.margin.left + viz.clust.dim.width + 4 * viz.dendro_room.row + 7; 12 | 13 | if (tmp_left > max_room){ 14 | tmp_left = max_room; 15 | } 16 | 17 | // tmp_top = viz.clust.margin.top + 3 * viz.uni_margin - 50; 18 | tmp_top = viz.clust.margin.top + 3 * viz.uni_margin + 152; 19 | 20 | // reposition tree icon 21 | d3.select(cgm.params.root + ' .' + 'filter_icon') 22 | .attr('transform', function() { 23 | var inst_translation; 24 | tmp_top = tmp_top - 75; 25 | inst_translation = 'translate(' + tmp_left + ',' + tmp_top + ')'; 26 | return inst_translation; 27 | }) 28 | .style('opacity', 1); 29 | }; -------------------------------------------------------------------------------- /src/menus/position_filter_menu.js: -------------------------------------------------------------------------------- 1 | module.exports = function position_filter_menu(cgm){ 2 | 3 | var params = cgm.params; 4 | 5 | if (d3.select(params.root+' .filter_menu').empty() === false){ 6 | 7 | var menu_width = cgm.params.viz.filter_menu_width; 8 | 9 | d3.select(params.root+' .filter_menu') 10 | .attr('transform', function(){ 11 | var shift = {}; 12 | shift.x = params.viz.clust.dim.width + params.viz.clust.margin.left - menu_width + 30; 13 | shift.y = params.viz.clust.margin.top + 80; 14 | return 'translate(' + shift.x + ', ' + shift.y + ')'; 15 | }); 16 | 17 | } 18 | }; -------------------------------------------------------------------------------- /src/menus/position_tree_icon.js: -------------------------------------------------------------------------------- 1 | module.exports = function position_tree_icon(cgm){ 2 | 3 | var viz = cgm.params.viz; 4 | var tmp_left; 5 | var tmp_top; 6 | 7 | // keep slider near clustergram 8 | var max_room = viz.svg_dim.width - 3 * viz.uni_margin; 9 | 10 | // position close to row dendrogram trapezoids 11 | tmp_left = viz.clust.margin.left + viz.clust.dim.width + 5.25 * viz.dendro_room.row; 12 | 13 | if (tmp_left > max_room){ 14 | tmp_left = max_room; 15 | } 16 | 17 | // tmp_top = viz.clust.margin.top + 3 * viz.uni_margin - 50; 18 | tmp_top = viz.clust.margin.top + 3 * viz.uni_margin + 90; 19 | 20 | // reposition tree icon 21 | d3.select(cgm.params.root + ' .' + 'tree_icon') 22 | .attr('transform', function() { 23 | var inst_translation; 24 | tmp_top = tmp_top - 75; 25 | inst_translation = 'translate(' + tmp_left + ',' + tmp_top + ')'; 26 | return inst_translation; 27 | }) 28 | .style('opacity', 1); 29 | }; -------------------------------------------------------------------------------- /src/menus/position_tree_menu.js: -------------------------------------------------------------------------------- 1 | module.exports = function position_tree_menu(cgm){ 2 | 3 | var params = cgm.params; 4 | 5 | if (d3.select(params.root+' .tree_menu').empty() === false){ 6 | 7 | var menu_width = cgm.params.viz.tree_menu_width; 8 | 9 | d3.select(params.root+' .tree_menu') 10 | .attr('transform', function(){ 11 | var shift = {}; 12 | shift.x = params.viz.clust.dim.width + params.viz.clust.margin.left - menu_width + 30; 13 | shift.y = params.viz.clust.margin.top + 15; 14 | return 'translate(' + shift.x + ', ' + shift.y + ')'; 15 | }); 16 | 17 | } 18 | }; -------------------------------------------------------------------------------- /src/menus/toggle_menu.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function toggle_menu(cgm, menu_type, toggle, make_menu=null){ 3 | 4 | var params = cgm.params; 5 | 6 | if (toggle === 'open'){ 7 | 8 | d3.selectAll(cgm.params.root + ' .svg_menus') 9 | .remove(); 10 | 11 | if (make_menu != null){ 12 | make_menu(cgm); 13 | } 14 | 15 | 16 | } else if (toggle === 'close'){ 17 | 18 | d3.select(params.root + ' .' + menu_type) 19 | .transition(700) 20 | .attr('opacity', 0); 21 | 22 | setTimeout(function(){ 23 | d3.select(params.root + ' .' + menu_type) 24 | .remove(); 25 | }, 700); 26 | } 27 | 28 | }; -------------------------------------------------------------------------------- /src/modal/make_modal_skeleton.js: -------------------------------------------------------------------------------- 1 | module.exports = function make_modal_skeleton(params, modal_class){ 2 | 3 | var modal_skeleton = {}; 4 | 5 | var modal = d3.select(params.root) 6 | .append('div') 7 | .classed('modal', true) 8 | .classed('fade', true) 9 | .classed(modal_class, true) 10 | .attr('role','dialog'); 11 | 12 | var modal_dialog = modal 13 | .append('div') 14 | .classed('modal-dialog', true); 15 | 16 | var modal_content = modal_dialog 17 | .append('div') 18 | .classed('modal-content', true); 19 | 20 | modal_skeleton.header = modal_content 21 | .append('div') 22 | .classed('modal-header', true); 23 | 24 | modal_skeleton.header 25 | .append('button') 26 | .attr('type','button') 27 | .classed('close', true) 28 | .attr('data-dismiss','modal') 29 | .html('×'); 30 | 31 | modal_skeleton.body = modal_content 32 | .append('div') 33 | .classed('modal-body', true); 34 | 35 | return modal_skeleton; 36 | 37 | }; -------------------------------------------------------------------------------- /src/network/change_category.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function(params, inst_cat) { 3 | // change the category 4 | params.current_col_cat = inst_cat; 5 | }; 6 | -------------------------------------------------------------------------------- /src/network/define_enter_exit_delays.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function(old_params, params) { 4 | 5 | // exit, update, enter 6 | 7 | // check if exit or enter or both are required 8 | var old_row_nodes = old_params.network_data.row_nodes; 9 | var old_col_nodes = old_params.network_data.col_nodes; 10 | var old_row = underscore.map(old_row_nodes, function(d){return d.name;}); 11 | var old_col = underscore.map(old_col_nodes, function(d){return d.name;}); 12 | var all_old_nodes = old_row.concat(old_col); 13 | 14 | var row_nodes = params.network_data.row_nodes; 15 | var col_nodes = params.network_data.col_nodes; 16 | var row = underscore.map(row_nodes, function(d){return d.name;}); 17 | var col = underscore.map(col_nodes, function(d){return d.name;}); 18 | var all_nodes = row.concat(col); 19 | 20 | var exit_nodes = underscore.difference( all_old_nodes, all_nodes ).length; 21 | var enter_nodes = underscore.difference( all_nodes, all_old_nodes ).length; 22 | 23 | var delays = {}; 24 | 25 | if (exit_nodes > 0){ 26 | delays.update = 1000; 27 | } else { 28 | delays.update = 0; 29 | } 30 | 31 | if (enter_nodes > 0){ 32 | delays.enter = 1000; 33 | } else { 34 | delays.enter = 0; 35 | } 36 | 37 | delays.enter = delays.enter + delays.update ; 38 | 39 | delays.run_transition = true; 40 | 41 | var old_num_links = old_params.network_data.links.length; 42 | var new_num_links = params.network_data.links.length; 43 | var cutoff_num_links = 0.5*params.matrix.def_large_matrix; 44 | 45 | if ( old_num_links > cutoff_num_links || new_num_links > cutoff_num_links ){ 46 | delays.run_transition = false; 47 | delays.update = 0; 48 | delays.enter = 0; 49 | } 50 | 51 | return delays; 52 | }; 53 | -------------------------------------------------------------------------------- /src/network/filter_network_using_new_nodes.js: -------------------------------------------------------------------------------- 1 | var utils = require('../Utils_clust'); 2 | var core = require('mathjs/core'); 3 | var underscore = require('underscore'); 4 | var math = core.create(); 5 | math.import(require('mathjs/lib/type/matrix')); 6 | math.import(require('mathjs/lib/function/matrix/zeros')); 7 | 8 | module.exports = function filter_network_using_new_nodes(config, new_nodes) { 9 | 10 | 11 | var links = config.network_data.links; 12 | 13 | // // make new mat from links 14 | // var new_mat = config.network_data.mat; 15 | 16 | // get new names of rows and cols 17 | var row_names = utils.pluck(new_nodes.row_nodes, 'name'); 18 | var col_names = utils.pluck(new_nodes.col_nodes, 'name'); 19 | 20 | var new_mat = math.matrix(math.zeros([new_nodes.row_nodes.length, new_nodes.col_nodes.length])); 21 | new_mat = new_mat.toArray(); 22 | 23 | var new_links = underscore.filter(links, function(inst_link){ 24 | 25 | var inst_row = inst_link.name.split('_')[0]; 26 | var inst_col = inst_link.name.split('_')[1]; 27 | 28 | var row_index = underscore.indexOf(row_names, inst_row); 29 | var col_index = underscore.indexOf(col_names, inst_col); 30 | 31 | // only keep links that have not been filtered out 32 | if ( row_index >-1 & col_index >-1 ){ 33 | 34 | // redefine source and target 35 | inst_link.source = row_index; 36 | inst_link.target = col_index; 37 | 38 | new_mat[row_index][col_index] = inst_link.value; 39 | 40 | return inst_link; 41 | } 42 | }); 43 | 44 | // set up new_network_data 45 | var new_network_data = {}; 46 | 47 | // rows 48 | new_network_data.row_nodes = new_nodes.row_nodes; 49 | new_network_data.row_nodes_names = row_names; 50 | 51 | // cols 52 | new_network_data.col_nodes = new_nodes.col_nodes; 53 | new_network_data.col_nodes_names = col_names; 54 | 55 | // save all links 56 | new_network_data.links = new_links; 57 | new_network_data.all_links = links; 58 | 59 | // mat 60 | new_network_data.mat = new_mat; 61 | 62 | // add back all views 63 | new_network_data.views = config.network_data.views; 64 | 65 | // add cat_colors if necessary 66 | if (_.has(config.network_data, 'cat_colors')){ 67 | new_network_data.cat_colors = config.network_data.cat_colors; 68 | } 69 | 70 | return new_network_data; 71 | }; 72 | -------------------------------------------------------------------------------- /src/network/filter_viz_using_names.js: -------------------------------------------------------------------------------- 1 | var filter_network_using_new_nodes = require('./filter_network_using_new_nodes'); 2 | var update_viz_with_network = require('../update/update_viz_with_network'); 3 | var underscore = require('underscore'); 4 | 5 | module.exports = function filter_viz_using_names(names, external_cgm = false){ 6 | 7 | // names is an object with row and column names that will be used to filter 8 | // the matrix 9 | 10 | var cgm; 11 | if (external_cgm === false){ 12 | cgm = this; 13 | } else { 14 | cgm = external_cgm; 15 | } 16 | 17 | var params = cgm.params; 18 | var new_nodes = {}; 19 | var found_nodes; 20 | 21 | underscore.each(['row', 'col'], function(inst_rc){ 22 | 23 | var orig_nodes = params.inst_nodes[inst_rc+'_nodes']; 24 | 25 | if (_.has(names, inst_rc)){ 26 | 27 | if (names[inst_rc].length > 0){ 28 | var inst_names = names[inst_rc]; 29 | found_nodes = $.grep(orig_nodes, function(d){ 30 | return $.inArray(d.name, inst_names) > -1 ; 31 | }); 32 | 33 | } else { 34 | 35 | found_nodes = orig_nodes; 36 | 37 | } 38 | 39 | } else { 40 | 41 | found_nodes = orig_nodes; 42 | } 43 | 44 | new_nodes[inst_rc+'_nodes'] = found_nodes; 45 | 46 | }); 47 | 48 | // keep backup of the nodes for resetting filtering 49 | var inst_row_nodes = cgm.params.network_data.row_nodes; 50 | var inst_col_nodes = cgm.params.network_data.col_nodes; 51 | 52 | var new_network_data = filter_network_using_new_nodes(cgm.config, new_nodes); 53 | 54 | // takes entire cgm object 55 | // last argument tells it to not preserve categoty colors 56 | update_viz_with_network(cgm, new_network_data); 57 | 58 | // only keep backup if previous number of nodes were larger than current number 59 | // of nodes 60 | if (inst_row_nodes.length > cgm.params.inst_nodes.row_nodes.length){ 61 | cgm.params.inst_nodes.row_nodes = inst_row_nodes; 62 | } 63 | 64 | if (inst_col_nodes.length > cgm.params.inst_nodes.col_nodes.length){ 65 | cgm.params.inst_nodes.col_nodes = inst_col_nodes; 66 | } 67 | 68 | }; -------------------------------------------------------------------------------- /src/network/filter_viz_using_nodes.js: -------------------------------------------------------------------------------- 1 | var filter_network_using_new_nodes = require('./filter_network_using_new_nodes'); 2 | var update_viz_with_network = require('../update/update_viz_with_network'); 3 | 4 | module.exports = function filter_viz_using_nodes(new_nodes){ 5 | 6 | var new_network_data = filter_network_using_new_nodes(this.config, new_nodes); 7 | update_viz_with_network(this, new_network_data); 8 | 9 | }; -------------------------------------------------------------------------------- /src/network/make_network_using_view.js: -------------------------------------------------------------------------------- 1 | var filter_network_using_new_nodes = require('./filter_network_using_new_nodes'); 2 | var get_subset_views = require('../filters/get_subset_views'); 3 | 4 | module.exports = function make_network_using_view(config, params, requested_view) { 5 | 6 | var orig_views = config.network_data.views; 7 | 8 | var is_enr = false; 9 | if (_.has(orig_views[0], 'enr_score_type')){ 10 | is_enr = true; 11 | } 12 | 13 | var sub_views = get_subset_views(params, orig_views, requested_view); 14 | 15 | ////////////////////////////// 16 | // Enrichr specific rules 17 | ////////////////////////////// 18 | if (is_enr && sub_views.length == 0){ 19 | requested_view = {'N_row_sum':'all', 'N_col_sum':'10'}; 20 | sub_views = get_subset_views(params, orig_views, requested_view); 21 | } 22 | 23 | var inst_view = sub_views[0]; 24 | 25 | var new_network_data; 26 | 27 | // get new_network_data or default back to old_network_data 28 | if (typeof inst_view !== 'undefined'){ 29 | var new_nodes = inst_view.nodes; 30 | new_network_data = filter_network_using_new_nodes(config, new_nodes); 31 | } else { 32 | new_network_data = config.network_data; 33 | } 34 | 35 | return new_network_data; 36 | }; 37 | -------------------------------------------------------------------------------- /src/network/transpose_network.js: -------------------------------------------------------------------------------- 1 | var utils = require('../Utils_clust'); 2 | /* Transpose network. 3 | */ 4 | module.exports = function (net) { 5 | var tnet = {}, 6 | inst_link, 7 | i; 8 | 9 | tnet.row_nodes = net.col_nodes; 10 | tnet.col_nodes = net.row_nodes; 11 | tnet.links = []; 12 | 13 | for (i = 0; i < net.links.length; i++) { 14 | inst_link = {}; 15 | inst_link.source = net.links[i].target; 16 | inst_link.target = net.links[i].source; 17 | inst_link.value = net.links[i].value; 18 | 19 | // Optional highlight. 20 | if (utils.has(net.links[i], 'highlight')) { 21 | inst_link.highlight = net.links[i].highlight; 22 | } 23 | if (utils.has(net.links[i], 'value_up')) { 24 | inst_link.value_up = net.links[i].value_up; 25 | } 26 | if (utils.has(net.links[i], 'value_dn')) { 27 | inst_link.value_dn = net.links[i].value_dn; 28 | } 29 | if (utils.has(net.links[i], 'info')) { 30 | inst_link.info = net.links[i].info; 31 | } 32 | tnet.links.push(inst_link); 33 | } 34 | 35 | return tnet; 36 | }; 37 | -------------------------------------------------------------------------------- /src/network/update_viz_with_view.js: -------------------------------------------------------------------------------- 1 | var make_network_using_view = require('./make_network_using_view'); 2 | var disable_sidebar = require('../sidebar/disable_sidebar'); 3 | var update_viz_with_network = require('../update/update_viz_with_network'); 4 | var underscore = require('underscore'); 5 | 6 | module.exports = function update_viz_with_view(cgm, requested_view) { 7 | 8 | disable_sidebar(cgm.params); 9 | 10 | // make new_network_data by filtering the original network data 11 | var new_network_data = make_network_using_view(cgm.config, cgm.params, 12 | requested_view); 13 | 14 | // reset crop button 15 | d3.select(cgm.params.root+' .crop_button') 16 | .style('color', '#337ab7') 17 | .classed('fa-crop', true) 18 | .classed('fa-undo', false) 19 | .classed('active_cropping', false); 20 | 21 | // reset dendrogram filtering when updating with a new view 22 | // e.g. with the row filter sliders 23 | underscore.each(['row', 'col'], function(inst_rc){ 24 | 25 | // set class to reflect that no filtering was ran 26 | d3.select(cgm.params.root+' .'+inst_rc+'_dendro_icons_group') 27 | .classed('ran_filter', false); 28 | 29 | // display all crop buttons when cropping has not been done 30 | d3.select(cgm.params.root+' .'+ inst_rc +'_dendro_icons_container') 31 | .style('display', 'block'); 32 | }); 33 | 34 | update_viz_with_network(cgm, new_network_data); 35 | 36 | }; 37 | -------------------------------------------------------------------------------- /src/params/calc_cat_params.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function calc_cat_params(params, viz){ 4 | 5 | var separtion_room; 6 | 7 | // increase the width of the label container based on the label length 8 | var label_scale = d3.scale.linear() 9 | .domain([5, 15]) 10 | .range([ 85, 120]).clamp('true'); 11 | 12 | viz.cat_room = {}; 13 | viz.cat_room.symbol_width = 12; 14 | viz.cat_room.separation = 3; 15 | 16 | underscore.each(['row','col'], function(inst_rc){ 17 | 18 | viz.norm_labels.width[inst_rc] = label_scale(params.labels[inst_rc+'_max_char']) 19 | * params[inst_rc+'_label_scale']; 20 | 21 | viz['num_'+inst_rc+'_nodes'] = params.network_data[inst_rc+'_nodes'].length; 22 | 23 | // if (_.has(config, 'group_level')){ 24 | // config.group_level[inst_rc] = 5; 25 | // } 26 | 27 | if(inst_rc === 'row'){ 28 | viz.dendro_room[inst_rc] = viz.dendro_room.symbol_width; 29 | } else { 30 | viz.dendro_room[inst_rc] = viz.dendro_room.symbol_width + 3*viz.uni_margin; 31 | } 32 | 33 | var num_cats = viz.all_cats[inst_rc].length; 34 | 35 | if (viz.show_categories[inst_rc]){ 36 | 37 | separtion_room = (num_cats-1)*viz.cat_room.separation; 38 | 39 | var adjusted_cats; 40 | if (inst_rc === 'row'){ 41 | adjusted_cats = num_cats + 1; 42 | } else { 43 | adjusted_cats = num_cats; 44 | } 45 | 46 | viz.cat_room[inst_rc] = adjusted_cats * viz.cat_room.symbol_width + separtion_room; 47 | 48 | } else { 49 | // no categories 50 | if (inst_rc == 'row'){ 51 | viz.cat_room[inst_rc] = viz.cat_room.symbol_width; 52 | } else { 53 | viz.cat_room[inst_rc] = 0; 54 | } 55 | } 56 | 57 | }); 58 | 59 | return viz; 60 | 61 | }; -------------------------------------------------------------------------------- /src/params/calc_clust_height.js: -------------------------------------------------------------------------------- 1 | module.exports = function calc_clust_height(viz){ 2 | 3 | // the clustergram/matrix height is the svg width minus: 4 | // the margin of the clustergram on the top 5 | // the dendrogram 6 | // the bottom_space 7 | var ini_clust_height = viz.svg_dim.height 8 | - viz.clust.margin.top 9 | - viz.dendro_room.col 10 | - viz.bottom_space; 11 | 12 | viz.clust.dim.height = ini_clust_height; 13 | 14 | return viz; 15 | }; -------------------------------------------------------------------------------- /src/params/calc_clust_width.js: -------------------------------------------------------------------------------- 1 | module.exports = function calc_clust_width(viz){ 2 | 3 | viz.clust = {}; 4 | viz.clust.margin = {}; 5 | 6 | // margin on left/top of the clustergram/matrix 7 | // 1) norm_label margin and width 8 | // 2) cat_room and uni_margin 9 | viz.clust.margin.left = viz.norm_labels.margin.left + 10 | viz.norm_labels.width.row + viz.cat_room.row + viz.uni_margin; 11 | 12 | viz.clust.margin.top = viz.norm_labels.margin.top + 13 | viz.norm_labels.width.col + viz.cat_room.col + viz.uni_margin; 14 | 15 | // the clustergram/matrix width is the svg width minus: 16 | // the margin of the clustergram on the left 17 | // the room for the spillover on the right 18 | // ** the dendro will fit in the spillover room on the right 19 | var ini_clust_width = viz.svg_dim.width 20 | - viz.clust.margin.left 21 | - viz.spillover_col_slant; 22 | 23 | // make tmp scale to calc height of triangle col labels 24 | var tmp_x_scale = d3.scale 25 | .ordinal() 26 | .rangeBands([0, ini_clust_width]) 27 | .domain(_.range( viz.num_col_nodes )); 28 | 29 | var triangle_height = tmp_x_scale.rangeBand()/2; 30 | 31 | // prevent the visualization from being unnecessarily wide 32 | if (triangle_height > viz.norm_labels.width.col) { 33 | var reduce_width = viz.norm_labels.width.col / triangle_height; 34 | ini_clust_width = ini_clust_width * reduce_width; 35 | } 36 | 37 | viz.clust.dim = {}; 38 | viz.clust.dim.width = ini_clust_width; 39 | 40 | return viz; 41 | }; -------------------------------------------------------------------------------- /src/params/calc_default_fs.js: -------------------------------------------------------------------------------- 1 | module.exports = function calc_default_fs(params){ 2 | 3 | params.labels.default_fs_row = params.viz.y_scale.rangeBand() * 1.01; 4 | params.labels.default_fs_col = params.viz.x_scale.rangeBand() * 0.87; 5 | 6 | if ( params.labels.default_fs_row > params.labels.max_allow_fs){ 7 | params.labels.default_fs_row = params.labels.max_allow_fs; 8 | } 9 | 10 | if ( params.labels.default_fs_col > params.labels.max_allow_fs){ 11 | params.labels.default_fs_col = params.labels.max_allow_fs; 12 | } 13 | 14 | return params; 15 | 16 | }; -------------------------------------------------------------------------------- /src/params/calc_label_params.js: -------------------------------------------------------------------------------- 1 | module.exports = function calc_label_params(viz){ 2 | 3 | viz.norm_labels.margin = {}; 4 | 5 | viz.norm_labels.margin.left = viz.super_labels.margin.left 6 | + viz.super_labels.dim.width; 7 | 8 | viz.norm_labels.margin.top = viz.super_labels.margin.top 9 | + viz.super_labels.dim.width; 10 | 11 | viz.label_background = {}; 12 | 13 | viz.label_background.row = viz.norm_labels.width.row + 14 | viz.cat_room.row + viz.uni_margin; 15 | 16 | viz.label_background.col = viz.norm_labels.width.col + 17 | viz.cat_room.col + viz.uni_margin; 18 | 19 | return viz; 20 | }; -------------------------------------------------------------------------------- /src/params/calc_matrix_params.js: -------------------------------------------------------------------------------- 1 | var ini_matrix_params = require('./ini_matrix_params'); 2 | var calc_downsampled_levels = require('../matrix/calc_downsampled_levels'); 3 | var underscore = require('underscore'); 4 | 5 | module.exports = function calc_matrix_params(params){ 6 | 7 | params.matrix = ini_matrix_params(params); 8 | 9 | // X and Y scales: set domains and ranges 10 | ////////////////////////////////////////////// 11 | params.viz.x_scale = d3.scale.ordinal() 12 | .rangeBands([0, params.viz.clust.dim.width]); 13 | 14 | params.viz.y_scale = d3.scale.ordinal() 15 | .rangeBands([0, params.viz.clust.dim.height]); 16 | 17 | var inst_order; 18 | 19 | underscore.each(['row','col'], function(inst_rc){ 20 | 21 | inst_order = params.viz.inst_order[inst_rc]; 22 | 23 | if (inst_order === 'custom'){ 24 | inst_order = 'clust'; 25 | } 26 | 27 | if (inst_rc === 'row'){ 28 | params.viz.x_scale 29 | .domain( params.matrix.orders[ inst_order + '_' + inst_rc ] ); 30 | } else{ 31 | params.viz.y_scale 32 | .domain( params.matrix.orders[ inst_order + '_' + inst_rc ] ); 33 | } 34 | 35 | }); 36 | 37 | // border width 38 | params.viz.border_width = {}; 39 | params.viz.border_width.x = params.viz.x_scale.rangeBand() / 40 | params.viz.border_fraction; 41 | params.viz.border_width.y = params.viz.y_scale.rangeBand() / 42 | params.viz.border_fraction; 43 | 44 | // rect width needs matrix and zoom parameters 45 | params.viz.rect_width = params.viz.x_scale.rangeBand() - 46 | params.viz.border_width.x; 47 | 48 | // moved calculateion to calc_matrix_params 49 | params.viz.rect_height = params.viz.y_scale.rangeBand() - 50 | params.viz.border_width.y; 51 | 52 | calc_downsampled_levels(params); 53 | 54 | return params; 55 | 56 | }; -------------------------------------------------------------------------------- /src/params/calc_val_max.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function calc_val_max(params){ 4 | 5 | var val_max = Math.abs(underscore.max(params.network_data.col_nodes, function (d) { 6 | return Math.abs(d.value); 7 | }).value); 8 | 9 | params.labels.bar_scale_col = d3.scale 10 | .linear() 11 | .domain([0, val_max]) 12 | .range([0, 0.75 * params.viz.norm_labels.width.col]); 13 | 14 | val_max = Math.abs(underscore.max(params.network_data.row_nodes, function (d) { 15 | return Math.abs(d.value); 16 | }).value); 17 | 18 | params.labels.bar_scale_row = d3.scale 19 | .linear() 20 | .domain([0, val_max]) 21 | .range([0, params.viz.norm_labels.width.row]); 22 | 23 | return params; 24 | }; -------------------------------------------------------------------------------- /src/params/calc_viz_dimensions.js: -------------------------------------------------------------------------------- 1 | module.exports = function calc_viz_dimensions(params){ 2 | 3 | var cont_dim = {}; 4 | var extra_space = params.buffer_width; 5 | 6 | // var screen_width = window.innerWidth; 7 | // var screen_height = window.innerHeight; 8 | 9 | // // resize container, then resize visualization within container 10 | // d3.select(params.root) 11 | // .style('width', screen_width+'px') 12 | // .style('height', screen_height+'px'); 13 | 14 | var container_width = d3.select(params.root).style('width').replace('px',''); 15 | var container_height = d3.select(params.root).style('height').replace('px',''); 16 | 17 | // get outer_margins 18 | var outer_margins; 19 | if (params.viz.is_expand === false) { 20 | outer_margins = params.viz.outer_margins; 21 | cont_dim.width = container_width - params.sidebar_width - extra_space; 22 | } else { 23 | outer_margins = params.viz.outer_margins; 24 | cont_dim.width = container_width - extra_space; 25 | } 26 | 27 | cont_dim.top = outer_margins.top; 28 | cont_dim.left = outer_margins.left; 29 | 30 | if (params.viz.resize) { 31 | 32 | cont_dim.height = container_height; 33 | 34 | } else { 35 | 36 | if (params.viz.is_expand){ 37 | cont_dim.width = params.viz.fixed_size.width; 38 | } else { 39 | cont_dim.width = params.viz.fixed_size.width - params.sidebar_width; 40 | } 41 | 42 | cont_dim.height = params.viz.fixed_size.height; 43 | 44 | } 45 | 46 | return cont_dim; 47 | 48 | }; 49 | -------------------------------------------------------------------------------- /src/params/check_if_value_cats.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function check_if_value_cats(cat_states){ 4 | 5 | var tmp_cat = cat_states[0]; 6 | 7 | var has_title = false; 8 | var might_have_values = false; 9 | var cat_types = 'cat_strings'; 10 | var max_abs_val = NaN; 11 | var all_values = []; 12 | var cat_scale = null; 13 | 14 | var super_string = ': '; 15 | 16 | if (typeof tmp_cat === 'string'){ 17 | if ( tmp_cat.indexOf(super_string) > -1 ){ 18 | has_title = true; 19 | tmp_cat = tmp_cat.split(super_string)[1]; 20 | } 21 | } 22 | 23 | if ( isNaN(tmp_cat) == false ){ 24 | might_have_values = true; 25 | } 26 | 27 | // check each value for number 28 | if (might_have_values){ 29 | 30 | // the default state is that all are now values, check each one 31 | cat_types = 'cat_values'; 32 | 33 | underscore.each(cat_states, function(inst_cat){ 34 | 35 | if (has_title){ 36 | inst_cat = inst_cat.split(super_string)[1]; 37 | } 38 | 39 | // checking whether inst_cat is 'not a number' 40 | if ( isNaN(inst_cat) === true ){ 41 | cat_types = 'cat_strings'; 42 | } else { 43 | inst_cat = parseFloat(inst_cat); 44 | all_values.push(inst_cat); 45 | } 46 | 47 | }); 48 | 49 | } 50 | 51 | if (cat_types === 'cat_values'){ 52 | 53 | // get absolute value 54 | var max_value = underscore.max(all_values, function (d) { 55 | return Math.abs(d); 56 | }); 57 | 58 | max_abs_val = Math.abs(max_value); 59 | 60 | cat_scale = d3.scale.linear().domain([0, max_abs_val]).range([0,1]); 61 | } 62 | 63 | var inst_info = {}; 64 | inst_info.type = cat_types; 65 | inst_info.max_abs_val = max_abs_val; 66 | inst_info.cat_scale = cat_scale; 67 | 68 | return inst_info; 69 | 70 | }; -------------------------------------------------------------------------------- /src/params/get_available_filters.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function get_available_filters(views){ 4 | 5 | var possible_filters = {}; 6 | var filter_data = {}; 7 | 8 | underscore.each(views, function(inst_view){ 9 | var inst_keys = underscore.keys(inst_view); 10 | 11 | underscore.each(inst_keys, function(inst_key){ 12 | 13 | if (inst_key != 'nodes'){ 14 | 15 | if (!_.has(filter_data, inst_key)){ 16 | filter_data[inst_key] = []; 17 | } 18 | 19 | filter_data[inst_key].push(inst_view[inst_key]); 20 | 21 | filter_data[inst_key] = underscore.uniq( filter_data[inst_key] ); 22 | 23 | } 24 | 25 | }); 26 | 27 | }); 28 | 29 | var tmp_filters = underscore.keys(filter_data); 30 | 31 | underscore.each( tmp_filters, function(inst_filter){ 32 | 33 | var options = filter_data[inst_filter]; 34 | var num_options = options.length; 35 | 36 | var filter_type = 'categorical'; 37 | underscore.each(options, function(inst_option){ 38 | if (typeof inst_option === 'number'){ 39 | filter_type = 'numerical'; 40 | } 41 | }); 42 | 43 | if (num_options > 1){ 44 | possible_filters[inst_filter] = filter_type; 45 | } 46 | 47 | }); 48 | 49 | var filters = {}; 50 | filters.possible_filters = possible_filters; 51 | filters.filter_data = filter_data; 52 | 53 | return filters; 54 | 55 | }; -------------------------------------------------------------------------------- /src/params/get_svg_dim.js: -------------------------------------------------------------------------------- 1 | module.exports = function get_svg_dim(params){ 2 | 3 | params.viz.svg_dim = {}; 4 | params.viz.svg_dim.width = Number( 5 | d3.select(params.viz.viz_wrapper) 6 | .style('width').replace('px', '') 7 | ); 8 | 9 | params.viz.svg_dim.height = Number( 10 | d3.select(params.viz.viz_wrapper) 11 | .style('height').replace('px', '') 12 | ); 13 | 14 | return params; 15 | }; -------------------------------------------------------------------------------- /src/params/ini_label_params.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function ini_label_params(params){ 4 | 5 | var labels = {}; 6 | labels.super_label_scale = params.super_label_scale; 7 | labels.super_labels = params.super_labels; 8 | labels.super_label_fs = 13.8; 9 | 10 | if (labels.super_labels) { 11 | labels.super = {}; 12 | labels.super.row = params.super.row; 13 | labels.super.col = params.super.col; 14 | } 15 | 16 | labels.show_label_tooltips = params.show_label_tooltips; 17 | 18 | labels.row_max_char = underscore.max(params.network_data.row_nodes, 19 | function (inst) { 20 | return inst.name.length; 21 | }).name.length; 22 | 23 | labels.col_max_char = underscore.max(params.network_data.col_nodes, 24 | function (inst) { 25 | return inst.name.length; 26 | }).name.length; 27 | 28 | labels.max_allow_fs = params.max_allow_fs; 29 | 30 | return labels; 31 | }; -------------------------------------------------------------------------------- /src/params/ini_sidebar_params.js: -------------------------------------------------------------------------------- 1 | module.exports = function ini_sidebar_params(params){ 2 | var sidebar = {}; 3 | 4 | sidebar.wrapper = {}; 5 | // sidebar.wrapper.width = 170; 6 | 7 | sidebar.row_search = {}; 8 | sidebar.row_search.box = {}; 9 | sidebar.row_search.box.height = 34; 10 | sidebar.row_search.box.width = 95; 11 | sidebar.row_search.placeholder = params.row_search_placeholder; 12 | sidebar.row_search.margin_left = 7; 13 | 14 | sidebar.slider = {}; 15 | sidebar.slider.width = params.sidebar_width - 30; 16 | sidebar.slider.margin_left = 15; 17 | 18 | 19 | sidebar.key_cat = {}; 20 | sidebar.key_cat.width = params.sidebar_width - 15; 21 | sidebar.key_cat.margin_left = 5; 22 | sidebar.key_cat.max_height = 100; 23 | 24 | sidebar.title = params.title; 25 | sidebar.title_margin_left = 7; 26 | sidebar.about = params.about; 27 | sidebar.width = params.sidebar_width; 28 | 29 | sidebar.buttons = {}; 30 | sidebar.buttons.width = params.sidebar_width - 15; 31 | 32 | sidebar.text = {}; 33 | 34 | sidebar.icons = params.sidebar_icons; 35 | sidebar.icon_margin_left = -5; 36 | 37 | return sidebar; 38 | }; -------------------------------------------------------------------------------- /src/params/make_params.js: -------------------------------------------------------------------------------- 1 | var make_network_using_view = require('../network/make_network_using_view'); 2 | var ini_sidebar_params = require('./ini_sidebar_params'); 3 | var make_requested_view = require('../filters/make_requested_view'); 4 | var get_available_filters = require('./get_available_filters'); 5 | var calc_viz_params = require('./calc_viz_params'); 6 | var ini_zoom_info = require('../zoom/ini_zoom_info'); 7 | 8 | /* 9 | Params: calculates the size of all the visualization elements in the 10 | clustergram. 11 | */ 12 | 13 | module.exports = function make_params(input_config) { 14 | 15 | var config = $.extend(true, {}, input_config); 16 | var params = config; 17 | 18 | // keep a copy of inst_view 19 | params.inst_nodes = {}; 20 | params.inst_nodes.row_nodes = params.network_data.row_nodes; 21 | params.inst_nodes.col_nodes = params.network_data.col_nodes; 22 | 23 | // when pre-loading the visualization using a view 24 | if (params.ini_view !== null) { 25 | 26 | var requested_view = params.ini_view; 27 | 28 | var filters = get_available_filters(params.network_data.views); 29 | 30 | params.viz = {}; 31 | params.viz.possible_filters = filters.possible_filters; 32 | params.viz.filter_data = filters.filter_data; 33 | 34 | requested_view = make_requested_view(params, requested_view); 35 | params.network_data = make_network_using_view(config, params, requested_view); 36 | 37 | // save ini_view as requested_view 38 | params.requested_view = requested_view; 39 | 40 | } 41 | 42 | params = calc_viz_params(params); 43 | 44 | if (params.use_sidebar){ 45 | params.sidebar = ini_sidebar_params(params); 46 | } 47 | 48 | params.zoom_info = ini_zoom_info(); 49 | 50 | return params; 51 | }; 52 | -------------------------------------------------------------------------------- /src/params/set_zoom_params.js: -------------------------------------------------------------------------------- 1 | var calc_zoom_switching = require('../zoom/calc_zoom_switching'); 2 | 3 | module.exports = function set_zoom_params(params){ 4 | 5 | params.viz.zoom_scale_font = {}; 6 | params.viz.zoom_scale_font.row = 1; 7 | params.viz.zoom_scale_font.col = 1; 8 | 9 | var max_zoom_limit = 0.75; 10 | var half_col_height = (params.viz.x_scale.rangeBand() / 2); 11 | params.viz.square_zoom = (params.viz.norm_labels.width.col / half_col_height )*max_zoom_limit; 12 | 13 | params.viz = calc_zoom_switching(params.viz); 14 | 15 | return params; 16 | }; -------------------------------------------------------------------------------- /src/recluster/distance_functions.js: -------------------------------------------------------------------------------- 1 | function vec_dot_product(vecA, vecB) { 2 | var product = 0; 3 | for (var i = 0; i < vecA.length; i++) { 4 | product = product + vecA[i] * vecB[i]; 5 | } 6 | return product; 7 | } 8 | 9 | function vec_magnitude(vec) { 10 | var sum = 0; 11 | for (var i = 0; i < vec.length; i++) { 12 | sum = sum + vec[i] * vec[i]; 13 | } 14 | return Math.sqrt(sum); 15 | } 16 | 17 | function vec_diff_value(vec, val){ 18 | var vec_sub = []; 19 | for (var i = 0; i < vec.length; i++){ 20 | vec_sub.push( vec[i] - val ); 21 | } 22 | return vec_sub; 23 | } 24 | 25 | function vec_mean(vec){ 26 | var sum = 0; 27 | var mean; 28 | for (var i = 0; i < vec.length; i++){ 29 | sum = sum + vec[i]; 30 | } 31 | 32 | mean = sum / vec.length; 33 | 34 | return mean; 35 | } 36 | 37 | module.exports = { 38 | 39 | 'euclidean': function(v1, v2) { 40 | var total = 0; 41 | for (var i = 0; i < v1.length; i++) { 42 | total = total + Math.pow(v2[i] - v1[i], 2); 43 | } 44 | return Math.sqrt(total); 45 | }, 46 | 'cosine': function(vecA, vecB) { 47 | 48 | var cos_sim = vec_dot_product(vecA, vecB) / (vec_magnitude(vecA) * vec_magnitude(vecB)); 49 | 50 | var cos_dist = 1 - cos_sim; 51 | 52 | return cos_dist; 53 | }, 54 | 'correlation': function(vecA, vecB){ 55 | 56 | var vecA_mean = vec_mean(vecA); 57 | var vecB_mean = vec_mean(vecB); 58 | 59 | var vecA_diff_mean = vec_diff_value(vecA, vecA_mean); 60 | var vecB_diff_mean = vec_diff_value(vecB, vecB_mean); 61 | 62 | var cor_sim = vec_dot_product(vecA_diff_mean, vecB_diff_mean) / ( vec_magnitude(vecA_diff_mean) * vec_magnitude(vecB_diff_mean) ); 63 | var cor_diff = 1 - cor_sim; 64 | 65 | return cor_diff; 66 | } 67 | }; -------------------------------------------------------------------------------- /src/recluster/get_max_distance_in_dm.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function get_max_tree_distance(dm){ 4 | 5 | var max_distance_in_dm = 0; 6 | 7 | underscore.each(dm, function(row){ 8 | underscore.each(row, function(inst_val){ 9 | if (isFinite(inst_val)){ 10 | if (inst_val > max_distance_in_dm){ 11 | max_distance_in_dm = inst_val; 12 | } 13 | } 14 | }); 15 | 16 | }); 17 | 18 | return max_distance_in_dm; 19 | 20 | }; -------------------------------------------------------------------------------- /src/reorder/ini_cat_reorder.js: -------------------------------------------------------------------------------- 1 | var all_reorder = require('./all_reorder'); 2 | var underscore = require('underscore'); 3 | 4 | module.exports = function ini_cat_reorder(cgm){ 5 | /* eslint-disable */ 6 | 7 | var params = cgm.params; 8 | 9 | underscore.each(['row','col'], function(inst_rc){ 10 | 11 | if (params.viz.show_categories[inst_rc]){ 12 | d3.selectAll(params.root+' .'+inst_rc+'_cat_super') 13 | .on('dblclick',function(){ 14 | 15 | if (params.sim_mat){ 16 | inst_rc = 'both'; 17 | } 18 | 19 | d3.selectAll(params.root+' .toggle_'+inst_rc+'_order .btn') 20 | .classed('active',false); 21 | 22 | var order_id = this.__data__.replace('-','_') + '_index'; 23 | if (params.viz.sim_mat){ 24 | all_reorder( cgm, order_id, 'row'); 25 | all_reorder( cgm, order_id, 'col'); 26 | } 27 | else { 28 | all_reorder( cgm, order_id, inst_rc); 29 | } 30 | }); 31 | } 32 | 33 | }); 34 | }; -------------------------------------------------------------------------------- /src/reorder/reposition_tile_highlight.js: -------------------------------------------------------------------------------- 1 | module.exports = function(params) { 2 | 3 | // resize click hlight 4 | var rel_width_hlight = 6; 5 | // var opacity_hlight = 0.85; 6 | 7 | var hlight_width = rel_width_hlight*params.viz.border_width.x; 8 | var hlight_height = rel_width_hlight*params.viz.border_width.y; 9 | 10 | // reposition tile highlight 11 | //////////////////////////////// 12 | // top highlight 13 | d3.select(params.root+' .top_hlight') 14 | .attr('width', params.viz.x_scale.rangeBand()) 15 | .attr('height', hlight_height) 16 | .transition().duration(2500) 17 | .attr('transform', function() { 18 | return 'translate(' + params.viz.x_scale(params.matrix.click_hlight_x) + ',0)'; 19 | }); 20 | 21 | // left highlight 22 | d3.select(params.root+' .left_hlight') 23 | .attr('width', hlight_width) 24 | .attr('height', params.viz.y_scale.rangeBand() - hlight_height*0.99 ) 25 | .transition().duration(2500) 26 | .attr('transform', function() { 27 | return 'translate(' + params.viz.x_scale(params.matrix.click_hlight_x) + ','+ 28 | hlight_height*0.99+')'; 29 | }); 30 | 31 | // right highlight 32 | d3.select(params.root+' .right_hlight') 33 | .attr('width', hlight_width) 34 | .attr('height', params.viz.y_scale.rangeBand() - hlight_height*0.99 ) 35 | .transition().duration(2500) 36 | .attr('transform', function() { 37 | var tmp_translate = params.viz.x_scale(params.matrix.click_hlight_x) + params.viz.x_scale.rangeBand() - hlight_width; 38 | return 'translate(' + tmp_translate + ','+ 39 | hlight_height*0.99+')'; 40 | }); 41 | 42 | // bottom highlight 43 | d3.select(params.root+' .bottom_hlight') 44 | .attr('width', function(){ 45 | return params.viz.x_scale.rangeBand() - 1.98*hlight_width;}) 46 | .attr('height', hlight_height) 47 | .transition().duration(2500) 48 | .attr('transform', function() { 49 | var tmp_translate_x = params.viz.x_scale(params.matrix.click_hlight_x) + hlight_width*0.99; 50 | var tmp_translate_y = params.viz.y_scale.rangeBand() - hlight_height; 51 | return 'translate(' + tmp_translate_x + ','+ 52 | tmp_translate_y+')'; 53 | }); 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /src/reorder/update_reorder_buttons.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function update_reorder_buttons(tmp_config, params){ 4 | underscore.each(['row','col'], function(inst_rc){ 5 | 6 | var other_rc; 7 | if (inst_rc === 'row'){ 8 | other_rc = 'col'; 9 | } else { 10 | other_rc = 'row'; 11 | } 12 | 13 | d3.selectAll(params.root+' .toggle_'+other_rc+'_order .btn') 14 | .filter(function(){ 15 | return d3.select(this).attr('name') === tmp_config.inst_order[inst_rc]; 16 | }) 17 | .classed('active',true); 18 | 19 | }); 20 | }; -------------------------------------------------------------------------------- /src/reset_size/resize_borders.js: -------------------------------------------------------------------------------- 1 | module.exports = function resize_borders(params, svg_group){ 2 | 3 | // left border 4 | svg_group.select('.left_border') 5 | .attr('width', params.viz.grey_border_width) 6 | .attr('height', params.viz.svg_dim.height) 7 | .attr('transform', 'translate(0,0)'); 8 | 9 | // right border 10 | svg_group.select('.right_border') 11 | .attr('width', params.viz.grey_border_width) 12 | .attr('height', params.viz.svg_dim.height) 13 | .attr('transform', function() { 14 | var inst_offset = params.viz.svg_dim.width - params.viz.grey_border_width; 15 | return 'translate(' + inst_offset + ',0)'; 16 | }); 17 | 18 | // top border 19 | svg_group.select('.top_border') 20 | .attr('width', params.viz.svg_dim.width) 21 | .attr('height', params.viz.grey_border_width) 22 | .attr('transform', function() { 23 | var inst_offset = 0; 24 | return 'translate(' + inst_offset + ',0)'; 25 | }); 26 | 27 | // bottom border 28 | svg_group.select('.bottom_border') 29 | .attr('width', params.viz.svg_dim.width) 30 | .attr('height', params.viz.grey_border_width) 31 | .attr('transform', function() { 32 | var inst_offset = params.viz.svg_dim.height - params.viz.grey_border_width; 33 | return 'translate(0,' + inst_offset + ')'; 34 | }); 35 | 36 | }; -------------------------------------------------------------------------------- /src/reset_size/resize_col_hlight.js: -------------------------------------------------------------------------------- 1 | var utils = require('../Utils_clust'); 2 | 3 | module.exports = function resize_col_hlight(params, svg_group, delay_info=false){ 4 | 5 | var delays = {}; 6 | // var duration = params.viz.duration; 7 | 8 | if(delay_info === false){ 9 | delays.run_transition = false; 10 | } else { 11 | delays = delay_info; 12 | } 13 | 14 | if (utils.has( params.network_data.col_nodes[0], 'value')) { 15 | 16 | svg_group 17 | .selectAll('.col_bars') 18 | .data(params.network_data.col_nodes, function(d){return d.name;}) 19 | .attr('width', function(d) { 20 | 21 | var inst_value = 0; 22 | 23 | if (d.value > 0){ 24 | inst_value = params.labels.bar_scale_col(d.value); 25 | } 26 | return inst_value; 27 | }) 28 | // rotate labels - reduce width if rotating 29 | .attr('height', params.viz.rect_width * 0.66); 30 | 31 | } 32 | 33 | }; -------------------------------------------------------------------------------- /src/reset_size/resize_col_text.js: -------------------------------------------------------------------------------- 1 | var utils = require('../Utils_clust'); 2 | 3 | module.exports = function resize_col_text(params, svg_group){ 4 | svg_group 5 | .selectAll('.col_label_group') 6 | .select('text') 7 | .style('font-size', params.labels.default_fs_col + 'px') 8 | .text(function(d){ return utils.normal_name(d);}); 9 | 10 | svg_group 11 | .selectAll('.col_label_group') 12 | .each(function() { 13 | d3.select(this) 14 | .select('text')[0][0] 15 | .getBBox(); 16 | }); 17 | }; -------------------------------------------------------------------------------- /src/reset_size/resize_col_triangle.js: -------------------------------------------------------------------------------- 1 | var col_viz_aid_triangle = require('../labels/col_viz_aid_triangle'); 2 | 3 | module.exports = function resize_col_triangle(params, ini_svg_group, delay_info=false){ 4 | 5 | // resize column triangle 6 | var ini_triangle_group = ini_svg_group 7 | .selectAll('.col_label_group') 8 | .select('path'); 9 | 10 | var delays = {}; 11 | var duration = params.viz.duration; 12 | 13 | if(delay_info === false){ 14 | delays.run_transition = false; 15 | } else { 16 | delays = delay_info; 17 | } 18 | 19 | var triangle_group; 20 | if (delays.run_transition){ 21 | triangle_group = ini_triangle_group 22 | .transition().delay(delays.update).duration(duration); 23 | } else { 24 | triangle_group = ini_triangle_group; 25 | } 26 | 27 | 28 | triangle_group 29 | .attr('d', function() { 30 | return col_viz_aid_triangle(params); 31 | }) 32 | .attr('fill', '#eee'); 33 | 34 | 35 | }; -------------------------------------------------------------------------------- /src/reset_size/resize_containers.js: -------------------------------------------------------------------------------- 1 | module.exports = function resize_containers(params){ 2 | 3 | // reposition matrix 4 | d3.select(params.root+' .clust_container') 5 | .attr('transform', 'translate(' + 6 | params.viz.clust.margin.left + ',' + 7 | params.viz.clust.margin.top + ')'); 8 | 9 | // reposition col container 10 | d3.select(params.root+' .col_label_outer_container') 11 | .attr('transform', 'translate(0,' + params.viz.norm_labels.width.col + ')'); 12 | 13 | // reposition col_viz container 14 | d3.select(params.root+' .col_cat_outer_container') 15 | .attr('transform', function() { 16 | var inst_offset = params.viz.norm_labels.width.col + 2; 17 | return 'translate(0,' + inst_offset + ')'; 18 | }); 19 | 20 | }; -------------------------------------------------------------------------------- /src/reset_size/resize_label_bars.js: -------------------------------------------------------------------------------- 1 | var calc_val_max = require('../params/calc_val_max'); 2 | // var underscore = require('underscore'); 3 | 4 | module.exports = function resize_label_bars(cgm, svg_group){ 5 | var params = cgm.params; 6 | 7 | // // set bar scale 8 | // var val_max = Math.abs(underscore.max( params.network_data.row_nodes, function(d) { 9 | // return Math.abs(d.value); 10 | // } ).value) ; 11 | 12 | // params.labels.bar_scale_row = d3.scale 13 | // .linear() 14 | // .domain([0, val_max]) 15 | // .range([0, params.viz.norm_labels.width.row ]); 16 | 17 | params = calc_val_max(params); 18 | 19 | svg_group.selectAll('.row_bars') 20 | // .transition().delay(delays.update).duration(duration) 21 | .attr('width', function(d) { 22 | var inst_value = 0; 23 | inst_value = params.labels.bar_scale_row( Math.abs(d.value) ); 24 | return inst_value; 25 | }) 26 | .attr('x', function(d) { 27 | var inst_value = 0; 28 | inst_value = -params.labels.bar_scale_row( Math.abs(d.value) ); 29 | return inst_value; 30 | }) 31 | .attr('height', params.viz.y_scale.rangeBand() ); 32 | 33 | }; -------------------------------------------------------------------------------- /src/reset_size/resize_row_labels.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function resize_row_labels(params, ini_svg_group, delay_info=false){ 4 | 5 | var delays = {}; 6 | var duration = params.viz.duration; 7 | var svg_group; 8 | 9 | var row_nodes = params.network_data.row_nodes; 10 | var row_nodes_names = params.network_data.row_nodes_names; 11 | 12 | if(delay_info === false){ 13 | delays.run_transition = false; 14 | } else { 15 | delays = delay_info; 16 | } 17 | 18 | if (delays.run_transition){ 19 | 20 | ini_svg_group.selectAll('.row_label_group') 21 | // data bind necessary for loss/gain of rows 22 | .data(row_nodes, function(d){return d.name;}) 23 | .transition().delay(delays.update).duration(duration) 24 | .attr('transform', function(d) { 25 | var inst_index = underscore.indexOf(row_nodes_names, d.name); 26 | return 'translate(0,' + params.viz.y_scale(inst_index) + ')'; 27 | }) 28 | .attr('y', params.viz.rect_height * 0.5 + params.labels.default_fs_row*0.35 ); 29 | 30 | svg_group = ini_svg_group 31 | .transition().delay(delays.update).duration(duration); 32 | 33 | } else { 34 | 35 | ini_svg_group.selectAll('.row_label_group') 36 | // data bind necessary for loss/gain of rows 37 | .data(row_nodes, function(d){return d.name;}) 38 | .attr('transform', function(d) { 39 | var inst_index = underscore.indexOf(row_nodes_names, d.name); 40 | return 'translate(0,' + params.viz.y_scale(inst_index) + ')'; 41 | }) 42 | .attr('y', params.viz.rect_height * 0.5 + params.labels.default_fs_row*0.35 ); 43 | 44 | svg_group = ini_svg_group; 45 | } 46 | 47 | svg_group.select(params.root+' .row_container') 48 | .attr('transform', 'translate(' + params.viz.norm_labels.margin.left + ',' + 49 | params.viz.clust.margin.top + ')'); 50 | 51 | svg_group.select(params.root+' .row_container') 52 | .select('.white_bars') 53 | .attr('width', params.viz.label_background.row) 54 | .attr('height', 30*params.viz.clust.dim.height + 'px'); 55 | 56 | svg_group.select(params.root + ' .row_container') 57 | .select('.row_label_container') 58 | .attr('transform', 'translate(' + params.viz.norm_labels.width.row + ',0)'); 59 | 60 | }; 61 | 62 | -------------------------------------------------------------------------------- /src/reset_size/resize_row_viz.js: -------------------------------------------------------------------------------- 1 | module.exports = function resize_row_viz(params, ini_svg_group, delay_info=false){ 2 | 3 | var delays = {}; 4 | var duration = params.viz.duration; 5 | var svg_group; 6 | 7 | if (delay_info === false){ 8 | delays.run_transition = false; 9 | } else { 10 | delays = delay_info; 11 | } 12 | 13 | if (delays.run_transition){ 14 | svg_group = ini_svg_group 15 | .transition().delay(delays.update).duration(duration); 16 | 17 | } else { 18 | svg_group = ini_svg_group; 19 | } 20 | 21 | svg_group.select('.row_cat_outer_container') 22 | .attr('transform', 'translate(' + params.viz.norm_labels.width.row + ',0)') 23 | .select('white_bars') 24 | .attr('width', params.viz.cat_room.row + 'px') 25 | .attr('height', function() { 26 | var inst_height = params.viz.clust.dim.height; 27 | return inst_height; 28 | }); 29 | 30 | var x_offset = params.viz.clust.margin.left + params.viz.clust.dim.width ; 31 | var y_offset = params.viz.clust.margin.top; 32 | svg_group.select('.row_dendro_outer_container') 33 | .attr('transform','translate('+ x_offset + ','+y_offset+')'); 34 | 35 | // !! tmp resize col dendro 36 | x_offset = params.viz.clust.margin.left; 37 | y_offset = params.viz.clust.margin.top + params.viz.clust.dim.height; 38 | 39 | svg_group 40 | .select(' .col_dendro_outer_container') 41 | .attr('transform', function() { 42 | return 'translate('+x_offset+',' + y_offset + ')'; 43 | }); 44 | 45 | }; -------------------------------------------------------------------------------- /src/reset_size/resize_super_labels.js: -------------------------------------------------------------------------------- 1 | module.exports = function resize_super_labels(params, ini_svg_group, delay_info=false){ 2 | 3 | var delays = {}; 4 | var duration = params.viz.duration; 5 | var svg_group; 6 | 7 | if(delay_info === false){ 8 | delays.run_transition = false; 9 | } else { 10 | delays = delay_info; 11 | } 12 | 13 | if (delays.run_transition){ 14 | svg_group = ini_svg_group 15 | .transition().delay(delays.update).duration(duration); 16 | } else { 17 | svg_group = ini_svg_group; 18 | } 19 | 20 | svg_group.select('.super_col_bkg') 21 | .attr('height', params.viz.super_labels.dim.width + 'px') 22 | .attr('transform', 'translate('+params.viz.clust.margin.left+',' + params.viz.grey_border_width + ')'); 23 | 24 | // super col title 25 | svg_group.select('.super_col') 26 | .attr('transform', function() { 27 | var inst_x = params.viz.clust.dim.width / 2 + params.viz.norm_labels.width 28 | .row; 29 | var inst_y = params.viz.super_labels.dim.width ; 30 | return 'translate(' + inst_x + ',' + inst_y + ')'; 31 | }); 32 | 33 | svg_group.select('.super_row_bkg') 34 | .attr('width', params.viz.super_labels.dim.width + 'px') 35 | .attr('transform', 'translate(' + params.viz.grey_border_width + ',0)'); 36 | 37 | svg_group.select('.super_row') 38 | .attr('transform', function() { 39 | var inst_x = params.viz.super_labels.dim.width; 40 | var inst_y = params.viz.clust.dim.height / 2 + params.viz.norm_labels.width 41 | .col; 42 | return 'translate(' + inst_x + ',' + inst_y + ')'; 43 | }); 44 | 45 | }; -------------------------------------------------------------------------------- /src/search/run_row_search.js: -------------------------------------------------------------------------------- 1 | var two_translate_zoom = require('../zoom/two_translate_zoom'); 2 | var underscore = require('underscore'); 3 | 4 | module.exports = function run_row_search(cgm, search_term, entities){ 5 | 6 | var prop = 'name'; 7 | 8 | if (entities.indexOf(search_term) !== -1) { 9 | 10 | // unhighlight 11 | d3.selectAll(cgm.params.root+' .row_label_group') 12 | .select('rect').style('opacity', 0); 13 | 14 | // calc pan_dy 15 | var idx = underscore.indexOf(entities, search_term); 16 | var inst_y_pos = cgm.params.viz.y_scale(idx); 17 | var pan_dy = cgm.params.viz.clust.dim.height / 2 - inst_y_pos; 18 | 19 | var inst_zoom = cgm.params.viz.zoom_ratio.x; 20 | 21 | // working on improving zoom behavior 22 | /////////////////////////////////////////////////// 23 | /////////////////////////////////////////////////// 24 | 25 | // // increase zoom 26 | // inst_zoom = 3 * inst_zoom; 27 | 28 | // // move visualization down less 29 | // pan_dy = pan_dy - 5; 30 | 31 | two_translate_zoom(cgm, 0, pan_dy, inst_zoom); 32 | 33 | // set y zoom to zoom_switch 34 | cgm.params.zoom_info.zoom_y = inst_zoom; 35 | 36 | // highlight 37 | d3.selectAll(cgm.params.root+' .row_label_group') 38 | .filter(function(d) { 39 | return d[prop] === search_term; 40 | }) 41 | .select('rect') 42 | .style('opacity', 1); 43 | } 44 | 45 | }; -------------------------------------------------------------------------------- /src/set_viz_wrapper_size.js: -------------------------------------------------------------------------------- 1 | var calc_viz_dimensions = require('./params/calc_viz_dimensions'); 2 | 3 | module.exports = function set_viz_wrapper_size(params) { 4 | 5 | // Create wrapper around SVG visualization 6 | if (d3.select(params.root+' .viz_wrapper').empty()){ 7 | 8 | d3.select(params.root) 9 | .append('div') 10 | .classed('sidebar_wrapper', true); 11 | 12 | d3.select(params.root) 13 | .append('div') 14 | .classed('viz_wrapper', true); 15 | 16 | } 17 | 18 | var cont_dim = calc_viz_dimensions(params); 19 | 20 | d3.select(params.root+' .sidebar_wrapper') 21 | .style('float', 'left') 22 | .style('width', params.sidebar_width+'px') 23 | .style('height', cont_dim.height+'px') 24 | .style('overflow','hidden'); 25 | 26 | d3.select(params.viz.viz_wrapper) 27 | .style('float', 'left') 28 | .style('width', cont_dim.width + 'px') 29 | .style('height', cont_dim.height + 'px'); 30 | }; 31 | -------------------------------------------------------------------------------- /src/sidebar/disable_sidebar.js: -------------------------------------------------------------------------------- 1 | module.exports = function disable_sidebar(params){ 2 | 3 | d3.selectAll(params.root+' .btn').attr('disabled',true); 4 | d3.select( params.viz.viz_svg ).style('opacity',0.70); 5 | 6 | }; 7 | -------------------------------------------------------------------------------- /src/sidebar/enable_sidebar.js: -------------------------------------------------------------------------------- 1 | module.exports = function enable_sidebar(params) { 2 | 3 | /* only enable dendrogram sliders if there has been no dendro_filtering */ 4 | 5 | // only enable reordering if params.dendro_filter.row === false 6 | if (params.dendro_filter.row === false){ 7 | 8 | // orders are switched! 9 | if (params.viz.inst_order.col === 'clust'){ 10 | d3.select(params.root+' .row_slider_group') 11 | .style('opacity',1) 12 | .style('pointer-events','all'); 13 | } 14 | 15 | } 16 | 17 | d3.selectAll(params.root+' .toggle_row_order .btn') 18 | .attr('disabled',null); 19 | 20 | if (params.dendro_filter.col === false){ 21 | 22 | // orders are switched! 23 | if (params.viz.inst_order.row === 'clust'){ 24 | d3.select(params.root+' .col_slider_group') 25 | .style('opacity',1) 26 | .style('pointer-events','all'); 27 | } 28 | 29 | } 30 | 31 | d3.selectAll(params.root+' .toggle_col_order .btn') 32 | .attr('disabled',null); 33 | 34 | d3.selectAll(params.root+' .gene_search_button .btn') 35 | .attr('disabled',null); 36 | 37 | 38 | params.viz.run_trans = false; 39 | 40 | }; 41 | -------------------------------------------------------------------------------- /src/sidebar/make_modals.js: -------------------------------------------------------------------------------- 1 | var make_modal_skeleton = require('../modal/make_modal_skeleton'); 2 | 3 | module.exports = function ini_modals(params){ 4 | 5 | // share modal 6 | /////////////////////////////////////// 7 | var share_modal = make_modal_skeleton(params, 'share_info'); 8 | 9 | share_modal.header 10 | .append('a') 11 | .attr('target','_blank') 12 | .attr('href', '/clustergrammer/'); 13 | 14 | share_modal.header 15 | .append('h4') 16 | .classed('modal-title', true) 17 | .html('Share the visualization using the current URL:'); 18 | 19 | share_modal.body 20 | .append('input') 21 | .classed('bootstrap_highlight', true) 22 | .classed('share_url', true); 23 | 24 | // picture modal 25 | /////////////////////////////////////// 26 | var screenshot_modal = make_modal_skeleton(params, 'picture_info'); 27 | 28 | screenshot_modal.header 29 | .append('h4') 30 | .classed('modal-title', true) 31 | .html('Save a snapshot of the visualization'); 32 | 33 | screenshot_modal.body 34 | .append('div') 35 | .classed('download_buttons', true); 36 | 37 | // dendro modal 38 | /////////////////////////////////////// 39 | var dendro_modal = make_modal_skeleton(params, 'dendro_info'); 40 | 41 | dendro_modal.header 42 | .append('h4') 43 | .classed('modal-title', true) 44 | .html('Cluster Information'); 45 | 46 | dendro_modal.body 47 | .append('g') 48 | .classed('cluster_info_container', true); 49 | 50 | dendro_modal.body 51 | .append('div') 52 | .classed('dendro_text', true) 53 | .append('input') 54 | .classed('bootstrap_highlight', true) 55 | .classed('current_names', true) 56 | .style('width', '100%'); 57 | 58 | }; -------------------------------------------------------------------------------- /src/sidebar/set_sidebar_ini_view.js: -------------------------------------------------------------------------------- 1 | var make_filter_title = require('../filters/make_filter_title'); 2 | var underscore = require('underscore'); 3 | 4 | module.exports = function set_sidebar_ini_view(params){ 5 | 6 | underscore.each( underscore.keys(params.ini_view), function(inst_filter){ 7 | 8 | // initialize filter slider using ini_view 9 | var inst_value = params.ini_view[inst_filter]; 10 | 11 | var filter_type = params.viz.possible_filters[inst_filter]; 12 | 13 | if (filter_type === 'numerical'){ 14 | 15 | if (inst_value != 'all'){ 16 | inst_value = parseInt(inst_value,10); 17 | } 18 | 19 | if (params.viz.filter_data[inst_filter].indexOf(inst_value) <= -1){ 20 | inst_value = 'all'; 21 | } 22 | 23 | var filter_title = make_filter_title(params, inst_filter); 24 | 25 | d3.select(params.root+' .title_'+inst_filter) 26 | .text(filter_title.text + inst_value + filter_title.suffix); 27 | 28 | d3.select(params.root+' .slider_'+inst_filter) 29 | .attr('current_state', inst_value); 30 | 31 | } else { 32 | 33 | // set up button initialization 34 | 35 | } 36 | 37 | }); 38 | 39 | }; 40 | -------------------------------------------------------------------------------- /src/sidebar/set_up_opacity_slider.js: -------------------------------------------------------------------------------- 1 | module.exports = function set_up_opacity_slider(sidebar){ 2 | 3 | var slider_container = sidebar 4 | .append('div') 5 | .classed('opacity_slider_container', true) 6 | .style('margin-top', '5px') 7 | .style('padding-left', '10px') 8 | .style('padding-right', '10px'); 9 | 10 | slider_container 11 | .append('div') 12 | .classed('sidebar_text', true) 13 | .classed('opacity_slider_text', true) 14 | .style('margin-bottom', '3px') 15 | .text('Opacity Slider'); 16 | 17 | slider_container 18 | .append('div') 19 | .classed('slider', true) 20 | .classed('opacity_slider', true); 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /src/sidebar/set_up_search.js: -------------------------------------------------------------------------------- 1 | module.exports = function set_up_search(sidebar, params ){ 2 | 3 | var search_container = sidebar 4 | .append('div') 5 | // .classed('row',true) 6 | .classed('gene_search_container',true) 7 | .style('padding-left','10px') 8 | .style('padding-right','10px') 9 | .style('margin-top','10px'); 10 | 11 | search_container 12 | .append('input') 13 | .classed('form-control',true) 14 | .classed('gene_search_box',true) 15 | .classed('sidebar_text', true) 16 | .attr('type','text') 17 | .attr('placeholder', params.sidebar.row_search.placeholder) 18 | .style('height', params.sidebar.row_search.box.height+'px') 19 | .style('margin-top', '10px'); 20 | 21 | search_container 22 | .append('div') 23 | .classed('gene_search_button',true) 24 | .style('margin-top', '5px') 25 | .attr('data-toggle','buttons') 26 | .append('button') 27 | .classed('sidebar_text', true) 28 | .html('Search') 29 | .attr('type','button') 30 | .classed('btn',true) 31 | .classed('btn-primary',true) 32 | .classed('submit_gene_button',true) 33 | .style('width', '100%') 34 | .style('font-size', '14px'); 35 | 36 | }; 37 | -------------------------------------------------------------------------------- /src/spillover/make_row_dendro_spillover.js: -------------------------------------------------------------------------------- 1 | var make_dendro_crop_buttons = require('../dendrogram/make_dendro_crop_buttons'); 2 | 3 | module.exports = function make_row_dendro_spillover(cgm){ 4 | 5 | var viz = cgm.params.viz; 6 | 7 | // hide spillover from right 8 | var tmp_left = viz.clust.margin.left + 9 | viz.clust.dim.width + 10 | viz.uni_margin + 11 | viz.dendro_room.row; 12 | 13 | var r_spill_container = d3.select(viz.viz_svg) 14 | .append('g') 15 | .classed('right_spillover_container', true) 16 | .attr('transform', function() { 17 | return 'translate(' + tmp_left + ', 0)'; 18 | }); 19 | 20 | var tmp_top = viz.norm_labels.margin.top + viz.norm_labels.width.col; 21 | 22 | r_spill_container 23 | .append('rect') 24 | .attr('fill', viz.background_color) //!! prog_colors 25 | .attr('width', 10*viz.clust.dim.width) 26 | .attr('height', viz.svg_dim.height+'px') 27 | .attr('class', 'white_bars') 28 | .attr('class','right_spillover') 29 | .attr('transform', function() { 30 | return 'translate( 0,' + tmp_top + ')'; 31 | }); 32 | 33 | var x_offset = 0; 34 | var y_offset = viz.clust.margin.top; 35 | r_spill_container 36 | .append('g') 37 | .classed('row_dendro_icons_container', true) 38 | .attr('transform', 'translate(' + x_offset + ','+ y_offset +')') 39 | .append('g') 40 | .classed('row_dendro_icons_group', true); 41 | 42 | make_dendro_crop_buttons(cgm, 'row'); 43 | 44 | // hide spillover from top of row dendrogram 45 | x_offset = viz.clust.margin.left + viz.clust.dim.width; 46 | y_offset = tmp_top; 47 | 48 | var tmp_width = viz.dendro_room.row + viz.uni_margin; 49 | var tmp_height = viz.cat_room.col + viz.uni_margin; 50 | d3.select(viz.viz_svg) 51 | .append('rect') 52 | .attr('fill', viz.background_color) 53 | .attr('width',tmp_width) 54 | .attr('height',tmp_height) 55 | .attr('transform', function(){ 56 | return 'translate('+x_offset+','+y_offset+')'; 57 | }) 58 | .classed('white_bars',true) 59 | .classed('dendro_row_spillover',true); 60 | 61 | }; -------------------------------------------------------------------------------- /src/update/remove_node_cats.js: -------------------------------------------------------------------------------- 1 | var underscore = require('underscore'); 2 | 3 | module.exports = function remove_node_cats(inst_node){ 4 | 5 | var all_props = underscore.keys(inst_node); 6 | 7 | underscore.each(all_props, function(inst_prop){ 8 | 9 | if (inst_prop.indexOf('cat-') > -1){ 10 | delete inst_node[inst_prop]; 11 | } 12 | 13 | if (inst_prop.indexOf('cat_') > -1){ 14 | delete inst_node[inst_prop]; 15 | } 16 | 17 | }); 18 | 19 | }; -------------------------------------------------------------------------------- /src/update/reset_cats.js: -------------------------------------------------------------------------------- 1 | var make_row_cat = require('../categories/make_row_cat'); 2 | var calc_viz_params = require('../params/calc_viz_params'); 3 | var resize_viz = require('../reset_size/resize_viz'); 4 | var modify_row_node_cats = require('./modify_row_node_cats'); 5 | var generate_cat_data = require('./generate_cat_data'); 6 | 7 | module.exports = function reset_cats(run_resize_viz = true){ 8 | 9 | // console.log('RESET CATS') 10 | 11 | var cgm = this; 12 | 13 | var cat_data = generate_cat_data(cgm); 14 | 15 | // do not change column category info 16 | var col_cat_colors = cgm.params.viz.cat_colors.col; 17 | 18 | modify_row_node_cats(cat_data, cgm.params.network_data.row_nodes); 19 | // modify the current inst copy of nodes 20 | modify_row_node_cats(cat_data, cgm.params.inst_nodes.row_nodes); 21 | 22 | cgm.params.new_row_cats = cat_data; 23 | cgm.params.viz.cat_colors.col = col_cat_colors; 24 | 25 | if (run_resize_viz){ 26 | 27 | // resize visualizatino 28 | //////////////////////////// 29 | // recalculate the visualization parameters using the updated network_data 30 | var predefine_cat_colors = true; 31 | cgm.params = calc_viz_params(cgm.params, predefine_cat_colors); 32 | 33 | make_row_cat(cgm, true); 34 | resize_viz(cgm); 35 | 36 | } 37 | 38 | }; -------------------------------------------------------------------------------- /src/update/update_cats.js: -------------------------------------------------------------------------------- 1 | var make_row_cat = require('../categories/make_row_cat'); 2 | var calc_viz_params = require('../params/calc_viz_params'); 3 | var resize_viz = require('../reset_size/resize_viz'); 4 | var modify_row_node_cats = require('./modify_row_node_cats'); 5 | 6 | module.exports = function update_cats(cgm, cat_data){ 7 | 8 | // Only accessible from the cgm API, cat_data is provided by externally 9 | /////////////////////////////////////////////////////////////////////////// 10 | 11 | if (cgm.params.cat_update_callback != null){ 12 | cgm.params.cat_update_callback(this); 13 | } 14 | 15 | // do not change column category info 16 | var col_cat_colors = cgm.params.viz.cat_colors.col; 17 | 18 | modify_row_node_cats(cat_data, cgm.params.network_data.row_nodes, true); 19 | // modify the current inst copy of nodes 20 | modify_row_node_cats(cat_data, cgm.params.inst_nodes.row_nodes, true); 21 | 22 | // recalculate the visualization parameters using the updated network_data 23 | cgm.params = calc_viz_params(cgm.params, false); 24 | 25 | make_row_cat(cgm, true); 26 | resize_viz(cgm); 27 | 28 | cgm.params.new_row_cats = cat_data; 29 | 30 | cgm.params.viz.cat_colors.col = col_cat_colors; 31 | 32 | }; -------------------------------------------------------------------------------- /src/update/update_view.js: -------------------------------------------------------------------------------- 1 | var update_viz_with_view = require('../network/update_viz_with_view'); 2 | var reset_other_filter_sliders = require('../filters/reset_other_filter_sliders'); 3 | 4 | module.exports = function update_view(cgm, filter_type, inst_state){ 5 | 6 | // add something to control slider position 7 | ///////////////////////////////////////////// 8 | 9 | var requested_view = {}; 10 | requested_view[filter_type] = inst_state; 11 | update_viz_with_view(cgm, requested_view); 12 | 13 | reset_other_filter_sliders(cgm, filter_type, inst_state); 14 | }; -------------------------------------------------------------------------------- /src/zoom/calc_real_font_size.js: -------------------------------------------------------------------------------- 1 | module.exports = function calc_real_font_size(params){ 2 | 3 | var real_font_size = {}; 4 | // zoom_switch behavior has to change with zoom_ratio.y 5 | if (params.viz.zoom_ratio.x > 1){ 6 | real_font_size.row = params.labels.default_fs_row * params.zoom_behavior.scale(); 7 | real_font_size.col = params.labels.default_fs_col * params.zoom_behavior.scale(); 8 | } else { 9 | real_font_size.row = params.labels.default_fs_row * params.zoom_behavior.scale()/params.viz.zoom_ratio.y; 10 | real_font_size.col = params.labels.default_fs_col * params.zoom_behavior.scale(); 11 | } 12 | 13 | return real_font_size; 14 | 15 | }; -------------------------------------------------------------------------------- /src/zoom/calc_zoom_switching.js: -------------------------------------------------------------------------------- 1 | module.exports = function calc_zoom_switching(viz){ 2 | 3 | var width_by_col = viz.clust.dim.width / viz.num_col_nodes; 4 | var height_by_row = viz.clust.dim.height / viz.num_row_nodes; 5 | 6 | viz.zoom_ratio = {}; 7 | viz.zoom_ratio.x = width_by_col / height_by_row; 8 | viz.zoom_ratio.y = 1; 9 | 10 | if (viz.zoom_ratio.x < 1) { 11 | viz.zoom_ratio.y = 1/viz.zoom_ratio.x; 12 | viz.zoom_ratio.x = 1; 13 | } 14 | 15 | return viz; 16 | }; -------------------------------------------------------------------------------- /src/zoom/check_zoom_stop_status.js: -------------------------------------------------------------------------------- 1 | module.exports = function check_zoom_stop_status(params){ 2 | 3 | var inst_zoom = Number(d3.select(params.root+' .viz_svg').attr('is_zoom')); 4 | 5 | var check_stop = Number(d3.select(params.root+' .viz_svg') 6 | .attr('stopped_zoom')); 7 | 8 | var stop_attributes = false; 9 | if (inst_zoom === 0 && check_stop != 0){ 10 | stop_attributes = true; 11 | } 12 | 13 | return stop_attributes; 14 | }; -------------------------------------------------------------------------------- /src/zoom/find_viz_rows.js: -------------------------------------------------------------------------------- 1 | module.exports = function find_viz_rows(params, viz_area){ 2 | 3 | var should_be_rows = []; 4 | var curr_rows = []; 5 | 6 | // find rows that should be visible 7 | var y_trans; 8 | 9 | // default y_scale (no downsampling) 10 | var y_scale = params.viz.y_scale; 11 | var ds_level = params.viz.ds_level; 12 | var row_names = params.network_data.row_nodes_names; 13 | var row_class = '.row'; 14 | 15 | // if downsampling redefine variables 16 | if (ds_level >=0){ 17 | y_scale = params.viz.ds[ds_level].y_scale; 18 | row_names = d3.range(params.matrix.ds_matrix[ds_level].length).map(String); 19 | row_class = '.ds'+String(ds_level)+'_row'; 20 | } 21 | 22 | // find rows that should be visible 23 | for (var i=0; i < row_names.length; i++){ 24 | y_trans = y_scale(i); 25 | if (y_trans < viz_area.max_y && y_trans > viz_area.min_y){ 26 | should_be_rows.push(row_names[i]); 27 | } 28 | } 29 | 30 | // find currently visible rows 31 | d3.selectAll(params.root+' '+row_class) 32 | .each(function(d){ 33 | curr_rows.push(d.name); 34 | }); 35 | 36 | // nodes that should be visible 37 | params.viz.viz_nodes.row = should_be_rows; 38 | // nodes that are visible 39 | params.viz.viz_nodes.curr_row = curr_rows; 40 | 41 | }; -------------------------------------------------------------------------------- /src/zoom/get_previous_zoom.js: -------------------------------------------------------------------------------- 1 | module.exports = function get_previous_zoom(params){ 2 | var prev_zoom = {}; 3 | 4 | var inst_trans = d3.select(params.root+' .clust_group') 5 | .attr('transform'); 6 | 7 | if (inst_trans != null){ 8 | 9 | // prevent from crashing if no scaling was done 10 | if (inst_trans.indexOf('scale') > 0){ 11 | prev_zoom.zoom_x = parseFloat(inst_trans.split('scale')[1].replace('(','') 12 | .replace(')','').split(',')[0]); 13 | 14 | prev_zoom.zoom_y = parseFloat(inst_trans.split('scale')[1].replace('(','') 15 | .replace(')','').split(',')[1]); 16 | } else { 17 | prev_zoom.zoom_x = 1; 18 | prev_zoom.zoom_y = 1; 19 | } 20 | 21 | } else { 22 | prev_zoom.zoom_x = 1; 23 | prev_zoom.zoom_y = 1; 24 | } 25 | 26 | return prev_zoom; 27 | 28 | }; -------------------------------------------------------------------------------- /src/zoom/ini_doubleclick.js: -------------------------------------------------------------------------------- 1 | var two_translate_zoom = require('./two_translate_zoom'); 2 | 3 | module.exports = function ini_doubleclick(cgm) { 4 | 5 | var params = cgm.params; 6 | // disable double-click zoom 7 | d3.selectAll(params.viz.zoom_element) 8 | .on('dblclick.zoom', null); 9 | 10 | d3.select(params.viz.zoom_element) 11 | .on('dblclick', function() { 12 | two_translate_zoom(cgm, 0, 0, 1); 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /src/zoom/ini_zoom_info.js: -------------------------------------------------------------------------------- 1 | module.exports = function ini_zoom_info(){ 2 | 3 | var zoom_info = {}; 4 | zoom_info.zoom_x = 1; 5 | zoom_info.zoom_y = 1; 6 | zoom_info.trans_x = 0; 7 | zoom_info.trans_y = 0; 8 | 9 | return zoom_info; 10 | 11 | }; -------------------------------------------------------------------------------- /src/zoom/num_visible_labels.js: -------------------------------------------------------------------------------- 1 | module.exports = function num_visible_labels(params, inst_rc){ 2 | 3 | // counting the number of visible labels, probably not necessary 4 | 5 | var num_visible; 6 | if (inst_rc === 'row'){ 7 | 8 | // initialize at high number 9 | num_visible = 10000; 10 | 11 | // only count visible rows if no downsampling 12 | if (params.viz.ds_level === -1){ 13 | num_visible = d3.selectAll(params.root+' .row')[0].length; 14 | } 15 | 16 | } else if (inst_rc === 'col') { 17 | 18 | num_visible = d3.selectAll(params.root+' .'+inst_rc+'_label_text') 19 | .filter(function(){ 20 | return d3.select(this).style('display')!='none'; 21 | })[0].length; 22 | 23 | } 24 | 25 | return num_visible; 26 | }; -------------------------------------------------------------------------------- /src/zoom/reset_zoom.js: -------------------------------------------------------------------------------- 1 | module.exports = function(params){ 2 | 3 | // reset zoom 4 | ////////////////////////////// 5 | var zoom_y = 1; 6 | // var zoom_x = 1; 7 | var pan_dx = 0; 8 | var pan_dy = 0; 9 | 10 | var half_height = params.viz.clust.dim.height / 2; 11 | var center_y = -(zoom_y - 1) * half_height; 12 | 13 | d3.select(params.root + ' .clust_group') 14 | .attr('transform', 'translate(' + [0, 0 + center_y] + ')' + 15 | ' scale(' + 1 + ',' + zoom_y + ')' + 'translate(' + [pan_dx,pan_dy] + ')'); 16 | 17 | d3.select(params.root+' .row_label_zoom_container') 18 | .attr('transform', 'translate(' + [0, center_y] + ')' + ' scale(' + 19 | zoom_y + ',' + zoom_y + ')' + 'translate(' + [0, pan_dy] + ')'); 20 | 21 | d3.select(params.root+' .row_cat_container') 22 | .attr('transform', 'translate(' + [0, center_y] + ')' + ' scale(' + 23 | 1 + ',' + zoom_y + ')' + 'translate(' + [0, pan_dy] + ')'); 24 | 25 | d3.select(params.root+' .row_dendro_container') 26 | .attr('transform', 'translate(' + [0, center_y] + ')' + ' scale(' + 27 | zoom_y + ',' + zoom_y + ')' + 'translate(' + [params.viz.uni_margin/2, pan_dy] + ')'); 28 | 29 | d3.select(params.root+' .col_zoom_container') 30 | .attr('transform', ' scale(' + 1 + ',' + 1 + ')' + 'translate(' + [pan_dx, 0] + ')'); 31 | 32 | d3.select(params.root+' .col_cat_container') 33 | .attr('transform', ' scale(' + 1 + ',' + 1 + ')' + 'translate(' + [pan_dx, 0] + ')'); 34 | 35 | d3.select(params.root+' .col_dendro_container') 36 | .attr('transform', ' scale(' + 1 + ',' + 1 + ')' + 'translate(' + [pan_dx, params.viz.uni_margin/2] + ')'); 37 | 38 | // reset crop button zooming 39 | d3.select(params.root+' .row_dendro_icons_group') 40 | .attr('transform', function(){ 41 | return 'translate(0,0) scale(1)'; 42 | }); 43 | 44 | d3.select(params.root+' .row_dendro_icons_group') 45 | .selectAll('path') 46 | .attr('transform', function(d){ 47 | var inst_x = 7; 48 | var inst_y = d.pos_mid; 49 | return 'translate('+ inst_x +',' + inst_y + ') ' + 'scale(1, 1)'; 50 | }); 51 | 52 | }; -------------------------------------------------------------------------------- /src/zoom/resize_label_val_bars.js: -------------------------------------------------------------------------------- 1 | var utils = require('../Utils_clust'); 2 | 3 | module.exports = function resize_label_val_bars(params){ 4 | 5 | var zoom_info = params.zoom_info; 6 | 7 | // resize label bars if necessary 8 | if (utils.has(params.network_data.row_nodes[0], 'value')) { 9 | d3.selectAll(params.root+' .row_bars') 10 | .attr('width', function(d) { 11 | var inst_value = 0; 12 | inst_value = params.labels.bar_scale_row(Math.abs(d.value))/zoom_info.zoom_y; 13 | return inst_value; 14 | }) 15 | .attr('x', function(d) { 16 | var inst_value = 0; 17 | inst_value = -params.labels.bar_scale_row(Math.abs(d.value))/zoom_info.zoom_y; 18 | return inst_value; 19 | }); 20 | } 21 | 22 | if (utils.has(params.network_data.col_nodes[0], 'value')) { 23 | d3.selectAll(params.root+' .col_bars') 24 | .attr('width', function(d) { 25 | var inst_value = 0; 26 | if (d.value > 0){ 27 | inst_value = params.labels.bar_scale_col(d.value)/zoom_info.zoom_x; 28 | } 29 | return inst_value; 30 | }); 31 | } 32 | 33 | }; -------------------------------------------------------------------------------- /src/zoom/run_zoom.js: -------------------------------------------------------------------------------- 1 | var run_transformation = require('./run_transformation'); 2 | var zoom_rules_y = require('./zoom_rules_y'); 3 | var zoom_rules_x = require('./zoom_rules_x'); 4 | 5 | module.exports = function zoomed(cgm) { 6 | 7 | var params = cgm.params; 8 | 9 | var zoom_info = {}; 10 | zoom_info.zoom_x = d3.event.scale; 11 | zoom_info.zoom_y = d3.event.scale; 12 | 13 | // subtract away the margin to easily calculate pan_room etc. 14 | zoom_info.trans_x = params.zoom_behavior.translate()[0] - params.viz.clust.margin.left; 15 | zoom_info.trans_y = params.zoom_behavior.translate()[1] - params.viz.clust.margin.top; 16 | 17 | d3.selectAll(params.viz.root_tips) 18 | .style('display','none'); 19 | 20 | // transfer zoom_info to params 21 | params.zoom_info = zoom_rules_y(params, zoom_info); 22 | params.zoom_info = zoom_rules_x(params, zoom_info); 23 | 24 | // do not run transformation if moving slider 25 | if (params.is_slider_drag === false && params.is_cropping === false){ 26 | 27 | // reset translate vector - add back margins to trans_x and trans_y 28 | var new_x = params.zoom_info.trans_x + params.viz.clust.margin.left; 29 | var new_y = params.zoom_info.trans_y + params.viz.clust.margin.top; 30 | 31 | params.zoom_behavior.translate([new_x, new_y]); 32 | cgm.params = params; 33 | 34 | run_transformation(cgm); 35 | 36 | } 37 | 38 | }; 39 | -------------------------------------------------------------------------------- /src/zoom/zoom_crop_triangles.js: -------------------------------------------------------------------------------- 1 | module.exports = function zoom_crop_triangles(params, zoom_info, inst_rc){ 2 | 3 | if (inst_rc === 'row'){ 4 | 5 | // transform icons (undo zoom on triangles) 6 | d3.select(params.root+' .row_dendro_icons_group') 7 | .selectAll('path') 8 | .attr('transform', function(d){ 9 | var inst_x = params.viz.uni_margin; 10 | var inst_y = d.pos_mid; 11 | var curr_zoom = zoom_info.zoom_y; 12 | var tri_dim = d3.select(this).data()[0].tri_dim; 13 | var inst_zoom = constrain_zoom(curr_zoom, tri_dim); 14 | return 'translate('+ inst_x +',' + inst_y + ') ' + 'scale(1, '+ 1/inst_zoom +')'; 15 | }); 16 | 17 | } else { 18 | 19 | // transform icons (undo zoom on triangles) 20 | d3.select(params.root+' .col_dendro_icons_group') 21 | .selectAll('path') 22 | .attr('transform', function(d){ 23 | var inst_x = d.pos_mid; 24 | var inst_y = params.viz.uni_margin; 25 | var curr_zoom = zoom_info.zoom_x; 26 | var tri_dim = d3.select(this).data()[0].tri_dim; 27 | var inst_zoom = constrain_zoom(curr_zoom, tri_dim); 28 | return 'translate('+ inst_x +',' + inst_y + ') ' + 'scale('+ 1/inst_zoom +', 1)'; 29 | }); 30 | 31 | } 32 | 33 | function constrain_zoom(curr_zoom, tri_height){ 34 | var inst_zoom; 35 | var default_tri_height = 10; 36 | if (tri_height * curr_zoom < default_tri_height){ 37 | inst_zoom = 1; 38 | } else { 39 | var max_zoom = default_tri_height/tri_height; 40 | inst_zoom = curr_zoom/max_zoom; 41 | } 42 | return inst_zoom; 43 | } 44 | 45 | }; -------------------------------------------------------------------------------- /src/zoom/zoom_rules_x.js: -------------------------------------------------------------------------------- 1 | module.exports = function zoom_rules_x(params, zoom_info){ 2 | 3 | var viz = params.viz; 4 | 5 | // zoom in the y direction before zooming in the x direction 6 | if (viz.zoom_ratio.x > 1){ 7 | 8 | if (zoom_info.zoom_x < viz.zoom_ratio.x) { 9 | 10 | // remove this 11 | // zoom_info.trans_x = - params.viz.clust.margin.left; 12 | 13 | zoom_info.zoom_x = 1; 14 | } else { 15 | zoom_info.zoom_x = zoom_info.zoom_x / viz.zoom_ratio.x; 16 | 17 | // console.log('********* zoom_x: ' + String(zoom_info.zoom_x)) 18 | 19 | // zoom_info.trans_x = zoom_info.trans_x + params.viz.x_offset; 20 | // zoom_info.trans_x = zoom_info.trans_x * (params.zoom_info.zoom_x/params.zoom_info.zoom_y); 21 | } 22 | } 23 | 24 | // calculate panning room available in the x direction 25 | zoom_info.pan_room_x = (zoom_info.zoom_x - 1) * viz.clust.dim.width; 26 | 27 | // console.log( 'pan_room_x: ' + String(zoom_info.pan_room_x) + ' trans_x: ' + String(-zoom_info.trans_x)) 28 | 29 | // no positive panning or panning more than pan_room 30 | if (zoom_info.trans_x > 0) { 31 | zoom_info.trans_x = 0; 32 | // console.log('no positive panning\n\n') 33 | } 34 | else if (zoom_info.trans_x <= -zoom_info.pan_room_x) { 35 | zoom_info.trans_x = -zoom_info.pan_room_x; 36 | // console.log('******* restrict pan room\n\n') 37 | } 38 | 39 | 40 | return zoom_info; 41 | }; -------------------------------------------------------------------------------- /src/zoom/zoom_rules_y.js: -------------------------------------------------------------------------------- 1 | module.exports = function zoom_rules_y(params, zoom_info){ 2 | 3 | var viz = params.viz; 4 | // zoom in the x direction before zooming in the y direction 5 | if (viz.zoom_ratio.y > 1){ 6 | if (zoom_info.zoom_y < viz.zoom_ratio.y){ 7 | zoom_info.trans_y = 0; 8 | zoom_info.zoom_y = 1; 9 | } else { 10 | zoom_info.zoom_y = zoom_info.zoom_y / viz.zoom_ratio.y; 11 | } 12 | } 13 | 14 | // calculate panning room available in the y direction 15 | zoom_info.pan_room_y = (zoom_info.zoom_y - 1) * viz.clust.dim.height; 16 | 17 | // console.log( 'pan_room_y: ' + String(zoom_info.pan_room_y) + ' ' + String(-zoom_info.trans_y)) 18 | 19 | // no positive panning or panning more than pan_room 20 | if (zoom_info.trans_y >= 0) { 21 | zoom_info.trans_y = 0; 22 | // console.log('y no positive panning\n\n') 23 | } 24 | else if (zoom_info.trans_y <= -zoom_info.pan_room_y) { 25 | zoom_info.trans_y = -zoom_info.pan_room_y; 26 | // console.log('y restrict pan room \n\n') 27 | } 28 | 29 | return zoom_info; 30 | }; -------------------------------------------------------------------------------- /txt/missing_values.txt: -------------------------------------------------------------------------------- 1 | c1 c2 c3 2 | r1 7 NaN 6 3 | r2 NaN 4 3 4 | r3 4 5 9 5 | r4 22 3 2 -------------------------------------------------------------------------------- /txt/number_labels.txt: -------------------------------------------------------------------------------- 1 | 1 2 3 2 | 1 -3 3 3 | 1 -7 1 2 3 4 | 2 2 10 11 12 5 | 3 -1 7 -12 9 6 | 4 7 4 -1 6 -------------------------------------------------------------------------------- /txt/rc_val_cats.txt: -------------------------------------------------------------------------------- 1 | col-A col-B col-C 2 | 1 -3 3 3 | row-A -7 1 2 3 4 | row-B 2 10 11 12 5 | row-C -1 7 -12 9 6 | row-D 7 4 -1 6 -------------------------------------------------------------------------------- /txt/tuple_cats.txt: -------------------------------------------------------------------------------- 1 | ('Cell Line: A549', 'Male') ('Cell Line: H1299', 'Female') ('Cell Line: H661', 'Female') 2 | ('Gene: EGFR','Type: 11') -3.234 5.03 0.001 3 | ('Gene: TP53','Type: 0.5') 8.3 4.098 -12.2 4 | ('Gene: IRAK','Type: 99') 7.23 3.01 0.88 --------------------------------------------------------------------------------