All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jungrapht.samples.large.ShowLayoutsWithDirectedGraphFileImport Maven / Gradle / Ivy

The newest version!
package org.jungrapht.samples.large;

import static java.util.Map.entry;
import static org.jungrapht.visualization.util.Attributed.*;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Paint;
import java.awt.Stroke;
import java.io.File;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import org.jgrapht.Graph;
import org.jgrapht.Graphs;
import org.jgrapht.alg.interfaces.VertexScoringAlgorithm;
import org.jgrapht.alg.scoring.BetweennessCentrality;
import org.jgrapht.alg.scoring.ClosenessCentrality;
import org.jgrapht.alg.scoring.ClusteringCoefficient;
import org.jgrapht.alg.scoring.HarmonicCentrality;
import org.jgrapht.alg.scoring.PageRank;
import org.jgrapht.graph.builder.GraphTypeBuilder;
import org.jungrapht.samples.spatial.RTreeVisualization;
import org.jungrapht.samples.util.*;
import org.jungrapht.visualization.MultiLayerTransformer;
import org.jungrapht.visualization.VisualizationViewer;
import org.jungrapht.visualization.control.DefaultGraphMouse;
import org.jungrapht.visualization.control.DefaultLensGraphMouse;
import org.jungrapht.visualization.decorators.EdgeShape;
import org.jungrapht.visualization.layout.algorithms.BalloonLayoutAlgorithm;
import org.jungrapht.visualization.layout.algorithms.LayoutAlgorithm;
import org.jungrapht.visualization.layout.algorithms.RadialTreeLayoutAlgorithm;
import org.jungrapht.visualization.transform.HyperbolicTransformer;
import org.jungrapht.visualization.transform.LayoutLensSupport;
import org.jungrapht.visualization.transform.Lens;
import org.jungrapht.visualization.transform.LensSupport;
import org.jungrapht.visualization.transform.MagnifyTransformer;
import org.jungrapht.visualization.transform.shape.HyperbolicShapeTransformer;
import org.jungrapht.visualization.transform.shape.MagnifyShapeTransformer;
import org.jungrapht.visualization.transform.shape.ViewLensSupport;
import org.jungrapht.visualization.util.LayoutAlgorithmTransition;
import org.jungrapht.visualization.util.LayoutPaintable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Demonstrates several of the graph layout algorithms. Allows the user to interactively select one
 * of several graphs, loaded from files using JGrapht io, and one of several layouts, and visualizes
 * the combination.
 *
 * 

