Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multilayer Network Visualization. #282

Open
wants to merge 16 commits into
base: master-forge
Choose a base branch
from
4 changes: 4 additions & 0 deletions modules/MultiVizPlugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## MultiVizPlugin

MultiViz: A Gephi Plugin for Scalable Visualization of Multi-Layer Networks
https://arxiv.org/abs/2209.03149
68 changes: 68 additions & 0 deletions modules/MultiVizPlugin/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>gephi-plugin-parent</artifactId>
<groupId>org.gephi</groupId>
<version>0.9.3</version>
</parent>

<groupId>amrita</groupId>
<artifactId>multiviz</artifactId>
<version>1.0.0</version>
<packaging>nbm</packaging>

<name>MultiVizPlugin</name>

<dependencies>
<!-- Insert dependencies here -->
<dependency>
<groupId>org.gephi</groupId>
<artifactId>layout-api</artifactId>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.gephi</groupId>
<artifactId>graph-api</artifactId>
</dependency>
<dependency>
<groupId>org.gephi</groupId>
<artifactId>layout-plugin</artifactId>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.gephi</groupId>
<artifactId>ui-utils</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.netbeans.utilities</groupId>
<artifactId>nbm-maven-plugin</artifactId>
<configuration>
<licenseName>MIT</licenseName>
<author>J</author>
<authorEmail>[email protected]</authorEmail>
<authorUrl></authorUrl>
<publicPackages>
<!-- Insert public packages -->
</publicPackages>
</configuration>
</plugin>
</plugins>
</build>

<!-- Snapshot Repositories (only needed if developing against a SNAPSHOT version) -->
<repositories>
<repository>
<id>oss-sonatype</id>
<name>oss-sonatype</name>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2010, Matt Groeninger
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

package algorithms.basic;

import java.util.HashMap;
import java.util.List;
import helpers.VizUtils;
import org.gephi.graph.api.Node;

/**
*
* @author J
*/
public class CircleLayout {

private HashMap<String, List<Node>> layers;
private String initialLayer;
private Node initialNode;
private int layerDistance;

public CircleLayout(int layerDistance, HashMap<String, List<Node>> layers, String initialLayer, Node initialNode, boolean sortLayers) {
this.initialLayer = initialLayer;
this.initialNode = initialNode;
if(sortLayers){
this.layers = VizUtils.sortedLayers(layers);
} else this.layers = layers;
this.layerDistance = layerDistance;
}

public void start() {
String previousLayer = initialLayer;
for (String currentLayer : layers.keySet()) {
float y = initialNode.y();
if (!previousLayer.equals(currentLayer)) {
y = VizUtils.getLayerPlacement(layers, previousLayer, layerDistance);
}
List<Node> nodes = layers.get(currentLayer);
if (nodes.size() == 1) {
nodes.get(0).setX(initialNode.x());
nodes.get(0).setY(y);
nodes.get(0).setZ(initialNode.z());
} else {
double circumference = 0;
for (Node node : nodes) {
circumference += (node.size() * 2) + node.getTextProperties().getWidth();
}
circumference = circumference * 1.2f;

double diameter = circumference / Math.PI;
double theta = (2 * Math.PI) / circumference;

double tempTheta = 0;
double nodeSize = 0;

for (Node node : nodes) {
if (!node.isFixed()) {
nodeSize = node.size() + node.getTextProperties().getWidth() / 2;
double arc = nodeSize * 1.2f * theta;
float dx = (float) (diameter * (Math.cos((tempTheta + arc) + (Math.PI / 2))));
float dy = (float) (diameter * (Math.sin((tempTheta + arc) + (Math.PI / 2))));
tempTheta += nodeSize * 2 * theta * 1.2f;
node.setX(initialNode.x() + dx);
node.setY(y + dy);
node.setZ(initialNode.z());
}
}
}
previousLayer = currentLayer;
}
}
}
103 changes: 103 additions & 0 deletions modules/MultiVizPlugin/src/main/java/algorithms/basic/GridLayout.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
Copyright 2008-2011 Gephi
Authors : Mathieu Bastian <[email protected]>
Website : http://www.gephi.org
This file is part of Gephi.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2011 Gephi Consortium. All rights reserved.
The contents of this file are subject to the terms of either the GNU
General Public License Version 3 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with the
License. You can obtain a copy of the License at
http://gephi.org/about/legal/license-notice/
or /cddl-1.0.txt and /gpl-3.0.txt. See the License for the
specific language governing permissions and limitations under the
License. When distributing the software, include this License Header
Notice in each file and include the License files at
/cddl-1.0.txt and /gpl-3.0.txt. If applicable, add the following below the
License Header, with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
If you wish your version of this file to be governed by only the CDDL
or only the GPL Version 3, indicate your decision by adding
"[Contributor] elects to include this software in this distribution
under the [CDDL or GPL Version 3] license." If you do not indicate a
single choice of license, a recipient has the option to distribute
your version of this file under either the CDDL, the GPL Version 3 or
to extend the choice of license to its licensees as provided above.
However, if you add GPL Version 3 code and therefore, elected the GPL
Version 3 license, then the option applies only if the new code is
made subject to such option by the copyright holder.
Contributor(s):
Portions Copyrighted 2011 Gephi Consortium.
*/
package algorithms.basic;

