package uk.ac.rhul.cs.cl1.ui.cytoscape;
import giny.model.Node;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.swing.AbstractAction;
import cytoscape.CyNetwork;
import cytoscape.Cytoscape;
import cytoscape.util.CytoscapeAction;
import cytoscape.view.CyNetworkView;
import uk.ac.rhul.cs.cl1.ClusterONEAlgorithmParameters;
import uk.ac.rhul.cs.cl1.NodeSet;
import uk.ac.rhul.cs.cl1.ValuedNodeSet;
import uk.ac.rhul.cs.cl1.seeding.NodeSetCollectionBasedSeedGenerator;
/**
* Action that grows a cluster from a given node and selects the
* grown cluster afterwards.
*
* @author tamas
*/
public class GrowClusterAction extends CytoscapeAction {
private static GrowClusterAction globalInstance;
/**
* The seed node
*/
private Node node = null;
/**
* Grows a cluster from the currently selected nodes of the currently selected network
*
* This constructor is private; if you need this functionality, use {@link getGlobalInstance()}
* instead.
*/
private GrowClusterAction() {
super("Grow cluster from selected nodes");
this.putValue(AbstractAction.MNEMONIC_KEY, KeyEvent.VK_S);
this.setPreferredMenu("Plugins.ClusterONE");
}
/**
* Grows a cluster from the given node
*
* @param node the node to grow a cluster from.
*/
public GrowClusterAction(Node node) {
super("Grow cluster from this node");
this.putValue(AbstractAction.MNEMONIC_KEY, KeyEvent.VK_G);
this.node = node;
}
@Override
public void actionPerformed(ActionEvent event) {
/* Get a handle to the control panel. If the control panel is not shown yet,
* we don't do anything */
ControlPanel panel = ControlPanel.getShownInstance();
if (panel == null)
return;
/* Get the currently selected network view */
CyNetworkView networkView = Cytoscape.getCurrentNetworkView();
/* Get the algorithm parameters */
ClusterONEAlgorithmParameters parameters = panel.getParameters();
String weightAttr = panel.getWeightAttributeName();
CyNetwork network = Cytoscape.getCurrentNetwork();
/* Get the Graph representation of the CyNetwork */
Graph graph = CytoscapePlugin.convertCyNetworkToGraph(network, weightAttr);
if (graph == null)
return;
/* Update the algorithm parameters: set the seeding method properly */
List<Node> nodeMapping = graph.getNodeMapping();
List<Integer> nodeIndices = new ArrayList<Integer>();
if (node != null) {
/* We are using the node given in the constructor */
nodeIndices.add(nodeMapping.indexOf(node));
if (nodeIndices.get(0) < 0) {
CytoscapePlugin.showBugMessage("The selected node does not belong to the selected graph.");
return;
}
} else {
/* Fetch all the selected nodes from the current view */
@SuppressWarnings("unchecked") Set<Node> selectedNodes = network.getSelectedNodes();
for (int idx = 0; idx < nodeMapping.size(); idx++) {
if (selectedNodes.contains(nodeMapping.get(idx))) {
nodeIndices.add(idx);
}
}
}
if (nodeIndices.size() == 0) {
CytoscapePlugin.showErrorMessage("There are no selected nodes in the current graph.");
return;
}
parameters.setSeedGenerator(new NodeSetCollectionBasedSeedGenerator(new NodeSet(graph, nodeIndices)));
/* Run the algorithm, get the results */
List<ValuedNodeSet> clusters = CytoscapePlugin.runAlgorithm(graph, parameters, weightAttr);
if (clusters == null) {
CytoscapePlugin.showBugMessage("No results returned from ClusterONE.");
return;
}
if (clusters.size() == 0) {
CytoscapePlugin.showInformationMessage("There is no cluster associated to this node.\nMaybe it was filtered out by the size or the density filter?");
return;
}
if (clusters.size() > 1) {
CytoscapePlugin.showBugMessage("More than one cluster was returned from ClusterONE.");
return;
}
NodeSet cluster = clusters.get(0);
List<Node> selectedNodes = new ArrayList<Node>();
for (int idx: cluster) {
selectedNodes.add(nodeMapping.get(idx));
}
network.unselectAllNodes();
network.unselectAllEdges();
network.setSelectedNodeState(selectedNodes, true);
network.setSelectedEdgeState(network.getConnectingEdges(selectedNodes), true);
if (networkView != null)
networkView.redrawGraph(false, true);
}
/**
* Returns a "global" instance of this action that grows a cluster from the selected nodes
* of the current view.
*
* There should be at most one global instance at any given time. If the global instance was
* not used before, this method will construct it
*
* @return the global instance of this action
*/
synchronized public static GrowClusterAction getGlobalInstance() {
if (globalInstance == null)
globalInstance = new GrowClusterAction();
return globalInstance;
}
@Override
public boolean isInToolBar() {
return false;
}
}