/* * BayesFactorsFrame.java * * Copyright (C) 2002-2007 Alexei Drummond and Andrew Rambaut * * 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.app.tracer.analysis; import dr.inference.trace.MarginalLikelihoodAnalysis; import jam.framework.AuxilaryFrame; import jam.framework.DocumentFrame; import javax.swing.*; import javax.swing.border.EmptyBorder; import javax.swing.plaf.BorderUIResource; import javax.swing.table.AbstractTableModel; import java.awt.*; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; public class BayesFactorsFrame extends AuxilaryFrame { private List<MarginalLikelihoodAnalysis> marginalLikelihoods = new ArrayList<MarginalLikelihoodAnalysis>(); private JPanel contentPanel; private JComboBox transformCombo; private BayesFactorsModel bayesFactorsModel; private JTable bayesFactorsTable; public BayesFactorsFrame(DocumentFrame frame, String title, boolean hasErrors, boolean isAICM) { super(frame); setTitle(title); bayesFactorsModel = new BayesFactorsModel(hasErrors, isAICM); bayesFactorsTable = new JTable(bayesFactorsModel); JScrollPane scrollPane1 = new JScrollPane(bayesFactorsTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); contentPanel = new JPanel(new BorderLayout(0, 0)); contentPanel.setOpaque(false); contentPanel.setBorder(new BorderUIResource.EmptyBorderUIResource( new java.awt.Insets(0, 0, 6, 0))); JToolBar toolBar = new JToolBar(); toolBar.setLayout(new FlowLayout(FlowLayout.LEFT)); toolBar.setFloatable(false); JPanel panel1 = new JPanel(new BorderLayout(0, 0)); panel1.setOpaque(false); JLabel label = new JLabel("<html>Models compared by marginal likelihood (S.E. estimated from bootstrap " + "replicates). Differences between log marginal likelihoods (specifically, log Bayes factors) are " + "reported. Positive values indicate better relative model fit of the rows's model compared to the " + "column's model.</html>"); if (isAICM) { label = new JLabel("<html>Models compared by AICM (S.E. estimated from bootstrap replicates). " + "Lower AICM values indicate better model fit. Differences between AICM estimates are reported. " + "Positive values indicate better relative model fit of the row's model compared to the column's " + "model.</html>"); label.setFont(UIManager.getFont("SmallSystemFont")); } label.setFont(UIManager.getFont("SmallSystemFont")); label.setBorder(new EmptyBorder(5, 5, 5, 5)); panel1.add(label, BorderLayout.NORTH); panel1.add(scrollPane1, BorderLayout.CENTER); contentPanel.add(panel1, BorderLayout.CENTER); label = new JLabel("<html>Marginal likelihood estimated using the smoothed harmonic mean estimator following " + "Newton & Raftery (1994, <i>J. Roy. Statist. Soc. B.</i> <b>56</b>: 3-48) " + "with the modifications proprosed by Suchard et al. (2001, <i>MBE</i> <b>18</b>: 1001-1013)</html>"); if (isAICM) { label = new JLabel("<html>AICM estimated using the method-of-moments estimator. Please cite: Baele, " + "Lemey, Bedford, Rambaut, Suchard and Alekseyenko. Improving the accuracy of demographic and " + "molecular clock model comparison while accommodating phylogenetic uncertainty. In prep.</html>"); label.setFont(UIManager.getFont("SmallSystemFont")); } label.setFont(UIManager.getFont("SmallSystemFont")); label.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPanel.add(label, BorderLayout.SOUTH); setContentsPanel(contentPanel); getSaveAction().setEnabled(false); getSaveAsAction().setEnabled(false); getCutAction().setEnabled(false); getCopyAction().setEnabled(true); getPasteAction().setEnabled(false); getDeleteAction().setEnabled(false); getSelectAllAction().setEnabled(false); getFindAction().setEnabled(false); getZoomWindowAction().setEnabled(false); } public void addMarginalLikelihood(MarginalLikelihoodAnalysis marginalLikelihood) { this.marginalLikelihoods.add(marginalLikelihood); bayesFactorsModel.fireTableStructureChanged(); bayesFactorsTable.repaint(); } public void initializeComponents() { setSize(new Dimension(640, 480)); } public boolean useExportAction() { return true; } public JComponent getExportableComponent() { return contentPanel; } public void doCopy() { java.awt.datatransfer.Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); java.awt.datatransfer.StringSelection selection = new java.awt.datatransfer.StringSelection(bayesFactorsModel.toString()); clipboard.setContents(selection, selection); } class BayesFactorsModel extends AbstractTableModel { String[] columnNames = {"Trace", "ln P(data | model)", "S.E."}; boolean isAICM = false; private DecimalFormat formatter2 = new DecimalFormat("####0.###"); private int columnCount; public BayesFactorsModel(boolean hasErrors, boolean isAICM) { this.columnCount = (hasErrors ? 3 : 2); this.isAICM = isAICM; if (isAICM) { columnNames[1] = "AICM"; } } public int getColumnCount() { return columnCount + marginalLikelihoods.size(); } public int getRowCount() { return marginalLikelihoods.size(); } public Object getValueAt(int row, int col) { if (col == 0) { return marginalLikelihoods.get(row).getTraceName(); } if (col == 1) { return formatter2.format(marginalLikelihoods.get(row).getLogMarginalLikelihood()); } else if (columnCount > 2 && col == 2) { return " +/- " + formatter2.format(marginalLikelihoods.get(row).getBootstrappedSE()); } else { if (col - columnCount != row) { double lnML1 = marginalLikelihoods.get(row).getLogMarginalLikelihood(); double lnML2 = marginalLikelihoods.get(col - columnCount).getLogMarginalLikelihood(); double lnRatio = lnML1 - lnML2; if (isAICM) { lnRatio = lnML2 - lnML1; } return formatter2.format(lnRatio); } else { return "-"; } } } public String getColumnName(int column) { if (column < columnCount) { return columnNames[column]; } return marginalLikelihoods.get(column - columnCount).getTraceName(); } public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(getColumnName(0)); for (int j = 1; j < getColumnCount(); j++) { buffer.append("\t"); buffer.append(getColumnName(j)); } buffer.append("\n"); for (int i = 0; i < getRowCount(); i++) { buffer.append(getValueAt(i, 0)); for (int j = 1; j < getColumnCount(); j++) { buffer.append("\t"); buffer.append(getValueAt(i, j)); } buffer.append("\n"); } return buffer.toString(); } } }