/* * NumberColumn.java * * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package dr.inference.loggers; import java.text.DecimalFormat; /** * An interface for a numerical column in a log. * * @version $Id: NumberColumn.java,v 1.4 2005/05/24 20:25:59 rambaut Exp $ * * @author Andrew Rambaut * @author Alexei Drummond */ public abstract class NumberColumn extends LogColumn.Abstract { private int sf = -1; private int dp = -1; private double upperCutoff; private double[] cutoffTable; private final DecimalFormat decimalFormat = new DecimalFormat(); private DecimalFormat scientificFormat = null; public NumberColumn(String label) { super(label); decimalFormat.setGroupingUsed(false); // not use comma } public NumberColumn(String label, int sf) { this(label); setSignificantFigures(sf); } /** * Set the number of significant figures to display when formatted. * Setting this overrides the decimal places option. */ public void setSignificantFigures(int sf) { this.sf = sf; this.dp = -1; upperCutoff = Math.pow(10,sf-1); cutoffTable = new double[sf]; long num = 10; for (int i =0; i < cutoffTable.length; i++) { cutoffTable[i] = (double)num; num *= 10; } decimalFormat.setGroupingUsed(false); decimalFormat.setMinimumIntegerDigits(1); decimalFormat.setMaximumFractionDigits(sf-1); decimalFormat.setMinimumFractionDigits(sf-1); scientificFormat = new DecimalFormat(getPattern(sf)); } /** * Get the number of significant figures to display when formatted. * Returns -1 if maximum s.f. are to be used. */ public int getSignificantFigures() { return sf; } /** * Set the number of decimal places to display when formatted. * Setting this overrides the significant figures option. */ public void setDecimalPlaces(int dp) { this.dp = dp; this.sf = -1; } /** * Get the number of decimal places to display when formatted. * Returns -1 if maximum d.p. are to be used. */ public int getDecimalPlaces() { return dp; } public String formatValue(double value) { if (dp < 0 && sf < 0) { // return it at full precision return Double.toString(value); } int numFractionDigits = 0; if (dp < 0) { double absValue = Math.abs(value); if ((absValue > upperCutoff) || (absValue < 0.1)) { return scientificFormat.format(value); } else { numFractionDigits = getNumFractionDigits(value); } } else { numFractionDigits = dp; } decimalFormat.setMaximumFractionDigits(numFractionDigits); decimalFormat.setMinimumFractionDigits(numFractionDigits); return decimalFormat.format(value); } /** * Returns a string containing the current value for this column with * appropriate formatting. * * @return the formatted string. */ protected String getFormattedValue() { return formatValue(getDoubleValue()); } private int getNumFractionDigits(double value) { value = Math.abs(value); for (int i = 0; i < cutoffTable.length; i++) { if (value < cutoffTable[i]) return sf-i-1; } return sf - 1; } private String getPattern(int sf) { String pattern = "0."; for (int i =0; i < sf-1; i++) { pattern += "#"; } pattern += "E0"; return pattern; } /** * Returns the current value as a double. */ public abstract double getDoubleValue(); }