Author: mes
Date: 2011-08-05 15:13:53 -0700 (Fri, 05 Aug 2011)
New Revision: 26396

Modified:
   csplugins/trunk/ucsd/mes/VennDiagram/build.xml
   csplugins/trunk/ucsd/mes/VennDiagram/src/edu/uic/ncdm/venn/VennAnalytic.java
Log:
updated with latest code from Lee

Modified: csplugins/trunk/ucsd/mes/VennDiagram/build.xml
===================================================================
--- csplugins/trunk/ucsd/mes/VennDiagram/build.xml      2011-08-05 22:06:44 UTC 
(rev 26395)
+++ csplugins/trunk/ucsd/mes/VennDiagram/build.xml      2011-08-05 22:13:53 UTC 
(rev 26396)
@@ -7,7 +7,7 @@
   <target name="init">
     <tstamp/>
     <property name="name" value="VennDiagram"/>
-    <property name="version" value="1.03"/>
+    <property name="version" value="1.04"/>
 
     <echo message="Building ${name} version ${version} ..."/>
 

Modified: 
csplugins/trunk/ucsd/mes/VennDiagram/src/edu/uic/ncdm/venn/VennAnalytic.java
===================================================================
--- 
csplugins/trunk/ucsd/mes/VennDiagram/src/edu/uic/ncdm/venn/VennAnalytic.java    
    2011-08-05 22:06:44 UTC (rev 26395)
+++ 
csplugins/trunk/ucsd/mes/VennDiagram/src/edu/uic/ncdm/venn/VennAnalytic.java    
    2011-08-05 22:13:53 UTC (rev 26396)
