Author: scooter
Date: 2012-08-09 21:51:16 -0700 (Thu, 09 Aug 2012)
New Revision: 30155

Added:
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachClustererOld.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAMCluster.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAMClusterer.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMCluster.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMClusterer.java
Removed:
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/treeview/CancelableSettingsDialog.java
Modified:
   csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/ClusterMaker.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/AbstractAttributeClusterAlgorithm.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/BaseMatrix.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/Clusters.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/DistanceMatrix.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/Hopach.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAM.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/types/Hopachable.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/HopachablePAM.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/HopachablePAMTest.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAM.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMTest.java
   
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/silhouette/MSplitSilhouetteCalculator.java
   csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/ui/KnnView.java
Log:
Added PAM and HOPACH


Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/ClusterMaker.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/ClusterMaker.java    
    2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/ClusterMaker.java    
    2012-08-10 04:51:16 UTC (rev 30155)
@@ -67,8 +67,10 @@
 import clusterMaker.algorithms.ClusterAlgorithm;
 import clusterMaker.algorithms.attributeClusterers.autosome.AutoSOMECluster;
 import 
clusterMaker.algorithms.attributeClusterers.hierarchical.HierarchicalCluster;
+import clusterMaker.algorithms.attributeClusterers.hopach.HopachPAMClusterer;
 import clusterMaker.algorithms.attributeClusterers.kmeans.KMeansCluster;
 import clusterMaker.algorithms.attributeClusterers.kmedoid.KMedoidCluster;
+import clusterMaker.algorithms.attributeClusterers.pam.PAMClusterer;
 import 
clusterMaker.algorithms.attributeClusterers.FeatureVector.FeatureVectorCluster;
 
 import clusterMaker.algorithms.networkClusterers.TransClust.TransClustCluster;
@@ -133,6 +135,8 @@
                addClusterAlgorithm(menu, new HierarchicalCluster());
                addClusterAlgorithm(menu, new KMeansCluster());
                addClusterAlgorithm(menu, new KMedoidCluster());
+               addClusterAlgorithm(menu, new PAMClusterer());
+               addClusterAlgorithm(menu, new HopachPAMClusterer());
                // addClusterAlgorithm(menu, new QTCluster());
 
                menu.addSeparator();

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/AbstractAttributeClusterAlgorithm.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/AbstractAttributeClusterAlgorithm.java
    2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/AbstractAttributeClusterAlgorithm.java
    2012-08-10 04:51:16 UTC (rev 30155)
@@ -359,8 +359,11 @@
                if (halted()) return "Halted by user";
 
                // Cluster
-               int ifound = kcluster(nClusters, nIterations, matrix, metric, 
clusters);
+               int nClustersFound = kcluster(nClusters, nIterations, matrix, 
metric, clusters);
                if (halted()) return "Halted by user";
+               
+               // TODO Change other algorithms s.t. the number of clusters 
found is returned
+               if (nClusters == 0) nClusters = nClustersFound;
 
                // OK, now run our silhouette on our final result
                Silhouettes sResult = SilhouetteCalculator.calculate(matrix, 
metric, clusters);
@@ -375,14 +378,24 @@
                this isn't working...
                renumberClusters(nClusters, clusters);
        */
+               // NB  HOPACH clusters should not be re-ordered
 
                rowOrder = matrix.indexSort(clusters, clusters.length);
                // System.out.println(Arrays.toString(rowOrder));
                // Update the network attributes
                updateAttributes(algorithm);
+               
+               // FIXME For HOPACH, nClusters is determined by the algorithm, 
and is neither estimated nor predefined... 
 
                String resultString =  "Created "+nClusters+" clusters with 
average silhouette = "+sResult.getMean();
                logger.info(resultString);
+               
+               String s = "Clusters: ";
+               for (int i = 0; i < clusters.length; ++i) {
+                       s += clusters[i] + ", ";
+               }
+               logger.info(s);
+               
                return resultString;
        }
        

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/BaseMatrix.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/BaseMatrix.java
   2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/BaseMatrix.java
   2012-08-10 04:51:16 UTC (rev 30155)
