Java tutorial
/* * Copyright (c) 2007-2010 by The Broad Institute, Inc. and the Massachusetts Institute of Technology. * All Rights Reserved. * * This software is licensed under the terms of the GNU Lesser General Public License (LGPL), Version 2.1 which * is available at http://www.opensource.org/licenses/lgpl-2.1.php. * * THE SOFTWARE IS PROVIDED "AS IS." THE BROAD AND MIT MAKE NO REPRESENTATIONS OR WARRANTIES OF * ANY KIND CONCERNING THE SOFTWARE, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT * OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE. IN NO EVENT SHALL THE BROAD OR MIT, OR THEIR * RESPECTIVE TRUSTEES, DIRECTORS, OFFICERS, EMPLOYEES, AND AFFILIATES BE LIABLE FOR ANY DAMAGES OF * ANY KIND, INCLUDING, WITHOUT LIMITATION, INCIDENTAL OR CONSEQUENTIAL DAMAGES, ECONOMIC * DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER THE BROAD OR MIT SHALL * BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE * FOREGOING. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.broad.igv; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.math.stat.Percentile; /** * Estimating percentiles -- weighted average of multiple estimates * * @author jrobinso * @author Thomas Abeel */ public class Accumulator { static Set<WindowFunction> PERCENTILE_WINDOW_FUNCTIONS = new HashSet(); public static int MAX_VALUE_COUNT = 100000; private static Logger log = Logger.getLogger(Accumulator.class.getCanonicalName()); static { PERCENTILE_WINDOW_FUNCTIONS.add(WindowFunction.median); PERCENTILE_WINDOW_FUNCTIONS.add(WindowFunction.percentile2); PERCENTILE_WINDOW_FUNCTIONS.add(WindowFunction.percentile10); PERCENTILE_WINDOW_FUNCTIONS.add(WindowFunction.percentile90); PERCENTILE_WINDOW_FUNCTIONS.add(WindowFunction.percentile98); } boolean isFinished = false; List<WindowFunction> windowFunctions; List<WindowFunction> quantileFunctions; DoubleArrayList values = null; float sum = 0.0f; int nPts = 0; Map<WindowFunction, List<PercentileValue>> percentiles = new HashMap(); float min = Float.NaN; float max = Float.NaN; float mean = Float.NaN; float median = Float.NaN; float percentile2 = Float.NaN; float percentile10 = Float.NaN; float percentile90 = Float.NaN; float percentile98 = Float.NaN; public Accumulator(Collection<WindowFunction> windowFunctions) { this.windowFunctions = new ArrayList(windowFunctions); quantileFunctions = new ArrayList(); for (WindowFunction wf : windowFunctions) { if (PERCENTILE_WINDOW_FUNCTIONS.contains(wf)) { quantileFunctions.add(wf); if (values == null) { values = new DoubleArrayList(); } } } } public void add(float v) { if (!Float.isNaN(v)) { min = Float.isNaN(min) ? v : Math.min(min, v); max = Float.isNaN(max) ? v : Math.max(max, v); sum += v; nPts++; if (values != null) { values.add(v); if (values.size() > MAX_VALUE_COUNT) { computePercentiles(); values.clear(); } } } } public void finish() { if (isFinished) { return; } mean = Float.isNaN(sum) ? Float.NaN : sum / nPts; if (values != null) { if (nPts == 1) { for (WindowFunction wf : quantileFunctions) { setValue(wf, mean); } } else { if (values.size() > 1) { computePercentiles(); } for (WindowFunction wf : quantileFunctions) { List<PercentileValue> pList = percentiles.get(wf); float v = Float.NaN; // <= Default, if (pList != null && pList.size() > 0) { double weightedSum = 0; double sumOfWeights = 0; for (PercentileValue pv : pList) { double weight = (double) pv.nPoints / nPts; sumOfWeights += weight; weightedSum += weight * pv.value; } v = (float) (weightedSum / sumOfWeights); } setValue(wf, v); } } } values = null; isFinished = true; } private Percentile percentile = new Percentile(); private void computePercentiles() { if (values != null) { double[] valueArray = values.toArray(); for (WindowFunction wf : quantileFunctions) { double p = this.getPercentile(wf); if (p > 0) { float v = (float) percentile.evaluate(valueArray, p); // float v = (float) StatUtils.percentile(valueArray, p); if (Float.isInfinite(v)) { log.log(Level.SEVERE, "Infinite percentile (" + wf + ")"); } else { List<PercentileValue> pList = percentiles.get(wf); if (pList == null) { pList = new ArrayList(); percentiles.put(wf, pList); } pList.add(new PercentileValue(valueArray.length, v)); } } } } } private void setValue(WindowFunction wf, float value) { switch (wf) { case mean: mean = value; break; case median: median = value; break; case min: min = value; break; case max: max = value; break; case percentile2: percentile2 = value; break; case percentile10: percentile10 = value; break; case percentile90: percentile90 = value; break; case percentile98: percentile98 = value; break; default: System.err.println("Unexpected window function: " + wf.toString()); } } public float getValue(WindowFunction wf) { switch (wf) { case mean: return mean; case median: return median; case min: return min; case max: return max; case percentile2: return percentile2; case percentile10: return percentile10; case percentile90: return percentile90; case percentile98: return percentile98; case count: return nPts; default: System.err.println("Unexpected window function: " + wf.toString()); } return Float.NaN; } public double getPercentile(WindowFunction wf) { switch (wf) { case percentile2: return 2; case percentile10: return 10; case percentile90: return 90; case percentile98: return 98; case median: return 50; default: return -1.0; } } class PercentileValue { int nPoints; double value; PercentileValue(int nPoints, double value) { this.nPoints = nPoints; this.value = value; } } }