/* * ExtendedTreeViewer.java * * Copyright (C) 2006-2014 Andrew Rambaut * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package figtree.treeviewer; import jebl.evolution.alignments.Alignment; import jebl.evolution.alignments.Pattern; import jebl.evolution.graphs.Node; import jebl.evolution.taxa.Taxon; import jebl.evolution.trees.Tree; import jebl.util.Attributable; import jam.panels.StatusListener; import jam.panels.StatusProvider; import figtree.treeviewer.annotations.AnnotationDefinition; import figtree.treeviewer.painters.CharactersPainter; import javax.swing.*; import java.awt.*; import java.util.*; import java.util.List; /** * @author Andrew Rambaut * @version $Id$ * * $HeadURL$ * * $LastChangedBy$ * $LastChangedDate$ * $LastChangedRevision$ */ public class ExtendedTreeViewer extends DefaultTreeViewer implements StatusProvider { public ExtendedTreeViewer() { this(null); } public ExtendedTreeViewer(JFrame frame) { super(frame); // setTreesPerPage(1); setBackground(Color.white); } public void setPattern(Pattern pattern) { if (pattern != null) { // setBranchDecorator(new ParsimonyBranchDecorator(pattern)); } else { setBranchDecorator(null, false); } } public void addTree(Tree tree) { Set<String> names = new TreeSet<String>(); for (Node node : tree.getNodes()) { names.addAll(node.getAttributeNames()); } for (Taxon taxon : tree.getTaxa()) { names.addAll(taxon.getAttributeNames()); } for (String name : names) { if (!name.startsWith("!")) { AnnotationDefinition annotation = getAnnotationDefinitions().get(name); Set<Attributable> items = new HashSet<Attributable>(tree.getNodes()); items.addAll(tree.getTaxa()); AnnotationDefinition.Type type = AnnotationDefinition.guessType(name, items); if (annotation == null) { annotation = new AnnotationDefinition(name, type); getAnnotationDefinitions().put(name, annotation); } else if (type != annotation.getType()){ AnnotationDefinition.Type newType = AnnotationDefinition.Type.STRING; if (type == AnnotationDefinition.Type.INTEGER && annotation.getType() == AnnotationDefinition.Type.REAL) { newType = AnnotationDefinition.Type.REAL; } if (newType != type) { annotation = new AnnotationDefinition(name, newType); getAnnotationDefinitions().put(name, annotation); } } } } super.addTree(tree); showStatus(); } public void showTree(int index) { super.showTree(index); showStatus(); } public void setCharacters(Alignment characters) { CharactersPainter painter = new CharactersPainter(characters); setTipLabelPainter(painter); } public void setTaxonAnnotations(Map<AnnotationDefinition, Map<Taxon, Object>> annotations) { for (AnnotationDefinition definition: annotations.keySet()) { getAnnotationDefinitions().put(definition.getName(), definition); Map<Taxon, Object> annotation = annotations.get(definition); for (Taxon taxon : annotation.keySet()) { taxon.setAttribute(definition.getName(), annotation.get(taxon)); } } fireAnnotationsChanged(); } public void showStatus() { fireStatusChanged(0, "Showing tree " + Integer.toString(getCurrentTreeIndex() + 1) + " / " + getTreeCount()); } public void showInfomation() { } public void showStatistics() { } public void annotateSelected(String name, Object value) { annotateSelectedNodes(name, value); annotateSelectedTips(name, value); fireAnnotationsChanged(); } public Map<String, AnnotationDefinition> getAnnotationDefinitions() { if (annotations == null) { annotations = new HashMap<String, AnnotationDefinition>(); } return annotations; } public void setAnnotationDefinitions(List<AnnotationDefinition> annotations) { if (this.annotations == null) { this.annotations = new HashMap<String, AnnotationDefinition>(); } this.annotations.clear(); for (AnnotationDefinition definition : annotations) { this.annotations.put(definition.getName(), definition); } } public void annotateNodesFromTips(String annotationName) { List<Object> stateCodes = new ArrayList<Object>(); Map<Taxon, Integer> stateMap = new HashMap<Taxon, Integer>(); Tree tree = treePane.getTree(); for (Node node : tree.getExternalNodes()) { Taxon taxon = tree.getTaxon(node); Object state = taxon.getAttribute(annotationName); int index = stateCodes.indexOf(state); if (index == -1) { index = stateCodes.size(); stateCodes.add(state); } stateMap.put(taxon, index); node.setAttribute(annotationName, state); } Parsimony parsimony = new Parsimony(stateCodes.size(), stateMap); for (Node node : tree.getInternalNodes()) { Integer stateIndex = parsimony.getState(tree, node); Object state = null; if (stateIndex != null) { state = stateCodes.get(stateIndex); } node.setAttribute(annotationName, state); } fireAnnotationsChanged(); } public void annotateTipsFromNodes(String annotationName) { Tree tree = treePane.getTree(); for (Node node : tree.getExternalNodes()) { Object state = node.getAttribute(annotationName); if (state != null) { Taxon taxon = tree.getTaxon(node); taxon.setAttribute(annotationName, state); } } fireAnnotationsChanged(); } private List<AnnotationsListener> listeners = new ArrayList<AnnotationsListener>(); public void addAnnotationsListener(AnnotationsListener listener) { listeners.add(listener); } public void fireAnnotationsChanged() { for (AnnotationsListener listener : listeners) { listener.annotationsChanged(); } fireTreeChanged(); } private static Map<String, AnnotationDefinition> annotations = null; private final StatusProvider.Helper statusHelper = new StatusProvider.Helper(); public void addStatusListener(StatusListener statusListener) { statusHelper.addStatusListener(statusListener); } public void removeStatusListener(StatusListener statusListener) { statusHelper.removeStatusListener(statusListener); } public void fireStatusChanged(int status, String statusText) { statusHelper.fireStatusChanged(status, statusText); } public void addOverrideProvider(StatusProvider provider) { statusHelper.addOverrideProvider(provider); } public void removeOverrideProvider(StatusProvider provider) { statusHelper.removeOverrideProvider(provider); } public void fireStatusButtonPressed() { statusHelper.fireStatusButtonPressed(); } public void statusButtonPressed() { statusHelper.statusButtonPressed(); } public int getStatus() { return statusHelper.getStatus(); } public String getStatusText() { return statusHelper.getStatusText(); } public void setStatusText(String statusText) { statusHelper.fireStatusChanged(0, statusText); } }