Author: pwang
Date: 2010-09-22 16:09:51 -0700 (Wed, 22 Sep 2010)
New Revision: 22020

Modified:
   
core3/layout-prefuse-impl/trunk/src/main/java/org/cytoscape/prefuse/layouts/internal/ForceDirectedLayout.java
Log:
Refactored

Modified: 
core3/layout-prefuse-impl/trunk/src/main/java/org/cytoscape/prefuse/layouts/internal/ForceDirectedLayout.java
===================================================================
--- 
core3/layout-prefuse-impl/trunk/src/main/java/org/cytoscape/prefuse/layouts/internal/ForceDirectedLayout.java
       2010-09-22 22:33:00 UTC (rev 22019)
+++ 
core3/layout-prefuse-impl/trunk/src/main/java/org/cytoscape/prefuse/layouts/internal/ForceDirectedLayout.java
       2010-09-22 23:09:51 UTC (rev 22020)
@@ -1,282 +1,106 @@
-
-/*
- Copyright (c) 2007, The Cytoscape Consortium (www.cytoscape.org)
-
- The Cytoscape Consortium is:
- - Institute for Systems Biology
- - University of California San Diego
- - Memorial Sloan-Kettering Cancer Center
- - Institut Pasteur
- - Agilent Technologies
-
- This library is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License, or
- any later version.
-
- This library is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  The software and
- documentation provided hereunder is on an "as is" basis, and the
- Institute for Systems Biology and the Whitehead Institute
- have no obligations to provide maintenance, support,
- updates, enhancements or modifications.  In no event shall the
- Institute for Systems Biology and the Whitehead Institute
- be liable to any party for direct, indirect, special,
- incidental or consequential damages, including lost profits, arising
- out of the use of this software and its documentation, even if the
- Institute for Systems Biology and the Whitehead Institute
- have been advised of the possibility of such damage.  See
- the GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this library; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-*/
-
-package org.cytoscape.prefuse.layouts.internal; 
-
-import java.awt.Dimension;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.cytoscape.view.layout.AbstractGraphPartition;
-import org.cytoscape.view.layout.EdgeWeighter;
-import org.cytoscape.view.layout.LayoutEdge;
-import org.cytoscape.view.layout.LayoutNode;
-import org.cytoscape.view.layout.LayoutPartition;
-import org.cytoscape.work.Tunable;
-import org.cytoscape.work.undo.UndoSupport;
-
-import prefuse.util.force.DragForce;
-import prefuse.util.force.EulerIntegrator;
-import prefuse.util.force.ForceItem;
-import prefuse.util.force.ForceSimulator;
-import prefuse.util.force.Integrator;
-import prefuse.util.force.NBodyForce;
-import prefuse.util.force.RungeKuttaIntegrator;
-import prefuse.util.force.SpringForce;
-
-enum Integrators{
-       RUNGEKUTTA("RUNGEKUTTA"),
-       EULER("EULER");
-       
-       private String name;
-       private Integrators(String str) { name=str; }
-       public String toString() { return name; }
-       public Integrator getNewIntegrator() {
-               // FIXME: could we use a switch on 'this' instead? (can't use 
one on
-               // name, because that is string, but) 'this' would be an enum, 
right?
-               // but eclipse complains if I have Integrators.EULER as a switch
-               // label...
-       
-               if (name.equals("EULER")){
-                       return new EulerIntegrator();
-               }
-               else if (name.equals("RUNGEKUTTA")){
-                       return new RungeKuttaIntegrator();
-               } else {// use Euler as default
-                       return new EulerIntegrator();
-               }
-       }
-}
-
-
-/**
- * This class wraps the Prefuse force-directed layout algorithm.
- * See {...@link http://prefuse.org} for more detail.
- */
-public class ForceDirectedLayout extends AbstractGraphPartition
-{
-       private ForceSimulator m_fsim;
-
-       @Tunable(description="Number of Iterations", groups="Algorithm 
settings")
-       public int numIterations = 100;
-       @Tunable(description="Default Spring Coefficient", groups="Algorithm 
settings")
-       public double defaultSpringCoefficient = 1e-4;
-       @Tunable(description="Default Spring Length", groups="Algorithm 
settings")
-       public double defaultSpringLength = 50.0;
-       @Tunable(description="Default Node Mass", groups="Algorithm settings")
-       public double defaultNodeMass = 3.0;
-
-       @Tunable(description="Integration algorithm to use", groups="Algorithm 
settings")
-       public Integrators integrator = Integrators.RUNGEKUTTA;
-
-       /**
-        * Value to set for doing unweighted layouts
-        */
-       public static final String UNWEIGHTEDATTRIBUTE = "(unweighted)";
-
-       private boolean supportWeights = true;
-       Map<LayoutNode,ForceItem> forceItems;
-
-       
-       public ForceDirectedLayout(UndoSupport undo) {
-               super(undo);
-
-               if (edgeWeighter == null)
-                       edgeWeighter = new EdgeWeighter();
-
-               m_fsim = new ForceSimulator();
-               m_fsim.addForce(new NBodyForce());
-               m_fsim.addForce(new SpringForce());
-               m_fsim.addForce(new DragForce());
-
-               forceItems = new HashMap<LayoutNode,ForceItem>();
-       }
-       
-       public String getName() {
-               return "force-directed";
-       }
-
-       public String toString() {
-               return "Force-Directed Layout";
-       }
-
-       protected void initialize_local() {
-       }
-
-
-       public void layoutPartion(LayoutPartition part) {
-               Dimension initialLocation = null;
-               // System.out.println("layoutPartion: 
"+part.getEdgeList().size()+" edges");
-               // Calculate our edge weights
-               part.calculateEdgeWeights();
-               // System.out.println("layoutPartion: 
"+part.getEdgeList().size()+" edges after calculateEdgeWeights");
-
-               m_fsim.setIntegrator(integrator.getNewIntegrator());
-               m_fsim.clear();
-
-               // initialize nodes
-               for (LayoutNode ln: part.getNodeList()) {
-                       if ( !forceItems.containsKey(ln) )
-                               forceItems.put(ln, new ForceItem());
-                       ForceItem fitem = forceItems.get(ln); 
-                       fitem.mass = getMassValue(ln);
-                       fitem.location[0] = 0f; 
-                       fitem.location[1] = 0f; 
-                       m_fsim.addItem(fitem);
-               }
-               
-               // initialize edges
-               for (LayoutEdge e: part.getEdgeList()) {
-                       LayoutNode n1 = e.getSource();
-                       ForceItem f1 = forceItems.get(n1); 
-                       LayoutNode n2 = e.getTarget();
-                       ForceItem f2 = forceItems.get(n2); 
-                       if ( f1 == null || f2 == null )
-                               continue;
-                       // System.out.println("Adding edge "+e+" with spring 
coeffficient = "+getSpringCoefficient(e)+" and length "+getSpringLength(e));
-                       m_fsim.addSpring(f1, f2, getSpringCoefficient(e), 
getSpringLength(e)); 
-               }
-
-               // setTaskStatus(5); // This is a rough approximation, but 
probably good enough
-               if (taskMonitor != null) {
-                       taskMonitor.setStatusMessage("Initializing partition 
"+part.getPartitionNumber());
-               }
-
-               // Figure out our starting point
-               if (selectedOnly) {
-                       initialLocation = part.getAverageLocation();
-               }
-
-               // perform layout
-               long timestep = 1000L;
-               for ( int i = 0; i < numIterations && !canceled; i++ ) {
-                       timestep *= (1.0 - i/(double)numIterations);
-                       long step = timestep+50;
-                       m_fsim.runSimulator(step);
-                       
setTaskStatus((int)(((double)i/(double)numIterations)*90.+5));
-               }
-               
-               // update positions
-               for (LayoutNode ln: part.getNodeList()) {
-                       if (!ln.isLocked()) {
-                               ForceItem fitem = forceItems.get(ln); 
-                               ln.setX(fitem.location[0]);
-                               ln.setY(fitem.location[1]);
-                               part.moveNodeToLocation(ln);
-                       }
-               }
-               // Not quite done, yet.  If we're only laying out selected 
nodes, we need
-               // to migrate the selected nodes back to their starting position
-               if (selectedOnly) {
-                       double xDelta = 0.0;
-                       double yDelta = 0.0;
-                       Dimension finalLocation = part.getAverageLocation();
-                       xDelta = finalLocation.getWidth() - 
initialLocation.getWidth();
-                       yDelta = finalLocation.getHeight() - 
initialLocation.getHeight();
-                       for (LayoutNode v: part.getNodeList()) {
-                               if (!v.isLocked()) {
-                                       v.decrement(xDelta, yDelta);
-                                       part.moveNodeToLocation(v);
-                               }
-                       }
-               }
-       }
-
-       /**
-        * Get the mass value associated with the given node. Subclasses should
-        * override this method to perform custom mass assignment.
-        * @param n the node for which to compute the mass value
-        * @return the mass value for the node. By default, all items are given
-        * a mass value of 1.0.
-        */
-       protected float getMassValue(LayoutNode n) {
-               return (float)defaultNodeMass;
-       }
-
-       /**
-        * Get the spring length for the given edge. Subclasses should
-        * override this method to perform custom spring length assignment.
-        * @param e the edge for which to compute the spring length
-        * @return the spring length for the edge. A return value of
-        * -1 means to ignore this method and use the global default.
-       */
-       protected float getSpringLength(LayoutEdge e) {
-               double weight = e.getWeight();
-               return (float)(defaultSpringLength/weight);
-       }
-
-       /**
-        * Get the spring coefficient for the given edge, which controls the
-        * tension or strength of the spring. Subclasses should
-        * override this method to perform custom spring tension assignment.
-        * @param e the edge for which to compute the spring coefficient.
-        * @return the spring coefficient for the edge. A return value of
-        * -1 means to ignore this method and use the global default.
-        */
-       protected float getSpringCoefficient(LayoutEdge e) {
-               return (float)defaultSpringCoefficient;
-       }
-
-       /**
-        * Return information about our algorithm
-        */
-       public boolean supportsSelectedOnly() {
-               return true;
-       }
-
-       public Set<Class<?>> supportsEdgeAttributes() {
-               Set<Class<?>> ret = new HashSet<Class<?>>();
-               if (!supportWeights)
-                       return ret;
-
-               ret.add( Integer.class );
-               ret.add( Double.class );
-
-               return ret;
-       }
-
-       public List getInitialAttributeList() {
-               ArrayList list = new ArrayList();
-               list.add(UNWEIGHTEDATTRIBUTE);
-
-               return list;
-       }
-
-}
+package org.cytoscape.prefuse.layouts.internal;
+
+import java.io.IOException;
+
+import org.cytoscape.view.layout.AbstractLayout;
+import org.cytoscape.view.layout.CyLayouts;
+import org.cytoscape.work.TaskIterator;
+import org.cytoscape.work.Tunable;
+import org.cytoscape.work.TunableValidator;
+import org.cytoscape.work.undo.UndoSupport;
+import org.cytoscape.work.util.ListSingleSelection;
+
+import prefuse.util.force.EulerIntegrator;
+import prefuse.util.force.RungeKuttaIntegrator;
+import prefuse.util.force.Integrator;
+import org.cytoscape.work.util.ListSingleSelection;
+
+public class ForceDirectedLayout extends AbstractLayout implements 
TunableValidator {
+       
+       @Tunable(description="Number of Iterations", groups="Algorithm 
settings")
+       public int numIterations = 100;
+       @Tunable(description="Default Spring Coefficient", groups="Algorithm 
settings")
+       public double defaultSpringCoefficient = 1e-4;
+       @Tunable(description="Default Spring Length", groups="Algorithm 
settings")
+       public double defaultSpringLength = 50.0;
+       @Tunable(description="Default Node Mass", groups="Algorithm settings")
+       public double defaultNodeMass = 3.0;
+       
+       //@Tunable(description="Integration algorithm to use", 
groups="Algorithm settings")
+       public Integrators integrator = Integrators.RUNGEKUTTA;
+       //public ListSingleSelection<String> integratorChoice = "RUNGEKUTTA";
+
+       //TODO refactor
+       public enum Integrators {
+               RUNGEKUTTA ("RUNGEKUTTA"),
+               EULER ("EULER");
+
+               private String name;
+               private Integrators(String str) { name=str; }
+               public String toString() { return name; }
+               public Integrator getNewIntegrator() {
+                       // FIXME: could we use a switch on 'this' instead? 
(can't use one on
+                       // name, because that is string, but) 'this' would be 
an enum, right?
+                       // but eclipse complains if I have Integrators.EULER as 
a switch
+                       // label...
+               
+                       if (name.equals("EULER")){
+                               return new EulerIntegrator();
+                       }
+                       else if (name.equals("RUNGEKUTTA")){
+                               return new RungeKuttaIntegrator();
+                       } else {// use Euler as default
+                               return new EulerIntegrator();
+                       }
+               }
+       }
+
+       
+       /**
+        * Creates a new GridNodeLayout object.
+        */
+       public ForceDirectedLayout(UndoSupport un) {
+               super(un);
+       }
+
+       //TODO how to validate these values?
+       public boolean tunablesAreValid(final Appendable errMsg) {
+               // Do something here to validate the parameter values
+               // ??????????????
+               
+               return true;
+       }
+
+       public TaskIterator getTaskIterator() {
+               
+               return new TaskIterator(new 
ForceDirectedLayoutTask(networkView, getName(), selectedOnly, staticNodes,
+                               numIterations, 
defaultSpringCoefficient,defaultSpringLength,defaultNodeMass,integrator));
+       }
+
+       /**
+        *  DOCUMENT ME!
+        *
+        * @return  DOCUMENT ME!
+        */
+       public String getName() {
+               return "Force-Directed";
+       }
+
+       /**
+        *  DOCUMENT ME!
+        *
+        * @return  DOCUMENT ME!
+        */
+       public String toString() {
+               return "Force Directed Layout";
+       }
+
+       /**
+        * We do support selected only
+        *
+        * @return true
+        */
+       public boolean supportsSelectedOnly() {
+               return true;
+       }
+}

-- 
You received this message because you are subscribed to the Google Groups 
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/cytoscape-cvs?hl=en.

Reply via email to