<commit_before>/* Reusable d3 force-directed layout for gene networks
 * Follows the design pattern suggested by <NAME>:
 * http://bost.ocks.org/mike/chart/
 */

(function() {

d3.network = function() {
        
    var options = 
        {start_color:"#006E2E", 
        mid_color:"#FFFF88",
        end_color:"#FF0000"};

    var force,
        edges = [],
        genes = [], 
        gene_map = {},
        draw_genes = [],
        draw_edges = [], 
        height, 
        width,
        selection,
        legend = false,
        edge_events = {},
        gene_events = {},
        bind_networks = [],
        legend_text = 'Relationship confidence',
        min_edge = 0,
        max_edge = 1,
        legendStart = min_edge,
        legendEnd = max_edge,
        event = d3.dispatch("edgeadd", "edgeremove", 
                "geneadd", "generemove", "genechange");

    // Functions for network attributes 
    var r = function(d) {return d.query ? 20 : Math.max(10,5+ d.query_degree ? d.query_degree*10 : 10);};
    var w = function(d) {return Math.max(2,d.weight*6);};
    var edgeColor = d3.scale.linear().domain([options.start_edge,.15,1])
        .range([options.start_color, options.mid_color, options.end_color]);
    var geneText = function(d) { return d.standard_name; };

    function my(_selection) {
        selection = _selection;

        if ( !width ) width = selection.attr("width");
        if ( !height) height = selection.attr("height");

        var i, 
            n = genes.length, m = edges.length, 
            gene, edge;

        // Bind nodes to edges
        for (i = 0; i < m; ++i) {
          edge = edges[i];
          if (typeof edge.source == "number") edge.source = genes[edge.source];
          if (typeof edge.target == "number") edge.target = genes[edge.target];
        }

        // Calculate node degrees to query genes and all genes
        for( i = 0; i < n; i++ ) {
            gene = genes[i];
            gene.query_degree = 0;
            gene.query_degreen = 0;
            gene.degree = 0;
            gene.degreen = 0;
        }
        for( i = 0; i < m; i++ ) {
            edge = edges[i];
            if ( edge.source.query ) {
                edge.target.query_degree += edge.weight;
                edge.target.query_degreen ++;
            }
            if ( edge.target.query ) { 
                edge.source.query_degree += edge.weight;
                edge.source.query_degreen ++;
            }
            edge.target.degree += edge.weight;
            edge.source.degree += edge.weight;
            edge.target.degreen ++;
            edge.source.degreen ++;
        }
        for( i = 0; i < n; i++ ) {
            genes[i].query_degree /= genes[i].query_degreen;
            genes[i].degree /= genes[i].degreen;
        }

        // Sort nodes according to background corrected degree
        // Store corresponding ranks
        genes.sort(function(a,b){return b.query_degree/b.degree
                                        -a.query_degree/a.degree;})
        for( i = 0; i < n; i++ ) { genes[i].rank = i; }
    }

    function draw(genes, edges) {
        if ( typeof force != "undefined" ) force.stop();

        force = d3.layout.force()
            .charge(-800)
            .distance(150)
            .gravity(.15)
            .nodes(genes)
            .links(edges)
            .size([width, height]).start();

        var node_data = selection.selectAll("g.gene-group")
                .data(genes, function(d) { return d.id; });
        var link_data = selection.selectAll("line.edge")
                .data(edges, function(d) { return d.id; });

        var link_rm = link_data.exit().remove();
        var link = link_data
                .enter().insert("svg:line", "g")
                .attr("class", "edge")
                .on("mouseover", linkMouseover)
                .on("mouseout", linkMouseout)
                .attr("id", function(d) { return d.id; })
                .style("stroke", function(d) {return edgeColor(d.weight);}) 
                .style("stroke-width", w); 
        for( var type in edge_events ) link.on(type, edge_events[type]);
        event.edgeadd(link.filter(function(d){return d;}));
        event.edgeremove(link_rm.filter(function(d){return d;}));

        var node_rm = node_data.exit().remove();
        var node = node_data
                .enter().append("svg:g")
                .attr("class", "gene-group")
                .on("mouseover", nodeMouseover)
                .on("mouseout", nodeMouseout)
                .on("click", nodeMouseclick)
                .on("mousedown", nodeMousedown)
                .attr("id", function(d) { return d.id; })
        for( var type in gene_events ) node.on(type, gene_events[type]);
        event.geneadd(node.filter(function(d){return d;}));
        event.generemove(node_rm.filter(function(d){return d;}));
        event.genechange(node.filter(function(d){return d;}), node_rm.filter(function(d){return d;}));

        node.append("svg:circle")
            .attr("class", "gene")
            .classed("gene-query", function(d) { return d.query; }) 
            .attr("r", r); 

        node.append("svg:text")
            .style("pointer-events","none")
            .attr("class", "gene-name")
            .attr("text-anchor", "middle")
            .attr("y", function(d) { return "-"+ (r(d)+5);})
            .text(geneText)

        node_data.call(force.drag);

        force.on("tick", function(event) {
            node_data.attr('cx', function(d) { 
                return d.x = Math.max(r(d),Math.min(width-r(d),d.x)); });
            node_data.attr('cy', function(d) { 
                return d.y = Math.max(r(d),Math.min(height-r(d),d.y)); });
            node_data.attr("transform", function(d,i) { 
                if ( bind_networks[0] && bind_networks[0].gene(d.id) 
                        && !isNaN(bind_networks[0].gene(d.id).x)) {
                    var ref = bind_networks[0].gene(d.id);
                    d.x = ref.x;
                    d.px = ref.px;
                    d.y = ref.y;
                    d.py = ref.py;
                }
                var x = Math.max(r(d),Math.min(width-r(d),d.x));
                var y = Math.max(r(d),Math.min(height-r(d),d.y)); 
                return "translate(" + x + "," + y + ")"; 
            });
            link_data.attr("x1", function(d) { return d.source.x; })
                .attr("y1", function(d) { return d.source.y; })
                .attr("x2", function(d) { return d.target.x; })
                .attr("y2", function(d) { return d.target.y; });
        });
    }            

    my.draw = function() {
        draw(draw_genes, draw_edges); 
        drawn = !selection.select("svg.legend").empty();
        if ( legend && !drawn ) addLegend();
        else if ( !legend && drawn ) removeLegend();
    };

    my.showLegend = function(x) {
        if (!arguments.length) x = true;
        legend = x;
        return my;
    };

    my.filter = function(edge_cut, node_cut) {
        var gene_filter = function(d) {
            return d.query || d.rank < node_cut; 
        };

        var edge_filter = function(d) {
            return d.weight > edge_cut && gene_filter(d.target)
                    && gene_filter(d.source);
        };
        
        draw_genes = genes.filter(gene_filter);
        draw_edges = edges.filter(edge_filter);

        // Remove hanging nodes: calculate node degrees to the filtered edges
        var n = genes.length, 
            m = draw_edges.length, 
            edge, i;
        for( i = 0; i < n; i++ ) {
            genes[i].draw_degree = 0; 
        }
        for( i = 0; i < m; i++ ) {
            edge = draw_edges[i];
            edge.source.draw_degree += edge.weight; 
            edge.target.draw_degree += edge.weight; 
        }
        draw_genes = draw_genes.filter(function(d) { 
            return d.draw_degree > 0 || d.query; })

        return my;<commit_msg>Update d3.network.js<commit_after>/* Reusable d3 force-directed layout for gene networks
 * Follows the design pattern suggested by <NAME>:
 * http://bost.ocks.org/mike/chart/
 */

(function() {

d3.network = function() {
        
    var options = 
        {start_color:"#006E2E", 
        mid_color:"#FFFF88",
        end_color:"#FF0000"};

    var force,
        edges = [],
        genes = [], 
        gene_map = {},
        draw_genes = [],
        draw_edges = [], 
        height, 
        width,
        selection,
        legend = false,
        edge_events = {},
        gene_events = {},
        bind_networks = [],
        legend_text = 'Relationship confidence',
        min_edge = 0,
        max_edge = 1,
        legendStart = min_edge,
        legendEnd = max_edge,
        event = d3.dispatch("edgeadd", "edgeremove", 
                "geneadd", "generemove", "genechange");

    // Functions for network attributes 
    var r = function(d) {return d.query ? 20 : Math.max(10,5+ d.query_degree ? d.query_degree*10 : 10);};
    var w = function(d) {return Math.max(2,d.weight*6);};
    var edgeColor = d3.scale.linear().domain([options.start_edge,.15,1])
        .range([options.start_color, options.mid_color, options.end_color]);
    var geneText = function(d) { return d.standard_name; };

    function my(_selection) {
        selection = _selection;

        if ( !width ) width = selection.attr("width");
        if ( !height) height = selection.attr("height");

        var i, 
            n = genes.length, m = edges.length, 
            gene, edge;

        // Bind nodes to edges
        for (i = 0; i < m; ++i) {
          edge = edges[i];
          if (typeof edge.source == "number") edge.source = genes[edge.source];
          if (typeof edge.target == "number") edge.target = genes[edge.target];
        }

        // Calculate node degrees to query genes and all genes
        for( i = 0; i < n; i++ ) {
            gene = genes[i];
            gene.query_degree = 0;
            gene.query_degreen = 0;
            gene.degree = 0;
            gene.degreen = 0;
        }
        for( i = 0; i < m; i++ ) {
            edge = edges[i];
            if ( edge.source.query ) {
                edge.target.query_degree += edge.weight;
                edge.target.query_degreen ++;
            }
            if ( edge.target.query ) { 
                edge.source.query_degree += edge.weight;
                edge.source.query_degreen ++;
            }
            edge.target.degree += edge.weight;
            edge.source.degree += edge.weight;
            edge.target.degreen ++;
            edge.source.degreen ++;
        }
        for( i = 0; i < n; i++ ) {
            genes[i].query_degree /= genes[i].query_degreen;
            genes[i].degree /= genes[i].degreen;
        }

        // Sort nodes according to background corrected degree
        // Store corresponding ranks
        genes.sort(function(a,b){return b.query_degree/b.degree
                                        -a.query_degree/a.degree;})
        for( i = 0; i < n; i++ ) { genes[i].rank = i; }
    }

    function draw(genes, edges) {
        if ( typeof force != "undefined" ) force.stop();

        force = d3.layout.force()
            .charge(-800)
            .distance(150)
            .gravity(.15)
            .nodes(genes)
            .links(edges)
            .size([width, height]).start();

        var node_data = selection.selectAll("g.gene-group")
                .data(genes, function(d) { return d.id; });
        var link_data = selection.selectAll("line.edge")
                .data(edges, function(d) { return d.id; });

        var link_rm = link_data.exit().remove();
        var link = link_data
                .enter().insert("svg:line", "g")
                .attr("class", "edge")
                .on("mouseover", linkMouseover)
                .on("mouseout", linkMouseout)
                .attr("id", function(d) { return d.id; })
                .style("stroke", function(d) {return edgeColor(d.weight);}) 
                .style("stroke-width", w); 
        for( var type in edge_events ) link.on(type, edge_events[type]);
        event.edgeadd(link.filter(function(d){return d;}));
        event.edgeremove(link_rm.filter(function(d){return d;}));

        var node_rm = node_data.exit().remove();
        var node = node_data
                .enter().append("svg:g")
                .attr("class", "gene-group")
                .on("mouseover", nodeMouseover)
                .on("mouseout", nodeMouseout)
                .on("click", nodeMouseclick)
                .on("mousedown", nodeMousedown)
                .attr("id", function(d) { return d.id; })
        for( var type in gene_events ) node.on(type, gene_events[type]);
        event.geneadd(node.filter(function(d){return d;}));
        event.generemove(node_rm.filter(function(d){return d;}));
        event.genechange(node.filter(function(d){return d;}), node_rm.filter(function(d){return d;}));

        node.append("svg:circle")
            .attr("class", "gene")
            .classed("gene-query", function(d) { return d.query; }) 
            .attr("r", r); 

        node.append("svg:text")
            .style("pointer-events","none")
            .attr("class", "gene-name")
            .attr("text-anchor", "middle")
            .attr("y", function(d) { return "-"+ (r(d)+5);})
            .text(geneText)

        node_data.call(force.drag);

        force.on("tick", function(event) {
            node_data.attr('cx', function(d) { 
                return d.x = Math.max(r(d),Math.min(width-r(d),d.x)); });
            node_data.attr('cy', function(d) { 
                return d.y = Math.max(r(d),Math.min(height-r(d),d.y)); });
            node_data.attr("transform", function(d,i) { 
                if ( bind_networks[0] && bind_networks[0].gene(d.id) 
                        && !isNaN(bind_networks[0].gene(d.id).x)) {
                    var ref = bind_networks[0].gene(d.id);
                    d.x = ref.x;
                    d.px = ref.px;
                    d.y = ref.y;
                    d.py = ref.py;
                }
                var x = Math.max(r(d),Math.min(width-r(d),d.x));
                var y = Math.max(r(d),Math.min(height-r(d),d.y)); 
                return "translate(" + x + "," + y + ")"; 
            });
            link_data.attr("x1", function(d) { return d.source.x; })
                .attr("y1", function(d) { return d.source.y; })
                .attr("x2", function(d) { return d.target.x; })
                .attr("y2", function(d) { return d.target.y; });
        });
    }            

    my.draw = function() {
        draw(draw_genes, draw_edges); 
        drawn = !selection.select("svg.legend").empty();
        if ( legend && !drawn ) addLegend();
        else if ( !legend && drawn ) removeLegend();
    };

    my.showLegend = function(x) {
        if (!arguments.length) x = true;
        legend = x;
        return my;
    };

    // Supports either: filter(min_edge_cut, node_cut)
    //              or: filter(min_edge_cut, max_edge_cut, node_cut)
    my.filter = function() {
        if (argument.length < 2 || argument > 3) {
            return;
        }

        var node_cut = argument[argument.length - 1];
        var min_edge_cut = argument[0];
        var max_edge_cut;
        if (argument.length === 2) {
          max_edge_weight = Number.MAX_VALUE;
        }
        else {  // argument.length === 3
          max_edge_weight = argument[1];
        }
            
        var gene_filter = function(d) {
            return d.query || d.rank < node_cut; 
        };

        var edge_filter = function(d) {
            return d.weight > min_edge_cut && d.weight < max_edge_cut
                && gene_filter(d.target) && gene_filter(d.source);
        };
        
        draw_genes = genes.filter(gene_filter);
        draw_edges = edges.filter(edge_filter);

        // Remove hanging nodes: calculate node degrees to the filtered edges
        var n = genes.length, 
            m = draw_edges.length, 
            edge, i;
        for( i = 0; i < n; i++ ) {
            genes[i].draw_degree = 0; 
        }
        for( i = 0; i < m; i++ ) {
            edge = draw_edges[i];
            edge.source.draw_degree += edge.weight; 
            edge.target.draw_degree += edge.weight; 
        }
        draw_genes = draw_genes.filter(function(d) { 
            return d.draw_degree > 0 || d.query; })

        return my;
{'fraction_non_alphanumeric': 0.15232431120281587, 'fraction_numerical': 0.007889306954727516, 'mean_word_length': 1.6485053037608486, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2792905', 'n_tokens_mistral': 5255, 'n_tokens_neox': 4937, 'n_words': 994}