/*
* MLEGSSDialog.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.app.beauti.components.marginalLikelihoodEstimation;
import dr.app.beauti.options.BeautiOptions;
import dr.app.beauti.types.TreePriorType;
import dr.app.beauti.util.PanelUtils;
import dr.app.gui.components.WholeNumberField;
import jam.panels.OptionsPanel;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
/**
* @author Guy Baele
*/
public class MLEGSSDialog {
private JFrame frame;
private final OptionsPanel optionsPanel;
private JLabel labelPathSteps, labelChainLength, labelLogEvery, labelLogFileName, labelResultFileName;
private JLabel labelStepDistribution, labelTreeWorkingPrior, labelParameterWorkingPrior;
private WholeNumberField pathStepsField = new WholeNumberField(1, Integer.MAX_VALUE);
private WholeNumberField chainLengthField = new WholeNumberField(1, Integer.MAX_VALUE);
private WholeNumberField logEveryField = new WholeNumberField(1, Integer.MAX_VALUE);
private JTextArea logFileNameField = new JTextArea("mle.log");
private JTextArea resultFileNameField = new JTextArea("mle.result.log");
JCheckBox operatorAnalysis = new JCheckBox("Print operator analysis");
private JComboBox stepDistribution = new JComboBox();
private JComboBox treeWorkingPrior = new JComboBox();
//private JComboBox parameterWorkingPrior = new JComboBox();
private MarginalLikelihoodEstimationOptions options;
private BeautiOptions beautiOptions;
private String description = "Settings for marginal likelihood estimation using GSS";
public MLEGSSDialog(final JFrame frame, final MarginalLikelihoodEstimationOptions options, final BeautiOptions beautiOptions) {
this.frame = frame;
this.options = options;
this.beautiOptions = beautiOptions;
optionsPanel = new OptionsPanel(12, 12);
optionsPanel.setOpaque(false);
JTextArea mleInfo = new JTextArea("Set the options to perform marginal likelihood " +
"estimation (MLE) using generalized stepping-stone sampling (GSS).");
mleInfo.setColumns(56);
PanelUtils.setupComponent(mleInfo);
optionsPanel.addSpanningComponent(mleInfo);
pathStepsField.setValue(100);
pathStepsField.setColumns(16);
pathStepsField.setMinimumSize(pathStepsField.getPreferredSize());
labelPathSteps = optionsPanel.addComponentWithLabel("Number of stepping stones:", pathStepsField);
pathStepsField.addKeyListener(new java.awt.event.KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
options.pathSteps = pathStepsField.getValue();
}
});
chainLengthField.setValue(1000000);
chainLengthField.setColumns(16);
chainLengthField.setMinimumSize(chainLengthField.getPreferredSize());
labelChainLength = optionsPanel.addComponentWithLabel("Length of chains:", chainLengthField);
chainLengthField.addKeyListener(new java.awt.event.KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
options.mleChainLength = chainLengthField.getValue();
}
});
optionsPanel.addSeparator();
logEveryField.setValue(1000);
logEveryField.setColumns(16);
logEveryField.setMinimumSize(logEveryField.getPreferredSize());
labelLogEvery = optionsPanel.addComponentWithLabel("Log likelihood every:", logEveryField);
logEveryField.addKeyListener(new java.awt.event.KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
options.mleLogEvery = logEveryField.getValue();
}
});
optionsPanel.addSeparator();
logFileNameField.setColumns(32);
logFileNameField.setEditable(false);
logFileNameField.setMinimumSize(logFileNameField.getPreferredSize());
labelLogFileName = optionsPanel.addComponentWithLabel("Log file name:", logFileNameField);
logFileNameField.addKeyListener(new java.awt.event.KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
options.mleFileName = logFileNameField.getText();
}
});
optionsPanel.addSeparator();
resultFileNameField.setColumns(32);
resultFileNameField.setEditable(false);
resultFileNameField.setMinimumSize(resultFileNameField.getPreferredSize());
labelResultFileName = optionsPanel.addComponentWithLabel("Results file name:", resultFileNameField);
resultFileNameField.addKeyListener(new java.awt.event.KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
options.mleResultFileName = resultFileNameField.getText();
}
});
optionsPanel.addSeparator();
JTextArea betaInfo = new JTextArea("By default, the power posteriors are determined according to " +
"evenly spaced quantiles of a Beta(0.3, 1.0) distribution, thereby estimating " +
"more power posteriors close to the prior.");
betaInfo.setColumns(56);
PanelUtils.setupComponent(betaInfo);
optionsPanel.addSpanningComponent(betaInfo);
treeWorkingPrior.addItem("Product of exponential distributions");
treeWorkingPrior.addItem("Matching coalescent model");
treeWorkingPrior.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
String selection = (String)((JComboBox)e.getSource()).getSelectedItem();
if (selection.equals("Matching coalescent model")) {
beautiOptions.logCoalescentEventsStatistic = false;
} else {
beautiOptions.logCoalescentEventsStatistic = true;
}
TreePriorType treePrior = beautiOptions.getPartitionTreePriors().get(0).getNodeHeightPrior();
boolean mcmAllowed = false;
if (treePrior.equals(TreePriorType.CONSTANT) || treePrior.equals(TreePriorType.EXPONENTIAL)
|| treePrior.equals(TreePriorType.EXPANSION) || treePrior.equals(TreePriorType.LOGISTIC)) {
mcmAllowed = true;
}
if (selection.equals("Matching coalescent model") && !mcmAllowed) {
JOptionPane.showMessageDialog(frame,
"The selected coalescent model can't be equipped with a \n" +
"matching working prior. Reverting back to use a product \n" +
"of exponential distributions.",
"Matching coalescent model warning",
JOptionPane.WARNING_MESSAGE);
treeWorkingPrior.setSelectedItem("Product of exponential distributions");
options.choiceTreeWorkingPrior = "Product of exponential distributions";
} else {
options.choiceTreeWorkingPrior = selection;
}
}
});
labelTreeWorkingPrior = optionsPanel.addComponentWithLabel("Tree working prior", treeWorkingPrior);
//parameterWorkingPrior.addItem("Normal KDE");
//parameterWorkingPrior.addItem("Gamma KDE");
//labelParameterWorkingPrior = optionsPanel.addComponentWithLabel("Parameter working prior", parameterWorkingPrior);
stepDistribution.addItem("Beta");
labelStepDistribution = optionsPanel.addComponentWithLabel("Stepping stone distribution:", stepDistribution);
optionsPanel.addSeparator();
optionsPanel.addComponent(operatorAnalysis);
operatorAnalysis.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
if (operatorAnalysis.isSelected()) {
options.printOperatorAnalysis = true;
} else {
options.printOperatorAnalysis = false;
}
}
});
optionsPanel.addSeparator();
JTextArea mleTutorial = new JTextArea("Additional information on marginal likelihood estimation in BEAST " +
"can be found on http://beast.bio.ed.ac.uk/Model-selection");
mleTutorial.setColumns(56);
PanelUtils.setupComponent(mleTutorial);
optionsPanel.addSpanningComponent(mleTutorial);
JTextArea citationText = new JTextArea("Baele G, Lemey P, Suchard MA (2016) Genealogical working " +
"distributions for Bayesian \nmodel testing with phylogenetic uncertainty. Syst. Biol. 65(2), 250-264 [GSS Paper].");
citationText.setColumns(45);
optionsPanel.addComponentWithLabel("Citation:", citationText);
optionsPanel.addSeparator();
/*JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
panel.add(optionsPanel, BorderLayout.CENTER);
panel.setOpaque(false);
JScrollPane scrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setOpaque(false);
scrollPane.setBorder(null);
scrollPane.getViewport().setOpaque(false);
add(scrollPane, BorderLayout.CENTER);*/
}
public int showDialog() {
JOptionPane optionPane = new JOptionPane(optionsPanel,
JOptionPane.QUESTION_MESSAGE,
JOptionPane.OK_CANCEL_OPTION,
null,
null,
null);
optionPane.setBorder(new EmptyBorder(12, 12, 12, 12));
final JDialog dialog = optionPane.createDialog(frame, description);
dialog.pack();
dialog.setVisible(true);
int result = JOptionPane.CANCEL_OPTION;
Integer value = (Integer) optionPane.getValue();
if (value != null && value != -1) {
result = value;
}
return result;
}
/*public JComponent getExportableComponent() {
return optionsPanel;
}*/
public void setFilenameStem(String fileNameStem, boolean addTxt) {
logFileNameField.setText(fileNameStem + ".mle.log" + (addTxt ? ".txt" : ""));
resultFileNameField.setText(fileNameStem + ".mle.result.log" + (addTxt ? ".txt" : ""));
options.mleFileName = logFileNameField.getText();
options.mleResultFileName = resultFileNameField.getText();
}
public void setOptions(MarginalLikelihoodEstimationOptions options) {
this.options = options;
pathStepsField.setValue(options.pathSteps);
chainLengthField.setValue(options.mleChainLength);
logEveryField.setValue(options.mleLogEvery);
logFileNameField.setText(options.mleFileName);
resultFileNameField.setText(options.mleResultFileName);
treeWorkingPrior.setSelectedItem(options.choiceTreeWorkingPrior);
if (options.choiceTreeWorkingPrior.equals("Product of exponential distributions") && options.performMLEGSS) {
beautiOptions.logCoalescentEventsStatistic = true;
} else {
beautiOptions.logCoalescentEventsStatistic = false;
}
optionsPanel.validate();
optionsPanel.repaint();
}
public void getOptions(MarginalLikelihoodEstimationOptions options) {
options.pathSteps = pathStepsField.getValue();
options.mleChainLength = chainLengthField.getValue();
options.mleLogEvery = logEveryField.getValue();
options.mleFileName = logFileNameField.getText();
options.mleResultFileName = resultFileNameField.getText();
options.choiceTreeWorkingPrior = treeWorkingPrior.getSelectedItem().toString();
if (options.choiceTreeWorkingPrior.equals("Product of exponential distributions") && options.performMLEGSS) {
beautiOptions.logCoalescentEventsStatistic = true;
} else {
beautiOptions.logCoalescentEventsStatistic = false;
}
}
}