@@ -37,6 +37,7 @@
 
 /**
  *  BaseMatrix is a basic numeric matrix.
+ *  Independent of Cytoscape.
  */
 public class BaseMatrix {
        protected int nRows;

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/Clusters.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/Clusters.java
     2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/Clusters.java
     2012-08-10 04:51:16 UTC (rev 30155)
@@ -5,6 +5,7 @@
 
 /**
  * Clusters store clustering results.
+ * Independent of Cytoscape.
  * @author djh.shih
  *
  */
@@ -32,6 +33,21 @@
        }
        
        /**
+        * Special constructor for building singleton clusters.
+        * @param k number of singleton clusters
+        */
+       public Clusters(int k) {
+               int[] t = new int[k];
+               for (int i = 0; i < k; ++i) {
+                       t[i] = k;
+               }
+               this.index = t;
+               this.orderedLabels = Arrays.copyOf(t, t.length);
+               this.k = k;
+               this.cost = 0.0;
+       }
+       
+       /**
         * Constructor. No cluster label reassignment. No error checking.
         * @param assignments cluster index/labels of each element (clusters 
must be labeled 0 to k-1)
         * @param k number of clusters

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/DistanceMatrix.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/DistanceMatrix.java
       2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/DistanceMatrix.java
       2012-08-10 04:51:16 UTC (rev 30155)
@@ -7,6 +7,7 @@
 
 /**
  * Distance matrix. Matrix of distances between data elements.
+ * Independent of Cytoscape.
  * @author djh.shih
  */
 public class DistanceMatrix {

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/Hopach.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/Hopach.java
        2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/Hopach.java
        2012-08-10 04:51:16 UTC (rev 30155)
@@ -9,6 +9,7 @@
 
 /**
  * Hopach performs HOPACH using a Hopachable partitioner.
+ * Independent of Cytoscape.
  * @author djh.shih
  *
  */
@@ -27,11 +28,14 @@
        ArrayList<Clusters> splits;
        
        // maximum number of partitioning levels
-       int maxLevel;
+       int maxLevel = 9;
        
        // minimum cost reduction
-       double minCostReduction;
+       double minCostReduction = 0;
        
+       // whether to force split the initial level
+       boolean forceInitSplit = false;
+       
        /*
         * Initial set of parameters implemented
         * clusters = best
@@ -43,13 +47,14 @@
         */
        
        public Hopach(Hopachable partitioner) {
-               this(partitioner, 9, 0);
+               this.partitioner = partitioner;
+               initialize();
        }
        
-       public Hopach(Hopachable partitioner, int maxLevel, int 
minCostReduction) {
-               this.partitioner = partitioner;
+       public void setParameters(int maxLevel, int minCostReduction, boolean 
forceInitSplit) {
                this.maxLevel = maxLevel;
                this.minCostReduction = minCostReduction;
+               this.forceInitSplit = forceInitSplit;
                initialize();
        }
        
@@ -124,14 +129,14 @@
         * @return possibility of continuing split
         */
        Clusters initLevel() {
-               Clusters split = partitioner.split();
+               Clusters split = partitioner.split(forceInitSplit);
                sortInitLevel(split);
                splits.set(0, split);
                return split;
        }
        
        /**
-        * Attempt to collapse clusters in the specified level.
+        * Attempt to collapse clusters at the specified level.
         * @param level
         */
        Clusters collapse(int level) {
@@ -239,13 +244,18 @@
                        boolean rightNeighbour = j < nClusters - 1;
                        
                        int[] partition = partitions[i];
+                       if (partition.length == 0) {
+                               // partition is empty (partitioner returned 
fewer partitions than requested)
+                               continue;
+                       }
+                       
                        int neighbourIndex = rightNeighbour ? i+1 : i-1;
                        
                        // split partition
                        // TODO cache sub-partitioner here and in MSS calculator
                        //      or, cache partition and split results
                        Hopachable sub = partitioner.subset(partition);
-                       Clusters subsplit = sub.split();
+                       Clusters subsplit = sub.split(false);
                        
                        int subk = subsplit.getNumberOfClusters();
                        
@@ -277,13 +287,10 @@
                        costs[i] = subsplit.getCost();
                        
                        // copy over new cluster index
-                       int js = 0;
-                       int jj;
-                       for (jj = j; jj < j + sub.size(); ++jj) {
-                               clusterIndex[jj] = 
subsplit.getClusterIndex(js++) + k;
+                       for (int jj = 0; jj < sub.size(); ++jj) {
+                               clusterIndex[ partition[jj] ] = 
subsplit.getClusterIndex(jj) + k;
                        }
-                       j = jj;
-                       
+                       j += sub.size();
                        k += subk;
                        
                }
@@ -323,7 +330,7 @@
         */
        void sortInitLevel(Clusters split) {
                if (split.getNumberOfClusters() <= 2) {
-                       // order of 2 or fewer clusters cannot be optiimized
+                       // order of 2 or fewer clusters cannot be optimized
                        return;
                }
                

Added: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachClustererOld.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachClustererOld.java
                            (rev 0)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachClustererOld.java
    2012-08-10 04:51:16 UTC (rev 30155)
@@ -0,0 +1,135 @@
+/* vim: set ts=2: */
+/**
+ * Copyright (c) 2011 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions, and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions, and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *   3. Redistributions must acknowledge that this software was
+ *      originally developed by the UCSF Computer Graphics Laboratory
+ *      under support by the NIH National Center for Research Resources,
+ *      grant P41-RR01081.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+package clusterMaker.algorithms.attributeClusterers.hopach;
+
+import java.awt.GridLayout;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import javax.swing.JPanel;
+
+// Cytoscape imports
+import cytoscape.Cytoscape;
+import cytoscape.data.CyAttributes;
+import cytoscape.layout.Tunable;
+import cytoscape.logger.CyLogger;
+import cytoscape.task.TaskMonitor;
+
+import clusterMaker.algorithms.AbstractClusterAlgorithm;
+import clusterMaker.algorithms.ClusterAlgorithm;
+import clusterMaker.algorithms.attributeClusterers.AbstractAttributeClusterer;
+import clusterMaker.algorithms.attributeClusterers.DistanceMetric;
+import clusterMaker.ui.ClusterViz;
+import clusterMaker.ui.KnnView;
+
+
+/**
+ * HopachCluster implements the HOPACH (Hierarchical Ordered Partitioning and 
Collapsing Hybrid) 
+ * algorithm of van der Laan and Pollard. The algorithm can be basically 
outlined as:
+ * while (minClusterSize &gt; 3)
+ *             foreach (level)
+ *                     k = averageSilhouette(K);       // Get the average 
silhouette for k=2,...,K
+ *                     partitionClusters(k);   // Partition the clusters with 
PAM
+ *                     orderClusters();                        // Order the 
new clusters
+ *                     collapseClusters();     // Collapse clusters
+ *                     level++;
+ *
+ * where partitionClusters() uses PAM (Partition About Medoids)
+ * algorithm (we actually use our k-medoid implementation)
+ *
+ * User inputs: 
+ *     K - the maximum number of levels in the tree (15)
+ *     kmax - the maximum number of children at at each node in the tree (1-9)
+ *     coll - collapse approach
+ *     attributeList - the names of the features to cluster on
+ *     metric - the distance metric (Euclidean distance is used in HOPACH)
+ *
+ * Output:
+ *     Ordered cluster tree
+ *
+ *     Reference: 
+ *             M.J. van der Laan, K.S. Pollard (2001). Hybrid clustering of 
gene expression 
+ *             data with visualization and the bootstrap. Journal of 
Statistical Planning and 
+ *             Inference, 2003, 117: 275-303
+ *
+ * TODO: Get R source code to figure out exact algorithm
+ */
+public class HopachClustererOld extends AbstractAttributeClusterer {
+
+       String[] attributeArray = new String[1];
+
+       TaskMonitor monitor = null;
+       CyLogger logger = null;
+
+       public HopachClustererOld() {
+               super();
+               logger = CyLogger.getLogger(HopachClustererOld.class);
+               initializeProperties();
+       }
+
+       public String getShortName() {return "hopach";};
+       public String getName() {return "HOPACH cluster";};
+
+       public JPanel getSettingsPanel() {
+               return null;
+       }
+
+       public ClusterViz getVisualizer() {
+               return null;
+       }
+
+       public void initializeProperties() {
+               super.initializeProperties();
+               updateSettings(true);
+       }
+
+       public void updateSettings() {
+               updateSettings(false);
+       }
+
+       public void updateSettings(boolean force) {
+               clusterProperties.updateValues();
+               super.updateSettings(force);
+
+       }
+
+       public void doCluster(TaskMonitor monitor) {
+               this.monitor = monitor;
+       }
+
+       public boolean isAvailable() {
+               return true;
+       }
+
+}

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAM.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAM.java
     2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAM.java
     2012-08-10 04:51:16 UTC (rev 30155)
@@ -7,6 +7,7 @@
 /**
  * HopachPAM is a specialized a specialized Hopach algorithm that uses the 
  * PAM partitioner (Hopach-PAM).
+ * Independent of Cytoscape.
  * @author djh.shih
  *
  */

Added: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAMCluster.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAMCluster.java
                              (rev 0)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAMCluster.java
      2012-08-10 04:51:16 UTC (rev 30155)
@@ -0,0 +1,36 @@
+package clusterMaker.algorithms.attributeClusterers.hopach;
+
+import cytoscape.logger.CyLogger;
+import cytoscape.task.TaskMonitor;
+import 
clusterMaker.algorithms.attributeClusterers.AbstractAttributeClusterAlgorithm;
+import clusterMaker.algorithms.attributeClusterers.Clusters;
+import clusterMaker.algorithms.attributeClusterers.DistanceMetric;
+import clusterMaker.algorithms.attributeClusterers.Matrix;
+
+public class HopachPAMCluster extends AbstractAttributeClusterAlgorithm {
+       
+       public HopachPAMCluster(String weightAttributes[], DistanceMetric 
metric, CyLogger logger, TaskMonitor monitor) {
+               this.logger = logger;
+               this.weightAttributes = weightAttributes;
+               this.metric = metric;
+               this.monitor = monitor;
+               resetAttributes();
+       }
+       
+       @Override
+       public int kcluster(int nClusters, int nIterations, Matrix matrix, 
DistanceMetric metric, int[] clusterId) {
+               
+               if (monitor != null) monitor.setPercentCompleted(0);
+               
+               HopachPAM hopachPam = new HopachPAM(matrix, metric);
+               hopachPam.setParameters(9,  0,  true);
+               Clusters c = hopachPam.run();
+               
+               // copy results into clusterId
+               for (int i = 0; i < c.size(); ++i) {
+                       clusterId[i] = c.getClusterIndex(i);
+               }
+               
+               return c.getNumberOfClusters();
+       }
+}

Added: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAMClusterer.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAMClusterer.java
                            (rev 0)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/HopachPAMClusterer.java
    2012-08-10 04:51:16 UTC (rev 30155)
@@ -0,0 +1,200 @@
+package clusterMaker.algorithms.attributeClusterers.hopach;
+
+import java.util.Arrays;
+
+import javax.swing.JPanel;
+
+import cytoscape.layout.Tunable;
+import cytoscape.logger.CyLogger;
+import cytoscape.task.TaskMonitor;
+import clusterMaker.algorithms.ClusterAlgorithm;
+import clusterMaker.algorithms.attributeClusterers.AbstractAttributeClusterer;
+import clusterMaker.algorithms.attributeClusterers.BaseMatrix;
+import clusterMaker.ui.ClusterViz;
+import clusterMaker.ui.KnnView;
+
+public class HopachPAMClusterer extends AbstractAttributeClusterer {
+       
+       public HopachPAMClusterer() {
+               logger = CyLogger.getLogger(HopachPAMClusterer.class);
+               initializeProperties();
+       }
+       
+       @Override
+       public void initializeProperties() {
+               super.initializeProperties();
+               
+               clusterProperties.add(
+                       new Tunable(
+                               "dMetric",
+                               "Distance Metric",
+                               Tunable.LIST, new Integer(0),
+                               (Object)BaseMatrix.distanceTypes, null, 0
+                       )
+               );
+               
+               clusterProperties.add(
+                       new Tunable(
+                               "attributeListGroup",
+                               "Source for array data",
+                               Tunable.GROUP, new Integer(1)
+                       )
+               );
+               
+               attributeArray = getAllAttributes();
+               clusterProperties.add(
+                       new Tunable(
+                               "attributeList",
+                               "Array sources",
+                               Tunable.LIST, "",
+                               (Object)attributeArray, null, 
Tunable.MULTISELECT
+                       )
+               );
+               
+               clusterProperties.add(
+                       new Tunable(
+                               "selectedOnly",
+                               "Only use selected nodes/edges for cluster",
+                               Tunable.BOOLEAN, new Boolean(selectedOnly)
+                       )
+               );
+               
+               clusterProperties.add(
+                       new Tunable(
+                               "clusterAttributes",
+                               "Cluster attributes as well as nodes",
+                               Tunable.BOOLEAN, new Boolean(clusterAttributes)
+                       )
+               );
+               
+               clusterProperties.add(
+                       new Tunable(
+                               "createGroups",
+                               "Create groups from clusters",
+                               Tunable.BOOLEAN, new Boolean(createGroups)
+                       )
+               );
+               
+               clusterProperties.initializeProperties();
+               updateSettings(true);
+       }
+       
+       @Override
+       public void updateSettings() {
+               updateSettings(false);
+       }
+       
+       public void updateSettings(boolean force) {
+               clusterProperties.updateValues();
+               super.updateSettings(force);
+               
+               Tunable t;
+               
+               t = clusterProperties.get("dMetric");
+               if ((t != null) && (t.valueChanged() || force)) {
+                       distanceMetric = BaseMatrix.distanceTypes[((Integer) 
t.getValue()).intValue()];
+               }
+               
+               t = clusterProperties.get("clusterAttributes");
+               if ((t != null) && (t.valueChanged() || force)) {
+                       clusterAttributes = ((Boolean) 
t.getValue()).booleanValue();
+               }
+
+               t = clusterProperties.get("selectedOnly");
+               if ((t != null) && (t.valueChanged() || force)) {
+                       selectedOnly = ((Boolean) t.getValue()).booleanValue();
+               }
+
+               t = clusterProperties.get("createGroups");
+               if ((t != null) && (t.valueChanged() || force)) {
+                       createGroups = ((Boolean) t.getValue()).booleanValue();
+               }
+
+               t = clusterProperties.get("attributeList");
+               if ((t != null) && (t.valueChanged() || force)) {
+                       dataAttributes = (String) t.getValue();
+               }
+       }
+
+       @Override
+       public String getShortName() {
+               return "HOPACH";
+       }
+
+       @Override
+       public String getName() {
+               return "HOPACH-PAM";
+       }
+       
+       @Override
+       public ClusterViz getVisualizer() {
+               return new KnnView();
+       }
+
+       @Override
+       public JPanel getSettingsPanel() {
+               // update attributes
+               Tunable attributeTunable = 
clusterProperties.get("attributeList");
+               attributeArray = getAllAttributes();
+               attributeTunable.setLowerBound((Object)attributeArray);
+               
+               return clusterProperties.getTunablePanel();
+       }
+
+       @Override
+       public void doCluster(TaskMonitor monitor) {
+               this.monitor = monitor;
+               
+               if (debug) {
+                       logger.debug("Performing HOPACH-PAM cluster with k = " 
+ kNumber + " using " + distanceMetric + " and attributes: " + dataAttributes);
+               }
+               
+               // sanity check of parameters
+               if (dataAttributes == null || dataAttributes.length() == 0) {
+                       if (monitor != null) {
+                               monitor.setException(null, "Error: no attribute 
list selected");
+                               logger.warning("Must have an attribute list to 
use for cluster weighting");
+                       } else {
+                               logger.error("Must have an attribute list to 
use or cluster weighting");
+                       }
+                       return;
+               }
+       
+               // get attributes to be used for clustering
+               String attributeArray[] = getAttributeArray(dataAttributes);
+               Arrays.sort(attributeArray);
+               
+               HopachPAMCluster algo = new HopachPAMCluster(attributeArray, 
distanceMetric, logger, monitor);
+               algo.setCreateGroups(createGroups);
+               algo.setIgnoreMissing(true);
+               algo.setSelectedOnly(selectedOnly);
+               algo.setDebug(debug);
+               algo.setUseSilhouette(useSilhouette);
+               algo.setKMax(kMax);
+               algo.setClusterInterface(this);
+               
+               String resultsString = getName() + " results:";
+               
+               int nIterations = 0;
+               
+               // Cluster the attributes
+               if (clusterAttributes && attributeArray.length > 1) {
+                       if (monitor != null) {
+                               monitor.setStatus("Clustering attributes");
+                       }
+                       resultsString = "\nAttributes: " + 
algo.cluster(kNumber,  nIterations,  true, getShortName());
+               }
+               
+               // Cluster the nodes
+               if (monitor != null) {
+                       monitor.setStatus("Clustering nodes");
+               }
+               resultsString = "\nNodes: " + algo.cluster(kNumber, 
nIterations, false, getShortName());
+               if (monitor != null) {
+                       monitor.setStatus(resultsString);
+               }
+               
+               // signal completion to listeners
+               pcs.firePropertyChange(ClusterAlgorithm.CLUSTER_COMPUTED, null, 
this);
+       }
+}

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/types/Hopachable.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/types/Hopachable.java
      2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/hopach/types/Hopachable.java
      2012-08-10 04:51:16 UTC (rev 30155)
@@ -12,7 +12,7 @@
        // Split elements into partitions
        // A class implementing Hopachable is free to choose the best k, and 
can use simply choose k = argmin_k MSS
        //   by calling a separately provided functions to calculate min MSS
-       Clusters split();
+       Clusters split(boolean forceSplit);
        
        // Return a matrix with distances from each element to each cluster
        double[][] segregations(Clusters clusters);

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/HopachablePAM.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/HopachablePAM.java
    2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/HopachablePAM.java
    2012-08-10 04:51:16 UTC (rev 30155)
@@ -52,8 +52,8 @@
        }
        
        @Override
-       public Clusters split() {
-               return 
MSplitSilhouetteCalculator.splitByMedianSplitSilhouette(this, maxK, maxL);
+       public Clusters split(boolean forceSplit) {
+               return 
MSplitSilhouetteCalculator.splitByMedianSplitSilhouette(this, maxK, maxL, 
forceSplit);
        }
 
        @Override

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/HopachablePAMTest.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/HopachablePAMTest.java
        2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/HopachablePAMTest.java
        2012-08-10 04:51:16 UTC (rev 30155)
@@ -92,7 +92,7 @@
                HopachablePAM pam = new HopachablePAM(mat, 
DistanceMetric.CITYBLOCK);
                pam.setParameters(9, 9);
                
-               Clusters c = pam.split();
+               Clusters c = pam.split(false);
                
                // check that data are split into expected number of clusters
                assertEquals(c.getNumberOfClusters(), k);

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAM.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAM.java
      2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAM.java
      2012-08-10 04:51:16 UTC (rev 30155)
@@ -13,6 +13,7 @@
  * Partitioning Around Medoids. Cluster data elements by aiming to minimize 
the average
  * dissimilarity of objects to their closest selected element (medoid).
  * Data elements are indexable.
+ * Independent of Cytoscape.
  * NB   This class is an implementation of the PAM algorithm described in the 
course notes
  *      at <www.cs.umb.edu/cs738/pam1.pdf> (accessed 2012-07-31).
  *      There appears to be different variants of the PAM algorithm varying in 
details
@@ -22,6 +23,7 @@
  *      The cluster results from current implementation can differ from the 
implementation 
  *      in R's cluster::pam. (See PAMTest for details.)
  * @author djh.shih
+ * @comment
  *
  */
 public class PAM implements KClusterable {
@@ -62,6 +64,8 @@
        // required since Java's HashSet cannot use native types
        Integer[] elements;
        
+       int maxSwaps = 1000;
+       
        public PAM(BaseMatrix data, DistanceMetric metric) {
                this(data, metric, null, null);
        }
@@ -95,11 +99,15 @@
 
        @Override
        public Clusters cluster(int k) {
-               if (size() == 0) {
+               int n = size();
+               if (n == 0) {
                        throw new IllegalArgumentException("No data elements 
are indexed.");
                }
-               if (k >= size()) {
+               if (k > n) {
                        throw new IllegalArgumentException("Number of clusters 
must be less than the number of data elements.");
+               } else if (k == n) {
+                       // build trivial single clusters
+                       return new Clusters(k);
                }
                
                this.nClusters = k;
@@ -239,12 +247,15 @@
         */
        private void swapPhase() {
                boolean notConverged = true;
+               boolean continueLoop = true;
+               int nSwaps = 0;
                
-               while (notConverged) {
+               while (notConverged && continueLoop) {
                        notConverged = false;
+                       continueLoop = false;
        
                        Iterator<Integer> medIt = medoids.iterator();
-                       while (medIt.hasNext()) {
+                       while (medIt.hasNext() && continueLoop) {
                                int ii = medIt.next().intValue();
                                
                                Iterator<Integer> nonmedIt = 
nonmedoids.iterator();
@@ -287,10 +298,15 @@
                                        if (change < 0) {
                                                // distance to nearest medoid 
summed over all nonmedoids is improved: swap
                                                swap(hh, ii);
-                                               // non-convergence if any swap 
occurs
-                                               notConverged = true;
                                                //System.out.print("Swap " + hh 
+ " and " + ii + " for change = " + change + "\n");
                                                
+                                               // non-convergence if any swap 
occurs, up to a maximum number of swaps (to guard against swap cycles)
+                                               if (nSwaps++ < maxSwaps) {
+                                                       notConverged = true;
+                                               } else {
+                                                       continueLoop = false;
+                                               }
+                                               
                                                // reset iterator
                                                medIt = medoids.iterator();
                                                // break out of inner loop to 
consider next medoid

Added: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMCluster.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMCluster.java
                               (rev 0)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMCluster.java
       2012-08-10 04:51:16 UTC (rev 30155)
@@ -0,0 +1,36 @@
+package clusterMaker.algorithms.attributeClusterers.pam;
+
+import cytoscape.logger.CyLogger;
+import cytoscape.task.TaskMonitor;
+
+import 
clusterMaker.algorithms.attributeClusterers.AbstractAttributeClusterAlgorithm;
+import clusterMaker.algorithms.attributeClusterers.Clusters;
+import clusterMaker.algorithms.attributeClusterers.DistanceMetric;
+import clusterMaker.algorithms.attributeClusterers.Matrix;
+
+public class PAMCluster extends AbstractAttributeClusterAlgorithm {
+       
+       public PAMCluster(String weightAttributes[], DistanceMetric metric, 
CyLogger log, TaskMonitor monitor) {
+               this.logger = log;
+               this.weightAttributes = weightAttributes;
+               this.metric = metric;
+               this.monitor = monitor;
+               resetAttributes();
+       }
+       
+       @Override
+       public int kcluster(int nClusters, int nIterations, Matrix matrix, 
DistanceMetric metric, int[] clusterId) {
+               
+               if (monitor != null) monitor.setPercentCompleted(0);
+               
+               PAM pam = new PAM(matrix, metric);
+               Clusters c = pam.cluster(nClusters);
+               
+               // copy results into clusterId
+               for (int i = 0; i < c.size(); ++i) {
+                       clusterId[i] = c.getClusterIndex(i);
+               }
+               
+               return c.getNumberOfClusters();
+       }
+}

Added: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMClusterer.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMClusterer.java
                             (rev 0)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMClusterer.java
     2012-08-10 04:51:16 UTC (rev 30155)
@@ -0,0 +1,217 @@
+package clusterMaker.algorithms.attributeClusterers.pam;
+
+import java.util.Arrays;
+
+import javax.swing.JPanel;
+
+import cytoscape.layout.Tunable;
+import cytoscape.logger.CyLogger;
+import cytoscape.task.TaskMonitor;
+
+import clusterMaker.algorithms.ClusterAlgorithm;
+import clusterMaker.algorithms.attributeClusterers.AbstractAttributeClusterer;
+import clusterMaker.algorithms.attributeClusterers.BaseMatrix;
+import clusterMaker.ui.ClusterViz;
+import clusterMaker.ui.KnnView;
+
+/**
+ * 
+ * @author DavidS
+ *
+ */
+public class PAMClusterer extends AbstractAttributeClusterer {
+       
+       public PAMClusterer() {
+               logger = CyLogger.getLogger(PAMClusterer.class);
+               initializeProperties();
+       }
+       
+       @Override
+       public void initializeProperties() {
+               super.initializeProperties();
+               
+               addKTunables();
+               
+               // TODO Number of iterations
+               
+               clusterProperties.add(
+                       new Tunable(
+                               "dMetric",
+                               "Distance Metric",
+                               Tunable.LIST, new Integer(0),
+                               (Object)BaseMatrix.distanceTypes, null, 0
+                       )
+               );
+               
+               clusterProperties.add(
+                       new Tunable(
+                               "attributeListGroup",
+                               "Source for array data",
+                               Tunable.GROUP, new Integer(1)
+                       )
+               );
+               
+               attributeArray = getAllAttributes();
+               clusterProperties.add(
+                       new Tunable(
+                               "attributeList",
+                               "Array sources",
+                               Tunable.LIST, "",
+                               (Object)attributeArray, null, 
Tunable.MULTISELECT
+                       )
+               );
+               
+               clusterProperties.add(
+                       new Tunable(
+                               "selectedOnly",
+                               "Only use selected nodes/edges for cluster",
+                               Tunable.BOOLEAN, new Boolean(selectedOnly)
+                       )
+               );
+               
+               clusterProperties.add(
+                       new Tunable(
+                               "clusterAttributes",
+                               "Cluster attributes as well as nodes",
+                               Tunable.BOOLEAN, new Boolean(clusterAttributes)
+                       )
+               );
+               
+               clusterProperties.add(
+                       new Tunable(
+                               "createGroups",
+                               "Create groups from clusters",
+                               Tunable.BOOLEAN, new Boolean(createGroups)
+                       )
+               );
+               
+               clusterProperties.initializeProperties();
+               updateSettings(true);
+       }
+       
+       @Override
+       public void updateSettings() {
+               updateSettings(false);
+       }
+       
+       public void updateSettings(boolean force) {
+               clusterProperties.updateValues();
+               super.updateSettings(force);
+               updateKTunables(force);
+               
+               Tunable t;
+               
+               // TODO Number of iterations
+               
+               t = clusterProperties.get("dMetric");
+               if ((t != null) && (t.valueChanged() || force)) {
+                       distanceMetric = BaseMatrix.distanceTypes[((Integer) 
t.getValue()).intValue()];
+               }
+               
+               t = clusterProperties.get("clusterAttributes");
+               if ((t != null) && (t.valueChanged() || force)) {
+                       clusterAttributes = ((Boolean) 
t.getValue()).booleanValue();
+               }
+
+               t = clusterProperties.get("selectedOnly");
+               if ((t != null) && (t.valueChanged() || force)) {
+                       selectedOnly = ((Boolean) t.getValue()).booleanValue();
+               }
+
+               t = clusterProperties.get("createGroups");
+               if ((t != null) && (t.valueChanged() || force)) {
+                       createGroups = ((Boolean) t.getValue()).booleanValue();
+               }
+
+               t = clusterProperties.get("attributeList");
+               if ((t != null) && (t.valueChanged() || force)) {
+                       dataAttributes = (String) t.getValue();
+               }
+       }
+
+       @Override
+       public String getShortName() {
+               return "PAM";
+       }
+
+       @Override
+       public String getName() {
+               return "Partitioning Around Medoids";
+       }
+       
+       @Override
+       public ClusterViz getVisualizer() {
+               return new KnnView();
+       }
+
+       @Override
+       public JPanel getSettingsPanel() {
+               // update attributes
+               Tunable attributeTunable = 
clusterProperties.get("attributeList");
+               attributeArray = getAllAttributes();
+               attributeTunable.setLowerBound((Object)attributeArray);
+               
+               // update estimate
+               updateKEstimates();
+               
+               return clusterProperties.getTunablePanel();
+       }
+
+       @Override
+       public void doCluster(TaskMonitor monitor) {
+               this.monitor = monitor;
+               
+               if (debug) {
+                       logger.debug("Performing PAM cluster with k = " + 
kNumber + " using " + distanceMetric + " and attributes: " + dataAttributes);
+               }
+               
+               // sanity check of parameters
+               if (dataAttributes == null || dataAttributes.length() == 0) {
+                       if (monitor != null) {
+                               monitor.setException(null, "Error: no attribute 
list selected");
+                               logger.warning("Must have an attribute list to 
use for cluster weighting");
+                       } else {
+                               logger.error("Must have an attribute list to 
use or cluster weighting");
+                       }
+                       return;
+               }
+       
+               // get attributes to be used for clustering
+               String attributeArray[] = getAttributeArray(dataAttributes);
+               Arrays.sort(attributeArray);
+               
+               PAMCluster algo = new PAMCluster(attributeArray, 
distanceMetric, logger, monitor);
+               algo.setCreateGroups(createGroups);
+               algo.setIgnoreMissing(true);
+               algo.setSelectedOnly(selectedOnly);
+               algo.setDebug(debug);
+               algo.setUseSilhouette(useSilhouette);
+               algo.setKMax(kMax);
+               algo.setClusterInterface(this);
+               
+               String resultsString = "PAM results:";
+               
+               int nIterations = 0;
+               
+               // Cluster the attributes
+               if (clusterAttributes && attributeArray.length > 1) {
+                       if (monitor != null) {
+                               monitor.setStatus("Clustering attributes");
+                       }
+                       resultsString = "\nAttributes: " + 
algo.cluster(kNumber,  nIterations,  true, getShortName());
+               }
+               
+               // Cluster the nodes
+               if (monitor != null) {
+                       monitor.setStatus("Clustering nodes");
+               }
+               resultsString = "\nNodes: " + algo.cluster(kNumber, 
nIterations, false, getShortName());
+               if (monitor != null) {
+                       monitor.setStatus(resultsString);
+               }
+               
+               // signal completion to listeners
+               pcs.firePropertyChange(ClusterAlgorithm.CLUSTER_COMPUTED, null, 
this);
+       }
+       
+}

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMTest.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMTest.java
  2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/pam/PAMTest.java
  2012-08-10 04:51:16 UTC (rev 30155)
@@ -9,6 +9,23 @@
 import clusterMaker.algorithms.attributeClusterers.DistanceMetric;
 
 public class PAMTest {
+       
+       @Test
+       public void testSingletonCluster() {
+               Double[] data = {
+                       .9, .9
+               };
+               int k = 1;
+               
+               int[] ans = {0};
+               
+               BaseMatrix mat = new BaseMatrix(0, 2, data);
+               PAM pam = new PAM(mat, DistanceMetric.CITYBLOCK);
+               
+               Clusters c = pam.cluster(k);
+               
+               assertEquals(c.getNumberOfClusters(), k);
+       }
 
        @Test
        public void testCluster() {

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/silhouette/MSplitSilhouetteCalculator.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/silhouette/MSplitSilhouetteCalculator.java
        2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/algorithms/attributeClusterers/silhouette/MSplitSilhouetteCalculator.java
        2012-08-10 04:51:16 UTC (rev 30155)
@@ -131,6 +131,10 @@
        }
        
        public static Clusters splitByMeanSplitSilhouette(Subsegregatable sseg, 
int K, int L) {
+               return splitByMeanSplitSilhouette(sseg, K, L, false);
+       }
+       
+       public static Clusters splitByMeanSplitSilhouette(Subsegregatable sseg, 
int K, int L, boolean forceSplit) {
                Clusters split = null;
                int m = sseg.size();
                
@@ -140,9 +144,11 @@
                        K = m / 3;
                }
                
+               int minK = (forceSplit ? 2 : 1);
+               
                // minimize the mean split silhouette
                double avgSplitSil = Double.POSITIVE_INFINITY;
-               for (int k = 1; k <= K; k++) {
+               for (int k = minK; k <= K; k++) {
                        Clusters clusters = sseg.cluster(k);
                        double t = meanSplitSilhouette(sseg, clusters, L);
                        if (t < avgSplitSil) {
@@ -151,13 +157,19 @@
                        }
                }
                
-               if (split != null) {
-                       split.setCost(avgSplitSil);
-               }
+               if (split == null) {
+                       split = sseg.cluster(minK);
+               } 
+               split.setCost(avgSplitSil);
+               
                return split;
        }
        
        public static Clusters splitByMedianSplitSilhouette(Subsegregatable 
sseg, int K, int L) {
+               return splitByMedianSplitSilhouette(sseg, K, L, false);
+       }
+       
+       public static Clusters splitByMedianSplitSilhouette(Subsegregatable 
sseg, int K, int L, boolean forceSplit) {
                Clusters split = null;
                int m = sseg.size();
                
@@ -167,9 +179,11 @@
                        K = m / 3;
                }
                
-               // minimize the mean split silhouette
+               int minK = (forceSplit ? 2 : 1);
+               
+               // minimize the median split silhouette
                double avgSplitSil = Double.POSITIVE_INFINITY;
-               for (int k = 1; k <= K; k++) {
+               for (int k = minK; k <= K; k++) {
                        Clusters clusters = sseg.cluster(k);
                        double t = medianSplitSilhouette(sseg, clusters, L);
                        if (t < avgSplitSil) {
@@ -178,9 +192,11 @@
                        }
                }
                
-               if (split != null) {
-                       split.setCost(avgSplitSil);
-               }
+               if (split == null) {
+                       split = sseg.cluster(minK);
+               } 
+               split.setCost(avgSplitSil);
+               
                return split;
        }
        

Deleted: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/treeview/CancelableSettingsDialog.java
===================================================================
--- 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/treeview/CancelableSettingsDialog.java
   2012-08-10 02:24:49 UTC (rev 30154)
+++ 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/treeview/CancelableSettingsDialog.java
   2012-08-10 04:51:16 UTC (rev 30155)
@@ -1,104 +0,0 @@
-/* BEGIN_HEADER                                              Java TreeView
- *
- * $Author: alokito $
- * $RCSfile: CancelableSettingsDialog.java,v $
- * $Revision: 1.6 $
- * $Date: 2004/12/21 03:28:13 $
- * $Name:  $
- *
- * This file is part of Java TreeView
- * Copyright (C) 2001-2003 Alok Saldanha, All Rights Reserved. Modified by 
- * Alex Segal 2004/08/13. Modifications Copyright (C) Lawrence Berkeley Lab.
- *
- * This software is provided under the GNU GPL Version 2. In particular,
- *
- * 1) If you modify a source file, make a comment in it containing your name 
and the date.
- * 2) If you distribute a modified version, you must do it under the GPL 2.
- * 3) Developers are encouraged but not required to notify the Java TreeView 
- * maintainers at [email protected] when they make a useful addition. 
It would 
- * be nice if significant contributions could be merged into the main 
distribution.
- *
- * A full copy of the license can be found in gpl.txt or online at
- * http://www.gnu.org/licenses/gpl.txt
- *
- * END_HEADER
- */
-package clusterMaker.treeview.dendroview;
-
-import clusterMaker.treeview.SettingsPanel;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-import javax.swing.JButton;
-import javax.swing.JDialog;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-
-/**
- *  this is a dialog which displays a single cancelable settings panel
- *
- * @author     Alok Saldanha <[email protected]>
- * @version    @version $Revision: 1.6 $ $Date: 2004/12/21 03:28:13 $
- */
-public class CancelableSettingsDialog extends JDialog {
-       SettingsPanel settingsPanel;
-       JDialog settingsFrame;
-
-
-       /**
-        *
-        * @param  frame  <code>JFrame</code> to block on
-        * @param  title  a title for the dialog
-        * @param  panel  A <code>SettingsPanel</code> to feature in the dialog.
-        */
-       public CancelableSettingsDialog(JFrame frame, String title, 
SettingsPanel panel) {
-               super(frame, title, true);
-               settingsPanel = panel;
-               settingsFrame = this;
-               JPanel inner  = new JPanel();
-               inner.setLayout(new BorderLayout());
-               inner.add((Component) panel, BorderLayout.CENTER);
-               inner.add(new ButtonPanel(), BorderLayout.SOUTH);
-               getContentPane().add(inner);
-               pack();
-       }
-
-
-       class ButtonPanel extends JPanel {
-               ButtonPanel() {
-                       JButton save_button    = new JButton("Save");
-                       save_button.addActionListener(
-                               new ActionListener() {
-                                       public void actionPerformed(ActionEvent 
e) {
-                                               try {
-                                                       
settingsPanel.synchronizeTo();
-                                                       settingsFrame.dispose();
-                                               } catch 
(java.lang.OutOfMemoryError ex) {
-                                                       JPanel temp = new 
JPanel();
-                                                       temp. add(new 
JLabel("Out of memory, try smaller pixel settings or allocate more RAM"));
-                                                       temp. add(new 
JLabel("see Chapter 3 of Help->Documentation... for Out of Memory and Image 
Export)"));
-                                                       
-                                                       
JOptionPane.showMessageDialog(CancelableSettingsDialog.this,  temp);
-                                               }
-                                       }
-                               });
-                       add(save_button);
-
-                       JButton cancel_button  = new JButton("Cancel");
-                       cancel_button.addActionListener(
-                               new ActionListener() {
-                                       public void actionPerformed(ActionEvent 
e) {
-                                               settingsPanel.synchronizeFrom();
-                                               settingsFrame.dispose();
-                                       }
-                               });
-                       add(cancel_button);
-               }
-       }
-}
-

Modified: 
csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/ui/KnnView.java
===================================================================
--- csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/ui/KnnView.java  
2012-08-10 02:24:49 UTC (rev 30154)
+++ csplugins/trunk/ucsf/scooter/clusterMaker/src/clusterMaker/ui/KnnView.java  
2012-08-10 04:51:16 UTC (rev 30155)
@@ -126,9 +126,13 @@
                String netId = network.getIdentifier();
                if (networkAttributes.hasAttribute(netId, 
ClusterMaker.CLUSTER_TYPE_ATTRIBUTE)) {
                        String type = 
networkAttributes.getStringAttribute(netId, 
ClusterMaker.CLUSTER_TYPE_ATTRIBUTE);
-                       if (!networkAttributes.getStringAttribute(netId, 
ClusterMaker.CLUSTER_TYPE_ATTRIBUTE).equals("kmeans") &&
-          !networkAttributes.getStringAttribute(netId, 
ClusterMaker.CLUSTER_TYPE_ATTRIBUTE).equals("kmedoid") &&
-                           !networkAttributes.getStringAttribute(netId, 
ClusterMaker.CLUSTER_TYPE_ATTRIBUTE).equals("autosome_heatmap"))
+                       // TODO why is KnnView deciding which algorithms are 
visualizable, rather than having each algorithm decide whether itself is 
visualizable?
+                       if (!type.equals("kmeans") &&
+                               !type.equals("kmedoid") &&
+                           !type.equals("autosome_heatmap") &&
+                           !type.equals("PAM") &&
+                           !type.equals("HOPACH")
+                           )
                                return false;
                }
 

-- 
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