From 8345651fbd1b727f874880a16f4cfca3530e205a Mon Sep 17 00:00:00 2001 From: Philipp Spohr <spohr.philipp@web.de> Date: Fri, 8 Sep 2017 21:36:28 +0200 Subject: [PATCH] Improved style handling --- .../de/hhu/ba/yoshikoWrapper/CyActivator.java | 22 +++-- .../de/hhu/ba/yoshikoWrapper/core/CyCore.java | 10 +-- .../yoshikoWrapper/cytoUtil/StyleManager.java | 88 +++++++++++++++++++ .../graphModel/YoshikoCluster.java | 66 +++++++------- .../graphModel/YoshikoSolution.java | 88 +++++++------------ 5 files changed, 167 insertions(+), 107 deletions(-) create mode 100644 src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/StyleManager.java diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java b/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java index 149563f..cb54e91 100644 --- a/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/CyActivator.java @@ -1,16 +1,16 @@ /******************************************************************************* * Copyright (C) 2017 Philipp Spohr - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -38,7 +38,6 @@ import org.cytoscape.service.util.AbstractCyActivator; import org.cytoscape.service.util.CyServiceRegistrar; import org.cytoscape.session.events.SessionLoadedListener; import org.cytoscape.task.create.CloneNetworkTaskFactory; -import org.cytoscape.task.visualize.ApplyVisualStyleTaskFactory; import org.cytoscape.view.model.CyNetworkViewFactory; import org.cytoscape.view.layout.CyLayoutAlgorithmManager; import org.cytoscape.view.model.CyNetworkViewManager; @@ -68,7 +67,7 @@ public class CyActivator extends AbstractCyActivator { public CyActivator() { super(); } - + @Override public void start(BundleContext context) throws Exception { //Initialize cytoscape configuration system @@ -77,9 +76,9 @@ public class CyActivator extends AbstractCyActivator { Properties propsReaderServiceProps = new Properties(); propsReaderServiceProps.setProperty("cyPropertyName", "yoshiko.props"); registerAllServices(context,cm,propsReaderServiceProps); - + //Create symbolic links to give other classes access to Cytoscape Services - CyCore.cy = getService(context, CyApplicationManager.class); + CyCore.cy = getService(context, CyApplicationManager.class); CyCore.dialogTaskManager = getService(context, DialogTaskManager.class); CyCore.registrar = getService(context, CyServiceRegistrar.class); CyCore.cm = cm; @@ -93,14 +92,13 @@ public class CyActivator extends AbstractCyActivator { 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); //Not sure how to correctly infer arguments here CyCore.renderingEngineFactory = getService(context,RenderingEngineFactory.class); CyCore.cloneNetworkTaskFactory = getService(context,CloneNetworkTaskFactory.class); //Store a reference to the Version YoshUtil.version = context.getBundle().getVersion(); - + //Set language according to settings -> Default to enUS LocalizationManager.switchLanguage(cm.getProperties().getProperty("locale", "enUS")); @@ -111,12 +109,12 @@ public class CyActivator extends AbstractCyActivator { YoshikoLoader.loadLibrary(pathToYosh); } } - + //Initialize and register main panel MainPanel mainPanel = new MainPanel(); registerService(context,mainPanel,CytoPanelComponent.class, new Properties()); - + //Listener for Network-Changes -> Updating possible columns for mapping NetChangeListener netChangeListener = new NetChangeListener(mainPanel.getColumnMapper()); registerService(context,netChangeListener, AddedEdgesListener.class, new Properties()); @@ -125,7 +123,7 @@ public class CyActivator extends AbstractCyActivator { registerService(context,netChangeListener, ColumnDeletedListener.class, new Properties()); registerService(context,netChangeListener, SessionLoadedListener.class, new Properties()); registerService(context,netChangeListener, SetCurrentNetworkListener.class, new Properties()); - + //Show Startup-Hint HintManager.showMappingHint(Hint.FIRST_START); 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 8c6462b..5276bab 100644 --- a/src/main/java/de/hhu/ba/yoshikoWrapper/core/CyCore.java +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/core/CyCore.java @@ -1,16 +1,16 @@ /******************************************************************************* * Copyright (C) 2017 Philipp Spohr - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -29,7 +29,6 @@ import org.cytoscape.model.CyNetworkManager; import org.cytoscape.model.subnetwork.CyRootNetworkManager; import org.cytoscape.service.util.CyServiceRegistrar; import org.cytoscape.task.create.CloneNetworkTaskFactory; -import org.cytoscape.task.visualize.ApplyVisualStyleTaskFactory; import org.cytoscape.view.layout.CyLayoutAlgorithmManager; import org.cytoscape.view.model.CyNetworkViewFactory; import org.cytoscape.view.model.CyNetworkViewManager; @@ -61,11 +60,10 @@ public class CyCore { public static VisualStyleFactory visualStyleFactory; public static VisualMappingFunctionFactory continuousMappingFactory; public static CyRootNetworkManager rootNetworkManager; - public static ApplyVisualStyleTaskFactory applyVisualStyleTaskFactory; public static RenderingEngineFactory<CyNetwork> renderingEngineFactory; public static CloneNetworkTaskFactory cloneNetworkTaskFactory; // - + //Convenience public static String getConfig(String key) { return cm.getProperties().getProperty(key); diff --git a/src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/StyleManager.java b/src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/StyleManager.java new file mode 100644 index 0000000..509926c --- /dev/null +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/cytoUtil/StyleManager.java @@ -0,0 +1,88 @@ +package de.hhu.ba.yoshikoWrapper.cytoUtil; + +import java.util.List; + +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.BoundaryRangeValues; +import org.cytoscape.view.vizmap.mappings.ContinuousMapping; + +import de.hhu.ba.yoshikoWrapper.core.CyCore; + +public class StyleManager { + + public static final String CLUSTERSIZE_COLUMN_NAME = "clusterSize"; + public static final String EDGESTRENGTH_COLUMN_NAME = "edgeStrength"; + + public static final double MIN_EDGE_SIZE = 1.0; + public static final double MAX_EDGE_SIZE = 10.0; + + public static final double MIN_NODE_SIZE = 5.0; + public static final double MAX_NODE_SIZE = 30.0; + + + private static void apply (CyNetworkView view, VisualStyle style) { + CyCore.visualMappingManager.setVisualStyle(style,view); + style.apply(view); + view.updateView(); + } + + public static void style(CyNetworkView view, VisualStyle style) { + apply(view,style); + } + + public static void styleWithMapping(CyNetworkView view, VisualStyle style) { + + style = CyCore.visualStyleFactory.createVisualStyle(style); + + //Define style for solution + ContinuousMapping<Integer, Double> contMapNodes = (ContinuousMapping<Integer, Double>)CyCore.continuousMappingFactory.createVisualMappingFunction( + CLUSTERSIZE_COLUMN_NAME, + Integer.class, + BasicVisualLexicon.NODE_SIZE + ); + + ContinuousMapping<Integer, Double> contMapEdges = (ContinuousMapping<Integer, Double>)CyCore.continuousMappingFactory.createVisualMappingFunction( + EDGESTRENGTH_COLUMN_NAME, + Integer.class, + BasicVisualLexicon.EDGE_WIDTH + ); + + //Calculate size range and scale accordingly + List<Integer> sizes = view.getModel().getDefaultNodeTable().getColumn(CLUSTERSIZE_COLUMN_NAME).getValues(Integer.class); + int min = Integer.MAX_VALUE; + int max = Integer.MIN_VALUE; + for (Integer i : sizes) { + if (i < min) { + min = i; + } + if (i > max) { + max = i; + } + } + contMapNodes.addPoint(min, new BoundaryRangeValues<Double>(MIN_NODE_SIZE,MIN_NODE_SIZE,MIN_NODE_SIZE)); + contMapNodes.addPoint(max, new BoundaryRangeValues<Double>(MAX_NODE_SIZE,MAX_NODE_SIZE,MAX_NODE_SIZE)); + + sizes = view.getModel().getDefaultEdgeTable().getColumn(EDGESTRENGTH_COLUMN_NAME).getValues(Integer.class); + min = Integer.MAX_VALUE; + max = Integer.MIN_VALUE; + for (Integer i : sizes) { + if (i < min) { + min = i; + } + if (i > max) { + max = i; + } + } + + contMapEdges.addPoint(min, new BoundaryRangeValues<Double>(MIN_EDGE_SIZE,MIN_EDGE_SIZE,MIN_EDGE_SIZE)); + contMapEdges.addPoint(max, new BoundaryRangeValues<Double>(MAX_EDGE_SIZE,MAX_EDGE_SIZE,MAX_EDGE_SIZE)); + + style.addVisualMappingFunction(contMapNodes); + style.addVisualMappingFunction(contMapEdges); + apply(view,style); + + } + +} 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 2e1f1d1..69e330a 100644 --- a/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoCluster.java +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoCluster.java @@ -1,16 +1,16 @@ /******************************************************************************* * Copyright (C) 2017 Philipp Spohr - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -38,7 +38,6 @@ import org.cytoscape.model.subnetwork.CySubNetwork; import org.cytoscape.view.layout.CyLayoutAlgorithm; import org.cytoscape.view.model.CyNetworkView; import org.cytoscape.view.presentation.RenderingEngine; -import org.cytoscape.view.vizmap.VisualStyle; import org.cytoscape.work.Task; import org.cytoscape.work.TaskIterator; import org.cytoscape.work.TaskMonitor; @@ -46,32 +45,33 @@ import org.slf4j.Logger; import de.hhu.ba.yoshikoWrapper.core.CyCore; import de.hhu.ba.yoshikoWrapper.core.LocalizationManager; +import de.hhu.ba.yoshikoWrapper.cytoUtil.StyleManager; import de.hhu.ba.yoshikoWrapper.logging.YoshikoLogger; import static org.cytoscape.view.presentation.property.BasicVisualLexicon.NETWORK_HEIGHT; import static org.cytoscape.view.presentation.property.BasicVisualLexicon.NETWORK_WIDTH; public class YoshikoCluster { - - + + private final long id; - + private ArrayList<CyNode> nodes; private CySubNetwork net; - + //SYMBOLIC LINKS private final CyNetwork originalGraph; private Logger logger = YoshikoLogger.getInstance().getLogger(); - - + + public YoshikoCluster(long id, CyNetwork originalGraph) { this.id = id; this.originalGraph = originalGraph; - this.nodes = new ArrayList<CyNode>(); + this.nodes = new ArrayList<CyNode>(); } - + private void createSubNetwork() { - + if (net == null) { CyRootNetwork originalGraphAsRoot = CyCore.rootNetworkManager.getRootNetwork(originalGraph); @@ -89,11 +89,11 @@ public class YoshikoCluster { CySubNetwork subnet = originalGraphAsRoot.addSubNetwork(nodes ,inducedEdges); subnet.getRow(subnet).set(CyNetwork.NAME, LocalizationManager.get("cluster")+" "+(id+1)); - - net = subnet; //Save for further reference + + net = subnet; //Save for further reference } } - + /** * Attempt to select the nodes belonging to this cluster in the original Graph given that they still exist */ @@ -112,41 +112,39 @@ public class YoshikoCluster { logger.warn("The graph doesn't exist anymore, can't highlight nodes!"); } } - + public void generateImage(JLabel label, int width, int height) { - + if (net == null) { createSubNetwork(); } - + final CyNetworkView view = CyCore.networkViewFactory.createNetworkView(net); - + //layout cluster final CyLayoutAlgorithm layout = CyCore.layoutAlgorithmManager.getDefaultLayout(); final TaskIterator createLayout = layout.createTaskIterator( - view, - layout.getDefaultLayoutContext(), + view, + layout.getDefaultLayoutContext(), CyLayoutAlgorithm.ALL_NODE_VIEWS, null ); - + createLayout.append( new Task() { @Override public void run(TaskMonitor taskMonitor) throws Exception { taskMonitor.setStatusMessage("Generating cluster view for C:"+id); - - VisualStyle vs= CyCore.visualStyleFactory.createVisualStyle(CyCore.visualMappingManager.getCurrentVisualStyle()); - CyCore.visualMappingManager.setVisualStyle(vs, view); - vs.apply(view); + + StyleManager.style(view, CyCore.visualMappingManager.getCurrentVisualStyle()); view.setVisualProperty(NETWORK_WIDTH, new Double(width)); view.setVisualProperty(NETWORK_HEIGHT, new Double(height)); view.fitContent(); view.updateView(); - + RenderingEngine<CyNetwork> renderingEngine = CyCore.renderingEngineFactory.createRenderingEngine(label, view); SwingUtilities.invokeLater(new Runnable() { @@ -154,28 +152,28 @@ public class YoshikoCluster { public void run() { Image img = renderingEngine.createImage(width,height); label.setIcon(new ImageIcon(img)); - + renderingEngine.dispose(); view.dispose(); } - + }); - + } @Override public void cancel() { //Nothing to do as GC is handled by JAVA } - + } ); - + CyCore.dialogTaskManager.execute( createLayout ); - + } 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 ed22279..62081db 100644 --- a/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoSolution.java +++ b/src/main/java/de/hhu/ba/yoshikoWrapper/graphModel/YoshikoSolution.java @@ -1,16 +1,16 @@ /******************************************************************************* * Copyright (C) 2017 Philipp Spohr - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -32,24 +32,22 @@ import org.cytoscape.model.CyEdge.Type; 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; +import de.hhu.ba.yoshikoWrapper.cytoUtil.StyleManager; public class YoshikoSolution { - + /** * The original Graph from which the solution was generated. * NOTE: This can be destroyed or modified during runtime while the solution still exists and may become invalid */ private CyNetwork originalGraph; - + public ArrayList<YoshikoCluster> cluster; public int id; - + public YoshikoSolution(CyNetwork originalGraph) { cluster = new ArrayList<YoshikoCluster>(); this.originalGraph = originalGraph; @@ -60,27 +58,26 @@ public class YoshikoSolution { * The nodes are linked to subgraphs representing the cluster and also their size is scaled relative to cluster size */ public void exportMetaGraph() { - + CyNetwork metaGraph = CyCore.networkFactory.createNetwork(); - + metaGraph.getRow(metaGraph).set(CyNetwork.NAME, LocalizationManager.get("metaGraph")); - + metaGraph.getDefaultNodeTable().createColumn("clusterSize", Integer.class, false); metaGraph.getDefaultEdgeTable().createColumn("edgeStrength", Integer.class, false); CyLayoutAlgorithm layout = CyCore.layoutAlgorithmManager.getDefaultLayout(); - + //Map Cluster to Nodes for further reference HashMap<YoshikoCluster,CyNode> map = new HashMap<YoshikoCluster,CyNode>(); - - + + //Add nodes for (YoshikoCluster c: cluster) { - - VisualStyle vs= CyCore.visualStyleFactory.createVisualStyle(CyCore.visualMappingManager.getCurrentVisualStyle()); - + + CyNode clusterNode = metaGraph.addNode(); CySubNetwork subnet = c.getSubNetwork(); CyCore.networkManager.addNetwork(subnet); @@ -90,22 +87,22 @@ public class YoshikoSolution { //layout cluster CyCore.dialogTaskManager.execute( layout.createTaskIterator( - subnetView, - layout.getDefaultLayoutContext(), + subnetView, + layout.getDefaultLayoutContext(), CyLayoutAlgorithm.ALL_NODE_VIEWS, null ) ); - CyCore.visualMappingManager.setVisualStyle(vs, subnetView); - vs.apply(subnetView); - subnetView.updateView(); + + StyleManager.style(subnetView,CyCore.visualMappingManager.getCurrentVisualStyle()); + clusterNode.setNetworkPointer(subnet); //Set node attributes metaGraph.getRow(clusterNode).set("name", LocalizationManager.get("cluster")+" "+c.getID()); - metaGraph.getRow(clusterNode).set("clusterSize",c.getSize()); + metaGraph.getRow(clusterNode).set(StyleManager.CLUSTERSIZE_COLUMN_NAME,c.getSize()); map.put(c, clusterNode); } - + //Add edges (O(|C|^2*|V|^2) can maybe be improved? //TODO for (YoshikoCluster c1:cluster) { for (YoshikoCluster c2:cluster) { @@ -120,12 +117,12 @@ public class YoshikoSolution { if (originalGraph.containsEdge(c1n, c2n) || originalGraph.containsEdge(c2n, c1n)) { if (!metaGraph.containsEdge(map.get(c1), map.get(c2))){ CyEdge edge = metaGraph.addEdge(map.get(c1), map.get(c2), false); - metaGraph.getRow(edge).set("edgeStrength",1); + metaGraph.getRow(edge).set(StyleManager.EDGESTRENGTH_COLUMN_NAME,1); } else { CyEdge edge = metaGraph.getConnectingEdgeList(map.get(c1), map.get(c2), Type.ANY).get(0); - metaGraph.getRow(edge).set("edgeStrength", - metaGraph.getRow(edge).get("edgeStrength", Integer.class)+1 + metaGraph.getRow(edge).set(StyleManager.EDGESTRENGTH_COLUMN_NAME, + metaGraph.getRow(edge).get(StyleManager.EDGESTRENGTH_COLUMN_NAME, Integer.class)+1 ); } } @@ -133,47 +130,28 @@ public class YoshikoSolution { } } } - + CyNetworkView view = CyCore.networkViewFactory.createNetworkView(metaGraph); //layout solution CyCore.dialogTaskManager.execute( layout.createTaskIterator( - view, - layout.getDefaultLayoutContext(), + view, + layout.getDefaultLayoutContext(), CyLayoutAlgorithm.ALL_NODE_VIEWS, null ) ); - - VisualStyle vs= CyCore.visualStyleFactory.createVisualStyle(CyCore.visualMappingManager.getCurrentVisualStyle()); - + + 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 - ); - - ContinuousMapping<Integer, Double> contMapEdges = (ContinuousMapping<Integer, Double>)CyCore.continuousMappingFactory.createVisualMappingFunction( - "edgeStrength", - Integer.class, - BasicVisualLexicon.EDGE_WIDTH - ); - //Apply visual style - CyCore.visualMappingManager.setVisualStyle(vs, view); - vs.addVisualMappingFunction(contMap); - vs.addVisualMappingFunction(contMapEdges); - vs.apply(view); - view.updateView(); - + StyleManager.styleWithMapping(view, CyCore.visualMappingManager.getCurrentVisualStyle()); + CyCore.cy.setCurrentNetworkView(view); } - + } -- GitLab