2016-09-30 58 views
1

我正在创建一个mpld3插件,用于将NetworkX图转换为Force Layout。我在理解mpld3上轴上的缩放如何工作以及如何将其转换为力布局图时遇到了一些麻烦。NetworkX D3 Force Layout Plugin for mpld3

import matplotlib 
import matplotlib.pyplot as plt 
import numpy as np 
import mpld3 
from mpld3 import plugins, utils 

from networkx.readwrite.json_graph import node_link_data 

class NetworkXD3ForceLayoutView(plugins.PluginBase): 
    """A simple plugin showing how multiple axes can be linked""" 

    JAVASCRIPT = """ 
    mpld3.register_plugin("networkxd3forcelayoutview", NetworkXD3ForceLayoutViewPlugin); 
    NetworkXD3ForceLayoutViewPlugin.prototype = Object.create(mpld3.Plugin.prototype); 
    NetworkXD3ForceLayoutViewPlugin.prototype.constructor = NetworkXD3ForceLayoutViewPlugin; 
    NetworkXD3ForceLayoutViewPlugin.prototype.requiredProps = ["graph", "charge", "linkDistance", "gravity"]; 

    function NetworkXD3ForceLayoutViewPlugin(fig, props){ 
     mpld3.Plugin.call(this, fig, props); 
    }; 

    var color = d3.scale.category20(); 


    NetworkXD3ForceLayoutViewPlugin.prototype.draw = function(){ 

     var zoom = d3.behavior.zoom(); 

     var height = this.fig.height 
     var width = this.fig.width 

     var graph = this.props.graph  
     var gravity = this.props.gravity.toFixed() 
     var charge = this.props.charge.toFixed() 
     var linkDistance = this.props.linkDistance.toFixed() 

     console.log(graph) 
     var ax = this.fig.axes[0] // axis required for zoomx and zoomy presumably? 

     var g = d3.select('.mpld3-axes').append('g') // This is right? 

     var vis = g.append('svg') 
      .attr('width', this.width) 
      .attr('height', this.height); 

     force = d3.layout.force() 
     .gravity(gravity) 
     .charge(charge) 
     .linkDistance(linkDistance) 
     .nodes(graph.nodes) 
     .links(graph.links) 
     .size([width, height]) 
     .start() 

     var link = vis.selectAll("line.link") 
      .data(graph.links) 
     .enter().append("svg:line") 
      .attr("class", "link") 
      .attr("stroke", "black") 
      .style("stroke-width", function(d) { return Math.sqrt(d.value); }) 
      .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; }); 

     var node = vis.selectAll("circle.node") 
      .data(graph.nodes) 
     .enter().append("svg:circle") 
      .attr("class", "node") 
      .attr("cx", function(d) { return d.x; }) 
      .attr("cy", function(d) { return d.y; }) 
      .attr("r", 5) 
      .style("fill", function(d) { return d.color; }) 
      .call(force.drag); 

     node.append("svg:title") 
      .text(function(d) { return d.name; }); 

     vis.style("opacity", 1e-6) 
     .transition() 
      .duration(1000) 
      .style("opacity", 1); 
     force.on("tick", function() { 
     link.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; }); 

     node.attr("cx", function(d) { return d.x; }) 
      .attr("cy", function(d) { return d.y; }); 
     }); 

     zoom.on("zoom", function() { 
      g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); 
     }) 

     g.call(zoom) 

    }; 
    """ 

    def __init__(self, G, gravity=0.5, link_distance=20, charge=-10): 
     self.dict_ = {"type": "networkxd3forcelayoutview", 
         "graph": node_link_data(G), 
         "gravity": gravity, 
         "charge": charge, 
         "linkDistance": link_distance} 


fig, ax = plt.subplots(1, 1) 

# scatter periods and amplitudes 

np.random.seed(0) 

import networkx as nx 
G=nx.Graph() 
G.add_node(1, color='red') 
G.add_edge(1,2) 

plugins.connect(fig, NetworkXD3ForceLayoutView(G)) 

mpld3.display() 

以上是我能够在笔记本上运行的最低工作示例。我为当前包含图形的组元素添加了缩放回调,因此如果鼠标位于节点上方,图形将缩放。当我在自定义工具栏上使用缩放功能时,如何使其工作。这是创建强制布局插件的正确方法吗?我也发布了here,但它可能是这个问题更好的地方。

+0

哦,很酷,我一直都想要这个!缩放对象非常复杂,我不记得它们是如何工作的。你可以在'ax'对象中找到它们,例如'ax.zoom','ax.zoom_x'和'ax.zoom_y'。我希望我能更好地记住他们所做的事情,但要找出我会从这里开始挖掘js代码:https://github.com/mpld3/mpld3/blob/73473c9ffd8ea36a1912244e664fdb7ce391fd8b/src/core/axes.js#L171 –

+0

谢谢回复!我已经开始深入代码,并且正在打墙。一旦我对发生的事情有了更好的了解,我会在这里发表评论。这将是很好,有mpld3 :) – kdheepak

+0

好吧我有一个版本工作! :)更多的纠结要解决,它应该是很好的去。你认为它应该在主回购中做什么?我认为如果我们在组织中创建了一个用户创建的插件回购将会很好。思考? – kdheepak

回答

0

我发布了一个工作示例here寻找类似的东西的人。