一、Gephi
Gephi是一款开源免费跨平台基于JVM的复杂网络分析软件,其主要用于各种网络和复杂系统,是一种动态和分层图的交互可视化与探测开源工具。它是一款非常好用的网络关系绘制软件,应用范围十分广泛,凡是可以抽象成节点(node)和边(edge)的关系数据,大都可以用Gephi绘制。如社交网络、交通网络等。
本文主要介绍如何利用Gephi源码的jar包以及sigma.js插件实现Gephi的自动化并将生成的图结果嵌入到web中。
二、Toolkit
Toolkit是Gephi提供的标准jar包,可以在任何java项目中导入该jar包以达到脱离Gephi的UI界面,实现自动化。同时,支持将Gephi提供的nbm格式插件转换为jar包,导入其中使用。
Toolkit下载:https://gephi.org/toolkit/
ToolkitAPI文档:https://gephi.org/gephi-toolkit/0.9.2/apidocs/
Github:https://github.com/gephi/gephi/wiki/Toolkit
如果是maven项目,可以在pom.xml中导入toolkit依赖:
<dependency>
<groupId>org.gephi</groupId>
<artifactId>gephi-toolkit</artifactId>
<version>0.9.2</version>
</dependency>
三、Sigma.js
Sigma.js是Gephi的一款插件,可以将Gephi生成的图结果嵌入到Web中,同时实现简单的统计和分析。以下是一张通过Sigma.js将Java包生成的网络嵌入到web的图片:
首先在Gephi插件库中下载sigma.js插件:https://gephi.org/plugins/#/plugin/sigmaexporter
懒得下可以在网盘提取,链接: https://pan.baidu.com/s/1UTBMK_6bGDpX_urP39G5hg 密码: 6cw2
下载好之后是一个nbm格式的文件,可以在Gephi中导入该插件并使用,但那并不是我们需要的,我们需要将nbm转换为jar包,并在Toolkit中使用。
使用Gephi提供的UnpackNBM工具包可以将nbm文件转换为jar包:https://github.com/gephi/gephi/wiki/How-to-use-plug-ins-with-the-Toolkit
转化之后得到sigma.js的jar包:uk-ax-ox-oii-sigmaexporter.jar,将该jar包导入到java项目即可使用了!
四、应用
以下为使用Toolkit和Sigma.js实现的网络生成与Web嵌入例子,执行后将会得到一个network的文件夹,其中index.html就是我们要的结果。
//相应的包,如果报错的话,检查sigma的jar包是否成功导入
import org.gephi.appearance.api.AppearanceController;
import org.gephi.appearance.api.AppearanceModel;
import org.gephi.appearance.api.Function;
import org.gephi.appearance.plugin.RankingElementColorTransformer;
import org.gephi.appearance.plugin.RankingLabelSizeTransformer;
import org.gephi.appearance.plugin.RankingNodeSizeTransformer;
import org.gephi.filters.api.FilterController;
import org.gephi.filters.api.Query;
import org.gephi.filters.api.Range;
import org.gephi.filters.plugin.graph.DegreeRangeBuilder;
import org.gephi.graph.api.*;
import org.gephi.io.exporter.api.ExportController;
import org.gephi.io.importer.api.Container;
import org.gephi.io.importer.api.EdgeDirectionDefault;
import org.gephi.io.importer.api.EdgeMergeStrategy;
import org.gephi.io.importer.api.ImportController;
import org.gephi.io.processor.plugin.AppendProcessor;
import org.gephi.io.processor.plugin.DefaultProcessor;
import org.gephi.layout.plugin.force.StepDisplacement;
import org.gephi.layout.plugin.force.yifanHu.YifanHuLayout;
import org.gephi.preview.api.PreviewController;
import org.gephi.preview.api.PreviewModel;
import org.gephi.preview.api.PreviewProperty;
import org.gephi.preview.types.EdgeColor;
import org.gephi.project.api.ProjectController;
import org.gephi.project.api.Workspace;
import org.gephi.statistics.plugin.GraphDistance;
import org.junit.jupiter.api.Test;
import org.openide.util.Lookup;
import uk.ac.ox.oii.sigmaexporter.SigmaExporter;
import uk.ac.ox.oii.sigmaexporter.model.ConfigFile;
public static void main(String[] args){
//初始化工作台
ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
pc.newProject();
Workspace workspace = pc.getCurrentWorkspace();
//获取到各个模块以及控制器
//整个图的边和节点信息模块
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getGraphModel();
//预览模块
PreviewModel model = Lookup.getDefault().lookup(PreviewController.class).getModel();
//导入模块
ImportController importController = Lookup.getDefault().lookup(ImportController.class);
//过滤模块
FilterController filterController = Lookup.getDefault().lookup(FilterController.class);
//外观展示模块
AppearanceController appearanceController = Lookup.getDefault().lookup(AppearanceController.class);
AppearanceModel appearanceModel = appearanceController.getModel();
//导入图文件
Container container;
try {
File file = new File("Java.gexf");
container = importController.importFile(file);
container.getLoader().setEdgeDefault(EdgeDirectionDefault.DIRECTED); //Force DIRECTED
} catch (Exception ex) {
ex.printStackTrace();
return;
}
importController.process(container, new DefaultProcessor(), workspace);
//打印信息看图文件是否成功导入
DirectedGraph graph = graphModel.getDirectedGraph();
System.out.println("Nodes: " + graph.getNodeCount());
System.out.println("Edges: " + graph.getEdgeCount());
//过滤器
DegreeRangeBuilder.DegreeRangeFilter degreeFilter = new DegreeRangeBuilder.DegreeRangeFilter();
degreeFilter.init(graph);
//过滤度小于10的节点
degreeFilter.setRange(new Range(10, Integer.MAX_VALUE));
Query query = filterController.createQuery(degreeFilter);
GraphView view = filterController.filter(query);
graphModel.setVisibleView(view);
//查看过滤是否生效
UndirectedGraph graphVisible = graphModel.getUndirectedGraphVisible();
System.out.println("After filter:");
System.out.println("Nodes: " + graphVisible.getNodeCount());
System.out.println("Edges: " + graphVisible.getEdgeCount());
//使用YifanHu布局
YifanHuLayout layout = new YifanHuLayout(null, new StepDisplacement(1f));
layout.setGraphModel(graphModel);
layout.resetPropertiesValues();
layout.setOptimalDistance(200f);
layout.initAlgo();
for (int i = 0; i < 100 && layout.canAlgo(); i++) {
layout.goAlgo();
}
layout.endAlgo();
GraphDistance distance = new GraphDistance();
distance.setDirected(true);
distance.execute(graphModel);
//根据节点度值分配节点颜色
Function degreeRanking = appearanceModel.getNodeFunction(graph, AppearanceModel.GraphFunction.NODE_DEGREE, RankingElementColorTransformer.class);
RankingElementColorTransformer degreeTransformer = degreeRanking.getTransformer();
//节点的度由少到多,颜色由color1渐变到color2
degreeTransformer.setColors(new Color[]{new Color(249,210,125), new Color(43,115,174)});
degreeTransformer.setColorPositions(new float[]{0f, 0.1f});
appearanceController.transform(degreeRanking);
//分配节点大小
Column centralityColumn = graphModel.getNodeTable().getColumn(GraphDistance.BETWEENNESS);
Function centralityRanking = appearanceModel.getNodeFunction(graph, centralityColumn, RankingNodeSizeTransformer.class);
RankingNodeSizeTransformer centralityTransformer = centralityRanking.getTransformer();
centralityTransformer.setMinSize(3);
centralityTransformer.setMaxSize(10);
appearanceController.transform(centralityRanking);
//标签大小
Function centralityRanking2 = appearanceModel.getNodeFunction(graph, centralityColumn, RankingLabelSizeTransformer.class);
RankingLabelSizeTransformer labelSizeTransformer = centralityRanking2.getTransformer();
labelSizeTransformer.setMinSize(1);
labelSizeTransformer.setMaxSize(3);
appearanceController.transform(centralityRanking2);
//预览设置
model.getProperties().putValue(PreviewProperty.SHOW_NODE_LABELS, Boolean.TRUE);
model.getProperties().putValue(PreviewProperty.EDGE_COLOR, new EdgeColor(Color.GRAY));
model.getProperties().putValue(PreviewProperty.EDGE_THICKNESS, 0.1f);
model.getProperties().putValue(PreviewProperty.NODE_LABEL_FONT, model.getProperties().getFontValue(PreviewProperty.NODE_LABEL_FONT).deriveFont(8));
//导出pdf
ExportController ec = Lookup.getDefault().lookup(ExportController.class);
try {
ec.exportFile(new File("demo.pdf"));
} catch (IOException ex) {
ex.printStackTrace();
}
//导出web
SigmaExporter se = new SigmaExporter();
se.setWorkspace(workspace);
ConfigFile cf = new ConfigFile();
cf.setDefaults();
se.setConfigFile(cf,"visualOutWeb/",false);
se.execute();
}
}