diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java b/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java index d7dd81cf1a0d9cf468d62ef61dce5d5dfecb999c..e663ccde4c3872b6b3cb56f820b16c05a56a03ae 100644 --- a/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java @@ -12,9 +12,11 @@ import org.cytoscape.model.events.ColumnCreatedListener; import org.cytoscape.model.events.ColumnDeletedListener; import org.cytoscape.model.events.NetworkAddedListener; import org.cytoscape.model.events.RemovedEdgesListener; +import org.cytoscape.model.subnetwork.CyRootNetworkManager; import org.cytoscape.service.util.AbstractCyActivator; import org.cytoscape.service.util.CyServiceRegistrar; import org.cytoscape.session.events.SessionLoadedListener; +import org.cytoscape.task.visualize.ApplyVisualStyleTaskFactory; import org.cytoscape.view.model.CyNetworkViewFactory; import org.cytoscape.view.layout.CyLayoutAlgorithmManager; import org.cytoscape.view.model.CyNetworkViewManager; @@ -59,6 +61,9 @@ public class CyActivator extends AbstractCyActivator { CyCore.visualMappingManager = getService(context,VisualMappingManager.class); CyCore.visualStyleFactory = getService(context,VisualStyleFactory.class); CyCore.continuousMappingFactory = getService(context,VisualMappingFunctionFactory.class, "(mapping.type=continuous)"); + CyCore.rootNetworkManager = getService(context,CyRootNetworkManager.class); + CyCore.applyVisualStyleTaskFactory = getService(context,ApplyVisualStyleTaskFactory.class); + //Set language according to settings LocalizationManager.switchLanguage(cm.getProperties().getProperty("locale", "enUS")); diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/core/AlgorithmTask.java b/src/main/java/de/hhu/ba/yoshikoWrapper/core/AlgorithmTask.java index d6ca606e47540c2998139fea4a2f5b3ed24eb47c..a07a2e9a6441444a9ed4883a647570a05d6cae66 100644 --- a/src/main/java/de/hhu/ba/yoshikoWrapper/core/AlgorithmTask.java +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/core/AlgorithmTask.java @@ -149,7 +149,9 @@ public class AlgorithmTask extends AbstractTask { //Loop over cluster for (long k=0;k<numberOfClusters;k++) { //Create java instance - YoshikoCluster cluster = new YoshikoCluster(k); + YoshikoCluster cluster = new YoshikoCluster(k,net); + + taskMonitor.setStatusMessage("Processing cluster "+(k+1)+" of "+numberOfClusters); SWIGTYPE_p_std__vectorT_int_t clusterVector = LibraryInterface.ClusterEditingSolutions_getCluster(result, i, k); diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/core/CyCore.java b/src/main/java/de/hhu/ba/yoshikoWrapper/core/CyCore.java index 984f59c0a92cb3e4fa13540059534aab6a4ffcbf..ef06d00fedfde22a2d6ea1428615d01c94e1d62b 100644 --- a/src/main/java/de/hhu/ba/yoshikoWrapper/core/CyCore.java +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/core/CyCore.java @@ -4,7 +4,9 @@ import org.cytoscape.application.CyApplicationManager; import org.cytoscape.application.swing.CySwingApplication; import org.cytoscape.model.CyNetworkFactory; import org.cytoscape.model.CyNetworkManager; +import org.cytoscape.model.subnetwork.CyRootNetworkManager; import org.cytoscape.service.util.CyServiceRegistrar; +import org.cytoscape.task.visualize.ApplyVisualStyleTaskFactory; import org.cytoscape.view.layout.CyLayoutAlgorithmManager; import org.cytoscape.view.model.CyNetworkViewFactory; import org.cytoscape.view.model.CyNetworkViewManager; @@ -34,6 +36,8 @@ public class CyCore { public static VisualMappingManager visualMappingManager; public static VisualStyleFactory visualStyleFactory; public static VisualMappingFunctionFactory continuousMappingFactory; + public static CyRootNetworkManager rootNetworkManager; + public static ApplyVisualStyleTaskFactory applyVisualStyleTaskFactory; // } diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoCluster.java b/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoCluster.java index 50d4a292d191e5377d08d6077803d86e233c8d4c..86021ef1f56e30484283ef8524c516e4764002fd 100644 --- a/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoCluster.java +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoCluster.java @@ -2,14 +2,22 @@ package de.hhu.ba.yoshikoWrapper.graphModel; import java.util.ArrayList; +import org.cytoscape.model.CyNetwork; import org.cytoscape.model.CyNode; + public class YoshikoCluster { - public long id; + + + public final long id; + public final CyNetwork originalGraph; + public ArrayList<CyNode> nodes; - public YoshikoCluster(long id) { + public YoshikoCluster(long id, CyNetwork originalGraph) { this.id = id; - this.nodes = new ArrayList<CyNode>(); + this.originalGraph = originalGraph; + this.nodes = new ArrayList<CyNode>(); } + } diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoSolution.java b/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoSolution.java index 083b120040ff093a9f9504a691498932d03e7c07..34394474241d8e3124cc54ffa7216c9b7dba65da 100644 --- a/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoSolution.java +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoSolution.java @@ -2,17 +2,25 @@ package de.hhu.ba.yoshikoWrapper.graphModel; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import org.cytoscape.model.CyEdge; import org.cytoscape.model.CyNetwork; import org.cytoscape.model.CyNode; - +import org.cytoscape.model.subnetwork.CyRootNetwork; +import org.cytoscape.model.subnetwork.CySubNetwork; +import org.cytoscape.view.layout.CyLayoutAlgorithm; +import org.cytoscape.view.model.CyNetworkView; +import org.cytoscape.view.presentation.property.BasicVisualLexicon; +import org.cytoscape.view.vizmap.VisualStyle; +import org.cytoscape.view.vizmap.mappings.ContinuousMapping; import de.hhu.ba.yoshikoWrapper.core.CyCore; import de.hhu.ba.yoshikoWrapper.core.LocalizationManager; public class YoshikoSolution { private CyNetwork originalGraph; + public ArrayList<YoshikoCluster> cluster; public int id; @@ -23,9 +31,9 @@ public class YoshikoSolution { /** * Transforms this solution in a meta-graph where each cluster is represented by one node - * @return The meta-graph as CyNetwork + * The nodes are linked to subgraphs representing the cluster and also their size is scaled relative to cluster size */ - public CyNetwork toMetaGraph() { + public void exportMetaGraph() { CyNetwork metaGraph = CyCore.networkFactory.createNetwork(); @@ -33,12 +41,48 @@ public class YoshikoSolution { metaGraph.getDefaultNodeTable().createColumn("clusterSize", Integer.class, false); + CyLayoutAlgorithm layout = CyCore.layoutAlgorithmManager.getDefaultLayout(); + + //Map Cluster to Nodes for further reference HashMap<YoshikoCluster,CyNode> map = new HashMap<YoshikoCluster,CyNode>(); + //Convert original graph to root graph to allow embedding of nodes + CyRootNetwork originalGraphAsRoot = CyCore.rootNetworkManager.getRootNetwork(originalGraph); + //Add nodes for (YoshikoCluster c: cluster) { CyNode clusterNode = metaGraph.addNode(); + //Create nested graph and cluster subnet + ArrayList<CyEdge> inducedEdges = new ArrayList<CyEdge>(); + for (CyNode n: c.nodes) { + //Sadly Cytoscape doesnt provide a comfort function here + List<CyEdge> adjacentEdges = originalGraph.getAdjacentEdgeList(n, CyEdge.Type.ANY); + for (CyEdge e: adjacentEdges) { + if (c.nodes.contains(e.getSource()) && c.nodes.contains(e.getTarget())) { + inducedEdges.add(e); + } + } + } + CySubNetwork subnet = originalGraphAsRoot.addSubNetwork(c.nodes ,inducedEdges); + + subnet.getRow(subnet).set(CyNetwork.NAME, LocalizationManager.get("cluster")+" "+(c.id+1)); + + CyCore.networkManager.addNetwork(subnet); + //Create network view and register it + CyNetworkView subnetView = CyCore.networkViewFactory.createNetworkView(subnet); + CyCore.networkViewManager.addNetworkView(subnetView); + //layout cluster + CyCore.dialogTaskManager.execute( + layout.createTaskIterator( + subnetView, + layout.getDefaultLayoutContext(), + CyLayoutAlgorithm.ALL_NODE_VIEWS, + null + ) + ); + clusterNode.setNetworkPointer(subnet); + //Set node attributes metaGraph.getRow(clusterNode).set("name", LocalizationManager.get("cluster")+" "+c.id); metaGraph.getRow(clusterNode).set("clusterSize",c.nodes.size()); map.put(c, clusterNode); @@ -64,7 +108,38 @@ public class YoshikoSolution { } } } - return metaGraph; + + CyNetworkView view = CyCore.networkViewFactory.createNetworkView(metaGraph); + //layout solution + CyCore.dialogTaskManager.execute( + layout.createTaskIterator( + view, + layout.getDefaultLayoutContext(), + CyLayoutAlgorithm.ALL_NODE_VIEWS, + null + ) + ); + + CyCore.networkManager.addNetwork(metaGraph); + CyCore.networkViewManager.addNetworkView( + view + ); + + //define style for solution + ContinuousMapping<Integer, Double> contMap = (ContinuousMapping<Integer, Double>)CyCore.continuousMappingFactory.createVisualMappingFunction( + "clusterSize", + Integer.class, + BasicVisualLexicon.NODE_SIZE + ); + VisualStyle vs= CyCore.visualStyleFactory.createVisualStyle("Meta-Graph Style"); + vs.addVisualMappingFunction(contMap); + CyCore.visualMappingManager.addVisualStyle(vs); + CyCore.cy.setCurrentNetworkView(view); + //Apply visual style + CyCore.visualMappingManager.setVisualStyle(vs, view); + vs.apply(view); + view.updateView(); + } } diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/gui/ClusterView.java b/src/main/java/de/hhu/ba/yoshikoWrapper/gui/ClusterView.java index 629289c4a142ba35f6e267ebad8d9a7a5303a122..3dbb10f31c4bafa52f416f3bd7b1fa60db97a7c3 100644 --- a/src/main/java/de/hhu/ba/yoshikoWrapper/gui/ClusterView.java +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/gui/ClusterView.java @@ -11,12 +11,9 @@ import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.border.Border; -import org.cytoscape.model.CyNetwork; import org.cytoscape.model.CyNode; import org.cytoscape.model.CyRow; -import org.cytoscape.view.model.CyNetworkView; -import de.hhu.ba.yoshikoWrapper.core.CyCore; import de.hhu.ba.yoshikoWrapper.core.LocalizationManager; import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoCluster; @@ -26,10 +23,6 @@ public class ClusterView extends ComfortPanel { private final JLabel title; private final JLabel clusterSize; - private final CyNetworkView clusterView; - - private CyNetwork clusterSubNet; - private final Border regularBorder = BorderFactory.createLineBorder(Color.GRAY); private final Border highlightBorder = BorderFactory.createLineBorder(Color.RED); @@ -42,16 +35,14 @@ public class ClusterView extends ComfortPanel { public ClusterView(YoshikoCluster c) { - this.cluster = c; + this.cluster = c; + //Swing init this.setLayout(new BoxLayout(this,BoxLayout.Y_AXIS)); title = new JLabel(LocalizationManager.get("cluster")+" "+(c.id+1)); clusterSize = new JLabel(LocalizationManager.get("clusterSize")+" "+c.nodes.size()); - - this.clusterSubNet = CyCore.networkFactory.createNetwork(); - this.clusterView = CyCore.networkViewFactory.createNetworkView(this.clusterSubNet); - + this.addAll(title,clusterSize); this.add(Box.createVerticalStrut(4)); @@ -59,7 +50,7 @@ public class ClusterView extends ComfortPanel { for (CyNode n : c.nodes) { this.add( new JLabel( - CyCore.cy.getCurrentNetwork().getRow(n).get("name", String.class) + c.originalGraph.getRow(n).get("name", String.class) ) ); } @@ -79,13 +70,13 @@ public class ClusterView extends ComfortPanel { public void mousePressed(MouseEvent e) { //Undo previous selection - List<CyRow> allRows = CyCore.cy.getCurrentNetwork().getDefaultNodeTable().getAllRows(); + List<CyRow> allRows = cluster.originalGraph.getDefaultNodeTable().getAllRows(); for (CyRow r: allRows) { r.set("selected", false); } //Select nodes corresponding to the cluster for (CyNode n : cluster.nodes) { - CyCore.cy.getCurrentNetwork().getRow(n).set("selected", true); + cluster.originalGraph.getRow(n).set("selected", true); } } diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/gui/SolutionTab.java b/src/main/java/de/hhu/ba/yoshikoWrapper/gui/SolutionTab.java index 3ed940f4a0edeb6e2dbe023940d2b2c114139a4c..8a71ad1426deacb9c16b0720ed3ed5b34fd46432 100644 --- a/src/main/java/de/hhu/ba/yoshikoWrapper/gui/SolutionTab.java +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/gui/SolutionTab.java @@ -10,14 +10,6 @@ import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JScrollPane; -import org.cytoscape.model.CyNetwork; -import org.cytoscape.view.layout.CyLayoutAlgorithm; -import org.cytoscape.view.model.CyNetworkView; -import org.cytoscape.view.presentation.property.BasicVisualLexicon; -import org.cytoscape.view.vizmap.VisualStyle; -import org.cytoscape.view.vizmap.mappings.ContinuousMapping; - -import de.hhu.ba.yoshikoWrapper.core.CyCore; import de.hhu.ba.yoshikoWrapper.core.LocalizationManager; import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoCluster; import de.hhu.ba.yoshikoWrapper.graphModel.YoshikoSolution; @@ -56,37 +48,7 @@ public class SolutionTab extends ComfortPanel { @Override public void actionPerformed(ActionEvent e) { - CyNetwork metaGraph = solution.toMetaGraph(); - CyNetworkView view = CyCore.networkViewFactory.createNetworkView(metaGraph); - //layout solution - CyLayoutAlgorithm layout = CyCore.layoutAlgorithmManager.getDefaultLayout(); - CyCore.dialogTaskManager.execute( - layout.createTaskIterator( - view, - layout.getDefaultLayoutContext(), - CyLayoutAlgorithm.ALL_NODE_VIEWS, - null - ) - ); - //define style for solution - ContinuousMapping<Integer, Double> contMap = (ContinuousMapping<Integer, Double>)CyCore.continuousMappingFactory.createVisualMappingFunction( - "clusterSize", - Integer.class, - BasicVisualLexicon.NODE_SIZE - ); - VisualStyle vs= CyCore.visualStyleFactory.createVisualStyle("Meta-Graph Style"); - vs.addVisualMappingFunction(contMap); - CyCore.visualMappingManager.addVisualStyle(vs); - - - CyCore.networkManager.addNetwork(metaGraph); - CyCore.networkViewManager.addNetworkView( - view - ); - - CyCore.cy.setCurrentNetworkView(view); - vs.apply(CyCore.cy.getCurrentNetworkView()); - CyCore.cy.getCurrentNetworkView().updateView(); + solution.exportMetaGraph(); } });