diff --git a/yeast_lab/source/java/ch/ethz/bsse/cisd/yeastlab/GenerationDetection.java b/yeast_lab/source/java/ch/ethz/bsse/cisd/yeastlab/GenerationDetection.java
index 027c45ef944f023a5b5b5df76b45d3dbe7b965d3..a5247e8d5ea898bff40e0ed98738f86cc70839ec 100644
--- a/yeast_lab/source/java/ch/ethz/bsse/cisd/yeastlab/GenerationDetection.java
+++ b/yeast_lab/source/java/ch/ethz/bsse/cisd/yeastlab/GenerationDetection.java
@@ -60,8 +60,9 @@ public class GenerationDetection
     @SuppressWarnings("unused")
     private static final String GENERATION_COL_NAME = "generation";
 
-    // TODO 2009-10-20, Piotr Buczek: parametrize
-    private static final int MAX_PIXELS_PER_NEW_BORN_CELL = 300; // 400 is better?
+    // Could be used as a parameter that user needs to specify but on test data
+    // using value that is higher produces more results that should rather be ignored.
+    private static final int MAX_PIXELS_PER_NEW_BORN_CELL = 300;
 
     private static final int MIN_PIXELS_PER_PARENT = MAX_PIXELS_PER_NEW_BORN_CELL;
 
@@ -84,15 +85,21 @@ public class GenerationDetection
 
     private static final int NUM_PIX_POSITION = 7;
 
-    // private static final int PERIM_POSITION = 9;
+    private static final int FFT_STAT_POSITION = 8;
+
+    private static final int PERIM_POSITION = 9;
 
     private static final int MAJ_AXIS_POSITION = 10;
 
     private static final int MIN_AXIS_POSITION = 11;
 
-    private static final int ROT_VOL_POSITION = 16;
+    private static final int ROT_VOL_POSITION = 15;
+
+    private static final int CON_VOL_POSITION = 16;
 
-    private static final int CON_VOL_POSITION = 17;
+    private static final int A_VACUOLE_POSITION = 17;
+
+    private static final int F_VACUOLE_POSITION = 18;
 
     private static final int A_SURF_POSITION = 58;
 
@@ -101,8 +108,7 @@ public class GenerationDetection
     @SuppressWarnings("unused")
     private static String headerInputRow;
 
-    // no need to use distance values and getting sqrt from values is an additional operation
-    private static int maxAxisSq; // (ceiling of) square of maximal major axis found in input data
+    private static double maxAxis; // maximal major axis found in input data
 
     private static int maxFrame; // maximal frame number (easy to read from file)
 
@@ -125,6 +131,12 @@ public class GenerationDetection
         /** number of pixels associated with the cell */
         private final int numPix; // num.pix
 
+        /** a measure of circularity - 0 means a perfect circle */
+        private final double fftStat;
+
+        /** circumference of the cell in pixel units */
+        private final double perim;
+
         /** length of the major axis in pixel units */
         private final double majAxis;
 
@@ -143,6 +155,10 @@ public class GenerationDetection
         /** volume of the cell as determined by the conical volume method */
         private final double conVol; // con.vol
 
+        private final double aVacuole;
+
+        private final double fVacuole;
+
         /** surface area as calculated by the union of spheres method */
         private final double aSurf; // a.surf
 
@@ -167,9 +183,15 @@ public class GenerationDetection
             this.y = Integer.parseInt(StringUtils.trim(tokens[Y_POS_POSITION]));
             this.numPix = Integer.parseInt(StringUtils.trim(tokens[NUM_PIX_POSITION]));
 
+            this.fftStat = Double.parseDouble(StringUtils.trim(tokens[FFT_STAT_POSITION]));
+            this.perim = Double.parseDouble(StringUtils.trim(tokens[PERIM_POSITION]));
+
             this.majAxis = Double.parseDouble(StringUtils.trim(tokens[MAJ_AXIS_POSITION]));
             this.minAxis = Double.parseDouble(StringUtils.trim(tokens[MIN_AXIS_POSITION]));
 
+            this.aVacuole = Double.parseDouble(StringUtils.trim(tokens[A_VACUOLE_POSITION]));
+            this.fVacuole = Double.parseDouble(StringUtils.trim(tokens[F_VACUOLE_POSITION]));
+
             this.fTot = Double.parseDouble(StringUtils.trim(tokens[F_TOT_POSITION]));
             this.aTot = Double.parseDouble(StringUtils.trim(tokens[A_TOT_POSITION]));
             this.rotVol = Double.parseDouble(StringUtils.trim(tokens[ROT_VOL_POSITION]));
