// $Id: // FORESTER -- software libraries and applications // for evolutionary biology research and applications. // // Copyright (C) 2008-2009 Christian M. Zmasek // Copyright (C) 2008-2009 Burnham Institute for Medical Research // Copyright (C) 2000-2001 Washington University School of Medicine // and Howard Hughes Medical Institute // All rights reserved // // This library 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.1 of the License, or (at your option) any later version. // // This library 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 this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA // // Contact: phylosoft @ gmail . com // WWW: www.phylosoft.org/forester package org.forester.sdi; import org.forester.phylogeny.Phylogeny; import org.forester.phylogeny.PhylogenyNode; import org.forester.phylogeny.data.Event; /* * Implements our algorithm for speciation - duplication inference (SDI).

* Reference:

The initialization is accomplished by: *

The recursion * part is accomplished by this class' method * "geneTreePostOrderTraversal(PhylogenyNode)".

Requires JDK 1.2 or greater. * * @see SDI#linkNodesOfG() * * @see Phylogeny#preorderReID(int) * * @see * PhylogenyMethods#taxonomyBasedDeletionOfExternalNodes(Phylogeny,Phylogeny) * * @see #geneTreePostOrderTraversal(PhylogenyNode) * * @author Christian M. Zmasek * * @version 1.102 -- last modified: 10/02/01 */ public class SDIse extends SDI { /** * Constructor which sets the gene tree and the species tree to be compared. * species_tree is the species tree to which the gene tree gene_tree will be * compared to - with method "infer(boolean)". Both Trees must be completely * binary and rooted. The actual inference is accomplished with method * "infer(boolean)". The mapping cost L can then be calculated with method * "computeMappingCost()". *

* (Last modified: 01/11/01) * * @see #infer(boolean) * @see SDI#computeMappingCostL() * @param gene_tree * reference to a rooted binary gene Phylogeny to which assign * duplication vs speciation, must have species names in the * species name fields for all external nodes * @param species_tree * reference to a rooted binary species Phylogeny which might get * stripped in the process, must have species names in the * species name fields for all external nodes */ public SDIse( final Phylogeny gene_tree, final Phylogeny species_tree ) { super( gene_tree, species_tree ); _duplications_sum = 0; getSpeciesTree().preOrderReId(); linkNodesOfG(); geneTreePostOrderTraversal( getGeneTree().getRoot() ); } // Helper method for updateM( boolean, PhylogenyNode, PhylogenyNode ) // Calculates M for PhylogenyNode n, given that M for the two children // of n has been calculated. // (Last modified: 10/02/01) private void calculateMforNode( final PhylogenyNode n ) { if ( !n.isExternal() ) { final boolean was_duplication = n.isDuplication(); PhylogenyNode a = n.getChildNode1().getLink(), b = n.getChildNode2().getLink(); while ( a != b ) { if ( a.getId() > b.getId() ) { a = a.getParent(); } else { b = b.getParent(); } } n.setLink( a ); Event event = null; if ( ( a == n.getChildNode1().getLink() ) || ( a == n.getChildNode2().getLink() ) ) { event = Event.createSingleDuplicationEvent(); if ( !was_duplication ) { ++_duplications_sum; } } else { event = Event.createSingleSpeciationEvent(); if ( was_duplication ) { --_duplications_sum; } } n.getNodeData().setEvent( event ); } } // calculateMforNode( PhylogenyNode ) /** * Traverses the subtree of PhylogenyNode g in postorder, calculating the * mapping function M, and determines which nodes represent speciation * events and which ones duplication events. *

* Preconditions: Mapping M for external nodes must have been calculated and * the species tree must be labelled in preorder. *

* (Last modified: 01/11/01) * * @param g * starting node of a gene tree - normally the root */ void geneTreePostOrderTraversal( final PhylogenyNode g ) { PhylogenyNode a, b; if ( !g.isExternal() ) { geneTreePostOrderTraversal( g.getChildNode( 0 ) ); geneTreePostOrderTraversal( g.getChildNode( 1 ) ); a = g.getChildNode( 0 ).getLink(); b = g.getChildNode( 1 ).getLink(); while ( a != b ) { if ( a.getId() > b.getId() ) { a = a.getParent(); } else { b = b.getParent(); } } g.setLink( a ); // Determines whether dup. or spec. Event event = null; if ( ( a == g.getChildNode( 0 ).getLink() ) || ( a == g.getChildNode( 1 ).getLink() ) ) { event = Event.createSingleDuplicationEvent(); ++_duplications_sum; } else { event = Event.createSingleSpeciationEvent(); } g.getNodeData().setEvent( event ); } } // geneTreePostOrderTraversal( PhylogenyNode ) /** * Updates the mapping function M after the root of the gene tree has been * moved by one branch. It calculates M for the root of the gene tree and * one of its two children. *

* To be used ONLY by method "SDIunrooted.fastInfer(Phylogeny,Phylogeny)". *

* (Last modfied: 10/02/01) * * @param prev_root_was_dup * true if the previous root was a duplication, false otherwise * @param prev_root_c1 * child 1 of the previous root * @param prev_root_c2 * child 2 of the previous root * @return number of duplications which have been assigned in gene tree */ int updateM( final boolean prev_root_was_dup, final PhylogenyNode prev_root_c1, final PhylogenyNode prev_root_c2 ) { final PhylogenyNode root = getGeneTree().getRoot(); if ( ( root.getChildNode1() == prev_root_c1 ) || ( root.getChildNode2() == prev_root_c1 ) ) { calculateMforNode( prev_root_c1 ); } else { calculateMforNode( prev_root_c2 ); } Event event = null; if ( prev_root_was_dup ) { event = Event.createSingleDuplicationEvent(); } else { event = Event.createSingleSpeciationEvent(); } root.getNodeData().setEvent( event ); calculateMforNode( root ); return getDuplicationsSum(); } // updateM( boolean, PhylogenyNode, PhylogenyNode ) } // End of class SDIse.