UNPKG

clustergrammer

Version:

This is a clustergram implemented in D3.js. I started from the example http://bost.ocks.org/mike/miserables/ and added the following features

262 lines (198 loc) 6.92 kB
var calc_row_dendro_triangles = require('./calc_row_dendro_triangles'); var calc_col_dendro_triangles = require('./calc_col_dendro_triangles'); var dendro_group_highlight = require('./dendro_group_highlight'); var d3_tip_custom = require('../tooltip/d3_tip_custom'); var make_dendro_crop_buttons = require('./make_dendro_crop_buttons'); var make_cat_breakdown_graph = require('./make_cat_breakdown_graph'); module.exports = function make_dendro_triangles(cgm, inst_rc, is_change_group = false) { var params = cgm.params; // in case sim_mat if (inst_rc === 'both'){ inst_rc = 'row'; } var other_rc; if (inst_rc === 'row'){ other_rc = 'col'; } else { other_rc = 'row'; } // orders are switched! if (params.viz.inst_order[other_rc] === 'clust'){ d3.select(params.root+' .'+ inst_rc +'_slider_group') .style('opacity', 1); } var dendro_info; if (params.viz.show_dendrogram){ if (inst_rc === 'row'){ dendro_info = calc_row_dendro_triangles(params); } else { dendro_info = calc_col_dendro_triangles(params); } if (d3.select(cgm.params.root+' .'+ inst_rc +'_dendro_crop_buttons').empty() === false){ make_dendro_crop_buttons(cgm, inst_rc); } } // constant dendrogram opacity var inst_dendro_opacity = params.viz.dendro_opacity; function still_hovering(inst_selection, inst_data, i){ if (d3.select(inst_selection).classed('hovering')){ // define where graph should be built var inst_selector = params.viz.root_tips + '_' + inst_rc + '_dendro_tip'; // prevent mouseover from making multiple graphs if (d3.select(inst_selector + ' .cat_graph').empty()){ if ( params.viz.cat_info[inst_rc] !== null ){ make_cat_breakdown_graph(params, inst_rc, inst_data, dendro_info[i], inst_selector, true); } } d3.selectAll(params.viz.root_tips + '_'+ inst_rc +'_dendro_tip') .style('opacity', 1); } } var wait_before_tooltip = 500; // remove any old dendro tooltips from this visualization d3.selectAll(cgm.params.viz.root_tips+'_'+ inst_rc +'_dendro_tip').remove(); // run transition rules var run_transition; if (d3.selectAll(params.root+' .' + inst_rc + '_dendro_group').empty()){ run_transition = false; } else { run_transition = true; d3.selectAll(params.root+' .'+ inst_rc +'_dendro_group').remove(); // d3.selectAll(params.root+' .dendro_tip').remove(); } // d3-tooltip var tmp_y_offset = 0; var tmp_x_offset = -5; var dendro_tip = d3_tip_custom() .attr('class',function(){ // add root element to class var root_tip_selector = params.viz.root_tips.replace('.',''); var class_string = root_tip_selector + ' d3-tip ' + root_tip_selector + '_' + inst_rc + '_dendro_tip'; return class_string; }) .direction('nw') .offset([tmp_y_offset, tmp_x_offset]) .style('display','none') .style('opacity', 0); dendro_tip .html(function(){ var full_string = '<div class="cluster_info_container"></div>Click for cluster information <br>'+ 'and additional options.'; return full_string; }); if (is_change_group){ run_transition = false; } var dendro_traps = d3.select(params.root+' .'+ inst_rc +'_dendro_container') .selectAll('path') .data(dendro_info, function(d){return d.name;}) .enter() .append('path') .style('opacity',0) .attr('class', inst_rc +'_dendro_group') .style('fill','black'); // draw triangles (shown as trapezoids) ////////////////////////////////////////// var start_x; var start_y; var mid_x; var mid_y; var final_x; var final_y; // row triangles dendro_traps .attr('d', function(d) { if (inst_rc === 'row'){ // row triangles start_x = 0 ; start_y = d.pos_top; mid_x = 30; mid_y = d.pos_mid; final_x = 0; final_y = d.pos_bot; } else { // column triangles start_x = d.pos_top; start_y = 0 ; mid_x = d.pos_mid; mid_y = 30; final_x = d.pos_bot; final_y = 0; } var output_string = 'M' + start_x + ',' + start_y + ', L' + mid_x + ', ' + mid_y + ', L' + final_x + ','+ final_y +' Z'; return output_string; }); dendro_traps .on('mouseover', function(d, i){ // if (params.sim_mat){ // inst_rc = 'both'; // } // run instantly on mouseover d3.select(this) .classed('hovering', true); if (cgm.params.dendro_callback != null){ cgm.params.dendro_callback(this); } // display tip // this is needed for it to show in the right place and the opacity // will be toggled to delay the tooltip for the user d3.select( params.viz.root_tips + '_' + inst_rc + '_dendro_tip' ) .style('display', 'block'); dendro_group_highlight(params, this, d, inst_rc); // show the tip (make sure it is displaying before it is shown) dendro_tip.show(d); // set opacity to zero d3.select( params.viz.root_tips + '_'+ inst_rc +'_dendro_tip') .style('opacity', 0); // check if still hovering setTimeout(still_hovering, wait_before_tooltip, this, d, i); }) .on('mouseout', function(){ if (params.viz.inst_order[other_rc] === 'clust'){ d3.select(this) .style('opacity', inst_dendro_opacity); } d3.selectAll(params.root+' .dendro_shadow') .remove(); d3.select(this) .classed('hovering',false); dendro_tip.hide(this); }) .on('click', function(d, i){ $(params.root+' .dendro_info').modal('toggle'); var group_string = d.all_names.join(', '); d3.select(params.root+' .dendro_info input') .attr('value', group_string); var inst_selector = params.root + ' .dendro_info'; // remove old graphs (modals are not within params.root) d3.selectAll('.dendro_info .cluster_info_container .cat_graph') .remove(); if ( params.viz.cat_info[inst_rc] !== null ){ make_cat_breakdown_graph(params, inst_rc, d, dendro_info[i], inst_selector); } if (cgm.params.dendro_click_callback != null){ cgm.params.dendro_click_callback(this); } }) .call(dendro_tip); var triangle_opacity; if (params.viz.inst_order[other_rc] === 'clust'){ triangle_opacity = inst_dendro_opacity; } else { triangle_opacity = 0; } if (run_transition){ d3.select(params.root+' .'+ inst_rc +'_dendro_container') .selectAll('path') .transition().delay(1000).duration(1000) .style('opacity', triangle_opacity); } else { d3.select(params.root+' .'+ inst_rc +'_dendro_container') .selectAll('path') .style('opacity', triangle_opacity); } };