@@ -270,12 +292,32 @@ public class GenerationDetection
             return sphereVol;
         }
 
+        public double getFftStat()
+        {
+            return fftStat;
+        }
+
+        public double getPerim()
+        {
+            return perim;
+        }
+
+        public double getAVacuole()
+        {
+            return aVacuole;
+        }
+
+        public double getFVacuole()
+        {
+            return fVacuole;
+        }
+
         public String getInputRow()
         {
             return inputRow;
         }
 
-        private int getAlternatives()
+        public int getAlternatives()
         {
             return getParentCandidates().length - 1;
         }
@@ -292,7 +334,7 @@ public class GenerationDetection
             final ParentCandidate[] candidates = getParentCandidates();
             for (ParentCandidate candidate : candidates)
             {
-                sb.append(candidate.parent.id + "\t" + candidate.distanceSq + ",");
+                sb.append(candidate.parent.id + " " + candidate.distanceSq + ", ");
             }
             return String.format("%d \t f:%d \t p:%d \t c(%d):%s", id, frame + 1,
                     getParentCellId(), candidates.length, sb.toString());
@@ -305,6 +347,8 @@ public class GenerationDetection
                         { Integer.toString(id), Integer.toString(frame + 1), Integer.toString(x),
                                 Integer.toString(y), Integer.toString(numPix),
                                 Double.toString(majAxis), Double.toString(minAxis),
+                                Double.toString(fftStat), Double.toString(perim),
+                                Double.toString(aVacuole), Double.toString(fVacuole),
                                 Double.toString(fTot), Double.toString(aTot),
                                 Double.toString(rotVol), Double.toString(conVol),
                                 Double.toString(aSurf), Double.toString(sphereVol),
@@ -356,14 +400,14 @@ public class GenerationDetection
 
         private final Cell parent;
 
-        // private final Cell child;
+        private final Cell child;
 
         private final Integer distanceSq;
 
         public ParentCandidate(Cell parent, Cell child)
         {
             this.parent = parent;
-            // this.child = child;
+            this.child = child;
             this.distanceSq = distanceSq(parent, child);
         }
 
@@ -372,15 +416,19 @@ public class GenerationDetection
             return distanceSq;
         }
 
-        // We use maxAxis as the threshold for valid distance. We could use even tighter condition
-        // (but maybe less safe) getting cells closer than:
+        // The tightest condition that we could use as a threshold for valid distance is
         // (maxAxis+currentMajorAxis)/2
         // which is the longest possible distance that current cell can be from another cell
-        // assuming they touch each other. Of course:
+        // assuming they touch each other. We take 120% of this value because sometimes there is a
+        // bit of a space between parent and child.
+        // We could use a less tighter threshold like maxAxis if we find that we have some false
+        // negatives but on the test data the results are better with this tighter threshold.
+        // Of course:
         // maxAxis > (maxAxis+currentMajorAxis)/2.
         public boolean isDistanceValid()
         {
-            return getDistanceSq() <= maxAxisSq;
+            double maxValidDistance = 1 * (maxAxis + child.getMajAxis()) / 2;
+            return getDistanceSq() <= square(maxValidDistance);
         }
 
         public boolean isNumPixValid()
@@ -447,9 +495,10 @@ public class GenerationDetection
             // writer.append(SEPARATOR + GENERATION_COL_NAME + NEW_LINE);
 
             String[] tokens =
-                        { "cellID", "frame", "x", "y", "numPix", "maxAxis", "minAxis", "fTot",
-                                "aTot", "rotVol", "conVol", "aSurf", "sphereVol", "parent",
-                                "alternatives", "generation" };
+                        { "cellID", "frame", "x", "y", "numPix", "maxAxis", "minAxis", "fftStat",
+                                "perim", "aVacuole", "fVacuole", "fTot", "aTot", "rotVol",
+                                "conVol", "aSurf", "sphereVol", "parent", "alternatives",
+                                "generation" };
             writer.append(StringUtils.join(tokens, SEPARATOR));
             writer.append(NEW_LINE);
             for (Cell cell : cells)
