/* * MCLogger.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.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; /** * A class for a general purpose logger. * * @author Andrew Rambaut * @author Alexei Drummond * @version $Id: MCLogger.java,v 1.18 2005/05/24 20:25:59 rambaut Exp $ */ public class MCLogger implements Logger { /** * Output performance stats in this log */ private final boolean performanceReport; private final int performanceReportDelay; /** * Constructor. Will log every logEvery. * * @param formatter the formatter of this logger * @param logEvery logging frequency */ public MCLogger(LogFormatter formatter, int logEvery, boolean performanceReport, int performanceReportDelay) { addFormatter(formatter); this.logEvery = logEvery; this.performanceReport = performanceReport; this.performanceReportDelay = performanceReportDelay; } /** * Constructor. Will log every logEvery. * * @param formatter the formatter of this logger * @param logEvery logging frequency */ public MCLogger(LogFormatter formatter, int logEvery, boolean performanceReport) { this(formatter, logEvery, performanceReport, 0); } /** * Constructor. Will log every logEvery. * * @param logEvery logging frequency */ public MCLogger(String fileName, int logEvery, boolean performanceReport, int performanceReportDelay) throws IOException { this(new TabDelimitedFormatter(new PrintWriter(new FileWriter(fileName))), logEvery, performanceReport, performanceReportDelay); } /** * Additional constructor that does not add a provided Formatter * @param performanceReport * @param performanceReportDelay */ public MCLogger(boolean performanceReport, int performanceReportDelay) { this.performanceReport = performanceReport; this.performanceReportDelay = performanceReportDelay; } /** * Constructor. Will log every logEvery. * * @param logEvery logging frequency */ public MCLogger(int logEvery) { this(new TabDelimitedFormatter(System.out), logEvery, true, 0); } public final void setTitle(String title) { this.title = title; } public final String getTitle() { return title; } public int getLogEvery() { return logEvery; } public void setLogEvery(int logEvery) { this.logEvery = logEvery; } public final void addFormatter(LogFormatter formatter) { formatters.add(formatter); } public final void add(Loggable loggable) { LogColumn[] columns = loggable.getColumns(); for (LogColumn column : columns) { addColumn(column); } } public final void addColumn(LogColumn column) { columns.add(column); } public final void addColumns(LogColumn[] columns) { for (LogColumn column : columns) { addColumn(column); } } public final int getColumnCount() { return columns.size(); } public final LogColumn getColumn(int index) { return columns.get(index); } public final String getColumnLabel(int index) { return columns.get(index).getLabel(); } public final String getColumnFormatted(int index) { return columns.get(index).getFormatted(); } protected void logHeading(String heading) { for (LogFormatter formatter : formatters) { formatter.logHeading(heading); } } protected void logLine(String line) { for (LogFormatter formatter : formatters) { formatter.logLine(line); } } protected void logLabels(String[] labels) { for (LogFormatter formatter : formatters) { formatter.logLabels(labels); } } protected void logValues(String[] values) { for (LogFormatter formatter : formatters) { formatter.logValues(values); } } public void startLogging() { for (LogFormatter formatter : formatters) { formatter.startLogging(title); } if (title != null) { logHeading(title); } if (logEvery > 0) { final int columnCount = getColumnCount(); String[] labels = new String[columnCount + 1]; labels[0] = "state"; for (int i = 0; i < columnCount; i++) { labels[i + 1] = getColumnLabel(i); } logLabels(labels); } } public final void log(int state) { // just to prevent overriding of the old 32 bit signature } public void log(long state) { if (performanceReport && !performanceReportStarted && state >= performanceReportDelay) { startTime = System.currentTimeMillis(); startState = state; formatter.setMaximumFractionDigits(2); } if (logEvery > 0 && (state % logEvery == 0)) { final int columnCount = getColumnCount(); String[] values = new String[columnCount + (performanceReport ? 2 : 1)]; values[0] = Long.toString(state); for (int i = 0; i < columnCount; i++) { values[i + 1] = getColumnFormatted(i); } if (performanceReport) { if (performanceReportStarted) { long time = System.currentTimeMillis(); double hoursPerMillionStates = (double) (time - startTime) / (3.6 * (double) (state - startState)); String hpm = formatter.format(hoursPerMillionStates); if (hpm.equals("0")) { // test cases can run fast :) hpm = formatter.format(1000 * hoursPerMillionStates); values[columnCount + 1] = hpm + " hours/billion states"; } else { values[columnCount + 1] = hpm + " hours/million states"; } } else { values[columnCount + 1] = "-"; } } logValues(values); } if (performanceReport && !performanceReportStarted && state >= performanceReportDelay) { performanceReportStarted = true; } } public void stopLogging() { for (LogFormatter formatter : formatters) { formatter.stopLogging(); } } private String title = null; private ArrayList<LogColumn> columns = new ArrayList<LogColumn>(); protected int logEvery = 0; public List<LogFormatter> getFormatters() { return formatters; } public void setFormatters(List<LogFormatter> formatters) { this.formatters = formatters; } protected List<LogFormatter> formatters = new ArrayList<LogFormatter>(); private boolean performanceReportStarted = false; private long startTime; private long startState; private final NumberFormat formatter = NumberFormat.getNumberInstance(); }