import java.util.HashMap;
import java.util.List;
import helpers.VizUtils;
import org.gephi.graph.api.Node;

/**
*
* @author J
*/
public class GridLayout {

private int layerDistance;
private HashMap<String, List<Node>> layers;
private String initialLayer;
private Node initialNode;
private boolean sortLayers;

public GridLayout(int layerDistance, HashMap<String, List<Node>> layers, String initialLayer, Node initialNode, boolean sortLayers) {
this.layerDistance = layerDistance;
this.initialLayer = initialLayer;
this.initialNode = initialNode;
this.sortLayers = sortLayers;
if(this.sortLayers) {
this.layers = VizUtils.sortedLayers(layers);
} else this.layers = layers;
}

public void start(){
String previousLayer = initialLayer;
for (String currentLayer : layers.keySet()) {
Node biggestNode = VizUtils.getBiggestNode(layers, currentLayer);
float y = initialNode.y();

if(!previousLayer.equals(currentLayer)){
y = VizUtils.getLayerPlacement(layers, previousLayer, layerDistance);
}

int rows = (int) Math.round(Math.sqrt(layers.get(currentLayer).size())) + 1;
int cols = (int) Math.round(Math.sqrt(layers.get(currentLayer).size())) + 1;
double layerSize = VizUtils.getLayerSize(layers, biggestNode, currentLayer) * 1.2f;

for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols && (i * rows + j) < layers.get(currentLayer).size(); j++) {

Node node = layers.get(currentLayer).get(i * rows + j);

double nx = (-layerSize / 2f) + ((float) j / cols) * layerSize;
double ny = (layerSize / 2f) - ((float) i / rows) * layerSize;

double tx = nx;
double ty = (y + (y + (ny - y)));

if (i == 0 && j == 0) {
tx = ((initialNode.x() + (nx - initialNode.x())) + (0));
} else {
tx = ((initialNode.x() + (nx - initialNode.x())) + (10 * j));
}
node.setX((float) tx);
node.setY((float) ty);
node.setZ(initialNode.z());
}
}
previousLayer = currentLayer;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

package algorithms.basic;

import java.util.HashMap;
import java.util.List;
import helpers.VizUtils;
import org.gephi.graph.api.Node;

/**
*
* @author J
*/
public class LinearLayout {

private HashMap<String, List<Node>> layers;
private String initialLayer;
private Node initialNode;
private boolean sortLayers;
private int layerDistance;

public LinearLayout(int layerDistance, HashMap<String, List<Node>> layers, String initialLayer, Node initialNode, boolean sortLayers) {
this.initialLayer = initialLayer ;
this.initialNode = initialNode ;
this.sortLayers = sortLayers;
this.layers = layers ;
if(this.sortLayers){
this.layers = VizUtils.sortedLayers(layers);
}
}

public void start() {
String previousLayer = initialLayer;
for (String currentLayer : layers.keySet()) {
Node biggestNode = VizUtils.getBiggestNode(layers, currentLayer);

float y = initialNode.y();

if(!previousLayer.equals(currentLayer)){
y = VizUtils.getLayerPlacement(layers, previousLayer, layerDistance);
}

double distance = 0;
int index = 0;
for (Node node : layers.get(currentLayer)) {
if(index == 0) {
node.setX(initialNode.x());
node.setY(y);
} else {
distance += (node.size() * 2) + (node.getTextProperties().getWidth() + 20);
double randomY = Math.random() * ((biggestNode.size() + biggestNode.getTextProperties().getSize()) - 1 + 1) + 1;

node.setX(initialNode.x() + (float)distance);
node.setY(y + (float)randomY);
}
node.setZ(initialNode.z());
index++;
}
previousLayer = currentLayer;
}
}
}
Loading