package com.compomics.util.math; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; /** * Simple functions to manipulate histograms. A histogram is here represented as * a HashMap where the keys are the bin values and the values the occurrence of * the bin values * * @author Marc Vaudel */ public class HistogramUtils { /** * Returns the median of a histogram. * * @param histogram the histogram * * @return the median */ public static Double getMedianValue(HashMap<Double, Integer> histogram) { long nValues = 0; for (Integer value : histogram.values()) { nValues += value; } return getMedianValue(histogram, nValues); } /** * Returns the median of a histogram. * * @param histogram the histogram * @param nValues the number of values in the histogram * * @return the median */ public static Double getMedianValue(HashMap<Double, Integer> histogram, long nValues) { ArrayList<Double> values = new ArrayList<Double>(histogram.keySet()); Collections.sort(values); long currentSum = 0; long previousSum = 0; Double previousValue = 0.0; for (Double value : values) { Integer currentOccurence = histogram.get(value); currentSum += currentOccurence; if (2 * currentSum >= nValues) { if (2 * (previousSum + 1) > nValues && previousSum > 0) { return (previousValue + value) / 2; } return value; } previousValue = value; } throw new IllegalArgumentException("Reached the end of the histogram before reaching the median."); } /** * Merges histograms in a single histogram by adding the values in each bin. * * @param histograms the histograms to merge * * @return the merged histogram */ public static HashMap<Double, Integer> mergeHistograms(Collection<HashMap<Double, Integer>> histograms) { HashMap<Double, Integer> result = new HashMap<Double, Integer>(); for (HashMap<Double, Integer> histogram : histograms) { for (Double value : histogram.keySet()) { Integer histogramValue = histogram.get(value); Integer resultValue = result.get(value); if (resultValue == null) { result.put(value, histogramValue); } else if (Integer.MAX_VALUE - histogramValue < resultValue) { throw new IllegalArgumentException("Reached the maximal capacity of an integer in a histogram bin."); } else { result.put(value, resultValue + histogramValue); } } } return result; } }