@@ -483,7 +532,7 @@ public class GenerationDetection
         }
 
         System.err.println((System.currentTimeMillis() - start) / 1000.0);
-        
+
         if (DEBUG)
         {
             for (Cell cell : newBornCells)
@@ -503,7 +552,7 @@ public class GenerationDetection
         // cellsByFrameAndId = new LinkedHashMap<Integer, Map<Integer, Cell>>();
         cellsByFrame = new LinkedHashMap<Integer, Set<Cell>>();
         parentCandidatesByChildId = new LinkedHashMap<Integer, ParentCandidate[]>();
-        double maxAxis = 0;
+        maxAxis = 0;
         maxFrame = -1;
         for (Cell cell : cells)
         {
@@ -543,7 +592,6 @@ public class GenerationDetection
                 maxFrame = cell.getFrame();
             }
         }
-        maxAxisSq = (int) Math.ceil(maxAxis * maxAxis);
     }
 
     private static void analyzeData() throws Exception
@@ -636,24 +684,34 @@ public class GenerationDetection
         assert candidates.length != 0;
         final Cell parent = candidates[0].parent;
         parentCandidatesByChildId.put(child.id, candidates);
-        increaseGeneration(parent.getId(), parent.getFrame()); // change to child.getFrame()?
+        increaseGeneration(parent.getId(), child); // parent is from previous frame
     }
 
     /**
-     * Increases generations of all cells with specified <var>id</var> and frame number at least
-     * equal to <var>startFrame</var>.
+     * Increases generations of all cells with specified id starting from frame of the specified
+     * <var>child</var> (it should be the first appearance of the cell with child id).
      */
-    private static void increaseGeneration(int cellID, int startFrame)
+    private static void increaseGeneration(int parentID, Cell child)
     {
-        for (Entry<Integer, Cell> byFrame : cellsByIdAndFrame.get(cellID).entrySet())
-        {
-            final Integer frame = byFrame.getKey();
-            final Cell cell = byFrame.getValue();
-            if (frame >= startFrame)
+        final int childFrame = child.getFrame();
+        final Map<Integer, Cell> parentByFrame = cellsByIdAndFrame.get(parentID);
+        int count = 0;
+        for (Entry<Integer, Cell> entry : parentByFrame.entrySet())
+        {
+            final Integer frame = entry.getKey();
+            final Cell cell = entry.getValue();
+            if (frame >= childFrame)
             {
                 cell.increaseGeneration();
+                count++;
             }
         }
+        if (count == 0) // 5 cases in test data
+        {
+            System.err.println(String.format("Cell with id '%d' disappears on frame '%d' "
+                    + "just after producing cell with id '%d' (on previous frame).", parentID,
+                    childFrame, child.getId()));
+        }
     }
 
     private static boolean isValidNewBornCell(Cell cell)
@@ -678,6 +736,12 @@ public class GenerationDetection
         return dx * dx + dy * dy;
     }
 