@@ -23,576 +23,595 @@
 import cytoscape.logger.CyLogger;
 
 public class VennAnalytic {
-    private int nRows;
-    private int nCircles;
-    private int nPolygons;
-    private int nTot;
-    private double stress;
-    private double minStress;
-    private double[] polyData;
-    private double[] polyAreas;
-    private double[] polyHats;
-    private double[] circleData;
-    private String[] circleLabels;
-    private double[][] centers;
-    private double[] diameters;
-    private double stepsize;
-    private double maxArea;
-    private int totalCount;
+       private int nRows;
+       private int nCircles;
+       private int nPolygons;
+       private int nTot;
+       private double stress;
+       private double minStress;
+       private double[] intersectionCounts;
+       private double[] polyData;
+       private double[] polyAreas;
+       private double[] polyHats;
+       private double[] circleData;
+       private String[] circleLabels;
+       private double[][] centers;
+       private double[] diameters;
+       private double stepsize;
+       private double maxArea;
+       private int totalCount;
+       private boolean isEqualArea;
 
-    private static final CyLogger logger = 
CyLogger.getLogger(VennAnalytic.class);
+       private static final CyLogger logger = 
CyLogger.getLogger(VennAnalytic.class);
 
-    public VennAnalytic() {
-        stepsize = .01;
-        minStress = .000001;
-    }
+       public VennAnalytic() {
+               stepsize = .01;
+               minStress = .000001;
+               isEqualArea = false;
+       }
 
-    public VennDiagram compute(VennData vd) {
-        String[][] data = vd.data;
-        double[] areas = vd.areas;
-        boolean isAreas = vd.isAreas;
+       public VennDiagram compute(VennData vd) {
+               String[][] data = vd.data;
+               double[] areas = vd.areas;
+               boolean isAreas = vd.isAreas;
 
-        if (isAreas)
-            processAreaData(data, areas);
-        else
-            processElementData(data);
+               if (isAreas)
+                       processAreaData(data, areas);
+               else
+                       processElementData(data);
 
-        computeInitialConfiguration();
-        scaleDiameters(isAreas);
-        scaleConfiguration();
+               computeInitialConfiguration();
+               scaleDiameters();
+               scaleConfiguration();
 
-        minimizeGlobal();
+               minimizeGlobal();
+               minimizeLocal();
 
-        double[][] previousCenters = new double[nCircles][2];
-        copyCircles(centers, previousCenters);
-        double previousStress = stress;
+               return collectResults();
+       }
 
-        minimizeLocal();
+       private VennDiagram collectResults() {
+               double[] colors = new double[nCircles];
+               for (int j = 0; j < nCircles; j++)
+                       colors[j] = (double) (j + 1) / (nCircles + 1);
+               double stress01 = 0;
+               double stress05 = 0;
+               if (nCircles > 2) {
+                       stress01 = Math.exp(.909 * (nCircles - 6.105)) / (1 + 
Math.exp(.909 * (nCircles - 6.105)));
+                       stress05 = Math.exp(.900 * (nCircles - 5.129)) / (1 + 
Math.exp(.900 * (nCircles - 5.129)));
+               }
+               double[] residuals = new double[nPolygons - 1];
+               String[] residualLabels = new String[nPolygons - 1];
+               boolean[] warnings = new boolean[nPolygons -1];
+               double[][] luneCenters = new double[nPolygons -1][2];
+               double area = 0;
+               int nonZero = 0;
+               for (int i = 1; i < nPolygons; i++) {
+                       residuals[i - 1] = polyAreas[i] - polyHats[i];
+                       char[] c = encode(i);
+                       String s = "";
+                       double numIntersecting = 0.0;
+                       for (int j = 0; j < c.length; j++) {
+                               if (c[j] == '1') {
+                                       s += (circleLabels[j] + "&");
+                                       // record the centers of the circles
+                                       luneCenters[i-1][0] += centers[j][0];
+                                       luneCenters[i-1][1] += centers[j][1];
+                                       numIntersecting += 1.0;
+                               }
+                       }
 
-        if (stress > previousStress)
-            copyCircles(previousCenters, centers);
-        stress = computeStress();
+                       // find the lune centers
+                       if ( numIntersecting > 0 ) {
+                               luneCenters[i-1][0] /= numIntersecting;
+                               luneCenters[i-1][1] /= numIntersecting;
+                       } 
 
-        return collectResults();
-    }
+                       area += polyAreas[i];
+                       if (residuals[i - 1] != 0)
+                               nonZero++;
+                       s = s.substring(0, s.length() - 1);
+                       residualLabels[i - 1] = s;
+               }
+               logger.info("stress = " + stress + ", stress01 = " + stress01 + 
", stress05 = " + stress05);
 
-    private VennDiagram collectResults() {
-        double[] colors = new double[nCircles];
-        for (int j = 0; j < nCircles; j++)
-            colors[j] = (double) (j + 1) / (nCircles + 1);
-        double stress01 = 0;
-        double stress05 = 0;
-        if (nCircles > 2) {
-            stress01 = Math.exp(.909 * (nCircles - 6.105)) / (1 + 
Math.exp(.909 * (nCircles - 6.105)));
-            stress05 = Math.exp(.900 * (nCircles - 5.129)) / (1 + 
Math.exp(.900 * (nCircles - 5.129)));
-        }
-        double[] residuals = new double[nPolygons - 1];
-        String[] residualLabels = new String[nPolygons - 1];
-        boolean[] warnings = new boolean[nPolygons -1];
-        double[][] luneCenters = new double[nPolygons -1][2];
-        double area = 0;
-        int nonZero = 0;
-        for (int i = 1; i < nPolygons; i++) {
-            residuals[i - 1] = polyAreas[i] - polyHats[i];
-            char[] c = encode(i);
-            String s = "";
-            double numIntersecting = 0.0;
-            for (int j = 0; j < c.length; j++) {
-                if (c[j] == '1') {
-                    s += (circleLabels[j] + "&");
-                    // record the centers of the circles
-                    luneCenters[i-1][0] += centers[j][0];
-                    luneCenters[i-1][1] += centers[j][1];
-                    numIntersecting += 1.0;
-                }
-            }
+               return new VennDiagram(centers, diameters, polyAreas, 
residuals, circleLabels, residualLabels, 
+                                      colors, intersectionCounts, warnings, 
luneCenters, stress, stress01, stress05);
+       }
 
-            // find the lune centers
-            if ( numIntersecting > 0 ) {
-                luneCenters[i-1][0] /= numIntersecting;
-                luneCenters[i-1][1] /= numIntersecting;
-            } 
+       private void processAreaData(String[][] data, double[] areas) {
+               HashMap<String, Double> sets = new HashMap<String, Double>();
+               for (int i = 0; i < data.length; i++) {
+                       String[] s = data[i][0].split("&");
+                       for (int j = 0; j < s.length; j++) {
+                               if (!sets.containsKey(s[j])) {
+                                       Double cat = new Double(sets.size());
+                                       sets.put(s[j], cat);
+                               }
+                       }
+               }
+               circleLabels = new String[sets.size()];
+               Set<String> keys = sets.keySet();
+               Iterator<String> it = keys.iterator();
+               while (it.hasNext()) {
+                       String key = it.next();
+                       int j = sets.get(key).intValue();
+                       circleLabels[j] = key;
+               }
+               nRows = data.length;
+               nCircles = sets.size();
+               nPolygons = (int) Math.pow(2, nCircles);
+               intersectionCounts = new double[nPolygons];
+               polyData = new double[nPolygons];
+               polyAreas = new double[nPolygons];
+               polyHats = new double[nPolygons];
+               circleData = new double[nCircles];
+               centers = new double[nCircles][2];
 
-            area += polyAreas[i];
-//            if (residuals[i - 1] != 0) 
-//                nonZero++;
-//            s = s.substring(0, s.length() - 1);
-//            residualLabels[i - 1] = s;
-//            logger.info("Set name: " + residualLabels[i - 1] + "  residual: 
" + residuals[i-1] + " set area: " + polyAreas[i] + "  num members: " + 
polyData[i]); 
-        }
-//        double cut = area / nonZero;
-//        for (int i = 0; i < residuals.length; i++) {
-//            if (Math.abs(residuals[i]) > cut) {
-//                logger.warn("OUTLIER!!   Set name: " + residualLabels[i] + " 
 residual: " + residuals[i]);
-//                warnings[i] = true;
-//            } else {
-//                warnings[i] = false;
-//            }
-//        }
-        logger.info("stress = " + stress + ", stress01 = " + stress01 + ", 
stress05 = " + stress05);
+               double totalArea = 0.0;
+               for (int i = 0; i < nRows; i++)
+                       totalArea += areas[i];
 
-        return new VennDiagram(centers, diameters, polyAreas, residuals, 
circleLabels, residualLabels, colors, polyData, warnings, luneCenters, stress, 
stress01, stress05);
-    }
+               for (int i = 0; i < nRows; i++) {
+                       int[] subsets = new int[nCircles];
+                       String[] s = data[i][0].split("&");
+                       for (int j = 0; j < s.length; j++) {
+                               int jj = sets.get(s[j]).intValue();
+                               subsets[jj] = 1;
+                       }
+                       int k = decode(subsets);
+                       polyData[k] = areas[i];
+                       for (int j = 0; j < nCircles; j++) {
+                               if (subsets[j] > 0)
+                                       circleData[j] += areas[i];
+                       }
+               }
+               for (int i = 0; i < polyData.length; i++) {
+                       intersectionCounts[i] = polyData[i];
+                       polyData[i] = polyData[i] / totalArea;
+               }
+               for (int j = 0; j < nCircles; j++) {
+                       circleData[j] = circleData[j] / totalArea;
+                       if (isEqualArea)
+                               circleData[j] = 1;
+               }
+       }
 
-    private void processAreaData(String[][] data, double[] areas) {
-        HashMap<String,Double> sets = new HashMap<String,Double>();
-        for (int i = 0; i < data.length; i++) {
-            String[] s = data[i][0].split("&");
-            for (int j = 0; j < s.length; j++) {
-                if (!sets.containsKey(s[j])) {
-                    Double cat = new Double((double) sets.size());
-                    sets.put(s[j], cat);
-                }
-            }
-        }
-        circleLabels = new String[sets.size()];
-        Set<String> keys = sets.keySet();
-        Iterator<String> it = keys.iterator();
-        while (it.hasNext()) {
-            String key = it.next();
-            int j = sets.get(key).intValue();
-            circleLabels[j] = key;
-        }
-        nRows = data.length;
-        nCircles = sets.size();
-        nPolygons = (int) Math.pow(2, nCircles);
-        polyData = new double[nPolygons];
-        polyAreas = new double[nPolygons];
-        polyHats = new double[nPolygons];
-        circleData = new double[nCircles];
-        centers = new double[nCircles][2];
-        for (int i = 0; i < nRows; i++) {
-            int[] subsets = new int[nCircles];
-            String[] s = data[i][0].split("&");
-            for (int j = 0; j < s.length; j++) {
-                int jj = sets.get(s[j]).intValue();
-                subsets[jj] = 1;
-            }
-            int k = decode(subsets);
-            polyData[k] = areas[i];
-            for (int j = 0; j < nCircles; j++) {
-                if (subsets[j] > 0)
-                    circleData[j] += areas[i];
-            }
-        }
-        for (int j = 0; j < nCircles; j++)
-            maxArea = Math.max(maxArea, circleData[j]);
-    }
+       private void processElementData(String[][] data) {
+               @SuppressWarnings("unchecked") 
+               HashMap<String,Double>[] categories = new HashMap[2];
+               categories[0] = new HashMap<String,Double>();
+               categories[1] = new HashMap<String,Double>();
+               for (int i = 0; i < data.length; i++) {
+                       for (int j = 0; j < 2; j++) {
+                               if (!categories[j].containsKey(data[i][j])) {
+                                       Double cat = new 
Double(categories[j].size());
+                                       categories[j].put(data[i][j], cat);
+                               }
+                       }
+               }
+               circleLabels = new String[categories[1].size()];
+               Set<String> keys = categories[1].keySet();
+               Iterator<String> it = keys.iterator();
+               while (it.hasNext()) {
+                       String key = it.next();
+                       int j =  categories[1].get(key).intValue();
+                       circleLabels[j] = key;
+               }
+               nRows = data.length;
+               nCircles = categories[1].size();
+               nPolygons = (int) Math.pow(2, nCircles);
+               intersectionCounts = new double[nPolygons];
+               polyData = new double[nPolygons];
+               polyAreas = new double[nPolygons];
+               polyHats = new double[nPolygons];
+               circleData = new double[nCircles];
+               centers = new double[nCircles][2];
+               int[][] subsets = new int[categories[0].size()][nCircles];
+               for (int i = 0; i < nRows; i++) {
+                       int i1 = categories[0].get(data[i][0]).intValue();
+                       int j1 = categories[1].get(data[i][1]).intValue();
+                       subsets[i1][j1]++;
+               }
+               for (int i = 0; i < subsets.length; i++)
+                       updateCounts(subsets[i]);
 
-    private void processElementData(String[][] data) {
-        @SuppressWarnings("unchecked") 
-        HashMap<String,Double>[] categories = new HashMap[2];
-        categories[0] = new HashMap<String,Double>();
-        categories[1] = new HashMap<String,Double>();
-        for (int i = 0; i < data.length; i++) {
-            for (int j = 0; j < 2; j++) {
-                if (!categories[j].containsKey(data[i][j])) {
-                    Double cat = new Double((double) categories[j].size());
-                    categories[j].put(data[i][j], cat);
-                }
-            }
-        }
-        circleLabels = new String[categories[1].size()];
-        Set<String> keys = categories[1].keySet();
-        Iterator<String> it = keys.iterator();
-        while (it.hasNext()) {
-            String key = it.next();
-            int j =  categories[1].get(key).intValue();
-            circleLabels[j] = key;
-        }
-        nRows = data.length;
-        nCircles = categories[1].size();
-        nPolygons = (int) Math.pow(2, nCircles);
-        polyData = new double[nPolygons];
-        polyAreas = new double[nPolygons];
-        polyHats = new double[nPolygons];
-        circleData = new double[nCircles];
-        centers = new double[nCircles][2];
-        int[][] subsets = new int[categories[0].size()][nCircles];
-        for (int i = 0; i < nRows; i++) {
-            int i1 = categories[0].get(data[i][0]).intValue();
-            int j1 = categories[1].get(data[i][1]).intValue();
-            subsets[i1][j1]++;
-        }
-        for (int i = 0; i < subsets.length; i++)
-            updateCounts(subsets[i]);
-    }
+               for (int i = 0; i < polyData.length; i++) {
+                       intersectionCounts[i] = polyData[i];
+                       polyData[i] = polyData[i] / nTot;
+               }
+               for (int j = 0; j < nCircles; j++) {
+                       circleData[j] = circleData[j] / nTot;
+                       if (isEqualArea)
+                               circleData[j] = 1;
+               }
+       }
 
-    protected void updateCounts(int[] counts) {
-        int index = decode(counts);
-        polyData[index]++;
-        for (int j = 0; j < counts.length; j++) {
-            if (counts[j] > 0)
-                circleData[j]++;
-        }
-        nTot++;
-    }
+       protected void updateCounts(int[] counts) {
+               int index = decode(counts);
+               polyData[index]++;
+               for (int j = 0; j < counts.length; j++) {
+                       if (counts[j] > 0)
+                               circleData[j]++;
+               }
+               nTot++;
+       }
 
-    private char[] encode(int index) {
-        String s = Integer.toBinaryString(index);
-        char[] c = s.toCharArray();
-        int offset = nCircles - c.length;
-        char[] result = new char[nCircles];
-        for (int i = 0; i < offset; i++)
-            result[i] = '0';
-        System.arraycopy(c, 0, result, offset, c.length);
-        return result;
-    }
+       private char[] encode(int index) {
+               String s = Integer.toBinaryString(index);
+               char[] c = s.toCharArray();
+               int offset = nCircles - c.length;
+               char[] result = new char[nCircles];
+               for (int i = 0; i < offset; i++)
+                       result[i] = '0';
+               System.arraycopy(c, 0, result, offset, c.length);
+               return result;
+       }
 
-    private int decode(int[] subsets) {
-        String b = "";
-        for (int j = 0; j < subsets.length; j++) {
-            if (subsets[j] > 0)
-                b += '1';
-            else
-                b += '0';
-        }
-        return Integer.parseInt(b, 2);
-    }
+       private int decode(int[] subsets) {
+               String b = "";
+               for (int j = 0; j < subsets.length; j++) {
+                       if (subsets[j] > 0)
+                               b += '1';
+                       else
+                               b += '0';
+               }
+               return Integer.parseInt(b, 2);
+       }
 
-    private void calculateAreas() {
-        totalCount = 0;
-        int size = 200;
-        byte[][][] bis = new byte[nCircles][size][size];
-        double mins = Double.POSITIVE_INFINITY;
-        double maxs = Double.NEGATIVE_INFINITY;
-        for (int i = 0; i < nCircles; i++) {
-            double radius = diameters[i] / 2;
-            mins = Math.min(centers[i][0] - radius, mins);
-            mins = Math.min(centers[i][1] - radius, mins);
-            maxs = Math.max(centers[i][0] + radius, maxs);
-            maxs = Math.max(centers[i][1] + radius, maxs);
-        }
-        for (int i = 0; i < nCircles; i++) {
-            double xi = (centers[i][0] - mins) / (maxs - mins);
-            double yi = (centers[i][1] - mins) / (maxs - mins);
-            double di = diameters[i] / (maxs - mins);
-            int r = (int) (di * size / 2.);
-            int r2 = r * r;
-            int cx = (int) (xi * size);
-            int cy = (int) (size - yi * size);
-            for (int x = 0; x < size; x++) {
-                for (int y = 0; y < size; y++) {
-                    if ((x - cx) * (x - cx) + (y - cy) * (y - cy) < r2)
-                        bis[i][x][y] = 1;
-                }
-            }
-        }
-        for (int x = 0; x < size; x++) {
-            for (int y = 0; y < size; y++) {
-                int[] counts = new int[nCircles];
-                int count = 0;
-                for (int j = 0; j < nCircles; j++) {
-                    if (bis[j][x][y] == 1) {
-                        counts[j]++;
-                        count++;
-                    }
-                }
-                if (count > 0)
-                    updatePixels(counts);
-            }
-        }
-        for (int i = 0; i < nPolygons; i++)
-            polyAreas[i] = 100 * polyAreas[i] / totalCount;
-    }
+       private void calculateAreas() {
+               totalCount = 0;
+               int size = 200;
+               byte[][][] bis = new byte[nCircles][size][size];
+               double mins = Double.POSITIVE_INFINITY;
+               double maxs = Double.NEGATIVE_INFINITY;
+               for (int i = 0; i < nCircles; i++) {
+                       double radius = diameters[i] / 2;
+                       mins = Math.min(centers[i][0] - radius, mins);
+                       mins = Math.min(centers[i][1] - radius, mins);
+                       maxs = Math.max(centers[i][0] + radius, maxs);
+                       maxs = Math.max(centers[i][1] + radius, maxs);
+               }
+               for (int i = 0; i < nCircles; i++) {
+                       double xi = (centers[i][0] - mins) / (maxs - mins);
+                       double yi = (centers[i][1] - mins) / (maxs - mins);
+                       double di = diameters[i] / (maxs - mins);
+                       int r = (int) (di * size / 2.);
+                       int r2 = r * r;
+                       int cx = (int) (xi * size);
+                       int cy = (int) (size - yi * size);
+                       for (int x = 0; x < size; x++) {
+                               for (int y = 0; y < size; y++) {
+                                       if ((x - cx) * (x - cx) + (y - cy) * (y 
- cy) < r2)
+                                               bis[i][x][y] = 1;
+                               }
+                       }
+               }
+               for (int x = 0; x < size; x++) {
+                       for (int y = 0; y < size; y++) {
+                               int[] counts = new int[nCircles];
+                               int count = 0;
+                               for (int j = 0; j < nCircles; j++) {
+                                       if (bis[j][x][y] == 1) {
+                                               counts[j]++;
+                                               count++;
+                                       }
+                               }
+                               if (count > 0)
+                                       updatePixels(counts);
+                       }
+               }
+               if (totalCount == 0)
+                       return;
+               for (int i = 0; i < nPolygons; i++)
+                       polyAreas[i] = 100 * polyAreas[i] / totalCount;
+       }
 
-    private void updatePixels(int[] counts) {
-        int index = decode(counts);
-        polyAreas[index]++;
-        totalCount++;
-    }
+       private void updatePixels(int[] counts) {
+               int index = decode(counts);
+               polyAreas[index]++;
+               totalCount++;
+       }
 
-    public void computeInitialConfiguration() {
-        double[][] s = computeDistanceMatrix();
-        if (s == null) {
-            fixedStart();
-            return;
-        }
+       public void computeInitialConfiguration() {
+               double[][] s = computeDistanceMatrix();
+               if (s == null) {
+                       fixedStart();
+                       return;
+               }
 
-        double[] q = new double[nCircles];
-        double[][] x = new double[nCircles][2];
+               double[] q = new double[nCircles];
 
-        double additiveConstant = estimateAdditiveConstant(nCircles, s);
+               computeScalarProducts(nCircles, s, q);
 
-        computeScalarProducts(additiveConstant, nCircles, s, q);
+               Eigen.eigenSymmetric(s, s, q);
 
-        Eigen.eigenSymmetric(s, s, q);
+               double rms = Math.sqrt(q[0]) + Math.sqrt(q[1]);
+               if (Double.isNaN(rms) || rms < .1) {
+                       fixedStart();
+                       return;
+               }
+               for (int i = 0; i < nCircles; i++) {
+                       centers[i][0] = .5 + .25 * s[i][0] * Math.sqrt(q[0]);
+                       centers[i][1] = .5 + .25 * s[i][1] * Math.sqrt(q[1]);
+               }
+       }
 
-        double[] min = new double[]{Double.POSITIVE_INFINITY, 
Double.POSITIVE_INFINITY};
-        double[] max = new double[]{Double.NEGATIVE_INFINITY, 
Double.NEGATIVE_INFINITY};
-        for (int j = 0; j < 2; j++) {
-            double rms = Math.sqrt(q[j]);
-            if (Double.isNaN(rms))
-                rms = 1;
-            for (int i = 0; i < nCircles; i++) {
-                x[i][j] = s[i][j] * rms;
-                min[j] = Math.min(x[i][j], min[j]);
-                max[j] = Math.max(x[i][j], max[j]);
-            }
-        }
+       private void fixedStart() {
+               double theta = Math.PI / 2;
+               double delta = 2 * Math.PI / nCircles;
+               for (int i = 0; i < nCircles; i++) {
+                       centers[i][0] = .5 + Math.cos(theta);
+                       centers[i][1] = .5 + Math.sin(theta);
+                       theta -= delta;
+               }
+       }
 
-        if (max[0] == min[0] || max[1] == min[1]) {
-            fixedStart();
-            return;
-        }
+       private double[][] computeDistanceMatrix() {
+               int nIntersections = 0;
+               double[][] s = new double[nCircles][nCircles];
+               for (int i = 0; i < nPolygons; i++) {
+                       char[] c = encode(i);
+                       for (int j = 0; j < c.length; j++) {
+                               if (c[j] == '0')
+                                       continue;
+                               for (int k = j + 1; k < c.length; k++) {
+                                       if (c[k] == '0')
+                                               continue;
+                                       s[j][k] += polyData[i];
+                                       s[k][j] = s[j][k];
+                                       nIntersections++;
+                               }
+                       }
+               }
 
-        for (int i = 0; i < nCircles; i++) {
-//            centers[i][0] = .5 + .25 * x[i][0] / (max[0] - min[0]);
-//            centers[i][1] = .5 + .25 * x[i][1] / (max[1] - min[1]);
-            centers[i][0] = .5 + .25 * x[i][0];
-            centers[i][1] = .5 + .25 * x[i][1];
-        }
-    }
+               for (int j = 0; j < nCircles; j++) {
+                       s[j][j] = 0;
+                       for (int k = 0; k < j; k++) {
+                               s[j][k] = 1 - s[j][k] / (circleData[j] + 
circleData[k]);
+                               s[k][j] = s[j][k];
+                       }
+               }
+               if (nIntersections < 1)
+                       s = null;
+               return s;
+       }
 
-    private void fixedStart() {
-        double theta = Math.PI / 2;
-        double delta = 2 * Math.PI / nCircles;
-        for (int i = 0; i < nCircles; i++) {
-            centers[i][0] = .5 + Math.cos(theta);
-            centers[i][1] = .5 + Math.sin(theta);
-            theta -= delta;
-        }
-    }
+       private void computeScalarProducts(int nPoints, double[][] s, double[] 
q) {
+               double rms = 0.;
+               for (int i = 1; i < nPoints; i++) {
+                       for (int j = 0; j < i; j++) {
+                               double dij = s[i][j] * s[i][j];
+                               rms += dij + dij;
+                               q[i] += dij;
+                               q[j] += dij;
+                       }
+               }
 
-    private double[][] computeDistanceMatrix() {
-        int nIntersections = 0;
-        double[][] s = new double[nCircles][nCircles];
-        for (int i = 0; i < nPolygons; i++) {
-            char[] c = encode(i);
-            for (int j = 0; j < c.length; j++) {
-                if (c[j] == '0')
-                    continue;
-                for (int k = j + 1; k < c.length; k++) {
-                    if (c[k] == '0')
-                        continue;
-                    s[j][k] += polyData[i];
-                    s[k][j] = s[j][k];
-                    nIntersections++;
-                }
-            }
-        }
-        for (int j = 0; j < nCircles; j++) {
-            s[j][j] = 0;
-            for (int k = 0; k < j; k++) {
-                s[j][k] = 1 - s[j][k] / (circleData[j] + circleData[k]);
-                s[k][j] = s[j][k];
-            }
-        }
-        if (nIntersections < 1)
-            s = null;
-        return s;
-    }
+               rms = rms / (nPoints * nPoints);
+               double dsm;
+               for (int i = 0; i < nPoints; i++) {
+                       for (int j = 0; j <= i; j++) {
+                               if (i == j)
+                                       dsm = 0.;
+                               else
+                                       dsm = s[i][j] * s[i][j];
+                               s[i][j] = ((q[i] + q[j]) / nPoints - rms - dsm) 
/ 2.;
+                               s[j][i] = s[i][j];
+                       }
+               }
+       }
 
-    private double estimateAdditiveConstant(int nPoints, double[][] s) {
-        double additiveConstant = Double.NEGATIVE_INFINITY;
-        for (int i = 1; i < nPoints; i++) {
-            for (int j = 0; j < i; j++) {
-                for (int k = 0; k < nPoints; k++) {
-                    if (k != i && k != j) {
-                        double cmin = s[i][j] - s[i][k] - s[j][k];
-                        if (additiveConstant < cmin)
-                            additiveConstant = cmin;
-                    }
-                }
-            }
-        }
-        return additiveConstant;
-    }
+       private void scaleDiameters() {
+               diameters = new double[nCircles];
+               for (int j = 0; j < nCircles; j++)
+                       diameters[j] = 2 * Math.sqrt(circleData[j] / Math.PI / 
nCircles);
+       }
 
-    private void computeScalarProducts(double additiveConstant, int nPoints, 
double[][] s, double[] q) {
-        if (additiveConstant == Double.NEGATIVE_INFINITY)
-            additiveConstant = 0.;
-        double rms = 0.;
-        for (int i = 1; i < nPoints; i++) {
-            for (int j = 0; j < i; j++) {
-                s[i][j] += additiveConstant;
-                double dij = s[i][j] * s[i][j];
-                rms += dij + dij;
-                q[i] += dij;
-                q[j] += dij;
-            }
-        }
+       private void rescaleDiameters(double[] realDiameters, int iteration) {
+               if (iteration > 5) {
+                       return;
+               } else if (iteration == 0) {
+                       double averageDiameter = 0;
+                       for (int j = 0; j < nCircles; j++)
+                               averageDiameter += realDiameters[j];
+                       averageDiameter /= nCircles;
+                       for (int j = 0; j < nCircles; j++)
+                               diameters[j] = averageDiameter;
+               } else if (iteration < 5) {
+                       for (int j = 0; j < nCircles; j++)
+                               diameters[j] = diameters[j] - (iteration / 5.0) 
* (diameters[j] - realDiameters[j]);
+               } else {
+                       for (int j = 0; j < nCircles; j++)
+                               diameters[j] = realDiameters[j];
+               }
+       }
 
-        rms = rms / (nPoints * nPoints);
-        double dsm;
-        for (int i = 0; i < nPoints; i++) {
-            for (int j = 0; j <= i; j++) {
-                if (i == j)
-                    dsm = 0.;
-                else
-                    dsm = s[i][j] * s[i][j];
-                s[i][j] = ((q[i] + q[j]) / nPoints - rms - dsm) / 2.;
-                s[j][i] = s[i][j];
-            }
-        }
-    }
+       private void scaleConfiguration() {
+               double vc = 0;
+               for (int j = 0; j < 2; j++) {
+                       double mc = 0;
+                       for (int k = 0; k < nCircles; k++)
+                               mc += centers[k][j];
+                       mc /= nCircles;
+                       for (int k = 0; k < nCircles; k++) {
+                               centers[k][j] -= mc;
+                               vc += centers[k][j] * centers[k][j];
+                       }
+               }
+               vc = 10. * Math.sqrt(vc / (2 * nCircles));
+               if (vc > 0) {
+                       for (int j = 0; j < 2; j++) {
+                               for (int k = 0; k < nCircles; k++)
+                                       centers[k][j] /= vc;
+                       }
+               }
+       }
 
-    private void scaleDiameters(boolean isAreas) {
-        diameters = new double[nCircles];
-        double area;
-        for (int j = 0; j < nCircles; j++) {
-            if (isAreas)
-                area = circleData[j] / maxArea;
-            else
-                area = circleData[j] / nTot;
-            diameters[j] = 2 * Math.sqrt(area / Math.PI / nCircles);
-        }
-    }
+       private double computeStress() {
+               /* regression through origin */
+               calculateAreas();
+               if (totalCount == 0) {
+                       scaleConfiguration();
+                       calculateAreas();
+               }
+               double xx = 0;
+               double xy = 0;
+               int n = polyData.length;
+               double sst = 0;
+               for (int i = 1; i < n; i++) {
+                       double x = polyData[i];
+                       double y = polyAreas[i];
+                       xy += x * y;
+                       xx += x * x;
+                       sst += y * y;
+               }
+               double slope = xy / xx;
 
-    private void scaleConfiguration() {
-        double vc = 0;
-        for (int j = 0; j < 2; j++) {
-            double mc = 0;
-            for (int k = 0; k < nCircles; k++)
-                mc += centers[k][j];
-            mc /= nCircles;
-            for (int k = 0; k < nCircles; k++) {
-                centers[k][j] -= mc;
-                vc += centers[k][j] * centers[k][j];
-            }
-        }
-        vc = 10. * Math.sqrt(vc / (2 * nCircles));
-        if (vc > 0) {
-            for (int j = 0; j < 2; j++) {
-                for (int k = 0; k < nCircles; k++)
-                    centers[k][j] /= vc;
-            }
-        }
-    }
+               double sse = 0;
+               for (int i = 1; i < n; i++) {
+                       double x = polyData[i];
+                       double y = polyAreas[i];
+                       double yhat = x * slope;
+                       polyHats[i] = yhat;
+                       sse += (y - yhat) * (y - yhat);
+               }
+               return sse / sst;
+       }
 
-    private double computeStress() {
-        /* regression through origin */
-        calculateAreas();
-        double xx = 0;
-        double xy = 0;
-        int n = polyData.length;
-        double sst = 0;
-        for (int i = 1; i < n; i++) {
-            double x = polyData[i];
-            double y = polyAreas[i];
-            xy += x * y;
-            xx += x * x;
-            sst += y * y;
-        }
-        double slope = xy / xx;
+       private void minimizeGlobal() {
+               double[] initialDiameters = new double[nCircles];
+               System.arraycopy(diameters, 0, initialDiameters, 0, nCircles);
+               double[][] previousCenters = new double[nCircles][2];
+               copyCircles(centers, previousCenters);
 
-        double sse = 0;
-        for (int i = 1; i < n; i++) {
-            double x = polyData[i];
-            double y = polyAreas[i];
-            double yhat = x * slope;
-            polyHats[i] = yhat;
-            sse += (y - yhat) * (y - yhat);
-        }
-        return sse / sst;
-    }
+               double lastStress = 1;
+               for (int iter = 0; iter < 50; iter++) {
+                       rescaleDiameters(initialDiameters, iter);
+                       recenter();
+                       stress = computeStress();
+                       if (stress > lastStress)
+                               copyCircles(previousCenters, centers);
+                       else
+                               copyCircles(centers, previousCenters);
+                       logger.info("global iteration, loss " + iter + " " + 
stress);
+                       if (iter > 10 && (stress < minStress || lastStress - 
stress < minStress))
+                               break;
+                       moveGlobal();
+                       lastStress = stress;
+               }
+               rescaleDiameters(initialDiameters, 50);
+               recenter();
+               stress = computeStress();
+       }
 
-    private void minimizeGlobal() {
-        double lastStress = 1;
-        for (int iter = 0; iter < 100; iter++) {
-            recenter();
-            stress = computeStress();
-            moveGlobal();
-            //System.out.println("global iteration, loss " + iter + " " + 
stress);
-            if (stress < minStress || lastStress - stress < minStress)
-                break;
-            lastStress = stress;
-        }
-        recenter();
-        stress = computeStress();
-    }
+       private void minimizeLocal() {
+               double[] initialDiameters = new double[nCircles];
+               System.arraycopy(diameters, 0, initialDiameters, 0, nCircles);
+               double[][] initialCenters = new double[nCircles][2];
+               copyCircles(centers, initialCenters);
+               double[][] previousCenters = new double[nCircles][2];
+               copyCircles(centers, previousCenters);
+               double previousStress = stress;
+               double lastStress = 1;
+               for (int iter = 0; iter < 50; iter++) {
+                       rescaleDiameters(initialDiameters, iter);
+                       recenter();
+                       stress = computeStress();
+                       logger.debug("local iteration, loss " + iter + " " + 
stress);
+                       if (stress > lastStress)
+                               copyCircles(previousCenters, centers);
+                       else
+                               copyCircles(centers, previousCenters);
+                       if (iter > 10 && (stress < minStress || lastStress - 
stress < minStress))
+                               break;
+                       moveLocal();
+                       lastStress = stress;
+               }
+               rescaleDiameters(initialDiameters, 50);
+               if (previousStress < stress)
+                       copyCircles(initialCenters, centers);
+               recenter();
+               stress = computeStress();
+       }
 
