2016-09-30 59 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尋找類似的東西的人。