/*
* PartitionTreeModelPanel.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.treespanel;
import dr.app.beauti.BeautiFrame;
import dr.app.beauti.options.BeautiOptions;
import dr.app.beauti.options.PartitionTreeModel;
import dr.app.beauti.types.StartingTreeType;
import dr.app.beauti.util.PanelUtils;
import dr.app.gui.components.RealNumberField;
import dr.app.util.OSType;
import dr.evolution.datatype.DataType;
import dr.evolution.datatype.PloidyType;
import dr.evolution.tree.NodeRef;
import dr.evolution.tree.Tree;
import jam.panels.OptionsPanel;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
/**
* @author Andrew Rambaut
* @author Alexei Drummond
* @author Walter Xie
* @version $Id: PriorsPanel.java,v 1.9 2006/09/05 13:29:34 rambaut Exp $
*/
public class PartitionTreeModelPanel extends OptionsPanel {
private static final long serialVersionUID = 8096349200725353543L;
private final String NO_TREE = "no tree loaded";
private JComboBox ploidyTypeCombo = new JComboBox(PloidyType.values());
private ButtonGroup startingTreeGroup = new ButtonGroup();
private JRadioButton randomTreeRadio = new JRadioButton("Random starting tree");
private JRadioButton upgmaTreeRadio = new JRadioButton("UPGMA starting tree");
private JRadioButton userTreeRadio = new JRadioButton("User-specified starting tree");
private JLabel userTreeLabel = new JLabel("Select user-specified tree:");
private JComboBox userTreeCombo = new JComboBox();
private JLabel treeFormatLabel = new JLabel("Export format for tree:");
private JComboBox treeFormatCombo = new JComboBox(new String[] {"Newick", "XML"});
private JLabel userTreeInfo = new JLabel("<html>" +
"Import user-specified starting trees from <b>NEXUS</b><br>" +
"format data files using the 'Import Data' menu option.<br>" +
"Trees must be rooted and strictly bifurcating (binary).</html>");
// private JButton treeDisplayButton = new JButton("Display selected tree");
// private JButton correctBranchLengthButton = new JButton("Correct branch lengths to get ultrametric tree");
private RealNumberField initRootHeightField = new RealNumberField(Double.MIN_VALUE, Double.POSITIVE_INFINITY, "Init root height");
private BeautiOptions options = null;
private final BeautiFrame parent;
private boolean settingOptions = false;
PartitionTreeModel partitionTreeModel;
public PartitionTreeModelPanel(final BeautiFrame parent, PartitionTreeModel parTreeModel, final BeautiOptions options) {
super(12, (OSType.isMac() ? 6 : 24));
this.partitionTreeModel = parTreeModel;
this.options = options;
this.parent = parent;
PanelUtils.setupComponent(initRootHeightField);
initRootHeightField.setColumns(10);
initRootHeightField.setEnabled(false);
PanelUtils.setupComponent(ploidyTypeCombo);
ploidyTypeCombo.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ev) {
partitionTreeModel.setPloidyType((PloidyType) ploidyTypeCombo.getSelectedItem());
}
});
if (options.isEBSPSharingSamePrior() || options.useStarBEAST) {
ploidyTypeCombo.setSelectedItem(partitionTreeModel.getPloidyType());
}
PanelUtils.setupComponent(randomTreeRadio);
PanelUtils.setupComponent(upgmaTreeRadio);
PanelUtils.setupComponent(userTreeRadio);
startingTreeGroup.add(randomTreeRadio);
startingTreeGroup.add(upgmaTreeRadio);
startingTreeGroup.add(userTreeRadio);
randomTreeRadio.setSelected(partitionTreeModel.getStartingTreeType() == StartingTreeType.RANDOM);
upgmaTreeRadio.setSelected(partitionTreeModel.getStartingTreeType() == StartingTreeType.UPGMA);
userTreeRadio.setSelected(partitionTreeModel.getStartingTreeType() == StartingTreeType.USER);
userTreeRadio.setEnabled(options.userTrees.size() > 0);
boolean enabled = partitionTreeModel.getStartingTreeType() == StartingTreeType.USER;
userTreeLabel.setEnabled(enabled);
userTreeCombo.setEnabled(enabled);
treeFormatLabel.setEnabled(enabled);
treeFormatCombo.setEnabled(enabled);
userTreeInfo.setEnabled(enabled);
PanelUtils.setupComponent(treeFormatCombo);
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
if (randomTreeRadio.isSelected()) {
partitionTreeModel.setStartingTreeType(StartingTreeType.RANDOM);
} else if (upgmaTreeRadio.isSelected()) {
partitionTreeModel.setStartingTreeType(StartingTreeType.UPGMA);
} else if (userTreeRadio.isSelected()) {
partitionTreeModel.setStartingTreeType(StartingTreeType.USER);
}
boolean enabled = partitionTreeModel.getStartingTreeType() == StartingTreeType.USER;
userTreeLabel.setEnabled(enabled);
userTreeCombo.setEnabled(enabled);
treeFormatLabel.setEnabled(enabled);
treeFormatCombo.setEnabled(enabled);
userTreeInfo.setEnabled(enabled);
}
};
randomTreeRadio.addActionListener(listener);
upgmaTreeRadio.addActionListener(listener);
userTreeRadio.addActionListener(listener);
treeFormatCombo.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent itemEvent) {
partitionTreeModel.setNewick(treeFormatCombo.getSelectedItem().equals("Newick"));
}
});
PanelUtils.setupComponent(userTreeCombo);
userTreeCombo.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ev) {
setUserSpecifiedStartingTree();
}
});
// PanelUtils.setupComponent(treeDisplayButton);
// treeDisplayButton.addActionListener(new ActionListener() {
// public void actionPerformed(ActionEvent e) {
// SquareTreePainter treePainter = new SquareTreePainter();
// treePainter.setColorAttribute("color");
// treePainter.setLineAttribute("line");
//// treePainter.setShapeAttribute("shape");
// treePainter.setLabelAttribute("label");
// Tree tree = getSelectedUserTree();
// JTreeDisplay treeDisplay = new JTreeDisplay(treePainter, tree);
//
// JTreePanel treePanel = new JTreePanel(treeDisplay);
//
// JOptionPane optionPane = new JOptionPane(treePanel,
// JOptionPane.PLAIN_MESSAGE,
// JOptionPane.OK_OPTION,
// null,
// null,
// null);
// optionPane.setBorder(new EmptyBorder(12, 12, 12, 12));
//
// final JDialog dialog = optionPane.createDialog(parent, "Display the selected starting tree - " + tree.getId());
// dialog.setSize(600, 400);
// dialog.setResizable(true);
// dialog.setVisible(true);
// }
// });
// PanelUtils.setupComponent(correctBranchLengthButton);
// correctBranchLengthButton.addActionListener(new ActionListener() {
// public void actionPerformed(ActionEvent e) {
// Tree tree = getSelectedUserTree();
// Tree.Utils.correctBranchLengthToGetUltrametricTree(tree);
// partitionTreeModel.setUserStartingTree(tree);
// }
// });
setupPanel();
}
private void setUserSpecifiedStartingTree() {
if (userTreeCombo.getSelectedItem() != null && (!userTreeCombo.getSelectedItem().toString().equalsIgnoreCase(NO_TREE))) {
Tree seleTree = getSelectedUserTree();
if (seleTree == null || isBifurcatingTree(seleTree, seleTree.getRoot())) {
partitionTreeModel.setUserStartingTree(seleTree);
} else {
JOptionPane.showMessageDialog(parent, "The selected user-specified starting tree " +
"is not fully bifurcating.\nBEAST requires rooted, bifurcating (binary) trees.",
"Illegal user-specified starting tree",
JOptionPane.ERROR_MESSAGE);
userTreeCombo.setSelectedItem(NO_TREE);
partitionTreeModel.setUserStartingTree(null);
}
}
}
public void setupPanel() {
removeAll();
if (options.isEBSPSharingSamePrior() || options.useStarBEAST) {
addComponentWithLabel("Ploidy type:", ploidyTypeCombo);
}
if (partitionTreeModel.getDataType().getType() != DataType.MICRO_SAT) {
addSpanningComponent(randomTreeRadio);
addSpanningComponent(upgmaTreeRadio);
addSpanningComponent(userTreeRadio);
addComponents(userTreeLabel, userTreeCombo);
userTreeCombo.removeAllItems();
if (options.userTrees.size() < 1) {
userTreeCombo.addItem(NO_TREE);
} else {
Object selectedItem = userTreeCombo.getSelectedItem();
for (Tree tree : options.userTrees) {
userTreeCombo.addItem(tree.getId());
}
if (selectedItem != null) {
userTreeCombo.setSelectedItem(selectedItem);
} else {
userTreeCombo.setSelectedIndex(0);
}
}
// addComponent(treeDisplayButton); // todo JTreeDisplay not work properly
addComponents(treeFormatLabel, treeFormatCombo);
addComponent(userTreeInfo);
}
// generateTreeAction.setEnabled(options != null && options.dataPartitions.size() > 0);
setOptions();
validate();
repaint();
}
public void setOptions() {
if (partitionTreeModel == null) {
return;
}
// setupPanel();
settingOptions = true;
initRootHeightField.setValue(partitionTreeModel.getInitialRootHeight());
// if (options.isEBSPSharingSamePrior() || options.useStarBEAST) {
// ploidyTypeCombo.setSelectedItem(partitionTreeModel.getPloidyType());
// }
// startingTreeCombo.setSelectedItem(partitionTreeModel.getStartingTreeType());
//
// if (partitionTreeModel.getUserStartingTree() == null) {
// userTreeCombo.setSelectedItem(NO_TREE);
// } else {
// userTreeCombo.setSelectedItem(partitionTreeModel.getUserStartingTree().getId());
// }
userTreeRadio.setEnabled(options.userTrees.size() > 0);
settingOptions = false;
}
public void getOptions(BeautiOptions options) {
if (settingOptions) return;
// all moved to event
// if (options.isEBSPSharingSamePrior() || options.starBEASTOptions.isSpeciesAnalysis()) {
//
// partitionTreeModel.setPloidyType( (PloidyType) ploidyTypeCombo.getSelectedItem());
// }
//
// partitionTreeModel.setStartingTreeType( (StartingTreeType) startingTreeCombo.getSelectedItem());
// partitionTreeModel.setUserStartingTree(getSelectedUserTree(options));
}
public boolean isBifurcatingTree(Tree tree, NodeRef node) {
if (tree.getChildCount(node) > 2) return false;
for (int i = 0; i < tree.getChildCount(node); i++) {
if (!isBifurcatingTree(tree, tree.getChild(node, i))) return false;
}
return true;
}
private Tree getSelectedUserTree() {
String treeId = (String) userTreeCombo.getSelectedItem();
for (Tree tree : options.userTrees) {
if (tree.getId().equals(treeId)) {
return tree;
}
}
return null;
}
}