+    /** @returns ceiling of given value squared */
+    private static int square(double value)
+    {
+        return (int) Math.ceil(value * value);
+    }
+
     private static List<Cell> load(final BufferedReader reader, final File file) throws IOException
     {
         assert reader != null : "Unspecified reader";
diff --git a/yeast_lab/source/java/ch/ethz/bsse/cisd/yeastlab/GenerationDetectionAccuracyTester.java b/yeast_lab/source/java/ch/ethz/bsse/cisd/yeastlab/GenerationDetectionAccuracyTester.java
index 4aa9e418d429053f5173f47927f46abee6dd9f6a..f1fcafc2e9e8c80bf82a032c5205a9520cb8abb1 100644
--- a/yeast_lab/source/java/ch/ethz/bsse/cisd/yeastlab/GenerationDetectionAccuracyTester.java
+++ b/yeast_lab/source/java/ch/ethz/bsse/cisd/yeastlab/GenerationDetectionAccuracyTester.java
@@ -16,7 +16,9 @@
 
 package ch.ethz.bsse.cisd.yeastlab;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -84,12 +86,10 @@ public class GenerationDetectionAccuracyTester
 
     public static void computeResultsAccuracy(List<Cell> results)
     {
-        int rightResults = 0;
-        int wrongResults = 0;
-        int fakeResults = 0;
-        int missingResults = 0;
-
-        Set<Integer> missingChildrenIds = parents.keySet();
+        final List<Cell> rightResults = new ArrayList<Cell>(results.size());
+        final List<Cell> wrongResults = new ArrayList<Cell>(results.size());
+        final List<Cell> fakeResults = new ArrayList<Cell>(results.size());
+        final Set<Integer> missingChildrenIds = new HashSet<Integer>(parents.keySet());
 
         for (Cell result : results)
         {
@@ -97,31 +97,45 @@ public class GenerationDetectionAccuracyTester
             Integer rightParentId = parents.get(result.getId());
             if (rightParentId == null)
             {
-                fakeResults++;
+                fakeResults.add(result);
             } else
             {
                 if (resultParentId.equals(rightParentId))
                 {
-                    rightResults++;
+                    rightResults.add(result);
                 } else
                 {
-                    wrongResults++;
+                    wrongResults.add(result);
                 }
             }
             missingChildrenIds.remove(result.getId());
         }
 
-        missingResults = missingChildrenIds.size();
+        final int rightResultsSize = rightResults.size();
+        final int wrongResultsSize = wrongResults.size();
+        final int fakeResultsSize = fakeResults.size();
+        final int missingResultsSize = missingChildrenIds.size();
         final int resultsSize = results.size();
-        final int withoutFakeSize = resultsSize - fakeResults;
+        final int resultsWithoutFakeSize = resultsSize - fakeResultsSize;
 
         System.out.println("\nAccuracy results:\n");
-        System.out.println(percentageMessage("right", "", rightResults, resultsSize));
-        System.out.println(percentageMessage("right", "(no fake)", rightResults, withoutFakeSize));
-        System.out.println(percentageMessage("wrong", "", wrongResults, resultsSize));
-        System.out.println(percentageMessage("wrong", "(no fake)", wrongResults, withoutFakeSize));
-        System.out.println(percentageMessage("fake", "", fakeResults, resultsSize));
-        System.out.println(percentageMessage("miss", "", missingResults, resultsSize));
+        System.out.println(percentageMessage("all", "", resultsSize, parents.size()));
+        System.out.println(percentageMessage("right", "", rightResultsSize, resultsSize));
+        System.out.println(percentageMessage("right", "(ignoring fake)", rightResultsSize,
+                resultsWithoutFakeSize));
+        System.out.println(percentageMessage("wrong", "", wrongResultsSize, resultsSize));
+        System.out.println(percentageMessage("wrong", "(ignoring fake)", wrongResultsSize,
+                resultsWithoutFakeSize));
+        System.out.println(percentageMessage("fake", "", fakeResultsSize, resultsSize));
+        System.out.println(percentageMessage("miss", "", missingResultsSize, resultsSize));
+        System.out.println("\nAlternatives:\n");
+        System.out.println(alternativesMessage("all", "", results));
+        System.out.println(alternativesMessage("right", "", rightResults));
+        System.out.println(alternativesMessage("wrong", "", wrongResults));
+        System.out.println(alternativesMessage("fake", "", fakeResults));
+        final List<Cell> resultsWithoutFakes = new ArrayList<Cell>(results);
+        results.removeAll(fakeResults);
+        System.out.println(alternativesMessage("all", "(ignoring fake)", resultsWithoutFakes));
     }
 
     private static String percentageMessage(String prefix, String suffix, int numerator,
@@ -131,7 +145,29 @@ public class GenerationDetectionAccuracyTester
         sb.append(prefix + ":\t");
         sb.append(numerator + "/" + denominator);
         sb.append(" = " + (numerator * 100) / denominator + "%");
-        sb.append("\t" + suffix);
+        sb.append(" " + suffix);
         return sb.toString();
     }
+
+    private static String alternativesMessage(String prefix, String suffix, List<Cell> cells)
+    {
+        int sum = 0;
+        int min = Integer.MAX_VALUE;
+        int max = Integer.MIN_VALUE;
+        for (Cell cell : cells)
+        {
+            final int current = cell.getAlternatives();
+            sum += current;
+            if (current > max)
+            {
+                max = current;
+            }
+            if (current < min)
+            {
+                min = current;
+            }
+        }
+        return String.format("%s:\t min:%d\t max:%d\t mean:%1.2f %s", prefix, min, max,
+                (double) sum / (double) cells.size(), suffix);
+    }
 }