-    private void minimizeLocal() {
-        double lastStress = 1;
-        for (int iter = 0; iter < 100; iter++) {
-            recenter();
-            stress = computeStress();
-            moveLocal();
-            //System.out.println("local iteration, loss " + iter + " " + 
stress);
-            if (stress < minStress || lastStress - stress < minStress)
-                break;
-            lastStress = stress;
-        }
-        recenter();
-        stress = computeStress();
-    }
+       private void moveGlobal() {
+               double[][] gradients = new double[nCircles][2];
+               for (int i = 0; i < nPolygons; i++) {
+                       String s = Integer.toBinaryString(i);
+                       char[] c = s.toCharArray();
+                       int offset = nCircles - c.length;
+                       for (int j = 0; j < c.length; j++) {
+                               if (c[j] == '0')
+                                       continue;
+                               int jo = j + offset;
+                               for (int k = j + 1; k < c.length; k++) {
+                                       if (c[k] == '0')
+                                               continue;
+                                       int ko = k + offset;
+                                       double resid = polyAreas[i] - 
polyHats[i];
+                                       double dx = resid * stepsize * 
(centers[jo][0] - centers[ko][0]);
+                                       double dy = resid * stepsize * 
(centers[jo][1] - centers[ko][1]);
+                                       gradients[jo][0] += dx;
+                                       gradients[jo][1] += dy;
+                                       gradients[ko][0] -= dx;
+                                       gradients[ko][1] -= dy;
+                               }
+                       }
+               }
+               for (int i = 0; i < nCircles; i++) {
+                       centers[i][0] += gradients[i][0];
+                       centers[i][1] += gradients[i][1];
+               }
+       }
 
