/*
* PathogenFrame.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
*/
/*
* BeautiFrame.java
*
* (c) 2002-2005 BEAST Development Core Team
*
* This package may be distributed under the
* Lesser Gnu Public Licence (LGPL)
*/
package dr.app.pathogen;
import dr.evolution.io.*;
import dr.evolution.tree.NodeRef;
import dr.evolution.tree.Tree;
import dr.evolution.tree.FlexibleTree;
import dr.evolution.util.TaxonList;
import dr.app.tools.NexusExporter;
import dr.stats.Regression;
import dr.util.NumberFormatter;
import figtree.treeviewer.TreeViewer;
import jam.framework.DocumentFrame;
import jam.framework.Exportable;
import jam.panels.SearchPanel;
import jam.panels.SearchPanelListener;
import jam.toolbar.Toolbar;
import jam.toolbar.ToolbarAction;
import jam.toolbar.ToolbarButton;
import jam.util.IconUtils;
import javax.swing.*;
import javax.swing.plaf.BorderUIResource;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.io.*;
import java.util.*;
/**
* @author Andrew Rambaut
* @author Alexei Drummond
* @version $Id: BeautiFrame.java,v 1.22 2006/09/09 16:07:06 rambaut Exp $
*/
public class PathogenFrame extends DocumentFrame {
private static final long serialVersionUID = 2114148696789612509L;
private JTabbedPane tabbedPane = new JTabbedPane();
private JLabel statusLabel = new JLabel("No data loaded");
private PathogenPanel pathogenPanel;
TaxonList taxa = null;
java.util.List<Tree> trees = new ArrayList<Tree>();
public PathogenFrame(String title) {
super();
setTitle(title);
// Prevent the application to close in requestClose()
// after a user cancel or a failure in beast file generation
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
getOpenAction().setEnabled(true);
getSaveAction().setEnabled(false);
getSaveAsAction().setEnabled(false);
getFindAction().setEnabled(false);
getCutAction().setEnabled(false);
getPasteAction().setEnabled(false);
getDeleteAction().setEnabled(false);
getSelectAllAction().setEnabled(false);
getCopyAction().setEnabled(false);
getZoomWindowAction().setEnabled(false);
}
public void initializeComponents() {
pathogenPanel = new PathogenPanel(this, taxa, trees.get(0));
JPanel panel = new JPanel(new BorderLayout(0, 0));
panel.add(pathogenPanel, BorderLayout.CENTER);
statusLabel.setBorder(new BorderUIResource.EmptyBorderUIResource(new Insets(0, 12, 6, 12)));
panel.add(statusLabel, BorderLayout.SOUTH);
getContentPane().setLayout(new BorderLayout(0, 0));
getContentPane().add(panel, BorderLayout.CENTER);
setSize(new Dimension(1024, 768));
setStatusMessage();
}
public void timeScaleChanged() {
pathogenPanel.timeScaleChanged();
setStatusMessage();
}
protected boolean readFromFile(File file) throws IOException {
Reader reader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(reader);
String line = bufferedReader.readLine();
while (line != null && line.length() == 0) {
line = bufferedReader.readLine();
}
boolean isNexus = (line != null && line.toUpperCase().contains("#NEXUS"));
reader = new FileReader(file);
Tree tree = null;
try {
if (isNexus) {
NexusImporter importer = new NexusImporter(reader);
tree = importer.importTree(taxa);
} else {
NewickImporter importer = new NewickImporter(reader);
tree = importer.importTree(taxa);
}
} catch (Importer.ImportException ime) {
JOptionPane.showMessageDialog(this, "Error parsing imported file: " + ime,
"Error reading file",
JOptionPane.ERROR_MESSAGE);
ime.printStackTrace();
return false;
} catch (IOException ioex) {
JOptionPane.showMessageDialog(this, "File I/O Error: " + ioex,
"File I/O Error",
JOptionPane.ERROR_MESSAGE);
ioex.printStackTrace();
return false;
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, "Fatal exception: " + ex,
"Error reading file",
JOptionPane.ERROR_MESSAGE);
ex.printStackTrace();
return false;
}
if (tree == null) {
JOptionPane.showMessageDialog(this, "The file is not in a suitable format or contains no trees.",
"Error reading file",
JOptionPane.ERROR_MESSAGE);
return false;
}
FlexibleTree binaryTree = new FlexibleTree(tree, true);
binaryTree.resolveTree();
trees.add(binaryTree);
if (taxa == null) {
taxa = binaryTree;
}
getExportTreeAction().setEnabled(true);
getExportDataAction().setEnabled(true);
return true;
}
protected boolean writeToFile(File file) throws IOException {
return false; //To change body of implemented methods use File | Settings | File Templates.
}
protected void doExportTree() {
FileDialog dialog = new FileDialog(this,
"Export Tree File...",
FileDialog.SAVE);
dialog.setVisible(true);
if (dialog.getFile() != null) {
File file = new File(dialog.getDirectory(), dialog.getFile());
PrintStream ps = null;
try {
ps = new PrintStream(file);
writeTreeFile(ps, false);
ps.close();
} catch (IOException ioe) {
JOptionPane.showMessageDialog(this, "Error writing tree file: " + ioe.getMessage(),
"Export Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
private void doExportTimeTree() {
FileDialog dialog = new FileDialog(this,
"Export Time Tree File...",
FileDialog.SAVE);
dialog.setVisible(true);
if (dialog.getFile() != null) {
File file = new File(dialog.getDirectory(), dialog.getFile());
PrintStream ps = null;
try {
ps = new PrintStream(file);
writeTimeTreeFile(ps);
ps.close();
} catch (IOException ioe) {
JOptionPane.showMessageDialog(this, "Error writing tree file: " + ioe.getMessage(),
"Export Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
protected void writeTimeTreeFile(PrintStream ps) throws IOException {
FlexibleTree tree = new FlexibleTree(pathogenPanel.getTreeAsViewed());
Regression r = pathogenPanel.getTemporalRooting().getRootToTipRegression(pathogenPanel.getTreeAsViewed());
for (int i = 0; i < tree.getInternalNodeCount(); i++) {
NodeRef node = tree.getInternalNode(i);
double height = tree.getNodeHeight(node);
tree.setNodeHeight(node, height/r.getGradient());
}
TreeUtils.setHeightsFromDates(tree);
NexusExporter nexusExporter = new NexusExporter(new PrintStream(ps));
nexusExporter.exportTree(tree);
}
protected void writeTreeFile(PrintStream ps, boolean newickFormat) throws IOException {
Tree tree = pathogenPanel.getTreeAsViewed();
// if (newickFormat) {
// NewickExporter newickExporter = new NewickExporter(ps);
// newickExporter.exportTree(tree);
// } else {
NexusExporter nexusExporter = new NexusExporter(new PrintStream(ps));
nexusExporter.exportTree(tree);
// }
}
// protected void doExportGraphic() {
// ExportDialog export = new ExportDialog();
// export.showExportDialog( this, "Export view as ...", treeViewer.getContentPane(), "export" );
// }
protected void doExportData() {
FileDialog dialog = new FileDialog(this,
"Export Data File...",
FileDialog.SAVE);
dialog.setVisible(true);
if (dialog.getFile() != null) {
File file = new File(dialog.getDirectory(), dialog.getFile());
Writer writer = null;
try {
writer = new PrintWriter(file);
pathogenPanel.writeDataFile(writer);
writer.close();
} catch (IOException ioe) {
JOptionPane.showMessageDialog(this, "Error writing data file: " + ioe.getMessage(),
"Export Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
private void setStatusMessage() {
Tree tree = pathogenPanel.getTree();
if (tree != null) {
String message = "";
message += "Tree loaded, " + tree.getTaxonCount() + " taxa";
TemporalRooting tr = pathogenPanel.getTemporalRooting();
if (tr.isContemporaneous()) {
message += ", contemporaneous tips";
} else {
NumberFormatter nf = new NumberFormatter(3);
message += ", dated tips with range " + nf.format(tr.getDateRange());
}
statusLabel.setText(message);
}
}
public JComponent getExportableComponent() {
JComponent exportable = null;
Component comp = tabbedPane.getSelectedComponent();
if (comp instanceof Exportable) {
exportable = ((Exportable) comp).getExportableComponent();
} else if (comp instanceof JComponent) {
exportable = (JComponent) comp;
}
return exportable;
}
@Override
public void doCopy() {
StringWriter writer = new StringWriter();
PrintWriter pwriter = new PrintWriter(writer);
for (String tip : pathogenPanel.getSelectedTips()) {
pwriter.println(tip);
}
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection selection = new StringSelection(writer.toString());
clipboard.setContents(selection, selection);
}
public Action getExportTreeAction() {
return exportTreeAction;
}
// public Action getExportGraphicAction() {
// return exportGraphicAction;
// }
public Action getExportDataAction() {
return exportDataAction;
}
protected AbstractAction exportTreeAction = new AbstractAction("Export Tree...") {
public void actionPerformed(ActionEvent ae) {
doExportTree();
}
};
// protected AbstractAction exportGraphicAction = new AbstractAction("Export Graphic...") {
// public void actionPerformed(ActionEvent ae) {
// doExportGraphic();
// }
// };
protected AbstractAction exportDataAction = new AbstractAction("Export Data...") {
public void actionPerformed(ActionEvent ae) {
doExportData();
}
};
public Action getExportTimeTreeAction() {
return exportTimeTreeAction;
}
protected AbstractAction exportTimeTreeAction = new AbstractAction("Export Time Tree...") {
public void actionPerformed(ActionEvent ae) {
doExportTimeTree();
}
};
}