diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculator.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculator.java index 61bb8b9f1ee9c95bc1e365477550445b0abd75c1..9311ae9bd7e4f3fc74527dcdcb85d1e77bd2ff3b 100644 --- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculator.java +++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculator.java @@ -286,28 +286,33 @@ public class WellReplicaSummaryCalculator @Private static float calculateMedian(List<IWellData> replicaWells, int featureIx) { - sortBySelectedFeature(replicaWells, featureIx); - int firstIx = 0; - int lastIx = replicaWells.size() - 1; - while (firstIx <= lastIx && isNumerical(replicaWells, firstIx, featureIx) == false) + List<Float> featureValues = new ArrayList<Float>(); + for (IWellData replicaWell : replicaWells) { - firstIx++; + float featureValue = getFeatureValue(replicaWell, featureIx); + if (isNumerical(featureValue)) + { + featureValues.add(featureValue); + } } - while (lastIx >= firstIx && isNumerical(replicaWells, lastIx, featureIx) == false) + return calculateMedian(featureValues); + } + + private static float calculateMedian(List<Float> numbers) + { + if (numbers.isEmpty()) { - lastIx--; + return Float.NaN; } - if (lastIx < firstIx) + Collections.sort(numbers); + int size = numbers.size(); + int index = size / 2; + float median = numbers.get(index); + if (size % 2 == 0) { - return Float.NaN; + median = (median + numbers.get(index - 1)) / 2; } - int medianIx = firstIx + ((lastIx - firstIx) / 2); - return getFeatureValue(replicaWells.get(medianIx), featureIx); - } - - private static boolean isNumerical(List<IWellData> replicaWells, int replicaIx, int featureIx) - { - return isNumerical(getFeatureValue(replicaWells.get(replicaIx), featureIx)); + return median; } private static float getFeatureValue(IWellData wellData, int featureIx) @@ -333,13 +338,7 @@ public class WellReplicaSummaryCalculator absDeviations.add(absDev); } } - if (absDeviations.isEmpty()) - { - return Float.NaN; - } - Collections.sort(absDeviations); - int medianIx = absDeviations.size() / 2; - return absDeviations.get(medianIx); + return calculateMedian(absDeviations); } private static boolean isNumerical(float value) diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculatorTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculatorTest.java index 6c819a71e131df542b9b53aff053d4fdbe4bd827..1f1155fee532e9be0d65dd29ab8a0a9702eae3b8 100644 --- a/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculatorTest.java +++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/plugin/screening/server/logic/WellReplicaSummaryCalculatorTest.java @@ -64,9 +64,9 @@ public class WellReplicaSummaryCalculatorTest extends AssertJUnit MaterialFeatureVectorSummary repl1 = summary.get(replica1Ix); assertArraysEqual(new float[] - { 2, 8 }, repl1.getFeatureVectorSummary()); + { 1.5f, 6 }, repl1.getFeatureVectorSummary()); assertArraysEqual(new float[] - { 1, 4 }, repl1.getFeatureVectorDeviations()); + { 0.5f, 2 }, repl1.getFeatureVectorDeviations()); MaterialFeatureVectorSummary repl2 = summary.get(1 - replica1Ix); assertArraysEqual(new float[] @@ -96,7 +96,7 @@ public class WellReplicaSummaryCalculatorTest extends AssertJUnit } @Test - public void testCalculateMedian() + public void testCalculateMedianForOddNumberOfValues() { List<IWellData> wellDataList = Arrays.asList( // ---- replicaId, [featureValues] @@ -108,14 +108,14 @@ public class WellReplicaSummaryCalculatorTest extends AssertJUnit createWellData(1, 0, 2), // 1 + createWellData(1, 0, 4), // 1 + + createWellData(1, 0, 100), // 97 + createWellData(1, 0, Float.NaN), createWellData(1, 0, 3), // 0 - createWellData(1, 0, 4), // 1 - - createWellData(1, 0, 100), // 97 - createWellData(1, 0, Float.POSITIVE_INFINITY)); float median = WellReplicaSummaryCalculator.calculateMedian(wellDataList, 1); assertEquals(3.0f, median); @@ -126,6 +126,35 @@ public class WellReplicaSummaryCalculatorTest extends AssertJUnit assertEquals(1.0f, mad); } + @Test + public void testCalculateMedianForEvenNumberOfValues() + { + List<IWellData> wellDataList = Arrays.asList( + // ---- replicaId, [featureValues] + createWellData(1, 0, Float.NaN), + + createWellData(1, 0, Float.NEGATIVE_INFINITY), + + createWellData(1, 0, 1), // 1.5 + + createWellData(1, 0, 3), // 0.5 + + createWellData(1, 0, 2), // 0.5 + + createWellData(1, 0, Float.NaN), + + createWellData(1, 0, 100), // 97.5 + + createWellData(1, 0, Float.POSITIVE_INFINITY)); + float median = WellReplicaSummaryCalculator.calculateMedian(wellDataList, 1); + assertEquals(2.5f, median); + + float mad = + WellReplicaSummaryCalculator.calculateMedianAbsoluteDeviation(median, wellDataList, + 1); + assertEquals(1.0f, mad); + } + @Test public void testCalculateMedianAbsoluteDeviationMedianUnknown() {