This application has been tested with the graphml sample files in * https://github.com/melaniewalsh/sample-social-network-datasets * * @author Tom Nelson */ public class ShowLayoutsWithDirectedGraphFileImport extends JFrame { private static final Logger log = LoggerFactory.getLogger(ShowLayoutsWithDirectedGraphFileImport.class); LayoutPaintable.BalloonRings balloonLayoutRings; LayoutPaintable.RadialRings radialLayoutRings; LayoutPaintable.LayoutBounds layoutBounds; JFileChooser fileChooser; VisualizationViewer vv; Paint[] colorArray = new Paint[] { Color.red, Color.green, Color.blue, Color.cyan, Color.magenta, Color.yellow, Color.pink, Color.gray, Color.darkGray, Color.lightGray, Color.orange }; Function vertexFillPaintFunction = v -> Colors.getColor(v.getAttributeMap()); Function edgeDrawPaintFunction = e -> Color.black; Graph graph = GraphTypeBuilder.directed() .vertexSupplier(new ASSupplier()) .allowingSelfLoops(true) .allowingMultipleEdges(true) .edgeSupplier(new AISupplier()) .buildGraph(); public ShowLayoutsWithDirectedGraphFileImport() { JPanel container = new JPanel(new BorderLayout()); final DefaultGraphMouse graphMouse = new DefaultGraphMouse<>(); vv = VisualizationViewer.builder(graph) .layoutSize(new Dimension(1800, 1800)) .viewSize(new Dimension(900, 900)) .graphMouse(graphMouse) .build(); vv.setVertexToolTipFunction(v -> v.toHtml()); vv.setEdgeToolTipFunction(e -> e.toHtml()); vv.getRenderContext().setVertexLabelFunction(v -> v.getValue()); // vertex -> { // Map map = vertex.getAttributeMap(); // return map.getOrDefault("label", map.getOrDefault("ID", "NONE")); // }); Function vertexStrokeFunction = v -> vv.getSelectedVertexState().isSelected(v) ? new BasicStroke(8.f) : new BasicStroke(2.f); vv.getRenderContext().setVertexStrokeFunction(vertexStrokeFunction); vv.getRenderContext().setEdgeShapeFunction(EdgeShape.line()); vv.scaleToLayout(); container.add(vv.getComponent(), BorderLayout.CENTER); LayoutHelperDirectedGraphs.Layouts[] combos = LayoutHelperDirectedGraphs.getCombos(); final JToggleButton animateLayoutTransition = new JToggleButton("Animate Layout Transition"); final JComboBox layoutComboBox = new JComboBox(combos); layoutComboBox.addActionListener( e -> SwingUtilities.invokeLater( () -> { LayoutHelperDirectedGraphs.Layouts layoutType = (LayoutHelperDirectedGraphs.Layouts) layoutComboBox.getSelectedItem(); LayoutAlgorithm layoutAlgorithm = layoutType.getLayoutAlgorithm(); vv.removePreRenderPaintable(balloonLayoutRings); vv.removePreRenderPaintable(radialLayoutRings); if (animateLayoutTransition.isSelected()) { LayoutAlgorithmTransition.animate(vv, layoutAlgorithm); } else { LayoutAlgorithmTransition.apply(vv, layoutAlgorithm); } if (layoutAlgorithm instanceof BalloonLayoutAlgorithm) { balloonLayoutRings = new LayoutPaintable.BalloonRings( vv, (BalloonLayoutAlgorithm) layoutAlgorithm); vv.addPreRenderPaintable(balloonLayoutRings); } if (layoutAlgorithm instanceof RadialTreeLayoutAlgorithm) { radialLayoutRings = new LayoutPaintable.RadialRings( vv, (RadialTreeLayoutAlgorithm) layoutAlgorithm); vv.addPreRenderPaintable(radialLayoutRings); } if (layoutBounds != null) { vv.removePreRenderPaintable(layoutBounds); } vv.addPreRenderPaintable(new LayoutPaintable.LayoutBounds(vv)); })); layoutComboBox.setSelectedItem(LayoutHelperDirectedGraphs.Layouts.FR_BH_VISITOR); // create a lens to share between the two hyperbolic transformers Lens lens = new Lens(); /* provides a Hyperbolic lens for the view */ LensSupport hyperbolicViewSupport = ViewLensSupport.builder(vv) .lensTransformer( HyperbolicShapeTransformer.builder(lens) .delegate( vv.getRenderContext() .getMultiLayerTransformer() .getTransformer(MultiLayerTransformer.Layer.VIEW)) .build()) .lensGraphMouse( DefaultLensGraphMouse.builder() .magnificationFloor(0.4f) .magnificationCeiling(1.0f) .magnificationDelta(0.05f) .build()) .build(); LensSupport hyperbolicLayoutSupport = LayoutLensSupport.builder(vv) .lensTransformer( HyperbolicTransformer.builder(lens) .delegate( vv.getRenderContext() .getMultiLayerTransformer() .getTransformer(MultiLayerTransformer.Layer.LAYOUT)) .build()) .lensGraphMouse( DefaultLensGraphMouse.builder() .magnificationFloor(0.4f) .magnificationCeiling(1.0f) .magnificationDelta(0.05f) .build()) .build(); // the magnification lens uses a different magnification than the hyperbolic lens // create a new one to share between the two magnigy transformers lens = new Lens(); lens.setMagnification(3.f); LensSupport magnifyViewSupport = ViewLensSupport.builder(vv) .lensTransformer( MagnifyShapeTransformer.builder(lens) .delegate( vv.getRenderContext() .getMultiLayerTransformer() .getTransformer(MultiLayerTransformer.Layer.VIEW)) .build()) .lensGraphMouse( // override with range for magnificaion DefaultLensGraphMouse.builder() .magnificationFloor(1.0f) .magnificationCeiling(4.0f) .build()) .build(); LensSupport magnifyLayoutSupport = LayoutLensSupport.builder(vv) .lensTransformer( MagnifyTransformer.builder(lens) .delegate( vv.getRenderContext() .getMultiLayerTransformer() .getTransformer(MultiLayerTransformer.Layer.LAYOUT)) .build()) .lensGraphMouse( // override with range for magnificaion DefaultLensGraphMouse.builder() .magnificationFloor(1.0f) .magnificationCeiling(4.0f) .build()) .build(); hyperbolicLayoutSupport .getLensTransformer() .getLens() .setLensShape(hyperbolicViewSupport.getLensTransformer().getLens().getLensShape()); magnifyViewSupport .getLensTransformer() .getLens() .setLensShape(hyperbolicLayoutSupport.getLensTransformer().getLens().getLensShape()); magnifyLayoutSupport .getLensTransformer() .getLens() .setLensShape(magnifyViewSupport.getLensTransformer().getLens().getLensShape()); JComponent lensBox = LensControlHelper.builder( Map.of( "Hyperbolic View", hyperbolicViewSupport, "Hyperbolic Layout", hyperbolicLayoutSupport, "Magnified View", magnifyViewSupport, "Magnified Layout", magnifyLayoutSupport)) .containerSupplier(JPanel::new) .containerLayoutManager(new GridLayout(0, 2)) .title("Lens Controls") .build() .container(); JPanel loadFilePanel = new JPanel(); JButton loadFileButton = new JButton("Load File"); loadFilePanel.add(loadFileButton); loadFileButton.addActionListener( e -> { if (fileChooser == null) { fileChooser = new JFileChooser(); } int option = fileChooser.showOpenDialog(vv.getComponent()); if (option == JFileChooser.APPROVE_OPTION) { File file = fileChooser.getSelectedFile(); boolean loaded = ASAILoader.load(file, graph); if (!loaded) { JOptionPane.showMessageDialog(vv.getComponent(), "Unable to open " + file.getName()); return; } vv.getRenderContext().setVertexFillPaintFunction(vertexFillPaintFunction); vv.getRenderContext().setEdgeDrawPaintFunction(edgeDrawPaintFunction); vv.getRenderContext().setArrowFillPaintFunction(edgeDrawPaintFunction); vv.getRenderContext().setArrowDrawPaintFunction(edgeDrawPaintFunction); List sorted = graph .vertexSet() .stream() .sorted(Comparator.comparingInt(v -> graph.degreeOf(v))) .collect(Collectors.toList()); sorted.forEach(v -> log.info("V: {} degree: {}", v, graph.degreeOf(v))); vv.getVisualizationModel().setGraph(graph); setTitle( "Graph of " + file.getName() + " with " + graph.vertexSet().size() + " vertices and " + graph.edgeSet().size() + " edges"); } }); JButton pageRankButton = new JButton("Page Rank"); pageRankButton.addActionListener(event -> computeScores(new PageRank(graph))); JButton betweennessButton = new JButton("Betweenness"); betweennessButton.addActionListener(event -> computeScores(new BetweennessCentrality<>(graph))); JButton closenessButton = new JButton("Closeness"); closenessButton.addActionListener(event -> computeScores(new ClosenessCentrality<>(graph))); JButton clusteringButton = new JButton("Clustering"); clusteringButton.addActionListener(event -> computeScores(new ClusteringCoefficient<>(graph))); JButton harmonicButton = new JButton("Harmonic"); harmonicButton.addActionListener(event -> computeScores(new HarmonicCentrality<>(graph))); JButton noScores = new JButton("None"); JPanel scoringGrid = new JPanel(new GridLayout(0, 2)); scoringGrid.add(pageRankButton); scoringGrid.add(betweennessButton); scoringGrid.add(closenessButton); scoringGrid.add(clusteringButton); scoringGrid.add(harmonicButton); scoringGrid.add(noScores); JPanel controlPanel = new JPanel(new GridLayout(2, 1)); JComponent top = ControlHelpers.getContainer( Box.createHorizontalBox(), ControlHelpers.getCenteredContainer("Graph Source", loadFilePanel), ControlHelpers.getCenteredContainer("Layouts", layoutComboBox), ControlHelpers.getCenteredContainer("Scoring", scoringGrid)); controlPanel.add(top); JButton showRTree = new JButton("Show RTree"); showRTree.addActionListener(e -> RTreeVisualization.showRTree(vv)); JComponent bottom = ControlHelpers.getContainer( Box.createHorizontalBox(), // ControlHelpers.getZoomControls("Scale", vv), lensBox, ControlHelpers.getCenteredContainer( "Effects", Box.createVerticalBox(), showRTree, animateLayoutTransition)); controlPanel.add(bottom); container.add(controlPanel, BorderLayout.NORTH); setTitle( "Graph With " + graph.vertexSet().size() + " vertices and " + graph.edgeSet().size() + " edges"); getContentPane().add(container); setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); pack(); setVisible(true); } private void computeScores(VertexScoringAlgorithm scoring) { Map scores = scoring.getScores(); if (scores.isEmpty()) return; double min = scores.values().stream().min(Double::compare).get(); double max = scores.values().stream().max(Double::compare).get(); double range = max - min; log.info("min:{}, max:{}, range:{}", min, max, range); double delta = range / colorArray.length; log.info("delta:{}", delta); vv.repaint(); } void clear(Graph graph) { Set edges = new HashSet(graph.edgeSet()); Set vertices = new HashSet(graph.vertexSet()); edges.forEach(graph::removeEdge); vertices.forEach(graph::removeVertex); } /** * these are vertex or edge types that have defined colors (the keys are the property values for * the vertex/edge keys: VertexType and EdgeType) */ public static Map VERTEX_TYPE_TO_COLOR_MAP = Map.ofEntries( entry("Body", Color.blue), entry("Entry", Colors.WEB_COLOR_MAP.get("DarkOrange")), entry("Exit", Color.magenta), entry("Switch", Color.cyan), entry("Bad", Color.red), entry("Entry-Nexus", Color.white), entry("External", Color.green), entry("Folder", Colors.WEB_COLOR_MAP.get("DarkOrange")), entry("Fragment", Colors.WEB_COLOR_MAP.get("Purple")), entry("Data", Color.pink)); /** * these are vertex or edge types that have defined colors (the keys are the property values for * the vertex/edge keys: VertexType and EdgeType) */ public static Map EDGE_TYPE_TO_COLOR_MAP = Map.ofEntries( entry("Entry", Color.gray), // white?? entry("Fall-Through", Color.blue), entry("Conditional-Call", Colors.WEB_COLOR_MAP.get("DarkOrange")), entry("Unconditional-Call", Colors.WEB_COLOR_MAP.get("DarkOrange")), entry("Computed", Color.cyan), entry("Indirection", Color.pink), entry("Unconditional-Jump", Color.green), entry("Conditional-Jump", Color.yellow.darker()), entry("Terminator", Colors.WEB_COLOR_MAP.get("Purple")), entry("Conditional-Return", Colors.WEB_COLOR_MAP.get("Purple"))); public static Paint getColor(Map map) { // Map map = attributed.getAttributeMap(); // if there is a 'VertexType' attribute key, use its value to choose a predefined color if (map.containsKey("VertexType")) { String typeValue = map.get("VertexType"); return VERTEX_TYPE_TO_COLOR_MAP.getOrDefault(typeValue, Color.blue); } // if there is an 'EdgeType' attribute key, use its value to choose a predefined color if (map.containsKey("EdgeType")) { String typeValue = map.get("EdgeType"); return EDGE_TYPE_TO_COLOR_MAP.getOrDefault(typeValue, Color.green); } // if there is a 'Color' attribute key, use its value (either a color name or an RGB hex string) // to choose a color if (map.containsKey("Color")) { String colorName = map.get("Color"); if (Colors.WEB_COLOR_MAP.containsKey(colorName)) { return Colors.WEB_COLOR_MAP.get(colorName); } // if the value matches an RGB hex string, turn that into a color Color c = Colors.getHexColor(colorName); if (c != null) { return c; } } // default value when nothing else matches return Color.green; } private Collection getRoots(Graph graph) { Set roots = new HashSet<>(); for (Object v : graph.vertexSet()) { if (Graphs.predecessorListOf(graph, v).isEmpty()) { roots.add(v); } } return roots; } public static void main(String[] args) { new ShowLayoutsWithDirectedGraphFileImport(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy