/*
* BayesFactorsDialog.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.app.gui.components.WholeNumberField;
import dr.app.gui.util.LongTask;
import dr.inference.trace.MarginalLikelihoodAnalysis;
import dr.inference.trace.TraceList;
import dr.util.TaskListener;
import jam.framework.DocumentFrame;
import jam.panels.OptionsPanel;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class BayesFactorsDialog {
private JFrame frame;
private JComboBox likelihoodCombo;
private JComboBox analysisTypeCombo;
private WholeNumberField bootstrapCountField;
private String[] likelihoodGuesses = {
"likelihood", "treelikelihood", "lnl", "lik"
};
private String likelihoodTrace = "None selected";
private OptionsPanel optionPanel;
public BayesFactorsDialog(JFrame frame) {
this.frame = frame;
likelihoodCombo = new JComboBox();
analysisTypeCombo = new JComboBox();
bootstrapCountField = new WholeNumberField(0, Integer.MAX_VALUE);
bootstrapCountField.setValue(1000);
optionPanel = new OptionsPanel(12, 12);
}
private int findArgument(JComboBox comboBox, String argument) {
for (int i = 0; i < comboBox.getItemCount(); i++) {
String item = ((String) comboBox.getItemAt(i)).toLowerCase();
if (item.indexOf(argument) != -1) return i;
}
return -1;
}
public String getLikelihoodTrace() {
return likelihoodTrace;
}
public int showDialog(List<TraceList> traceLists) {
setArguments();
likelihoodCombo.removeAllItems();
List<String> statistics = new ArrayList<String>();
TraceList tl = traceLists.get(0);
for (int j = 0; j < tl.getTraceCount(); j++) {
statistics.add(tl.getTraceName(j));
}
for (int i = 1; i < traceLists.size(); i++) {
tl = traceLists.get(i);
Set<String> statistics2 = new HashSet<String>();
for (int j = 0; j < tl.getTraceCount(); j++) {
statistics2.add(tl.getTraceName(j));
}
statistics.retainAll(statistics2);
}
if (statistics.size() == 0) {
JOptionPane.showMessageDialog(frame,
"These trace files don't seem to have any traces in common.",
"Unable to perform analysis",
JOptionPane.ERROR_MESSAGE);
return JOptionPane.CANCEL_OPTION;
}
for (String statistic : statistics) {
likelihoodCombo.addItem(statistic);
}
int index = -1;
for (String guess : likelihoodGuesses) {
if (index != -1) break;
index = findArgument(likelihoodCombo, guess);
}
if (index == -1) index = 0;
likelihoodCombo.setSelectedIndex(index);
analysisTypeCombo.removeAllItems();
analysisTypeCombo.addItem("aicm");
analysisTypeCombo.addItem("harmonic mean");
JOptionPane optionPane = new JOptionPane(optionPanel,
JOptionPane.QUESTION_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
null,
null,
null);
optionPane.setBorder(new EmptyBorder(12, 12, 12, 12));
final JDialog dialog = optionPane.createDialog(frame, "Model Comparison");
dialog.pack();
dialog.setVisible(true);
int result = JOptionPane.CANCEL_OPTION;
Integer value = (Integer) optionPane.getValue();
if (value != null && value != -1) {
result = value;
}
if (result == JOptionPane.OK_OPTION) {
likelihoodTrace = (String) likelihoodCombo.getSelectedItem();
}
return result;
}
private void setArguments() {
optionPanel.removeAll();
optionPanel.addLabel("Select the trace to analyse:");
optionPanel.addComponents(new JLabel("Likelihood trace:"), likelihoodCombo);
optionPanel.addComponents(new JLabel("Analysis type:"), analysisTypeCombo);
bootstrapCountField.setColumns(12);
optionPanel.addComponents(new JLabel("Bootstrap replicates:"), bootstrapCountField);
}
Timer timer = null;
public void createBayesFactorsFrame(List<TraceList> traceLists, DocumentFrame parent) {
String analysisType = analysisTypeCombo.getSelectedItem().toString();
int bootstrapLength = bootstrapCountField.getValue();
boolean isAICM = false;
if (analysisType.equals("aicm")) {
isAICM = true;
}
BayesFactorsFrame frame = new BayesFactorsFrame(parent, "Model Comparison", bootstrapLength > 1, isAICM);
frame.initialize();
frame.setVisible(true);
final MarginalLikelihoodTask analyseTask = new MarginalLikelihoodTask(frame, traceLists, analysisType, bootstrapLength);
final ProgressMonitor progressMonitor = new ProgressMonitor(frame,
"Estimating Marginal Likelihoods",
"", 0, analyseTask.getLengthOfTask());
progressMonitor.setMillisToPopup(0);
progressMonitor.setMillisToDecideToPopup(0);
timer = new Timer(100, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
progressMonitor.setProgress(analyseTask.getCurrent());
if (progressMonitor.isCanceled() || analyseTask.done()) {
progressMonitor.close();
analyseTask.stop();
timer.stop();
}
}
});
analyseTask.go();
timer.start();
}
class MarginalLikelihoodTask extends LongTask {
List<TraceList> traceLists;
BayesFactorsFrame frame;
String analysisType;
int bootstrapLength;
private int lengthOfTask = 0;
private int current = 0;
public MarginalLikelihoodTask(BayesFactorsFrame frame, List<TraceList> traceLists, String analysisType, int bootstrapLength) {
this.traceLists = traceLists;
this.analysisType = analysisType;
this.bootstrapLength = bootstrapLength;
this.frame = frame;
lengthOfTask = traceLists.size() * 100;
}
public int getCurrent() {
return current;
}
public int getLengthOfTask() {
return lengthOfTask;
}
public String getDescription() {
return "Estimating marginal likelihoods...";
}
public String getMessage() {
return null;
}
public Object doWork() {
current = 0;
int i = 0;
for (TraceList traceList : traceLists) {
final int offset = i * 100;
int index = traceList.getTraceIndex(likelihoodTrace);
List<Double> likelihoods = traceList.getValues(index);
final MarginalLikelihoodAnalysis analysis = new MarginalLikelihoodAnalysis(likelihoods,
traceList.getName(), traceList.getBurnIn(), analysisType, bootstrapLength);
analysis.setTaskListener(new TaskListener() {
public void progress(double progress) {
current = offset + (int) (progress * 100);
}
});
// call to force calculation...
analysis.calculate();
EventQueue.invokeLater(
new Runnable() {
public void run() {
frame.addMarginalLikelihood(analysis);
}
});
i++;
}
return null;
}
}
}