-    private void moveGlobal() {
-        double[][] gradients = new double[nCircles][2];
-        for (int i = 0; i < nPolygons; i++) {
-            String s = Integer.toBinaryString(i);
-            char[] c = s.toCharArray();
-            int offset = nCircles - c.length;
-            for (int j = 0; j < c.length; j++) {
-                if (c[j] == '0')
-                    continue;
-                int jo = j + offset;
-                for (int k = j + 1; k < c.length; k++) {
-                    if (c[k] == '0')
-                        continue;
-                    int ko = k + offset;
-                    double resid = polyAreas[i] - polyHats[i];
-                    double dx = 0.5 * resid * stepsize * (centers[jo][0] - 
centers[ko][0]);
-                    double dy = 0.5 * resid * stepsize * (centers[jo][1] - 
centers[ko][1]);
-                    gradients[jo][0] += dx;
-                    gradients[jo][1] += dy;
-                    gradients[ko][0] -= dx;
-                    gradients[ko][1] -= dy;
-                }
-            }
-        }
-        for (int i = 0; i < nCircles; i++) {
-            centers[i][0] += gradients[i][0];
-            centers[i][1] += gradients[i][1];
-        }
-    }
+       private void moveLocal() {
+               double[][] gradients = new double[nCircles][2];
+               for (int i = 0; i < nCircles; i++) {
+                       centers[i][0] += stepsize;
+                       double xPlus = computeStress();
+                       centers[i][0] -= 2 * stepsize;
+                       double xMinus = computeStress();
+                       centers[i][0] += stepsize;
+                       if (xPlus < xMinus)
+                               gradients[i][0] = stepsize;
+                       else
+                               gradients[i][0] = -stepsize;
 
-    private void moveLocal() {
-        double[][] gradients = new double[nCircles][2];
-        for (int i = 0; i < nCircles; i++) {
-            centers[i][0] += stepsize;
-            double xPlus = computeStress();
-            centers[i][0] -= 2 * stepsize;
-            double xMinus = computeStress();
-            centers[i][0] += stepsize;
-            if (xPlus < xMinus)
-                gradients[i][0] = stepsize;
-            else
-                gradients[i][0] = -stepsize;
+                       centers[i][1] += stepsize;
+                       double yPlus = computeStress();
+                       centers[i][1] -= 2 * stepsize;
+                       double yMinus = computeStress();
+                       centers[i][1] += stepsize;
+                       if (yPlus < yMinus)
+                               gradients[i][1] = stepsize;
+                       else
+                               gradients[i][1] = -stepsize;
+               }
+               for (int i = 0; i < nCircles; i++) {
+                       centers[i][0] += gradients[i][0];
+                       centers[i][1] += gradients[i][1];
+               }
+       }
 
-            centers[i][1] += stepsize;
-            double yPlus = computeStress();
-            centers[i][1] -= 2 * stepsize;
-            double yMinus = computeStress();
-            centers[i][1] += stepsize;
-            if (yPlus < yMinus)
-                gradients[i][1] = stepsize;
-            else
-                gradients[i][1] = -stepsize;
-        }
-        for (int i = 0; i < nCircles; i++) {
-            centers[i][0] += gradients[i][0];
-            centers[i][1] += gradients[i][1];
-        }
-    }
+       private void recenter() {
+               double cx = 0;
+               double cy = 0;
+               for (int i = 0; i < nCircles; i++) {
+                       cx += centers[i][0];
+                       cy += centers[i][1];
+               }
+               cx = cx / nCircles;
+               cy = cy / nCircles;
+               for (int i = 0; i < nCircles; i++) {
+                       centers[i][0] = .5 + centers[i][0] - cx;
+                       centers[i][1] = .5 + centers[i][1] - cy;
+               }
+       }
 
-    private void recenter() {
-        double cx = 0;
-        double cy = 0;
-        for (int i = 0; i < nCircles; i++) {
-            cx += centers[i][0];
-            cy += centers[i][1];
-        }
-        cx = cx / nCircles;
-        cy = cy / nCircles;
-        for (int i = 0; i < nCircles; i++) {
-            centers[i][0] = .5 + centers[i][0] - cx;
-            centers[i][1] = .5 + centers[i][1] - cy;
-        }
-    }
+       private void copyCircles(double[][] a, double[][] b) {
+               for (int i = 0; i < nCircles; i++)
+                       System.arraycopy(a[i], 0, b[i], 0, 2);
+       }
+}
 
-    private void copyCircles(double[][] a, double[][] b) {
-        for (int i = 0; i < nCircles; i++)
-            System.arraycopy(a[i], 0, b[i], 0, 2);
-    }
-}

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