Skip to content

Commit

Permalink
Merge pull request #45 from LHuang2019/pathlinker-33
Browse files Browse the repository at this point in the history
Pathlinker #33: Apply style of original network to pathlinker subnetwork
  • Loading branch information
jlaw9 authored Sep 5, 2017
2 parents da7afa0 + b97b0a4 commit 116fad6
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import javax.swing.*;
import javax.swing.border.TitledBorder;
Expand Down Expand Up @@ -82,8 +84,6 @@ public class PathLinkerControlPanel extends JPanel implements CytoPanelComponent
private CySwingApplication _cySwingApp;
protected static CyApplicationManager _applicationManager;
private CyNetworkManager _networkManager;
private CyNetworkViewFactory _networkViewFactory;
private CyNetworkViewManager _networkViewManager;
private CyAppAdapter _adapter;

/** The model that runs ksp algorithm from the user input */
Expand All @@ -94,11 +94,12 @@ public class PathLinkerControlPanel extends JPanel implements CytoPanelComponent
private Container _parent;
/** State of the panel. Initially null b/c it isn't open or closed yet */
private PanelState _state = null;
/** Index of the tab in the parent panel */
private int _tabIndex;
private boolean _allEdgesContainWeights = true;
/** The original network selected by the user */
private CyNetwork _originalNetwork;
/** The sub-network created by the algorithm */
private CyNetwork _kspSubgraph = null;
/** The sub-network view created by the algorithm */
private CyNetworkView _kspSubgraphView = null;
/** column name that links to the edge weight values */
private String _edgeWeightColumnName;
/** The k value to be used in the algorithm */
Expand Down Expand Up @@ -192,8 +193,6 @@ public void initialize(CySwingApplication cySwingApp, CyServiceRegistrar service
_serviceRegistrar = serviceRegistrar;
_applicationManager = applicationManager;
_networkManager = networkManager;
_networkViewFactory = networkViewFactory;
_networkViewManager = networkViewManager;
_adapter = adapter;
_parent = this.getParent();

Expand Down Expand Up @@ -434,14 +433,14 @@ private boolean callRunKSP() {
// runs the setup and KSP algorithm
ArrayList<Path> result = _model.runKSP();

// generates a subgraph of the nodes and edges involved in the resulting
// paths and displays it to the user
if (!_model.getDisableSubgraph())
createKSPSubgraphView();
// generates a subgraph of the nodes and edges involved in the resulting paths and displays it to the user
if (!_model.getDisableSubgraph()) {
createKSPSubgraphAndView();
}

// update the table path index attribute
updatePathIndexAttribute(result);

// writes the result of the algorithm to a table
writeResult(result);

Expand Down Expand Up @@ -652,9 +651,10 @@ private void writeResult(ArrayList<Path> paths) {
}

// create and register a new panel in result panel with specific title
// if user did not generate sub-network then we pass down the original network to the result panel
PathLinkerResultPanel resultsPanel = new PathLinkerResultPanel(
String.valueOf(_cySwingApp.getCytoPanel(CytoPanelName.EAST).getCytoPanelComponentCount() + 1),
_applicationManager.getCurrentNetwork(),
_kspSubgraph == null ? _applicationManager.getCurrentNetwork() : _kspSubgraph,
paths);
_serviceRegistrar.registerService(resultsPanel, CytoPanelComponent.class, new Properties());

Expand All @@ -670,99 +670,116 @@ private void writeResult(ArrayList<Path> paths) {
}

/**
* Creates a new network and view for the subgraph
* Creates a new sub-network and sub-network view for the subgraph generated by the KSP
*/
private void createKSPSubgraphView() {

CyNetwork kspSubgraph = _model.getKspSubgraph();
private void createKSPSubgraphAndView() {
// creates task iterator and execute it to generate a sub-network from the original network
// the bypass values and other styles from the original network will be pass down to the sub-network
TaskIterator subNetworkTask = _adapter.get_NewNetworkSelectedNodesAndEdgesTaskFactory()
.createTaskIterator(_model.getOriginalNetwork());
_adapter.getTaskManager().execute(subNetworkTask);

// This is a HACK: pausing execution with sleep to wait for the sub network to be created
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// creates the new network and its view
CyNetworkView kspSubgraphView = _networkViewFactory.createNetworkView(kspSubgraph);
_networkManager.addNetwork(kspSubgraph);
_networkViewManager.addNetworkView(kspSubgraphView);
// this is a hack as we can't access the new sub-network generated from the task
// loop through all the networks and find one with the highest SUID,
// which is the sub-network we created
Set<CyNetwork> allNetworks = _networkManager.getNetworkSet();
long maxSUID = Integer.MIN_VALUE;
for(CyNetwork network : allNetworks) {
if (network.getSUID() > maxSUID) maxSUID = network.getSUID();
}

// Apply the new name to the sub-network
_kspSubgraph = _networkManager.getNetwork(maxSUID);
String subgraphName = "PathLinker-subnetwork-" + _model.getK() + "-paths";
_kspSubgraph.getRow(_kspSubgraph).set(CyNetwork.NAME, subgraphName);

// The current network view is set to the new sub-network view already
// while current network is still the originalNetwork
_kspSubgraphView = _applicationManager.getCurrentNetworkView();

// use a visual bypass to color the sources and targets for the sub-network view
Color targetColor = new Color(255, 223, 0);

// use a visual bypass to color the sources and targets

for (CyNode source : _model.getSubgraphSources()) {
View<CyNode> currView = kspSubgraphView.getNodeView(source);
View<CyNode> currView = _kspSubgraphView.getNodeView(source);
currView.setLockedValue(BasicVisualLexicon.NODE_SHAPE, NodeShapeVisualProperty.DIAMOND);
currView.setLockedValue(BasicVisualLexicon.NODE_FILL_COLOR, Color.CYAN);
}
for (CyNode target : _model.getSubgraphTargets()) {
View<CyNode> currView = kspSubgraphView.getNodeView(target);
View<CyNode> currView = _kspSubgraphView.getNodeView(target);
currView.setLockedValue(BasicVisualLexicon.NODE_SHAPE, NodeShapeVisualProperty.RECTANGLE);
currView.setLockedValue(BasicVisualLexicon.NODE_FILL_COLOR, targetColor);

}

applyLayout(kspSubgraph, kspSubgraphView);

_kspSubgraphView.updateView();

// applies hierarchical layout if the k <= 200
if (_model.getK() <= 200)
applyHierarchicalLayout();
}

/**
* Applies a layout algorithm to the nodes If k <= 200, we apply a
* hierarchical layout Otherwise, we apply the default layout of the existing network view
* @param kspSubgraph
* @param kspSubgraphView
* Applies hierarchical layout to the sub-network If k <= 200
*/
private void applyLayout(CyNetwork kspSubgraph, CyNetworkView kspSubgraphView) {
boolean hierarchical = _model.getK() <= 200;
private void applyHierarchicalLayout() {

// set node layout by applying the default layout algorithm
CyLayoutAlgorithm algo = hierarchical ? _adapter.getCyLayoutAlgorithmManager().getLayout("hierarchical")
: _adapter.getCyLayoutAlgorithmManager().getDefaultLayout();
TaskIterator iter = algo.createTaskIterator(kspSubgraphView, algo.createLayoutContext(),
// set node layout by applying the hierarchical layout algorithm
CyLayoutAlgorithm algo = _adapter.getCyLayoutAlgorithmManager().getLayout("hierarchical");
TaskIterator iter = algo.createTaskIterator(_kspSubgraphView, algo.createLayoutContext(),
CyLayoutAlgorithm.ALL_NODE_VIEWS, null);
_adapter.getTaskManager().execute(iter);
SynchronousTaskManager<?> synTaskMan = _adapter.getCyServiceRegistrar()
.getService(SynchronousTaskManager.class);
synTaskMan.execute(iter);
_adapter.getVisualMappingManager().getVisualStyle(_applicationManager.getCurrentNetworkView()).apply(kspSubgraphView);
kspSubgraphView.updateView();

// if we applied the hierarchical layout, by default it is rendered
// upside down
// if we applied the hierarchical layout, by default it is rendered upside down
// so we reflect all the nodes about the x axis
if (hierarchical) {
// sleep so the hierarchical layout can get applied
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// sleep so the hierarchical layout can get applied
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// reflect nodes about the x-axis because the default hierarchical
// layout renders the nodes upside down
// reflect nodes
double maxY = Integer.MIN_VALUE;
double minY = Integer.MAX_VALUE;
// reflect nodes about the x-axis because the default hierarchical
// layout renders the nodes upside down
// reflect nodes
double maxY = Integer.MIN_VALUE;
double minY = Integer.MAX_VALUE;

// finds the midpoint x coordinate
for (CyNode node : kspSubgraph.getNodeList()) {
View<CyNode> nodeView = kspSubgraphView.getNodeView(node);
double yCoord = nodeView.getVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION);
// finds the midpoint x coordinate
for (CyNode node : _kspSubgraph.getNodeList()) {
View<CyNode> nodeView = _kspSubgraphView.getNodeView(node);
double yCoord = nodeView.getVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION);

if (yCoord > maxY)
maxY = yCoord;
if (yCoord > maxY)
maxY = yCoord;

if (yCoord < minY)
minY = yCoord;
}

double midY = (maxY + minY) / 2;
if (yCoord < minY)
minY = yCoord;
}

// reflects each node about the midpoint x axis
for (CyNode node : kspSubgraph.getNodeList()) {
View<CyNode> nodeView = kspSubgraphView.getNodeView(node);
double yCoord = nodeView.getVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION);
double midY = (maxY + minY) / 2;

double newY = -1 * yCoord + 2 * midY;
nodeView.setVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION, newY);
}
// reflects each node about the midpoint x axis
for (CyNode node : _kspSubgraph.getNodeList()) {
View<CyNode> nodeView = _kspSubgraphView.getNodeView(node);
double yCoord = nodeView.getVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION);

kspSubgraphView.updateView();
double newY = -1 * yCoord + 2 * midY;
nodeView.setVisualProperty(BasicVisualLexicon.NODE_Y_LOCATION, newY);
}

_kspSubgraphView.updateView();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,9 +374,9 @@ public ArrayList<Path> runKSP() {
// in terms of the edge weights
undoLogTransformPathLength(result);

// generates a subgraph of the nodes and edges involved in the resulting
// selects all the paths that involved in the resulting for generating ksp subgraph
if(!disableSubgraph)
createKSPSubgraph(result);
selectKSPSubgraph(result);

return result;
}
Expand Down Expand Up @@ -621,19 +621,12 @@ private void checkAddEdge(HashMap<String, CyEdge> sourcetargetToEdge,
}

/**
* Generates a subgraph of the user supplied graph that contains only the
* nodes and edges that are in the k shortest paths
* Selects all the nodes and edges that is in the k shortest paths to generate the ksp subgraph
* The PathLinkerControlPanel->createKSPSubgraphAndView method uses the selected paths to generate the ksp subgraph
* @param paths the list of paths generated by ksp algorithm
*/
private void createKSPSubgraph(ArrayList<Path> paths) {

// creates a new network in the same network collection
// as the original network
CyRootNetwork root = ((CySubNetwork) originalNetwork).getRootNetwork();

HashSet<CyNode> nodesToAdd = new HashSet<CyNode>();
HashSet<CyEdge> edgesToAdd = new HashSet<CyEdge>();

private void selectKSPSubgraph(ArrayList<Path> paths) {

// keeps track of sources/targets in the ksp subgraph
// to change their visual properties later
subgraphSources = new HashSet<CyNode>();
Expand All @@ -644,8 +637,8 @@ private void createKSPSubgraph(ArrayList<Path> paths) {
for (int i = 1; i < currPath.size() - 2; i++) {
CyNode node1 = currPath.get(i);
CyNode node2 = currPath.get(i + 1);
nodesToAdd.add(node1);
nodesToAdd.add(node2);
originalNetwork.getRow(node1).set(CyNetwork.SELECTED, true);
originalNetwork.getRow(node2).set(CyNetwork.SELECTED, true);

// check if the nodes are part of the sources or targets specified
String node1name = originalNetwork.getRow(node1).get(CyNetwork.NAME, String.class);
Expand All @@ -660,18 +653,13 @@ private void createKSPSubgraph(ArrayList<Path> paths) {
for (CyEdge edge : edges){
// verifies the edges direction
if (edge.getSource().equals(node1) && edge.getTarget().equals(node2))
edgesToAdd.add(edge);
originalNetwork.getRow(edge).set(CyNetwork.SELECTED, true);
}
// also add all of the undirected edges from node1 to node2
edgesToAdd.addAll(originalNetwork.getConnectingEdgeList(node1, node2, CyEdge.Type.UNDIRECTED));
edges = originalNetwork.getConnectingEdgeList(node1, node2, CyEdge.Type.UNDIRECTED);
for (CyEdge edge : edges) originalNetwork.getRow(edge).set(CyNetwork.SELECTED, true);
}
}

kspSubgraph = root.addSubNetwork(nodesToAdd, edgesToAdd);

// sets the network name
String subgraphName = "PathLinker-subnetwork-" + k + "-paths";
kspSubgraph.getRow(kspSubgraph).set(CyNetwork.NAME, subgraphName);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class PathLinkerResultPanel extends JPanel implements CytoPanelComponent
/** The k shortest paths generated from the network **/
private final ArrayList<Path> _results;
/** The current network associated with the result panel **/
private final CyNetwork _originalNetwork;
private final CyNetwork _currentNetwork;
/** The tab title of the result panel **/
private String _title;
private JButton _discardBtn;
Expand All @@ -60,13 +60,13 @@ public class PathLinkerResultPanel extends JPanel implements CytoPanelComponent
/**
* Constructor for the result frame class
* @param title the title of the result panel
* @param originalNetwork the current network associated with the result panel
* @param currentNetwork the current network associated with the result panel
* @param results the results from pathlinker
*/
public PathLinkerResultPanel(String title, CyNetwork originalNetwork, ArrayList<Path> results)
public PathLinkerResultPanel(String title, CyNetwork currentNetwork, ArrayList<Path> results)
{
this._title = title;
this._originalNetwork = originalNetwork;
this._currentNetwork = currentNetwork;
this._results = results;
initializePanel();
}
Expand Down Expand Up @@ -120,14 +120,14 @@ class ResultTableListener implements ListSelectionListener {
public void valueChanged(ListSelectionEvent e) {
ListSelectionModel lsm = (ListSelectionModel)e.getSource();

List<CyNode> selectedNodes = CyTableUtil.getNodesInState(_originalNetwork, "selected", true);
List<CyEdge> selectedEdges = CyTableUtil.getEdgesInState(_originalNetwork, "selected", true);
List<CyNode> selectedNodes = CyTableUtil.getNodesInState(_currentNetwork, "selected", true);
List<CyEdge> selectedEdges = CyTableUtil.getEdgesInState(_currentNetwork, "selected", true);

// clear the original selected nodes and edges from the view
for (CyNode node : selectedNodes)
_originalNetwork.getRow(node).set(CyNetwork.SELECTED, false);
_currentNetwork.getRow(node).set(CyNetwork.SELECTED, false);
for (CyEdge edge : selectedEdges)
_originalNetwork.getRow(edge).set(CyNetwork.SELECTED, false);
_currentNetwork.getRow(edge).set(CyNetwork.SELECTED, false);

// return if nothing is selected
if (lsm.isSelectionEmpty()) return;
Expand All @@ -147,19 +147,19 @@ public void valueChanged(ListSelectionEvent e) {
CyNode node1 = currPath.get(j);
CyNode node2 = currPath.get(j + 1);

_originalNetwork.getRow(node1).set(CyNetwork.SELECTED, true);
_originalNetwork.getRow(node2).set(CyNetwork.SELECTED, true);
_currentNetwork.getRow(node1).set(CyNetwork.SELECTED, true);
_currentNetwork.getRow(node2).set(CyNetwork.SELECTED, true);

// add all of the directed edges from node1 to node2
List<CyEdge> edges = _originalNetwork.getConnectingEdgeList(node1, node2, CyEdge.Type.DIRECTED);
List<CyEdge> edges = _currentNetwork.getConnectingEdgeList(node1, node2, CyEdge.Type.DIRECTED);
for (CyEdge edge : edges) {
if (edge.getSource().equals(node1) && edge.getTarget().equals(node2)) { // verifies the edges direction
_originalNetwork.getRow(edge).set(CyNetwork.SELECTED, true);
_currentNetwork.getRow(edge).set(CyNetwork.SELECTED, true);
}
}
// also add all of the undirected edges from node1 to node2
edges = _originalNetwork.getConnectingEdgeList(node1, node2, CyEdge.Type.UNDIRECTED);
for (CyEdge edge : edges) _originalNetwork.getRow(edge).set(CyNetwork.SELECTED, true);
edges = _currentNetwork.getConnectingEdgeList(node1, node2, CyEdge.Type.UNDIRECTED);
for (CyEdge edge : edges) _currentNetwork.getRow(edge).set(CyNetwork.SELECTED, true);
}
}
}
Expand Down

0 comments on commit 116fad6

Please sign in to comment.